Mislav Marohnić
2009-Nov-07 13:21 UTC
will_paginate to Rails 3: ActionView, routing oddities
Last night I tried making necessary changes to the "agnostic" branch of will_paginate so it would work with Rails 3. http://github.com/mislav/will_paginate/commits/rails3 My ActionView specs were failing miserably. First they wouldn''t run because of this require: require ''action_controller/assertions/selector_assertions'' I poked around rails source to find where it has moved, and changed the path accordingly: require ''action_dispatch/testing/assertions/selector'' That also failed with an error that ActionDispatch::Assertions::SelectorAssertions is an undefined constant. Of course it''s undefined; I''m trying to require a file that defines it! This weird error seemed to originate from the very second line of code in that file: module ActionDispatch module Assertions # <-- this one ... end end Turns out, ActionDisplatch has set "Assertions" constant to autoload ''action_dispatch/testing/assertions'', which in turn tries to load all its submodules, which tried to mix in ActionDispatch::Assertions::SelectorAssertions before it''s even defined [1]. The solution was to simply load the complete assertions module: require ''action_dispatch/testing/assertions'' Now the spec suite would run, but all specs were failing. I started out with easy ones: there''s an expectation that a certain view helper would raise an ArgumentError. This failed because a different error class was rescued: ActionView::TemplateError. Now, I''m aware that exceptions from view templates were wrapped in TemplateError even before Rails 3, but I have two questions: 1) why didn''t I get TemplateError in previous versions of Rails, 2) why do we need to wrap view exceptions at runtime anyway? Next, specs that assigned instance variables to a view were failing because those instance variables were nil. I was doing something in the lines of: @view = ActionView::Base.new # later, in example blocks: @view.assigns[:foo] = ''bar'' # finally, when rendering @view.render(:inline => @template, :locals => locals) This stopped working. I investigated and I found that I have to give a complete list of assigns at instantation time: @view = ActionView::Base.new([], @assigns) This is because the ActionView initializer eagerly copies values from this hash to its instance variables [2]. Then it saves them to @assigns, provides an accessor for them but never does anything with that object again, so changing that hash through the accessor has no effect, although in the past it had. Is this a regression? The rest of the failures in this test suite were all routing errors. Here is the routing setup in my tests: ActionController::Routing::Routes.draw do |map| map.connect ''dummy/page/:page'', :controller => ''dummy'' map.connect ''dummy/dots/page.:page'', :controller => ''dummy'', :action => ''dots'' map.connect ''ibocorp/:page'', :controller => ''ibocorp'', :requirements => { :page => /\d+/ }, :defaults => { :page => 1 } map.connect '':controller/:action/:id'' end The "ibocorp" route tests that if you generate a page link with {:controller => ''ibocorp'', :page => 1}, because of the ":defaults" parameter you should get "/ibocorp" URL, not "/ibocorp/1". This worked in previous versions of Rails, fails in Rails 3. Most other specs rely on the generic, ":controller/:action/:id" fallback route. They try to generate pagination links in the context of fake controller & action names and arbitrary number of additional parameters. In Rails 3, they all fail miserably with the exception like: No route matches {:controller=>"foo", :developers_page=>1, :action=>"bar"} This leaves me clueless. Why doesn''t the generic route handle this? So far this is my biggest problem. Finally, I had to mark all output from will_paginate view helpers as `html_safe!`. That worked like a charm. That''s about it concerning views and routing. There is an Arel bug with performing `count` on a named scope through a hmt association, but I guess I''ll be reporting that to the Arel project. [1]: http://github.com/rails/rails/blob/7b3b7cb2ab1ccf96d4c8a1bafd87dbfbd2ac8c84/actionpack/lib/action_dispatch/testing/assertions.rb#L5 [2]: http://github.com/rails/rails/blob/976c2647240fd40a2b706ab5e41856cd47e7b212/actionpack/lib/action_view/base.rb#L278 --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Eloy Duran
2009-Nov-07 15:08 UTC
Re: will_paginate to Rails 3: ActionView, routing oddities
Hey Mislav, I recently rewrote large parts of ActionView::TestCase, so there are probably still some rough edges. You shouldn''t need to instantiate a view yourself anymore. The test case will set this up for you when render is called and assign the test case instance variables to it. The theory is that you should be able to work with it as from a controller. class SomeHelperTest < ActionView::TestCase def test_rendering @foo = ''bar'' render(:inline => @template, :locals => locals) end end The other issues are indeed more Rails 3 related, afaik. HTH, Eloy On 7 nov 2009, at 14:21, Mislav Marohnić wrote:> Last night I tried making necessary changes to the "agnostic" branch > of will_paginate so it would work with Rails 3. > http://github.com/mislav/will_paginate/commits/rails3 > > My ActionView specs were failing miserably. First they wouldn''t run > because of this require: > > require ''action_controller/assertions/selector_assertions'' > > I poked around rails source to find where it has moved, and changed > the path accordingly: > > require ''action_dispatch/testing/assertions/selector'' > > That also failed with an error that > ActionDispatch::Assertions::SelectorAssertions is an undefined > constant. Of course it''s undefined; I''m trying to require a file > that defines it! This weird error seemed to originate from the very > second line of code in that file: > > module ActionDispatch > module Assertions # <-- this one > ... > end > end > > Turns out, ActionDisplatch has set "Assertions" constant to autoload > ''action_dispatch/testing/assertions'', which in turn tries to load > all its submodules, which tried to mix in > ActionDispatch::Assertions::SelectorAssertions before it''s even > defined [1]. The solution was to simply load the complete assertions > module: > > require ''action_dispatch/testing/assertions'' > > Now the spec suite would run, but all specs were failing. I started > out with easy ones: there''s an expectation that a certain view > helper would raise an ArgumentError. This failed because a different > error class was rescued: ActionView::TemplateError. Now, I''m aware > that exceptions from view templates were wrapped in TemplateError > even before Rails 3, but I have two questions: 1) why didn''t I get > TemplateError in previous versions of Rails, 2) why do we need to > wrap view exceptions at runtime anyway? > > Next, specs that assigned instance variables to a view were failing > because those instance variables were nil. I was doing something in > the lines of: > > @view = ActionView::Base.new > # later, in example blocks: > @view.assigns[:foo] = ''bar'' > # finally, when rendering > @view.render(:inline => @template, :locals => locals) > > This stopped working. I investigated and I found that I have to give > a complete list of assigns at instantation time: > > @view = ActionView::Base.new([], @assigns) > > This is because the ActionView initializer eagerly copies values > from this hash to its instance variables [2]. Then it saves them to > @assigns, provides an accessor for them but never does anything with > that object again, so changing that hash through the accessor has no > effect, although in the past it had. Is this a regression? > > The rest of the failures in this test suite were all routing errors. > Here is the routing setup in my tests: > > ActionController::Routing::Routes.draw do |map| > map.connect ''dummy/page/:page'', :controller => ''dummy'' > map.connect ''dummy/dots/page.:page'', :controller => > ''dummy'', :action => ''dots'' > map.connect ''ibocorp/:page'', :controller => ''ibocorp'', > :requirements => { :page => /\d > +/ }, > :defaults => { :page => 1 } > > map.connect '':controller/:action/:id'' > end > > The "ibocorp" route tests that if you generate a page link with > {:controller => ''ibocorp'', :page => 1}, because of the ":defaults" > parameter you should get "/ibocorp" URL, not "/ibocorp/1". This > worked in previous versions of Rails, fails in Rails 3. > > Most other specs rely on the generic, ":controller/:action/:id" > fallback route. They try to generate pagination links in the context > of fake controller & action names and arbitrary number of additional > parameters. In Rails 3, they all fail miserably with the exception > like: > > No route matches > {:controller=>"foo", :developers_page=>1, :action=>"bar"} > > This leaves me clueless. Why doesn''t the generic route handle this? > So far this is my biggest problem. > > Finally, I had to mark all output from will_paginate view helpers as > `html_safe!`. That worked like a charm. > > That''s about it concerning views and routing. There is an Arel bug > with performing `count` on a named scope through a hmt association, > but I guess I''ll be reporting that to the Arel project. > > [1]: http://github.com/rails/rails/blob/7b3b7cb2ab1ccf96d4c8a1bafd87dbfbd2ac8c84/actionpack/lib/action_dispatch/testing/assertions.rb#L5 > [2]: http://github.com/rails/rails/blob/976c2647240fd40a2b706ab5e41856cd47e7b212/actionpack/lib/action_view/base.rb#L278 > > >--~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Mislav Marohnić
2009-Nov-08 14:17 UTC
Re: will_paginate to Rails 3: ActionView, routing oddities
On Sat, Nov 7, 2009 at 16:08, Eloy Duran <eloy.de.enige@gmail.com> wrote:> > You shouldn''t need to instantiate a view yourself anymore. The test case > will set this up for you when render is called and assign the test case > instance variables to it. The theory is that you should be able to work with > it as from a controller. >Hey Eloy, I''m not using rspec-rails, just rspec and I don''t inherit all the *::TestCase goodness from Rails. Now, it''s not hard to render your own template manually, and I''m not having problem with that, I just noticed how previously you could add stuff to `assigns` hash and now you can''t — well, you can but it has no effect. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Mislav Marohnić
2009-Nov-09 00:21 UTC
Re: will_paginate to Rails 3: ActionView, routing oddities
I have submitted tickets for some of the above mentioned issues: - ActionView::Base#assigns<https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/3471-actionviewassigns-lost-its-usefulness> - SelectorAssertions loading<https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/3470-cannot-require-actiondispatch-selectorassertions> Still waiting for someone to comment on routing issues. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---
Joshua Peek
2009-Nov-10 03:58 UTC
Re: will_paginate to Rails 3: ActionView, routing oddities
I added a pending test for the one routing issue. The failing default route tests are a problem with your test fixtures. Now you must define "FooController" if you are going route to it. Or you can use with_controllers! [''foo'', ...]. I also suggest you use with_routing do |set| instead of editing the AC::Routing::Routes global since it will be going away soon. http://github.com/rails/rails/commit/763489ce064b92609634638c93022b6916976e4f
Mislav Marohnić
2009-Nov-10 13:46 UTC
Re: will_paginate to Rails 3: ActionView, routing oddities
On Tue, Nov 10, 2009 at 04:58, Joshua Peek <josh@joshpeek.com> wrote:> > The failing default route tests are a problem with your test fixtures. Now > you must define > "FooController" if you are going route to it. Or you can > use with_controllers! [''foo'', ...]. >Thanks. I put this before my routes declaration: ActionController::Routing.use_controllers!(%w(foo baz)) I also suggest you use with_routing do |set| instead of editing the> AC::Routing::Routes global since it will be going away soon.I can''t use `with_routing`, I''m not using ActionController::TestProcess as my tests don''t need a real request/response cycle, only view rendering and URL generation. --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---