Tiago Scolari

Programming notes

Gemserver as a Docker Image

I’ve posted before about how to setup a private gemserver using geminabox, but I’ve just released a docker image that does the all the job:

1
2
  docker pull tscolari/gemserver
  docker run -e USERNAME=test -e PASSWORD=password -p localhost:3000:3000 -d tscolari/gemserver

This will start the server on your localhost:3000. You can then use it in the Gemfile:

Gemfile
1
2
3
4
5
source 'http://test:password@localhost:3000'
source 'https://rubygems.org'

...
gem 'my_private_gem', '>= 0.0.1'

Automatic Git Bisect

There are some situations that you found your build broken and need to know at what revision the “brokeness” was introduced.

git bisect is a great tool for that, basically you tell git at which revision the build was good (assuming HEAD is broken), and it does a binary search for the revision where the bug was introduced.

The standard way to do it:

1
2
git bisect start
git bisect good SOME_WORKING_PAST_REVISION

git will tell your how many revisions are between HEAD and WORKING_PAST_REVISION and how many steps it will take. Then it will walk you through each step (revisions), where you manually mark them good or bad.

If the revision still works, you mark it as good:

1
git bisect good

If the revision doesn’t work, you mark it as bad:

1
git bisect good

When you reach the last step git will tell you at what revision the bug was introduced.

The good stuff

You can automate this process if you have test coverage on the bug. git bisect has a run argument that accepts an external program to automatically flag a revision as good or bad. This makes things very easy:

1
2
3
4
5
6
7
8
9
10
git bisect start
git bisect good WORKING_PAST_REVISION
git bisect run rspec spec/models/user_spec.rb
...
...
abcde1234def is the first bad commit
commit abc1234def5678
Author: John Snow <john@starks.com>
Date: Thu Dec 23 13:37:00 2010 +0100
    Some stuff

Kill the View Logic

Views with logic are awful. They are hard to maintain and are terrible to look at.

It’s a common need to take decisions in the rendering time, but this decisions should be abstracted. Well, helpers are here for this right? not exactly. Think of helpers as methods of your view instance.

So now we are in the scope of the view instance, it’s already huge. It’s responsibility is to render stuff and it does this pretty well. But it’s quite out of it’s scope to know how your models should behave, even more out of scope for it to take decisions based that. Tell what you need, don’t ask what it can give you.

It’s wrong for the view object (and helpers nevertheless) to ask questions to another object, and then do something according to it’s answer - this for wrong at any object, it violates encapsulation. But it’s ok for the view object to tell other objects to do something.

At her LESS - The path to better design talk, Sandi Metz says that you cannot avoid dependecies, but you can choose them. And we definitely don’t want it to be in the view.

With this in mind, it makes perfect sense to create a small decoupled class - for each situation -, with high cohesion and easily composable (fancy words hum?) with the only responsibility of taking this decision (not these decisions), don’t? I think so.

Build Your Own Private Gem Server

With Bundler/Gemfile, it’s easy to link gems directly to it’s git repository. But some times it’s not ideal. You must use tags and revisions to keep track of versions yourself.

Don’t worry, It’s easy to setup a private gem server!

Complex Constraints for Rails Routes

It’s possible to use a custom class as a constraint for your routes. For example:

lib/domain_constraint.rb
1
2
3
4
5
6
7
8
9
class DomainConstraint
  def initialize(domains)
    @domains = [domains].flatten
  end

  def matches?(request)
    @domains.include? request.env["SERVER_NAME"]
  end
end

Keeping Track of Your Deploys With Capistrano and Git

I’ve created a simple capistrano task to keep track of my deploys. When I deploy to a server, it will create a git tag and push it to origin. This way I can keep track of each deploy revision.

1
2
3
4
5
6
7
8
after 'deploy:update_code', 'git:create_deploy_tag'

namespace :git
  task :create_deploy_tag do
    puts "[git] creating new deploy tag"
    `git tag -a 'deploy--#{Time.now.strftime("%Y-%m-%d-%H-%M-%S")}' -m 'Deploy: #{Time.now}' origin/production && git push origin --tags`
   end
end

p.s: I use the production branch as my deploy branch. You can change it for master, or anything else.

Ruby’s Autoload No More

Date: Sat, 19 Nov 2011 16:11:29 +0900

Hi,

Today, I talked with NaHi about enhancing const_missing to enable autoload-like feature with nested modules. But autoload itself has fundamental flaw under multi-thread environment. I should have remove autoload when I added threads to the language (threads came a few months after autoload).

So I hereby declare the future deprecation of autoload. Ruby will keep autoload for a while, since 2.0 should keep compatibility to 1.9. But you don’t expect it will survive further future, e.g. 3.0.

I strongly discourage the use of autoload in any standard libraries.

matz

-> Source