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.
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:
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.
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.
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.
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”
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
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?