Mastodon

cannot load such file — taps/operation

I am an eternal optimist. With very few exceptions I will upgrade to the latest version of just about anything. Beta versions are close to being my norm and deprecation warnings are like nails on a chalkboard to me. A while ago I got deprecation warning while using one of my favorite heroku commands, heroku db:pull

The `heroku` gem has been deprecated and replaced with the Heroku Toolbelt. Download and install from: https://toolbelt.heroku.com

Obviously I installed the toolbelt. Of course everything looks find until I am trying to get some work done and try my next db:pull:


mike@sleepycat:~/projects/capoeiraottawa.ca$ heroku db:pull
! Taps Load Error: cannot load such file -- taps/operation
! You may need to install or update the taps gem to use db commands.
! On most systems this will be:
!
! sudo gem install taps

Taps is already installed but I humour them and install it again. Same deal. Purge and reinstall the Toolbelt. Same deal.
For the moment my solution is to back out of the toolbelt thing and use the gem again. Grr.
To do that I just did sudo apt-get purge heroku-toolbelt heroku. Keep in mind that heroku’s repo is still in the list of places apt will search. If you want to get rid of it you will have to delete /etc/apt/sources.list.d/heroku.list.

The last bit of the cleanup is removing the stuff heroku added to your path in your ~/.bashrc:


### Added by the Heroku Toolbelt
export PATH="/usr/local/heroku/bin:$PATH"

Then reopen your terminal. After that you are ready to install the gem as usual with gem install heroku


mike@sleepycat:~/projects/capoeiraottawa.ca☺ heroku db:pull
Loaded Taps v0.3.24
...
The 'heroku' gem has been deprecated and replaced with the Heroku Toolbelt, download and install from https://toolbelt.heroku.com.

Receiving schema
...

Sigh.

Keeping credentials out of your code with environmental vars

I have a project that is up on Github and deployed to Heroku. As I was adding the user credentials file to my project it dawned on me: my application needs these credentials when I run it on Heroku but I don’t want them to be part of my project and therefore visible to everyone on Github.

Turning to the great minds at Stackoverflow, I was advised to use environmental variables.
Since my application is connecting to another site via SFTP I have a hash of all the usual stuff; username password and hostname. It turns out you can just reference environmental variables like this:

@sftp_credentials = {Rails.env.to_sym => {
:sftp_host => ENV[‘SFTP_HOST’],
:sftp_user => ENV[‘SFTP_USER’],
:sftp_password => ENV[‘SFTP_PASSWORD’]
}}

And then make sure you have the environment vars set in your .bashrc so they are available during local development:

export SFTP_HOST=’somesite.com’
export SFTP_USER=’someuser’
export SFTP_PASSWORD=’somepassword’

And then set those variables on Heroku so they are available when your app runs there:

mike@sleepycat:~/projects/myapp$ heroku config:add SFTP_HOST=somesite.com SFTP_USER=someuser SFTP_PASSWORD=somepassword
Adding config vars:
SFTP_HOST => somesite.com
SFTP_PASSWORD => somepassword
SFTP_USER => someuser
Restarting app…done.

Rails 3 on Heroku

Heroku sent around an email a little while ago talking about their “experimental” Rails 3 support. After a night of tinkering with a Rails 3 project  I thought I might try it out. When I pushed my project I got this:

Total 131 (delta 27), reused 0 (delta 0)

—–> Heroku receiving push
—–> Gemfile detected, running Bundler
Unresolved dependencies detected; Installing…
Fetching source index from http://gemcutter.org/
Resolving dependencies
Installing abstract (1.0.0) from system gems
Installing actionmailer (3.0.0.beta) from rubygems repository at http://gemcutter.org/
Installing actionpack (3.0.0.beta) from rubygems repository at http://gemcutter.org/
Installing activemodel (3.0.0.beta) from rubygems repository at http://gemcutter.org/
Installing activerecord (3.0.0.beta) from rubygems repository at http://gemcutter.org/
Installing activeresource (3.0.0.beta) from rubygems repository at http://gemcutter.org/
Installing activesupport (3.0.0.beta) from rubygems repository at http://gemcutter.org/
Installing arel (0.2.1) from rubygems repository at http://gemcutter.org/
Installing builder (2.1.2) from system gems
Installing bundler (0.9.12) from rubygems repository at http://gemcutter.org/ /usr/local/lib/ruby/site_ruby/

1.8/rubygems/installer.rb:192:in `install’: bundler requires RubyGems version >= 1.3.6 (Gem::InstallError)
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/source.rb:42:in `install’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/installer.rb:30:in `run’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/installer.rb:18:in `each’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/installer.rb:18:in `run’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/installer.rb:6:in `install’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/cli.rb:60:in `install’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/task.rb:33:in `send’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/task.rb:33:in `run’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/invocation.rb:109:in `invoke’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/invocation.rb:116:in `call’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/invocation.rb:116:in `invoke’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor.rb:137:in `start’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor/base.rb:378:in `start’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/lib/bundler/vendor/thor.rb:124:in `start’
from /usr/local/lib/ruby/gems/1.8/gems/bundler-0.9.9/bin/bundle:11
from /usr/local/bin/bundle:19:in `load’
from /usr/local/bin/bundle:19
FAILED: Have you updated to use a 0.9 Gemfile?

Wha? I had filled out my Gemfile, what could it be? It turns out that you need to specify a “stack” to use when you are running Rails 3. The stack is basically all the a specific configuration of all the supporting software (the OS, Ruby, whatever else). Whatever stack I had been given by default (“aspen”) was not the one that contained Rubygems 1.3.6. Check out their stacks page on the Heroku site for more info.

The fix? Even Though I find Heroku’s documentation is usually pretty bad, this time they had exactly what I needed:

mike@sleepycat:~/projects/myapp$ heroku stack:migrate bamboo-ree-1.8.7
—–> Preparing to migrate
aspen-mri-1.8.6 -> bamboo-ree-1.8.7

NOTE: You must specify ALL gems (including Rails) in manifest

Please read the migration guide:
http://docs.heroku.com/bamboo

—–> Migration prepared.
Run ‘git push heroku master’ to execute migration.
Next time I pushed it worked fine. Yay!

Bundle mania

I ended up using Heroku’s bundles feature a fair bit today. For those who have not played with this yet, a bundle is essentially a zip/tar file containing all the code from your application along with a dump  of your database. From the help file:

bundles                      # list bundles for the app
bundles:capture [<bundle>]   # capture a bundle of the app’s code and data
bundles:download             # download most recent app bundle as a tarball
bundles:download <bundle>    # download the named bundle
bundles:animate <bundle>     # animate a bundle into a new app
bundles:destroy <bundle>     # destroy the named bundle

In general its pretty intuitive. The commands do what you expect; “bundles:capture” captures a bundle, while “bundles:download mybundle” downloads the bundle named mybundle. With my expectations set by using the other commands I tried out bundles:animate

mike@sleepycat:~/projects/myapp$ heroku bundles
2010-03-16        complete 03/17/2010 14:25
mike@sleepycat:~/projects/myapp$ heroku bundles:animate 2010-03-16
Animated myapp 2010-03-16 into http://myapp-2010-03-16.heroku.com/ | git@heroku.com:myapp-2010-03-16.git

Given the description “animate a bundle into a new app” I was expecting a fully functional copy of my application waiting for me at that new address, based on the code and the database dump contained in the bundle. Instead I get:

mike@sleepycat:~/projects/myapp$ heroku console –app myapp-2010-03-16
!   myapp-2010-03-16 has an empty code repository. Push and try again.

When I log in and look at my account, sure enough the repository is empty and even more surprising:

Data size

0 Bytes in 0 tables

So if it does not load any of the code from my bundle, and doesn’t use the database dump to create a database, how does this differ from creating a new app?

Lost in translation: the down side of taps

UPDATE: Both Taps and Sequel have been updated and the problems that caused my issues have been resolved. I am now happily db:pushing and db:pulling. It took a while, but it got fixed in the end. :)

I have been using Heroku for a while now and its definitely great. One of the things that really blew me away when I started using it was being able to send my my entire database data up to the server with a single command:

heroku db:push

Could it be any easier? Thanks to the magic of taps, Schema AND data, transferred between my local MySQL database and Heroku’s Postgres database. At the time I might of stopped for a second to marvel at how big a deal that is, but only for a second. It turns out that its really worth stopping and thinking about what goes on when you run that command; especially when you are developing on MySQL. MySQL and Postgres have different datatypes to store data in and making an finding an exact equivalent from one database to the next is much easier said than done.

I think I will let the data do the talking for me on this. Keep you eye on the terminal_id column:

mysql> desc terminals;
+————-+—————+——+—–+————-+—————-+
| Field       | Type          | Null | Key | Default     | Extra          |
+————-+—————+——+—–+————-+—————-+
| id          | int(11)       | NO   | PRI | NULL        | auto_increment |
| location_id | int(11)       | YES  |     | NULL        |                |
| merchant_id | int(11)       | YES  |     | NULL        |                |
| terminal_id | decimal(11,0) | YES  |     | NULL        |                |
| reference   | varchar(255)  | YES  |     | NULL        |                |

8 rows in set (0.00 sec)

The data:

mysql> select terminal_id from terminals;
+————-+
| terminal_id |
+————-+
| 10792146001 |
| 10152407001 |
| 10392407002 |
| 10152617003 |
| 10184619001 |

16 rows in set (0.00 sec)

Pushing it up to the server  this suddenly becomes:

CREATE TABLE terminals (
id integer NOT NULL,
location_id integer,
merchant_id integer,
terminal_id integer,
reference character varying(255),

After a Heroku db:pull command:

mysql> desc terminals;
+————-+————–+——+—–+————-+—————-+
| Field       | Type         | Null | Key | Default     | Extra          |
+————-+————–+——+—–+————-+—————-+
| id          | int(11)      | NO   | PRI | NULL        | auto_increment |
| location_id | int(11)      | YES  |     | NULL        |                |
| merchant_id | int(11)      | YES  |     | NULL        |                |
| terminal_id | int(11)      | YES  |     | NULL        |                |
| reference   | varchar(255) | YES  |     | NULL        |                |

8 rows in set (0.00 sec)

The data:

mysql> select terminal_id from terminals;
+————-+
| terminal_id |
+————-+
|  2147483647 |
|  2147483647 |
|  2147483647 |
|  2147483647 |
|  2147483647 |
|  2147483647 |
|  2147483647 |
|  2147483647 |

How about that. Now I have a column of maxint values and a lot of very confusing bugs. Nothing like a little integer overflow to make the day go quickly. Worse still is pushing back up to the staging server before noticing, duplicating the corrupted data up there. Good thing it didn’t effect production. I am guessing that had I been developing using Postgres there would be no problem, because taps would not have to convert from one datatype to another.  I am going to have to think about doing that even though I am much more familiar with MySQL. Either way the ease of that heroku db:push/pull command definitely belies the magnitude of what that command is doing.

So the takeaway from this? For me:

Backups = good.

Staging server = good.

Taps = use with caution.

Heroku, Taps and Ubuntu

After beavering away on a Rails app for the last little while I wanted to put it up somewhere so the rest of the world can see it. I signed up with Heroku since they specialise in hosting Rails apps. Their database setup is kind of confusing. It turns out that they totally ignore your database configuration (database.yml is not used.) They just use the schema.rb to create the database that your app needs in their Postgres database. You just run your rake task to set it up. Thats pretty cool, but there is something cooler; can copy your entire local database with data and everything over to their server with the command:

heroku db:push

The only problem for me was that on Ubuntu (jaunty) the command failed telling me that I needed to intall Taps. More aggravating still was the fact that my attempt to install Taps also failed because its dependent on Sqlite3:

mike@jauntyjackalope:~$ sudo gem install taps
[sudo] password for mike:
Building native extensions.  This could take a while…
ERROR:  Error installing taps:
ERROR: Failed to build gem native extension.

/usr/bin/ruby1.8 extconf.rb install taps
checking for fdatasync() in -lrt… yes
checking for sqlite3.h… no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
–with-opt-dir
–without-opt-dir
–with-opt-include
–without-opt-include=${opt-dir}/include
–with-opt-lib
–without-opt-lib=${opt-dir}/lib
–with-make-prog
–without-make-prog
–srcdir=.
–curdir
–ruby=/usr/bin/ruby1.8
–with-sqlite3-dir
–without-sqlite3-dir
–with-sqlite3-include
–without-sqlite3-include=${sqlite3-dir}/include
–with-sqlite3-lib
–without-sqlite3-lib=${sqlite3-dir}/lib
–with-rtlib
–without-rtlib

Gem files will remain installed in /var/lib/gems/1.8/gems/sqlite3-ruby-1.2.5 for inspection.
Results logged to /var/lib/gems/1.8/gems/sqlite3-ruby-1.2.5/ext/sqlite3_api/gem_make.out

This was pretty annoying. Worse still installing sqlite3 didn’t fix it. It took some googling to figure out what needed to be installed to make Taps and therefore Heroku happy. It turns out that sqlite.h lives in the package libsqlite3-dev:

mike@jauntyjackalope:~$ sudo aptitude install libsqlite3-dev
mike@jauntyjackalope:~$ sudo aptitude install libsqlite3-doc

mike@jauntyjackalope:~$ sudo gem install taps
Building native extensions.  This could take a while…
Successfully installed sqlite3-ruby-1.2.5
Successfully installed taps-0.2.19
2 gems installed

mike@jauntyjackalope:~/dexterchief$ heroku db:push
Auto-detected local database
Sending schema
Sending data
6 tables, 53 records
comments:      100% |==========================================| Time: 00:00:01
posts:         100% |==========================================| Time: 00:00:01
roles:         100% |==========================================| Time: 00:00:00
roles_users:   100% |==========================================| Time: 00:00:00
schema_migrat: 100% |==========================================| Time: 00:00:01
users:         100% |==========================================| Time: 00:00:00
Sending indexes
Resetting sequences

Finally!