Feb 082015
 

First you need to know how to connect to your Heroku application using bash. You can then use the du -h command to get a read on how big the files inside your slug are.

heroku run bash -a yourappname

Once you’ve done that, here’s the magic command that will show you how big each folder in your slug is:

du -h --max-depth=1

Max-depth of 1 will give you 1 level deep output of how big each of those root folders are. You can change the max-depth to see more granular introspection of each folder. (However, realistically, it is probably more useful to cd down to some subfolders and run du -h --max-depth=1 again.)

Some observations I have made:

1. Obviously you basically want to get as much out of your assets/ folder as you possibly can. Almost everything I do these days is tied to some kind of managed content, so I can safely put almost all the images and videos in my app into a Paperclip-backed data model. Using S3, Paperclip stores all the different sized versions it will render remotely, so all that stuff stays out of the slug.

2. Beware of Gem bloat. If you don’t use it, you probably want to get it out of there.

3. Generally speaking just keep large files out of your app. If you’re needing a lot of larger data files re-think your architecture to work in a more distributed, background job kind of way that doesn’t require the files to be in the slug. (Remember, worker dynos can always download from or upload to S3 and storage on S3 is much cheaper than keeping things in your slug.)

4. Use .slugignore (well documented so I won’t go into it here.)

5. I found that using gems directly from Rubygems seems to save a lot of space compared to using gems which point to a Github repo.

You can recognize a gem pulled from its Rubygems version because it usually has few or no parameters, or only a version parameter:

(pulling from Rubygems)

gem ‘spree’, ‘2.1.12’

It turns out that because Spree can be a little lazy about building the Gems, they recommend you just point your Gemfile to the github repo. (To be fair, they maintain a lot of bugfixes across several branches, and pointing to a branch on Github makes much more sense if you have software that is retroactively fixed like Spree)

(Pointing to a github repo)

gem ‘spree’, git: ‘https://github.com/spree/spree.git’, branch: ‘2-1-stable’

The difference here is that Bundler can just pull a compiled gemfile in the first example, whereas it has to download the repo and turn it into a Gem in the second example. In my app, the latter (pulling from Rubygems) saves me a whopping 70 MB compressed in my slug. Although I haven’t confirmed, I suspect this is because Bundler is actually very efficient at packaging up a Gem and excludes all the support files you don’t want when you create the gem, whereas the ‘lazy’ way of just pointing to a Git repo has the side-effect of including all the files in the repo in your finished slug.

Oct 272014
 

Now with full test coverage using MiniTest.

Rubygems link:
http://rubygems.org/gems/nondestructive_migrations

Github Link:
https://github.com/jasonfb/nondestructive_migrations

A few things I learned here along the way:

MiniTest has not replaced TestUnit for the hard-core Rails developer. MiniTest worked great fro this, except Rails version 4.0.x, 3.1.x and 3.2.x needs “minitest-rails”, “~> 1.0”. I tried testing with Rspec but since Rails itself is tested with Minitest this was actually easier (since I needed access to some special tests written inside of Railtie)

I used a fantastic tool called Appraisal to run my tests suite against several different versions of Rails (3.1, 3.2, 4.0, 4.1, and 4.2). Getting this set up with a little bit of work, but well worth it. You can configure Travis CI to work seamlessly with Appraisal, so you can run your Gem against different versions of Ruby, Rails, and three different databases (SQLite, MySQL, and Postgres). See the .travis.yml and Appraisals inside the gem code for details.

When writing a Gem, you’ll want to explicitly include all your files in the files setting inside the Gemspec (example). This is important, and if you fail to do this those files will work when the Gem is loaded via git: or path: but not when it is pulled from RubyGems.

Rubygems forces you to publish explicit version numbers on your gems. You cannot overwrite an existing version number, but you are allowed to “yank” a version down to remove it from Rubygems.

 Posted by at 8:28 am  Tagged with:
Oct 212014
 

This is a useful little trick to get all the methods that you can call on any Ruby object. This is extremely helpful when poking around someone else’s code (like Gem code) that is poorly documented.

foo.methods

This will return a long list of methods that you can call on the object. That list will include all the methods on all the superclasses of the object, including the Object object methods (the grandaddy of all objects). That’s often not very useful, so you can filter out the superclasses’s methods and only look at the methods associated with the subclass using:

foo.methods(false)
 Posted by at 3:49 pm  Tagged with:
Oct 142014
 

Learned something on the Rails-talk list today that blew me away.

You can install an older version of rails using this syntax:

rails _4.0.8_ new appname

(Where “4.0.8” is the version you want and “appname” is the name of your new rails app.)

Yes, you actually type those underscores around the version number. By the way, if you don’t have that version installed (it installs via bundler), bundler will tell you it can’t find the gem. In that case, you’ll want to do gem install rails -v 4.0.8 and then re-run the command above.

This is a :thumbs down: for Rails documentation. This little trick isn’t even documented when I get the manual page for the rails new command (rails new -h)

Voila!

 Posted by at 10:49 am  Tagged with:
Oct 102014
 

Every restart your Mac and have it boot up only to open all the last Safari windows you had just opened? This feature – introduced a few operating systems ago – is something I personally don’t like at all. Perhaps I’m a “power user” but I often find that I open so many browser windows in the course of my work that I don’t really want them to all re-open

Ostensibly, Safari appears to have a preference to turn this off or on, here:

However in my version of Safari (7.0.6 on Mac OS X 10.9.5), this preference appears to not actually work at all. (annoying)

So here’s how to go into your system defaults and turn it off for real:

defaults write com.apple.Safari NSQuitAlwaysKeepsWindows -bool false