In Rails, you can run rake test:units, rake test:functionals, and rake test:integration which run the tests in ./test/unit, ./test/functional, and ./test/integration, respectively. You can also run rake test, which runs all three.
But rake test runs all three one after another—I’ve always wondered why—so you pay the cost of loading the test suite (and Rails) three times.
It’s not hard to run unit, functional, and integration tests all at once (although I had a couple of false starts). Here’s a test:all task that does the trick:
require 'rbconfig'
require 'rake/testtask'
namespace :test do
Rake::TestTask.new(:all => "test:prepare") do |t|
t.libs << "test"
t.test_files = %w{unit functional integration}.map { |dir| Dir.glob("test/#{dir}/*_test.rb") }.flatten
end
end
Lots of Javascript
In more than one of my projects, I have javascript or stylesheet files with several hundred lines. Also, I rotate between several active projects and forget exactly where I put things. :( What I want to do is break these files into smaller ones by responsibility but be able to concatenate them for production to reduce requests.
Rails has an excellent way of accomplishing the concatenation: the :cache option that works for both javascript_include_tag and stylesheet_link_tag. With it, you can write:
javascript_include_tag “effects”, “controls”, “builder”, “scriptaculous”, :cache => “scriptaculous_cached”
Rails will even let you shorten this by using register_javascript_expansion so that you can write:
javascript_include_tag :scriptaculous, :cache => “scriptaculous_cached”
That’s pretty awesome; but not as awesome as
helper :all
Automagic
I love how the macro for ActionController scours my helpers directory and includes whatever I place there. If I add a helper or refactor my helpers, I don’t have to remember update a list of helpers that lives somewhere else. That’s what I’d like to see from javascript_include_tag. So here’s what I came up with:
def include_javascript_dir(path)
javascripts = Dir.glob_in(File.join(RAILS_ROOT, “public/javascripts”, path), “*.js”)
javascripts = javascripts.map{|file| File.join(“/javascripts”, path, file)}
javascript_include_tag *(javascripts + [{:cache => “#{path}/all”}])
end
(NB: The above method uses a customization of Ruby’s Dir class, glob_in which executes glob in a relative path.)
This method includes every file with the extension .js in a given directory. Thanks to Rails, they’re each included separately in the development environment but are concatenated into the file all.js in production. Sweet!
Order
We’re not done yet, though. If I move all of the Scriptaculous files to /public/javascripts/scriptaculous and then put include_javascript_dir "scriptaculous" in my layouts, the files will get loaded: but there’s no guarantee that “effects” will be loaded before “controls” and JavaScript errors will be thrown.
We need to supply more information to include_javascript_dir; but I don’t want to have to spell out the order the files should be in or there won’t be any point to having this method discover them automatically. Here’s what I settled on:
((order & javascripts) + (javascripts - order))
Here order is a list of script file names in the order you care about and javascripts is a list of real javascript files that Ruby has discovered. The intersection of order and javascripts yields files-that-really-exist in the order you care about; and javascripts - order gives you all the rest of the real files.
I added another parameter to let you specify the relative path to your javascript files. (One of my projects uses “/public/js” and another “/public/javascripts”) Here’s what I’m using now:
def include_javascript_dir( path, options={} )
js_path = options[:path] || “javascripts”
javascripts = Dir.glob_in(File.join(RAILS_ROOT, “public”, js_path, path), “*.js”)
if (order=options[:order])
order = order.map{|s| “#{s}.js”}
javascripts = ((order & javascripts) + (javascripts - order))
end
javascripts = javascripts.map{|file| File.join(“/#{js_path}”, path, file)}
javascript_include_tag *(javascripts + [{:cache => “#{path}/concat”}])
end
I’ve wrapped it up with the helper methods I use in all my Rails applications: ttp://github.com/boblail/lail_extensions
One of the pieces of code I find myself writing over and over again is a banner for flash messages.
<div class="error" id="error">
<%=h flash[:error] %>
</div>
<div class="notice" id="notice">
<%=h flash[:notice] %>
</div>
That already is six lines of code that I will never care about again. And, to date, I’ve written then 5 times. They get worse, though, if I want those divs to be hidden when there is no message to display. I could wrap them like this:
<% if flash[:notice] %>
...
<% end %>
And if there is no message, the block will be absent from the page. But inevitably, I want to show those messages on an XHR, so my layouts get a little more complex:
<div class="error" id="error" <%= "style=\"display:none;\"" if flash[:error] %>
This is a perfect candidate for refactoring. My final product looks like this:
def flash_message(key, options={})
message = flash[key] || ""
options.reverse_merge!(:class => "flash #{key}", :id => "flash_#{key}")
options.merge!(:style => "display:none;") if message.empty?
content_tag :div, message, options
end
It replaces the six lines above with these two:
<%= flash_message :notice %>
<%= flash_message :error %>
I’ve tucked it into a plugin of other private conventions and will drop it into every new Rails app I write.