Problems with form_for and partials

i’m having problem with a form_for situation where i’m trying to DRY
out the repeated parts of my forms and put them in common/form and
render the form elements via another partial in controller_name/_form.
Here’s the first form

app/views/common/form

<% form_for … do |f| -%>
<%= render :partial => “params[:controller]/form”, :object => f %>

Submit buttons...

<% end -%>

I’m having problems with stub_render because of the :object => f. I
have tried creating a FormBuilder instance to use there as the :object
but it doesn’t seem to want to match the actual instance there, which
has a large amount of additional information due to the template being
run at that point.

Then in the partial:

app/views/users/_form

Name <%= f.text_field :user, ... %>

I can create a FormBuilder instance here and solve the ‘f’ problem by
stubbing f and returnign the new FormBuilder but then I have to stub
the text_field method which is what i’m actually spec’ing.

I’d appreciate any suggestions on how to accomplish this without
having to repeat the same basic form information and buttons over
multiple forms. Something about sacrificing DRYness to achieve BDD
seems off. I’d imagine you can have both and I’m just not hitting the
mark.

Thanks in advance.

RSL

On 10/20/07, Russell N. [email protected] wrote:

Name
seems off. I’d imagine you can have both and I’m just not hitting the
mark.

There should not be any conflict between BDD and DRY code. There has
been some debate about DRY specs, but that’s a completely different
matter.

One way that I’ve handled this that works well is that I’ve got a
shared behaviour for the common elements in the form and I use that in
all the specs for the forms that use the partial:

http://pastie.caboo.se/109164

This works whether there is a partial being used or not, and I think
that it makes it easier to refactor things later.

Cheers,
David

David, thanks for that code. I was thinking of something like that
myself.

As for the form_for stuff, problem B solved itself when I created the
form builder with its arguments in the correct order, heh. Problem A
is much bigger and harder as the mock form builder i make creates a
wholly different Proc than the form builder in the code. I’m giving up
trying to solve that and just not specing it to expect_render(…). So
I’m gonna consider this problem solved and move on. :slight_smile:

RSL

Has anyone come up with a solution for stubbing partials and passing
form builders to it?
i have a complex form with many parts, and those are rendered in
partials

You can use mocha parameter matching to match on “anything” where your
form builder would be passed in. You could also use Mocha’s “kind_of”
parameter matcher to ensure that what you expect is a FormBuilder
object.

Another way to do this is to not pass in your form builder, but the
object needed, and then use fields_for inside the partial itself. This
works well in some scenarios.

Zach

On Wed, Mar 12, 2008 at 4:24 PM, Jonathan L.

i’m having problem with a form_for situation where i’m trying to DRY
out the repeated parts of my forms and put them in common/form and
render the form elements via another partial in controller_name/_form.
Here’s the first form

app/views/common/form

<% form_for … do |f| -%>
<%= render :partial => “params[:controller]/form”, :object => f %>

Submit buttons...

<% end -%>

I had exactly the same problem and ending up putting the

form_for …do |f|

in the partial so I didn’t have to pass form builders around. This
won’t be practical though if you are using multiple partials for your
forms fields.

Rupert

On Mar 12, 2008, at 5:47 PM, David C. wrote:

object needed, and then use fields_for inside the partial itself.
This
works well in some scenarios.

You could also use rspec’s parameter matching, which also supports
“anything” but not “kind_of” :wink:

how would i use that in stub_render? eg if my view has
<%= render :partial => ‘pages/foo’, :layout => ‘bar’, :locals =>
{ :f => f } %>

what’s the stub?

On Wed, Mar 12, 2008 at 9:43 PM, Zach D. [email protected]
wrote:

You can use mocha parameter matching to match on “anything” where your
form builder would be passed in. You could also use Mocha’s “kind_of”
parameter matcher to ensure that what you expect is a FormBuilder
object.

Another way to do this is to not pass in your form builder, but the
object needed, and then use fields_for inside the partial itself. This
works well in some scenarios.

You could also use rspec’s parameter matching, which also supports
“anything” but not “kind_of” :wink:

On Wed, Mar 12, 2008 at 10:19 PM, Jonathan L.
[email protected] wrote:

object.
<%= render :partial => ‘pages/foo’, :layout => ‘bar’, :locals =>
{ :f => f } %>

what’s the stub?

As of 1.1.3:

stub_render(:partial => ‘pages/foo’, :layout => ‘bar’, :locals => {:f
=> })

There is now, in trunk, hash_including matcher, so you should (I
haven’t tried yet) be able to do this:

stub_render(hash_including(:locals => {:f => }))

That keeps it a bit less brittle, as the previous version will fail if
you add anything else to the actual render call this won’t fail.

Cheers,
David

We’ve been going down this route:

http://pastie.caboo.se/165265

We use mocha for our mocking and originally we mocked out the form
builder, but the specs felt crufty. We then converted to instantiating
the FormBuilder and passing it to partials that needed it.

For the views that send in the FormBuilder, we use the #with passing a
block and assert the “is_a?” inside (I’m still not too keen on using
the param helper/matchers). This looks a bit more bulky (and is kinda
ugly in having assertions in a setup) but it really greased the wheels
for us.

We ended up preferring to assert the presence of html vs expectations
on a FormBuilder stub, and it made the view specs feel a bit more
natural.

One last note: we hacked the #render in rspec_on_rails to output the
contents of a partial (which is why the template stubbing the render
returns “form partial”) and we assert the presence of that text in the
response. Helps catch those rascally <% %> instead of <%= %>. I’ve
been meaning to form together a patch and submit a proper extension,
but it’s as time allows.

Perhaps a bit more than you were asking for, but I hope this helps

-Zach

Thank you!

for the record, I refactored my code so the view does a form_for, and
any partials that render fields with the form builder does its own
fields_for. This makes the design cleaner and more testable. However,
I’m not sure if there’s any performance cost in doing it this way
instead of passing the form builder around, anyone?

This hints at another extension I’ve wanted to write for us for a while.

Common html selector strings, Labels, input fields, textareas, forms,
links, etc

Really just rolling up something like:

response.should have_tag(“input[type=text][name=?][value=?][id=company-
name]”, “user[company_name]”, “Some Company Inc.”)

into something like:

respose.should have_text_input(:user, :company_name, :id => “company-
name”, “Some Company Inc.”)

It feels closer to the Rails view helpers. Not a huge win, but we have
so many selectors than abstracting up one would make our specs more
readable.

Damn “To Code” list…

-Zach

Begin forwarded message:

My pair and I have written a bunch of these helpers. I’ll post what we
have later, perhaps it will be a starting point,

Zach

Zach,

On 3/14/08, Zach M. [email protected] wrote:

into something like:

respose.should have_text_input(:user, :company_name, :id =>
“company-name”, “Some Company Inc.”)

It feels closer to the Rails view helpers. Not a huge win, but we have so
many selectors than abstracting up one would make our specs more readable.

I’ve been thinking about doing the same thing. I want matchers like
have_text_input and have_text_input_with_label.

I think I’ll write them for my next project, and then extract them if
they’re useful.

brandon

seems like it’d make sense to just add this to http://code.google.com/
p/rspec-on-rails-matchers/

linoj

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs