form_for and partials

48 views
Skip to first unread message

Frederick Cheung

unread,
Sep 25, 2007, 4:04:09 PM9/25/07
to rubyonra...@googlegroups.com
I love form_for, but I really hate

<% form_for :person, @person, :url => {...} do |f| %>
...
<%= render :partial => 'form', :locals => {'f' => f}
...
<% end %>

I've been thinking of instead allowing

<% form_for :person, @person, :url => {...} do |f| %>
...
<%= f.partial 'form' %>
...
<% end %>

f.partial would be exactly the same as the previous snippet, just
making the form builder available in the partial without the hassle
of :locals => {'f' => f}
the one thing I'm not sure about is how you pick the name under which
the form builder should appear in the partial.

Ideally f.partial 'form' would give you something sensible, but I'm
not sure how you would pick such a default

f.partial 'form', :name => 'f' would work, but then it's almost as
awkward as :locals => {'f' => f}

Any ideas (or is this one just stupid ?) ?

Fred

Damian Janowski

unread,
Sep 25, 2007, 4:44:32 PM9/25/07
to rubyonra...@googlegroups.com
On 9/25/07, Frederick Cheung <frederic...@gmail.com> wrote:
> I've been thinking of instead allowing
>
> <% form_for :person, @person, :url => {...} do |f| %>
> ...
> <%= f.partial 'form' %>
> ...
> <% end %>
>
> f.partial would be exactly the same as the previous snippet, just
> making the form builder available in the partial without the hassle
> of :locals => {'f' => f}

Looks great!

> the one thing I'm not sure about is how you pick the name under which
> the form builder should appear in the partial.

Well, we could leave a simple "f" by default. Most people are probably
used to that, right?

> Ideally f.partial 'form' would give you something sensible, but I'm
> not sure how you would pick such a default

Why not something like:

-- environment.rb
Rails::Initializer.run do |config|
config.action_view.form_builder_name = :f
end

And even:

config.action_view.form_builder = :labelled_form_builder

To always have form_for give you a custom builder.

> f.partial 'form', :name => 'f' would work, but then it's almost as
> awkward as :locals => {'f' => f}

We could leave that option for the very rare case where you want to
override the local variable name on a specific partial...

> Any ideas (or is this one just stupid ?) ?

I wonder if this is the reason why the scaffold_resource generator
doesn't deal with form partials like scaffold did? (ie the lack of a
nice way to do it).

Overall, +1!

Pratik

unread,
Sep 25, 2007, 4:47:45 PM9/25/07
to rubyonra...@googlegroups.com
Why not use name of the partial to refer to form object ?

On 9/25/07, Frederick Cheung <frederic...@gmail.com> wrote:
>


--
Cheers!
- Pratik
http://m.onkey.org

Andrew Kaspick

unread,
Sep 25, 2007, 4:51:14 PM9/25/07
to rubyonra...@googlegroups.com
I hate the form :partial, :locals thing too... feels dirty.

I like the idea of taking the partial name as the local name... that's
how things like the :collection partial works already.

Frederick Cheung

unread,
Sep 25, 2007, 5:04:08 PM9/25/07
to rubyonra...@googlegroups.com

On 25 Sep 2007, at 21:51, Andrew Kaspick wrote:
>
> I like the idea of taking the partial name as the local name... that's
> how things like the :collection partial works already.
>

Seems like this one has the people's vote. The one think holding me
back would be that this conflicts with the current behaviour of
partial (ie the object/collection with the write name materialising).
It would be pretty weird to have objects called @something_form, but
what if you did want to build up a form by iterating over some
collection ?

Fred

Shane Vitarana

unread,
Sep 25, 2007, 5:07:56 PM9/25/07
to rubyonra...@googlegroups.com
+1 but I think it might be too succinct for newbies.  I guess it's okay if you think of it as an alternative syntax, like sexy migrations.

Shane

Andrew Kaspick

unread,
Sep 25, 2007, 5:20:35 PM9/25/07
to rubyonra...@googlegroups.com
What about...

<%= f.render :partial => 'form' %>

?

And it would still perhaps allow all the usual render params to be
passed to it. I'm just thinking of this quickly, haven't thought
about it too too much. :)

On 9/25/07, Frederick Cheung <frederic...@gmail.com> wrote:
>
>

Mislav Marohnić

unread,
Sep 25, 2007, 5:30:23 PM9/25/07
to rubyonra...@googlegroups.com
On 9/25/07, Pratik <prati...@gmail.com> wrote:

Why not use name of the partial to refer to form object ?

Consistency!
+1

- Mislav

Joe Noon

unread,
Sep 25, 2007, 6:12:43 PM9/25/07
to Ruby on Rails: Core
> I love form_for, but I really hate
>
> <% form_for :person, @person, :url => {...} do |f| %>
> ...
> <%= render :partial => 'form', :locals => {'f' => f}
> ...
> <% end %>
>
> I've been thinking of instead allowing
>
> <% form_for :person, @person, :url => {...} do |f| %>
> ...
> <%= f.partial 'form' %>
> ...
> <% end %>

Isn't this what :object => f is for?

<% form_for :person, @person, :url => {...} do |f| %>

<%= render :partial => 'fields', :object => f
<% end %>

_fields.erb:

<%= fields.text_field :name %> (local variable is the name of the
partial)
<%= fields.text_field :age %>

Joe

Frederick Cheung

unread,
Sep 25, 2007, 6:43:45 PM9/25/07
to rubyonra...@googlegroups.com

On 25 Sep 2007, at 23:12, Joe Noon wrote:
>
> Isn't this what :object => f is for?
>
> <% form_for :person, @person, :url => {...} do |f| %>
> <%= render :partial => 'fields', :object => f
> <% end %>
>

It's just a bit of convenience - neither <render :partial =>
'fields', :object => f nor <%= render :partial => 'fields', :locals
=> {'f' => f} are very nice, compared to just "render :partial =>
form" as one can do with form_tag

Fred

Frederick Cheung

unread,
Sep 25, 2007, 6:48:16 PM9/25/07
to rubyonra...@googlegroups.com
I'm pretty much sold on this. The one thing is of course that it
doesn't have to boil down to a single name. The form builder can
easily be made available under more than one name if there's a demand
for that (so you could just always make it available as f, but I
think that would be a bit ugly.

Or is this super evil ;-)

class FormBuilder
def partial(name, options={}, &block)
builder_name = nil
block_locals = eval('local_variables', block.binding)

block_locals.each do |local|
value = eval(local, block.binding)
builder_name = local and break if value == self
end

@template.render options.merge(:partial => name, :object =>
self, :locals => {builder_name => self})
end
end

form_for(...) do |f|
f.partial('form'){}
end

this will work find what name (or rather one of the names) the form
builder had when the partial method was called

Fred

Michael Koziarski

unread,
Sep 26, 2007, 6:57:24 PM9/26/07
to rubyonra...@googlegroups.com
On 9/25/07, Frederick Cheung <frederic...@gmail.com> wrote:
>
> I love form_for, but I really hate
>
> <% form_for :person, @person, :url => {...} do |f| %>
> ...
> <%= render :partial => 'form', :locals => {'f' => f}

You can already do:

<%= render :partial=>'form', :object=>f %>

Which at least avoids the duplication in :locals.

It seems funny to me to have the form builder classes know about
rendering partials, or even rendering at all?


--
Cheers

Koz

Frederick Cheung

unread,
Sep 26, 2007, 7:14:03 PM9/26/07
to rubyonra...@googlegroups.com

To a large extent I'm nostalgic about being able to do <%=
render :partial=>'form' %>. :object=>f is better than :locals (should
of thought of that one), but it still seems a little redundant to
have to say 'and yes I do actually want my form builder available in
the partial. Maybe the form builder classes aren't the place for this
but I couldn't think of another way.

Fred

Michael Koziarski

unread,
Sep 26, 2007, 8:59:36 PM9/26/07
to rubyonra...@googlegroups.com
> Maybe the form builder classes aren't the place for this
> but I couldn't think of another way.

Perhaps:

<% form_for ... do |f|
<%= render :partial=>f %>
<% end %>

The enhance the polymorphic code to take account of FormBuilder and
make a FormBuilder for a Customer build:

customers/_form.format.erb ?

--
Cheers

Koz

Frederick Cheung

unread,
Sep 26, 2007, 9:18:55 PM9/26/07
to rubyonra...@googlegroups.com

so in render_partial, case FormBuilder does render :partial => "#
{f.object.class}/_form.format.erb", :object => f (apologies for
pseudoness of code) ?

As long as you don't have more than one form per model that you want
easily accessible (and even if you did have that I suppose that falls
under the general 'make the common case easy etc...', as it's not
that bad having to type out the :object if you do have some
complicated nesting/set of form partials.

Fred

Mislav Marohnić

unread,
Sep 26, 2007, 10:13:17 PM9/26/07
to rubyonra...@googlegroups.com
On 9/27/07, Michael Koziarski <mic...@koziarski.com> wrote:

The enhance the polymorphic code to take account of FormBuilder and
make a FormBuilder for a Customer build:

Neat idea, but that would mean tight coupling of render logic with view helper(s), which IMO is not a path to follow.

Michael Koziarski

unread,
Sep 30, 2007, 11:33:57 PM9/30/07
to rubyonra...@googlegroups.com
> so in render_partial, case FormBuilder does render :partial => "#
> {f.object.class}/_form.format.erb", :object => f (apologies for
> pseudoness of code) ?

Yeah, that's what I've been doing, and depending on the implementation
required it seems like it should be ok...

I can see mislav's point on coupling, but it seems consistent with the
current behaviour where:

render :partial=>@foo -> /foos/_foo.html.erb

> As long as you don't have more than one form per model that you want
> easily accessible (and even if you did have that I suppose that falls
> under the general 'make the common case easy etc...', as it's not
> that bad having to type out the :object if you do have some
> complicated nesting/set of form partials.
>
> Fred
>
> >
>


--
Cheers

Koz

Damian Janowski

unread,
Sep 30, 2007, 11:49:21 PM9/30/07
to rubyonra...@googlegroups.com
On 10/1/07, Michael Koziarski <mic...@koziarski.com> wrote:
>
> > so in render_partial, case FormBuilder does render :partial => "#
> > {f.object.class}/_form.format.erb", :object => f (apologies for
> > pseudoness of code) ?
>
> Yeah, that's what I've been doing, and depending on the implementation
> required it seems like it should be ok...
>
> I can see mislav's point on coupling, but it seems consistent with the
> current behaviour where:
>
> render :partial=>@foo -> /foos/_foo.html.erb

http://pastie.caboo.se/pastes/101420

This simple patch allows for render :partial => f, begin f a
FormBuilder, to render /_form.html.erb, and being f a
LabelledFormBuilder to render /_labelled_form.html.erb. It looks for
any FormBuilder subclass, and also sets the local variable name to
form, labelled_form, or whatever form builder you're using...

I don't know if there's a ticket already for this, and if anybody
wants this applied anyway... :)

Frederick Cheung

unread,
Dec 9, 2007, 7:09:15 AM12/9/07
to rubyonra...@googlegroups.com
Digging through some old stuff, I don't think this discussion every
really came to a conclusion.
I still feel the burn every time I write render :partial =>
'form', :object => f, and I believe the solution underlined below
takes care of it most of the time

Fred

Damian Janowski

unread,
Jan 15, 2008, 10:06:58 AM1/15/08
to rubyonra...@googlegroups.com
On Dec 9, 2007, at 9:09 AM, Frederick Cheung wrote:
> Digging through some old stuff, I don't think this discussion every
> really came to a conclusion.
> I still feel the burn every time I write render :partial =>
> 'form', :object => f, and I believe the solution underlined below
> takes care of it most of the time

The solution Fred mentions, as a proper patch with tests:

http://dev.rubyonrails.org/ticket/10814

Comments, +1's, everything is welcome :)

Michael Koziarski

unread,
Jan 15, 2008, 5:31:08 PM1/15/08
to rubyonra...@googlegroups.com

This looks wicked, but it should have some documentation too. Either
in the section on partials, or form builders, or both.


--
Cheers

Koz

Damian Janowski

unread,
Jan 15, 2008, 10:38:19 PM1/15/08
to rubyonra...@googlegroups.com

For the record, this has been committed after adding docs to both
sections. Thanks Koz!

Reply all
Reply to author
Forward
0 new messages