For some reason I can''t figure out how to make the fields_for tags render in the trivial example below; however, it works in the browser. What does #build_association do that my stubbed method does not replicate? (Or is that even the issue?) I appreciate the insight. Thanks! Matt Smith #spec/views/assets/new.html.erb_spec.rb describe "assets/new.html.erb" do let(:asset) { mock_model("Asset").as_new_record.as_null_object } let(:owner) { mock_model("Owner").as_new_record.as_null_object } before(:each) do asset.stub(:owner => owner) assign(:asset, asset) end it "renders new asset form" do render assert_select "form", :action => assets_path, :method => "post" do assert_select "input#asset_name", :name => "asset[name]" # passes assert_select "input#asset_owner_attributes_name", :name => "asset[owner_attributes][name]" # fails! end end end #app/views/assets/_form.html.erb <%= form_for(@asset) do |f| %> <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name %> </div> <%= f.fields_for :owner do |owner_fields| %> <div class="field"> <%= owner_fields.label :name %> <%= owner_fields.text_field :name %> </div> <% end %> <div class="actions"> <%= f.submit %> </div> <% end %> -- Posted via http://www.ruby-forum.com/.
On 4 April 2011 02:00, Matt S. <lists at ruby-forum.com> wrote:> For some reason I can''t figure out how to make the fields_for tags > render in the trivial example below; however, it works in the browser. > What does #build_association do that my stubbed method does not > replicate? (Or is that even the issue?) > > I appreciate the insight. Thanks! Matt Smith > > #spec/views/assets/new.html.erb_spec.rb > describe "assets/new.html.erb" do > ?let(:asset) { mock_model("Asset").as_new_record.as_null_object } > ?let(:owner) { mock_model("Owner").as_new_record.as_null_object } > > ?before(:each) do > ? ?asset.stub(:owner => owner) > ? ?assign(:asset, asset) > ?end > > ?it "renders new asset form" do > ? ?render > > ? ?assert_select "form", :action => assets_path, :method => "post" do > ? ? ?assert_select "input#asset_name", :name => "asset[name]" # passes > ? ? ?assert_select "input#asset_owner_attributes_name", :name => > "asset[owner_attributes][name]" # fails! > ? ?end > ?end > end > > #app/views/assets/_form.html.erb > <%= form_for(@asset) do |f| %> > > ?<div class="field"> > ? ?<%= f.label :name %><br /> > ? ?<%= f.text_field :name %> > ?</div> > > ?<%= f.fields_for :owner do |owner_fields| %> > ? ?<div class="field"> > ? ? ?<%= owner_fields.label :name %> > ? ? ?<%= owner_fields.text_field :name %> > ? ?</div> > ?<% end %> > > ?<div class="actions"> > ? ?<%= f.submit %> > ?</div> > <% end %>In similar view specs, I''ve stubbed #owner_attributes= on the ''assets'' mock. I think Rails'' nested form/assignment implementation does a check on the existence of this method to make sure that the Asset model does indeed accept nested assignment for that attribute. Chris
Chris Mear wrote in post #990804:> On 4 April 2011 02:00, Matt S. <lists at ruby-forum.com> wrote: >> let(:owner) { mock_model("Owner").as_new_record.as_null_object } >> assert_select "input#asset_name", :name => "asset[name]" # passes >> <%= f.label :name %><br /> >> <div class="actions"> >> <%= f.submit %> >> </div> >> <% end %> > > In similar view specs, I''ve stubbed #owner_attributes= on the ''assets'' > mock. I think Rails'' nested form/assignment implementation does a > check on the existence of this method to make sure that the Asset > model does indeed accept nested assignment for that attribute. > > ChrisThanks Chris, I''ll give that a try and post my solution. Matt -- Posted via http://www.ruby-forum.com/.
Matt S. wrote in post #991032:>> In similar view specs, I''ve stubbed #owner_attributes= on the ''assets'' >> mock. I think Rails'' nested form/assignment implementation does a >> check on the existence of this method to make sure that the Asset >> model does indeed accept nested assignment for that attribute. >> >> Chris > > Thanks Chris, > > I''ll give that a try and post my solution. > > MattWell it appears I am still stumped... If I change Asset to: class Asset < ActiveRecord::Base belongs_to :owner accepts_nested_attributes_for :owner def owner_attributes=(attributes) #test end end The new form works in the browser, but not in the test. If I change my before block to the following (and eliminate the def owner_attributes=), the test still fails. before(:each) do asset.stub(:owner => owner) asset.stub(:owner_attributes=).with(anything()) # new line assign(:asset, asset) end Any thoughts? Am I stubbing this incorrectly? Much thanks, Matt -- Posted via http://www.ruby-forum.com/.
1) Is there a way to make this trivial example spec to pass? (If so, how?) 2) Advice: I would like to write more view specs, especially on views for models with more complex relationships. Is it worth it? (The reason I ask this somewhat rhetorical question is because I cannot find any examples of this on the web and have tried about everything I can think of, but I still can''t get view specs containing nested model forms to pass, using fields_for on models with accepts_nested_attributes_for.) Much thanks!!! Matt Smith #spec/views/assets/new.html.erb_spec.rb describe "assets/new.html.erb" do let(:asset) { mock_model("Asset").as_new_record.as_null_object } let(:owner) { mock_model("Owner").as_new_record.as_null_object } before(:each) do asset.stub(:owner => owner) assign(:asset, asset) end it "renders new asset form with owner attributes" do render assert_select "form[method=post][action=?]", assets_path do assert_select "input[type=text][name=''asset[owner_attributes][name]'']" end end end #app/views/assets/new.html.erb <%= form_for(@asset) do |f| %> <div class="field"> <%= f.label :name %><br /> <%= f.text_field :name %> </div> <%= f.fields_for :owner do |owner_fields| %> <div class="field"> <%= owner_fields.label :name %> <%= owner_fields.text_field :name %> </div> <% end %> <div class="actions"> <%= f.submit %> </div> <% end %> # Where the relationship will be the following.... class Asset < ActiveRecord::Base has_one :owner accepts_nested_attributes_for :owner end class Owner < ActiveRecord::Base belongs_to :asset end class AssetController < ApplicationController def new @asset = Asset.new @asset.build_owner end end -- Posted via http://www.ruby-forum.com/.
On 2 May 2011 00:58, Matt S. <lists at ruby-forum.com> wrote:> 1) Is there a way to make this trivial example spec to pass? (If so, > how?) > > 2) Advice: I would like to write more view specs, especially on views > for models with more complex relationships. Is it worth it? > > (The reason I ask this somewhat rhetorical question is because I cannot > find any examples of this on the web and have tried about everything I > can think of, but I still can''t get view specs containing nested model > forms to pass, using fields_for on models with > accepts_nested_attributes_for.) > > Much thanks!!! > > Matt Smith > > #spec/views/assets/new.html.erb_spec.rb > describe "assets/new.html.erb" do > ?let(:asset) { mock_model("Asset").as_new_record.as_null_object } > ?let(:owner) { mock_model("Owner").as_new_record.as_null_object } > > ?before(:each) do > ? ?asset.stub(:owner => owner) > ? ?assign(:asset, asset) > ?end > > ?it "renders new asset form with owner attributes" do > ? ?render > ? ?assert_select "form[method=post][action=?]", assets_path do > ? ? ?assert_select > "input[type=text][name=''asset[owner_attributes][name]'']" > ? ?end > ?end > end > > #app/views/assets/new.html.erb > <%= form_for(@asset) do |f| %> > > ?<div class="field"> > ? ?<%= f.label :name %><br /> > ? ?<%= f.text_field :name %> > ?</div> > > ?<%= f.fields_for :owner do |owner_fields| %> > ? ?<div class="field"> > ? ? ?<%= owner_fields.label :name %> > ? ? ?<%= owner_fields.text_field :name %> > ? ?</div> > ?<% end %> > > ?<div class="actions"> > ? ?<%= f.submit %> > ?</div> > <% end %> > > # Where the relationship will be the following.... > class Asset < ActiveRecord::Base > ?has_one :owner > ?accepts_nested_attributes_for :owner > end > > class Owner < ActiveRecord::Base > ?belongs_to :asset > end > > class AssetController < ApplicationController > ?def new > ? ?@asset = Asset.new > ? ?@asset.build_owner > ?end > endCan you get the contents of ''response.body'' from inside that spec example, so we can see what''s being rendered when the spec is run? Chris
Chris Mear wrote in post #996234:> On 2 May 2011 00:58, Matt S. <lists at ruby-forum.com> wrote: >> accepts_nested_attributes_for.) >> before(:each) do >> end >> <%= f.fields_for :owner do |owner_fields| %> >> >> class AssetController < ApplicationController >> def new >> @asset = Asset.new >> @asset.build_owner >> end >> end > > Can you get the contents of ''response.body'' from inside that spec > example, so we can see what''s being rendered when the spec is run? > > ChrisThanks Chis, Here is the rendered content: <h1>New asset</h1> <form accept-charset="UTF-8" action="/assets" class="new_asset" id="new_asset" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="✓" /></div> <div class="field"> <label for="asset_name">Name</label><br /> <input id="asset_name" name="asset[name]" size="30" type="text" value="Asset_#<RSpec::Core::ExampleGroup::Nested_2:0x00000004217d08>" /> </div> <h2>Owner</h2> <div class="actions"> <input id="asset_submit" name="commit" type="submit" value="Create Asset" /> </div> </form> <a href="/assets">Back</a> As you can see nothing comes up for the fields_for :owner block. I have tried stubbing owner_attributes and owner_attributes=, as your previously suggested, but I saw no change. It does seem that I need to mock something else on the assets model to get this to work. I have started combing through the the action_view source code but have not run into anything to get me on the right trail yet, although I have learned a lot about other things! If you want to see everything you can do a ''git clone git://github.com/matthewcalebsmith/asset_owner.git'' to get the whole mock project, in case I have left out any pertinent details. Thank you! Matt Smith -- Posted via http://www.ruby-forum.com/.
On 3 May 2011, at 15:05, Matt S. wrote:> Chris Mear wrote in post #996234: >> On 2 May 2011 00:58, Matt S. <lists at ruby-forum.com> wrote: >>> accepts_nested_attributes_for.) >>> before(:each) do >>> end >>> <%= f.fields_for :owner do |owner_fields| %> >>> >>> class AssetController < ApplicationController >>> def new >>> @asset = Asset.new >>> @asset.build_owner >>> end >>> end >> >> Can you get the contents of ''response.body'' from inside that spec >> example, so we can see what''s being rendered when the spec is run? >> >> Chris > > Thanks Chis, > > Here is the rendered content: > > <h1>New asset</h1> > > <form accept-charset="UTF-8" action="/assets" class="new_asset" > id="new_asset" method="post"><div > style="margin:0;padding:0;display:inline"><input name="utf8" > type="hidden" value="✓" /></div> > > <div class="field"> > <label for="asset_name">Name</label><br /> > <input id="asset_name" name="asset[name]" size="30" type="text" > value="Asset_#<RSpec::Core::ExampleGroup::Nested_2:0x00000004217d08>" > /> > </div> > > <h2>Owner</h2> > > <div class="actions"> > <input id="asset_submit" name="commit" type="submit" value="Create > Asset" /> > </div> > </form> > > <a href="/assets">Back</a> > > > As you can see nothing comes up for the fields_for :owner block. I have > tried stubbing owner_attributes and owner_attributes=, as your > previously suggested, but I saw no change. It does seem that I need to > mock something else on the assets model to get this to work. I have > started combing through the the action_view source code but have not run > into anything to get me on the right trail yet, although I have learned > a lot about other things! > > If you want to see everything you can do a ''git clone > git://github.com/matthewcalebsmith/asset_owner.git'' to get the whole > mock project, in case I have left out any pertinent details.The following patch makes the example pass for me. The key change was to take out the #as_null_object call on your mock models. That seems to be interfering with Action View''s detection of nested attributes acceptance, but I''m not sure exactly why. Chris
Chris Mear wrote in post #996461:> On 3 May 2011, at 15:05, Matt S. wrote: > >>>> @asset.build_owner >> Here is the rendered content: >> <input id="asset_name" name="asset[name]" size="30" type="text" >> </form> >> a lot about other things! >> >> If you want to see everything you can do a ''git clone >> git://github.com/matthewcalebsmith/asset_owner.git'' to get the whole >> mock project, in case I have left out any pertinent details. > > The following patch makes the example pass for me. The key change was to > take out the #as_null_object call on your mock models. That seems to be > interfering with Action View''s detection of nested attributes > acceptance, but I''m not sure exactly why. > > Chris > >>From 0829776dd45b3a0c57134f7af5d4f21feebe5fd7 Mon Sep 17 00:00:00 2001 > From: Chris Mear <chris at feedmechocolate.com> > Date: Tue, 3 May 2011 18:11:40 +0100 > Subject: [PATCH] Fix stubbing for nested form in assets/new. > > --- > spec/views/assets/new.html.erb_spec.rb | 11 ++++++++--- > 1 files changed, 8 insertions(+), 3 deletions(-) > > diff --git a/spec/views/assets/new.html.erb_spec.rb > b/spec/views/assets/new.html.erb_spec.rb > index b8845fe..9bf3b26 100644 > --- a/spec/views/assets/new.html.erb_spec.rb > +++ b/spec/views/assets/new.html.erb_spec.rb > @@ -1,13 +1,18 @@ > require ''spec_helper'' > > describe "assets/new.html.erb" do > - let(:asset) { mock_model("Asset").as_new_record.as_null_object } > - let(:owner) { mock_model("Owner").as_new_record.as_null_object } > + let(:asset) { mock_model("Asset").as_new_record } > + let(:owner) { mock_model("Owner").as_new_record } > > before(:each) do > asset.stub(:owner => owner) > - asset.accepts_nested_attributes_for :owner > + asset.stub(:name) > + asset.stub(:owner_attributes=) > + > + owner.stub(:name) > + > assign(:asset, asset) > + > end > > it "renders new asset form with owner attributes" do > -- > 1.7.4.4Thanks Chris, I guess it ended up being like you said at the beginning. It is good to know about the as_null_object behavior, which seems a bit odd, but I have too much work to worry about it right now. Definitely reinforces the idea of writing as little code as possible to make it pass, and only then refactor. If I had truly done that I probably would have caught this. Thank you for your time. I hope this also saves someone else a headache in the future. Thanks again, Matt Smith -- Posted via http://www.ruby-forum.com/.