John Pignata's blog
Yesterday we had Mat Brown of Patch.com giving us a presentation on his Sunspot gem for easily adding full-text search to a Rails application via Solr.
Mat walked us through the steps for adding Sunspot to a Rails application, talked through some of the production deployment concerns of Solr and illustrated some of the new features of Solr 1.4 such as master/slave replication and sharding that make it worth a look for full-text search.
Most of our tech talks are open to the public. If you're interested in joining us for presentations like this please join our mailing list.
At stand-up this past Monday after the whirlwind of the holidays, our team anchor encouraged us to pair with somebody we hadn't paired with much recently. While this was good advice I really didn't have a clear idea in my mind of how often I'd been pairing with specific developers on the team.
Interesting
>> false.blank?
=> true
blank? first checks to see if a method responds to empty? and if not evaluates !self which in false's case will always be true. This caused a pair a bit of confusion when trying to validate the completeness of a form that had a checkbox.
Railscamp — an all-weekend hackfest — is being held in Rhode Island in March of next year.
All API keys were recently reset on Gemcutter due to a security bugfix - in order to publish gems you'll need to update your gemcutter gem to regenerate your key.
Postgres will return an error if you attempt to ORDER BY columns that are not specified in the SELECT. This is painful in cases where you're using DISTINCT with any kind of JOIN.
One team cut their deployment down from 7 minutes to 30 seconds with a few cap recipe tweaks. Most of the time was saved by symlinking gem bundler-related directories to prevent bundler from building native gems on each deploy and by only running database migrations when anything in db/migrate had changed.
When using the inherited hook for ActiveRecord::Base, beware of tables that have their name overriden by set_table_name. The inherited hook will execute prior to that statement being evaluated which can cause strange results.
Getting Selenium to work with Snow Leopard involves some manual file renaming hackery — for anybody struggling with this there are a couple of posts out there to walk you through the process.
Help
RubyMine and gem bundler don't seem to get along - RubyMine complains that bundled gems aren't attached but these gems aren't available when we try to attach them. Any ideas?
RubyMine uses your gem path so you'll be able to attach to the gem if you add your gem bundler path to your ~/.gemrc file
There's an option to disable this nagging alert in the preferences.
Is there a good Rails plugin skeleton/template out there?
Know of one? Let us know in the comments.
Interesting
Don't use sleep 1 or such in before blocks in rspec if you need to ensure a delay between two events. A before block is ran between all nested contexts so you're probably incurring a larger penalty. Instead, you should stub Time.now.
One team implemented git commit hooks to facilitate communication - on rebase or merge new messages from a text file in the project root are displayed to alert other pairs to changes such as gem upgrades, noteworthy database changes, etc.
Earlier this week, the Rails core team released Rails 2.3.5 which introduces a major new feature: support for automatic cross-site scripting protection via the rails_xss plugin. rails_xss switches the default behavior of Rails to automatically escape all unsafe strings emitted into the view.
Help
Is there a way to ensure at_exit will always be ran regardless of how the program exits without wrapping all code in an ensure block?
Ideas included:
Use a runner class to execute the program and wrap that in an ensure block.
trap("EXIT") { block } should get triggered no matter how the program terminates (sigint, exception, etc)
What are the likely causes of RangeError exceptions during test runs?
<RangeError: 0x23513ec is recycled object>
This is generally caused by C extensions.
Their appearance coincided with a Darwin ports update — perhaps you're running native gems against different versions of libraries than they were compiled against.
Are there any techniques out there to take a series of bytes and run some heuristics on them to determine the likely encoding of the string it represents?
Anybody out there have any ideas? Please let us know in the comments!
Interesting
Passing :multiple => false or nil to the select helpers causes unpredictable results — the helper still builds input element names assuming an array of items will be passed back. The helper checks only that the key is present in the options hash and not the value which means if you need to conditionally render a multiple, you'll have to make sure you don't specify the :multiple key at all.
Using $('textarea').val() causes unpredictable results as a textarea doesn't keep its data in a value attribute. Use text()) instead.
IE 7 and 8 (and more than likely 6) seem to have a problem with jQuery selectors that match links based upon the href attribute — changing the href of the matched elements does not get reflected in the document.
From a Blabs comment: Taps is a Sinatra web service from Heroku that's used to move data from one database to another. It transmits data as serialized arrays and loads them using ActiveRecord so it's DB agnostic.
Disabling a label via jQuery will not disable the input that it refers to in the for attribute as the label is not a container.
Happy Thanksgiving!
One of our projects had a pending chore in Tracker to move its backend to PostgreSQL from MySQL. This project has about a quarter of a million rows of production data and around a hundred tables in its schema which needed to be exactly migrated into PostgreSQL.
Forklifting the data proved more complicated than expected due to incompatibilities in the two DBMS' syntax such as in the way string escaping worked, how booleans were represented and a bunch of other small but painful differences. Despite MySQL's mysqldump utility including a command-line option to write statements in PostgeSQL format, it became clear that it wasn't going to be simple to create a repeatable procedure to do this work across our environments.
There's a bunch of information out there about how to approach this problem but none felt right. Most are multi-step manual procedures that require altering a dump file using sed or perl and others require the data to be loaded into an intermediary database and massaged prior to import. After testing some of these approaches, Todd and I decided to timebox ourselves to an hour to test the viability of a Ruby script using the DBI gem to move the data. We came up with:
require 'dbi'
require 'dbd/mysql'
require 'dbd/pg'
begin
mysql = DBI.connect("DBI:Mysql:source:localhost", "username", "password")
postgres = DBI.connect("DBI:Pg:destination:localhost", "username", "password")
mysql.select_all("SHOW TABLES") do |table|
next if ['schema_migrations', 'sessions'].include?(table.to_s)
select = mysql.execute("SELECT * FROM #{table}")
columns = select.column_names.map { |key| "\"#{key}\"" }.join(', ')
placeholders = (['?'] * select.column_names.size).join(', ')
insert = postgres.prepare("INSERT INTO #{table} (#{columns}) VALUES(#{placeholders})")
select.each { |row| insert.execute(*row) }
insert.finish
end
rescue DBI::DatabaseError => e
puts "Error #{e.err}: #{e.errstr}"
ensure
mysql.disconnect if mysql
postgres.disconnect if postgres
end
Our antiquely Perl-like script worked better than we expected — our application started right up with all of its data intact.
Has anybody out there encountered this need before? What kinds of solutions did you come up with?







