I have a bunch of iOS apps that use the same Google API identity with different client IDs for sign-in through Google. I just made another one but kept running into this problem where auth would work, but when the browser redirect occurred, I’d get a message reading “Cannot Open Page: Safari cannot open the page because the address is invalid.”

Photo Sep 18, 9 15 00 PM

That didn’t seem right b/c it was redirecting to an internal URL based on the bundle ID I specified when generating the client ID, and the bundle ID for the app was right.

Screen Shot 2013-09-18 at 9.12.49 PM

Turned out I was forgetting that you can specify a URL identifier and URL scheme in the *-Info.plist file. Changing that to match the bundle ID fixed the problem… after suffering hours of madness and having my life expectancy shortened by several years.

AREL where() to sql

Sometimes you just want the SQL for a WHERE clause:

 > Post.send(:sanitize_sql, :title => "foo", :body => "bar")
 => "\"posts\".\"title\" = 'foo' AND \"posts\".\"body\" = 'bar'"

iNat started crashing periodically this weekend, and after numerous attempts to figure out what was wrong, I finally found the culprit with some new-to-me tools: gdb and gdb.rb. For each crash load average was huge (like 10), and it was clearly the rack processes that were eating all the CPU (memory and swap were fine). Restarting nginx and/or killing the rack processes brought things back up, so clearly it was those hung processes that were killing things. Strangely, the rails logs seemed to be humming along normally (probably b/c not all procs were hung). There was some uptick in traffic around each crash, but not like a DOS-level uptick. After ruling out memory leak, DOS, and Rackspace issues (they claimed everything was fine), I figured there was an app-level issue, but none of the changes immediately preceding the crashes looked like they could be causing infinite loops or the like, sooooo I was at a loss.

I talked to n8 and he got me thinking about tools that look directly at the current state of the server processes, strace, gdb, and the like. gdb, which lets you look at what a live process is doing (if it was written in c, c++, or a number of other languages) ended up being the most useful, when combined with gdb.rb, which actually lets you execute ruby commands within the context of a live ruby process. I suck at interpreting C code from the interpreter, but with ruby I’m home. Inspection went something like this:

# install deps on Ubuntu and gdb.rb gem
sudo apt-get install gdb python-dev ncurses-dev
gem install gdb.rb
 
# wait for crash to happen again... and wait... and wait...
 
# CRASH! Attach to hung process by PID (use rvmsudo if you use rvm)
rvmsudo gdb.rb PID
 
# in gdb get a ruby stacktrace with file names and line numbers
# here I'm filtering by files that are actually in my app dir
(gdb) ruby eval caller.select{|l| l =~ /app\//}

That outed some infinite recursion from a totally unexpected place that I was able to fix in a few minutes. Unfortunately running ruby eval in gdb occasionally crashed the process, I think when the proc received a signal while gdb was attached, but stubborn repetition eventually got me my trace. Also, not all of gdb.rb’s commands seemed to be available, like ruby trace and ruby threads. I basically only had ruby objects and ruby eval, not sure why, but ruby eval was all I needed.

Anyway, there are tons of posts about using gdb to inspect ruby procs out there, but almost all of them are really old, and it took me a while to find the right tool for this job, so maybe this post will help someone. The best overview I found was this post from Big Nerd Ranch. This gist by tmm1 (author of gdb.rb) also collects a bunch of useful information about a hung process by combining output from multiple tools.

Recently started using RGeo a bit (I know, way late, but hey, it’s pretty awesome!), and ran into a production problem when using contains?

RGeo::Error::UnsupportedOperation: Method Geometry#contains? not defined.

RGeo depends on some kind of underlying geometry library, usually GEOS. In Ubuntu, the headers and source files for GEOS don’t get installed by default when you install geos, so the solution is to install them, as it is with so many of these issues:

sudo aptitude install geos-dev
bundle exec gem uninstall rgeo
bundle update rgeo

Update from April24, 2014

In Ubuntu 13.10 (saucy) package names are a bit different. Not sure if both of these are required, but the ++ one certainly is:

sudo aptitude install libgeos-dev
sudo aptitude install libgeos++-dev

bundler cheat

Dependency management that barely solves more problems than it creates.

# reinstall a single gem (why can't this be gem reinstall gemname?!)
bunde exec gem uninstall gemname
bunde update gemname

capistrano cheatsheet

# run task on particular host / server
cap HOSTS=foo.bar.com,baz.bar.com deploy
 
# run task on particular host / server AND respect roles
cap HOSTFILTER=foo.bar.com,baz.bar.com deploy
 
# run tasks for a particular role
cap ROLES=db deploy
 
# checkout a branch for only one host / server
cap HOSTFILTER=foo.bar.com -s branch=i18n deploy

If you’re a responsible / anal Rails dev you’ll probably want to include foreign key validations in your join models, b/c what’s a the point of a join model that doesn’t join anything? Well, maybe you’re working on some kind of pork barrel project building models to nowhere. I suppose that could happen. Maybe. I hope not. Anyway, example:

class ProjectObservationField < ActiveRecord::Base
  belongs_to :project
  belongs_to :observation_field
  validates :project, :presence => true
  validates :observation_field, :presence => true
end

And if you make a lot of forms you’ve probably run into accepts_nested_attributes_for, e.g.

class Project < ActiveRecord::Base
  has_many :project_observation_fields
  accepts_nested_attributes_for :project_observation_fields
end

Combining these two leads to sadness: Rails will try to validate the presence of the associate in the join record before that associate exists in the database, so in this case, the validation on the ProjectObservationField will get run before that record is assigned an associated Project.

The solution:

class ProjectObservationField < ActiveRecord::Base
  belongs_to :project, :inverse_of => :project_observation_fields
  belongs_to :observation_field, :inverse_of => :project_observation_fields
  validates :project, :presence => true
  validates :observation_field, :presence => true
end
 
class Project < ActiveRecord::Base
  has_many :project_observation_fields, :inverse_of => :project
  accepts_nested_attributes_for :project_observation_fields
end

:inverse_of makes Ruby smarter about nested attributes, as has been documented here. For whatever reason my normal reflexive Googling / StackOverflowing did not turn this up, and thus, I am writing a silly blog post.

I’m working on a Rails 2 to Rails 3 upgrade (I know, just in time for Rails 4), and I’ve been annoyed by the fact that ActiveRecord kept spewing its log statements out to the terminal and not to the log file. After realizing this was not a commonly encountered problem, I realized the culprit was an old, out-dated plugin in vendor/plugins that was looking for a variable called RAILS_DEFAULT_LOGGER which no longer exists, and was then creating a new Logger that just writes to STDERR. Ditching the plugin solved my problem. Sane people probably remove / update their plugins first. For the rest of us, keep this in mind.

postgres cheatsheet

psql

# copy data to csv
psql yourdb -c "COPY (SELECT * FROM tablename) TO STDOUT WITH CSV HEADER" > file.csv
 
# copy data out, load it back in
psql yourdb -c "COPY (SELECT * FROM tablename) TO STDOUT WITH CSV" > file.csv
psql yourdb -c "\copy tablename FROM 'file.csv' WITH CSV"

Stats

View more about stats tables at http://www.postgresql.org/docs/9.2/static/monitoring-stats.html

-- view currently running queries
SELECT client_addr, query_start, current_query FROM pg_stat_activity;

Admin

The first step is always to have a relaxing beverage in hand…

Connecting multiple servers

http://www.cyberciti.biz/tips/postgres-allow-remote-access-tcp-connection.html is a good guide. The most salient points in addition to editing pg_hba.conf are

  1. both client and server firewalls must allow TCP connections from each other on port 5432
  2. you have to alter listen_addresses in postgresql.conf

Some useful debugging commands:

# Check that the port is open from the client. Make sure your firewalls are
# configured correctly on both ends and that SSL has been set up and
# configured
nmap -v -sV remote_host -p 5432
 
# Both of these will tell you if pg is up and listening on the server machine
netstat -plnt on localhost
lsof -i:5432

Setting Up SSL

http://www.howtoforge.com/postgresql-ssl-certificates is a good step-by-step. Note that in ubuntu pg’s data dir seems to live somewhere like /var/lib/postgresql/9.1/main/, and that sever.crt and server.key are already there as symlinks to a self-signed certificate. Seems like you still have to copy server.crt to root.crt, though, and of course you need to make your client certs. Setting the -subj flag to something simple like '/CN=inaturalist' seemed to work for me.

I was revisiting a Rails 3 upgrade last night, rolled things back this morning, and realized Rails was requiring all the wrong gems. Turned out the problem was I was using the global RVM gemset for all the Rails 3 gems, which, as the name would suggest, is for gems that are used by all gemsets. Silly me. Solution:

rvm env # revealed the multiple gem paths
rvm use ruby-1.8.7@global
 
# http://geekystuff.net/2009/01/14/remove-all-ruby-gems/
gem list | cut -d" " -f1 | xargs gem uninstall -aIx
 
rvm gemset create rails3
rvm use ruby-1.8.7@rails3
git checkout rails3 # branch for the upgrade w/ Gemfile etc
bundle
 
git checkout master
rvm use ruby-1.8.7@rails2
# everything back to normal