Rails tip #3: Filter BLOBs from ActiveRecord logging
We threw attachment_fu into our app the other day, starting off with the default :db_file setting to store images in the database. (I’ve been bitten by this approach before, but this time around I’m intrigued by page caching. We’ll see.)
In the meantime, we’ve got blob after blob flying by in the script/server output, and it’s messing up our Terminal fonts. No good.
Here’s a quick fix, config/initializers/filter_db_files_logging.rb:
dump = 'INSERT INTO db_files' if dump.to_s =~ /^INSERT INTO db_files/
dump = 'UPDATE db_files' if dump.to_s =~ /^UPDATE db_files/
format_log_entry_without_db_files_filtering(message, dump)
end
alias_method_chain :format_log_entry, :db_files_filtering
end
Note that this isn’t yet a general solution (other tables’ blobs will still be logged), but it’s good enough for our needs, and we’ve got a known place we can come back to should we need to filter more blobs in the future.
Also, looking at AbstractAdapter#log_info just now, we notice that could have written our own Logger and saved the monkeypatch. Maybe we’ll look into doing that some day.
5 Rails tips
Each day this week, Joachim and I will post something we’ve learned in our time programming together. It’s fun to do, and we might just win something as well.
So far, we’ve written:
- Reloadable custom FormBuilder
- Faking DATA in tests
- Filter BLOBs from ActiveRecord logging
Rails tip #2: Faking DATA in tests
Ruby gives you access to the raw text after an __END__ statement in the currently running file through the DATA IO object.
Sometimes you’d like to use DATA in a test. You’ll find it works when you run the test individually but then fails when you run the whole suite. (Remember DATA comes from $0, the currently running file, only.)
We’ve found a nice way to fake it in the rubyforge gem: read __FILE__ instead, then split the results.
Here’s an example of the technique in use, functionally testing a wiki parser we’ve been tinkering with. It can often be painful to work with metaprogrammed tests like this, but on balance, we like the results here:
EXAMPLES = /={80}\n/m
PARTS = /-{80}\n/m
# Faking data = DATA.read
data = File.read(__FILE__).split('__END__').last
data.split(EXAMPLES).map {|example| example.split(PARTS) }.each do |comment, markup, html|
define_method "test_" do
assert_equal html, Parser.new.parse(markup).result.to_html
end
end
end
__END__
A single wiki word should be linked and wrapped in a paragraph.
--------------------------------------------------------------------------------
WikiWord
--------------------------------------------------------------------------------
<p><a href="WikiWord">WikiWord</a></p>
================================================================================
Two wiki words on separate lines should become two paragraphs
--------------------------------------------------------------------------------
WikiWord
WikiWord
--------------------------------------------------------------------------------
<p><a href="WikiWord">WikiWord</a></p>
<p><a href="WikiWord">WikiWord</a></p>
5 Rails tips
Each day this week, Joachim and I will post something we’ve learned in our time programming together. It’s fun to do, and we might just win something as well.
So far, we’ve written:
- Reloadable custom FormBuilder
- Faking DATA in tests
Rails tip #1: Reloadable custom FormBuilder
August Lilleaas has a nice writeup on making your own FormBuilder. Towards the end, he describes wiring it up as the default:
Create a new file called
config/initializers/setup.rb. Or, if you’re on pre-2.0, add it to the bottom ofconfig/environment.rb:
ActionView::Base.default_form_builder = LabellingFormBuilder
Though “proper,” this approach requires restarting the server to see changes in LabellingFormBuilder.
You can avoid restarting the server by doing this instead:
LabellingFormBuilder
end
end
It’s a subtle difference, but it provides a nice window into understanding the Dependencies mechanism:
In August’s version, const_missing loads the LabellingFormBuilder class only once, when the initializer is run.
In our version, we’ve tricked const_missing into running on each request by not holding onto the class it loads. That is, instead of caching the class lookup in @@default_form_builder, we’re allowing the lookup to be performed on demand.
Sweet.
5 Rails tips
Each day this week, Joachim and I will post something we’ve learned in our time programming together. It’s fun to do, and we might just win something as well.
