When an exception is raised during rendering of a view it is wrapped inside an ActionView::Template::Error which is then reraised.
This leads to unhelpful failure messages in view specs, along the lines of
contact/index.html.haml renders a form to send feedback
Failure/Error: it "renders a form to send feedback" do render
ActionView::Template::Error
# ./app/views/contact/index.html.haml:19
# ./spec/views/contact/index.html.haml_spec.rb:10:in `block (2 levels) in '
I loathe helper :all. What’s the point of nicely divided helper modules if they’re all injected into same namespace, overwriting each other at random? I like to write reusable helpers that individual controllers can use by implementing their version of a foo method. I see no reason why two completely unrelated helper modules couldn’t both has a display_help_text method. helper :all prevents both of these and creates situations where you can accidentally overwrite a helper method in a completely different part of your application.
Obviously not everyone agrees with me because Rails continues to move in the other direction. Once upon a time, a bare controller only pulled in its default helper (ie Bar::FooController gets Bar::FooHelper) and the helpers for its ancestors. Later, the default application skeleton added helper :all to ApplicationController but this was still an opt in scheme. With Rails 3 it is an opt out scheme: you have to put clear_helpers in a controller to clear out the helpers Rails includes automatically for it.
Update:
As of Rails 3.1, you can do config.action_controller.include_all_helpers = false to escape this madness.
View Specs
Rspec tries to do the right thing - if you poke into view_example_group.rb in rspec-rails you can see it determining the default helper class and including that and ApplicationHelper into the view object. Unforunately it also includes controller._helpers. This controller isn’t an instance of the controller class that will use the view - it’s an instance of ActionView::TestCase::TestController, so has Rails’ default of the full set of helpers, irrespective of how the controller in the app is configured.
The first step is of course calling clear_helpers on ActionView::TestCase::TestController but if your application has helper modules that are used by multiple controllers then some of your view specs may start to fail. You could of course add those helpers to the view from your before(:each) blocks but that is a slightly nasty piece of duplication: you’ve already specified once which helpers should be used. More dangerously you could develop a situation where your view specs pass because they specify one set of helpers but your app fails because your controllers specify a different set.
To remedy this I’ve got the following in one of my apps:
This works out what controller class the view will normally be used with, for admin/foo/bar.html.haml this would be Admin::FooController and uses the helpers that controller would use normally.
A call to config.include(ViewHelpersSpecHelper) in my RSpec.configure block ensures that this module gets included everywhere relevant.
Cells
This starts to break down for partials that are rendered by multiple different controllers or for shared ones that don’t have a natural controller they can be tested with. This is perhaps the one thing that helper :all doesn’t make worse, since it does mean that a given view is always rendered with the same set of helper functions available. If you do have such units of view and helper code, the cells library is well worth a look.
Range#include?changed in ruby 1.9 . In ruby 1.8, testing whether a value was included in a range meant testing that it was greater than the start of the range and smaller than the end. Ruby 1.9 will iterate through all values in the range, checking whether any of them are equal to the value being tested.
The justification is that this is needed for some special cases. The example given in the link above is a range of objects wrapping integers, where #succ is defined to add 2 to the wrapped integer and comparison is defined by comparing the wrapped integer. If we write f(x) for the object wrapping x then you would have f(1) <= f(2) and f(2) <= f(3), but f(2) is not in the sequence generated by calling #succ repeatedly on f(1), since that yields only objects wrapping odd numbers.
While more correct in this sense, this is obviously a lot slower. It’s also not immune from a different class of issues. As Xavier Noria pointed out on the rails-core list, it’s easy enough to construct ranges with an infinite amount of elements in them for example. Calling include on them would hang forever on 1.9.
In the real world, my main concern is the speed. In our app we had a validates_inclusion_of on dates with a 100 year date range. On 1.8 this was instant, but on 1.9 calling include? on that range was taking around 130ms (on a 2.66Ghz Core i7).
Luckily the old include? logic is available as cover?. As of 3.0.5 Rails will use cover? rather than include? for validates_inclusion_of, until then you could drop something like this in an initializer.
1234567891011121314151617181920
ifRUBY_VERSION=~/1\.9/moduleActiveModel# == Active Model Inclusion ValidatormoduleValidationsclassInclusionValidator<EachValidatordefvalidate_each(record,attribute,value)match=ifoptions[:in].is_a?(Range)options[:in].cover?(value)elseoptions[:in].include?(value)endunlessmatchrecord.errors.add(attribute,:inclusion,options.except(:in).merge!(:value=>value))endendendendendend
A colleague and I recently updated an app to rails 2.3.4 and found ourselves with a slightly sticky performance problem - slow app response times, with time disappearing seemingly nowhere. New Relic also showed that requests were queueing inside mongrels which wasn’t shouldn’t have been a problem since there were plenty of mongrels for the traffic being received at the time
Our friendly Engineyard support engineer pointed us to a ticket on the Rails lighthouse describing a rather similar situation encountered during the RC phase of rails 2.3: Active record based sessions causing trouble because they weren’t returning their connection to the connection pool [1]. Connection pooling isn’t new in 2.3 but the move to rack changed the order in which things like sessions, query caching, connection pool are put up.
This ticket was mark as resolved, however looking at the fix it became clear why we were still experiencing the problem:
Since our session store isn’t ActiveRecord::SessionStore, the code to put the database related middleware in the right place in the chain isn’t executed. I’m not entirely sure what to do about this - the rails initializer cannot be expected to know the details of what the session store is doing (unless part of the session store interface was a uses_active_record? flag) but as it is this very sneaky and would have taken a while to find if we hadn’t been pointed in the right direction.
[1] As of Rails 2.2, Active Record has a concept of a connection pool: a given rails instance won’t use more than a certain number of connections (5 by default) even if that rails instance was a jruby based instance with hundreds or threads. If you need a connection from the pool and they are all in use then you have to wait until one becomes available. Normally you are blissfully unaware of this - rails marks your connection as no longer used when your action has finished processing.