Focusing autotest
August 24th, 2008
The usual autotest workflow goes something like this:
- Edit and save
- Autotest runs associated specs
- Are there failures? Fix and start over
- Autotest runs the entire suite
Sometimes though, you want autotest to just ignore most of your specs and focus on a few specs.
Last week, while Kevin, Rick, and Yossef (OG) were here, they shared an autotest tweak that does exactly that.
The tweak allows you to specify a regular expression to limit the files which autotest watches; for example, to autotest only files matching *user*.rb you would (atest is an alias):
% atest user
Here is the (lightly modified) code to do this; in your .autotest file add:
if ENV['AUTOTEST'] and not ENV['AUTOTEST'].empty?
only_these_files_re = Regexp.new(ENV['AUTOTEST'])
Autotest.send(:alias_method, :real_find_files, :find_files)
Autotest.send(:define_method, :find_files) do |*args|
real_find_files.reject do |k, v|
!only_these_files_re.match(k)
end
end
end
And in your .bash_profile add:
# Autotest
function fn_autotest() {
AUTOTEST=$1 autotest
}
alias atest='fn_autotest'
Now use the alias to invoke autotest. For standard autotest behavior:
% atest
To limit what autotest is watching, pass a regular expression (which can be a simple string):
% atest user.*html
Control your layout
April 22nd, 2008
Recently, I added jQuery ajax tabs to an application. To reuse the existing views, I moved the relevant view code to partials for each required action:
render :partial => "entry", :object => journal_entry
and using something like the following in all the relevant controller methods:
format.html { render :partial => 'index' if request.xhr? }
As I added more features to the ajax tabs, I was conditionally rendering partials in every relevant action, as well as creating a partial. Not DRY.
layout provides a much DRY-er solution without the need for the partials. In application.rb:
layout proc { |controller| controller.request.xhr? ? false : 'application' }
When a controller action is invoked, if it is an XHR, no layout will be used. Otherwise the default Rails layout, ‘application’, will be used1.
1 layout expects the name of a layout to be returned from the proc; in this case, I am returning the name of the default. Returning false indicates that no layout should be used.
Monkey Patch!
February 22nd, 2008
So after missing the wisdom[1] of this:
And responding to this:
http://b.lesseverything.com/2008/2/19/haml-doesn-t-like-javascript
I went to bed.
This morning I wrote my first Rails (really Haml) Monkey Patch[2]. This adds some of what Steve wanted: undisturbed inline javascript with variable interpolation. I am not sure what else he wanted as I did not read his blog carefully :)
Throw this into lib/inline_javascript.rb
module Haml
module Filters
class InlineJavascript
HEAD =<<EOH
<script type="text/javascript">
//<![CDATA[
EOH
FOOT =<<EOF
//]]>
</script>
EOF
def initialize(text)
@text = HEAD + text + FOOT
end
def render
@text
end
end
end
module Precompiler
def close_filtered(filter)
@flat_spaces = -1
filtered = filter.new(@filter_buffer).render
if filter == Haml::Filters::Preserve
push_silent("_hamlout.buffer << #{filtered.dump} << \"\\n\";")
elsif filter == Haml::Filters::InlineJavascript
# suppress eval option does not apply to us
flush_merged_text
js = unescape_interpolation(filtered)
@precompiled << "_hamlout.buffer << #{js};"
else
push_text(filtered.rstrip.gsub("\n", "\n#{' ' * @output_tabs}"))
end
@filter_buffer = nil
@template_tabs -= 1
end
end
end
Throw this at the bottom of your environment.rb, taken from here http://groups.google.com/group/haml/msg/2d890cf1ede761ea
require 'inline_javascript'
Haml::Template.options = {
:filters => {
'javascript' => Haml::Filters::InlineJavascript
}
}
And then do this in your Haml:
:javascript
function oh_yea() {
alert('Hello' + '#{@message}')
}
%a{ :href =>"javascript:oh_yea()" } Oh Yea!
Update
I decided to make a patch and submit it to the Haml folks directly. This gave me the ‘opportunity’ to get git going.
Nathan Weizenbaum took the time to put in a more comprehensive fix to expose the interpolation functionality to all filters – look for it in an upcoming release.
[1] It’s turtles all the way down.
[2] You do not want to know what my subconscious originally thought up as the way to do this – that was twisted.