Category: Ruby on Rails

Add Gitlab CI to your Hanami project

I host my personal projects in gitlab because it’s free and it gives you free runners for your ci.ย  I recently started studying the Hanami framework in ruby and when it was time to build the test suite, I initially couldn’t properly get it to work because of a strange error.

My initial gitlab-ci.yml was as follows

image: ruby:2.5

services:
  - postgres:latest

variables:
  DATABASE_URL: 'postgresql://postgres/budget_tracker_test'
  POSTGRES_DB: budget_tracker_test
  HANAMI_ENV: test

cache:
  paths:
    - vendor/ruby

rspec:
  before_script:
    - gem install bundler  --no-ri --no-rdoc 
    - bundle install -j $(nproc) --path vendor --quiet

  script:
    - echo 'Trying to create db for develop'
    - bundle exec hanami db prepare
    - echo 'Trying to create db for test'
    - HANAMI_ENV=test bundle exec hanami db prepare
    - rspec spec

Pretty straightforward right? But for some reason I was encountering this error:

Could not find executable in your PATH: `createdb`
/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-model-1.2.0/lib/hanami/model/migrator/postgres_adapter.rb:104:in `rescue in call_db_command'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-model-1.2.0/lib/hanami/model/migrator/postgres_adapter.rb:97:in `call_db_command'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-model-1.2.0/lib/hanami/model/migrator/postgres_adapter.rb:36:in `create'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-model-1.2.0/lib/hanami/model/migrator.rb:287:in `create'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-model-1.2.0/lib/hanami/model/migrator.rb:332:in `prepare'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-model-1.2.0/lib/hanami/model/migrator.rb:247:in `prepare'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-1.2.0/lib/hanami/cli/commands/db/prepare.rb:26:in `prepare_database'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-1.2.0/lib/hanami/cli/commands/db/prepare.rb:17:in `call'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-1.2.0/lib/hanami/cli/commands/command.rb:85:in `call'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-cli-0.2.0/lib/hanami/cli.rb:57:in `call'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/gems/hanami-1.2.0/bin/hanami:6:in `<top (required)>'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/bin/hanami:23:in `load'
	/builds/sylv3rblade/budget_tracker/vendor/ruby/2.5.0/bin/hanami:23:in `<top (required)>'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli/exec.rb:74:in `load'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli/exec.rb:74:in `kernel_load'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli/exec.rb:28:in `run'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli.rb:424:in `exec'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/vendor/thor/lib/thor/command.rb:27:in `run'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/vendor/thor/lib/thor/invocation.rb:126:in `invoke_command'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/vendor/thor/lib/thor.rb:387:in `dispatch'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli.rb:27:in `dispatch'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/vendor/thor/lib/thor/base.rb:466:in `start'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/cli.rb:18:in `start'
	/usr/local/lib/ruby/gems/2.5.0/gems/bundler-1.16.2/exe/bundle:30:in `block in <top (required)>'
	/usr/local/lib/ruby/site_ruby/2.5.0/bundler/friendly_errors.rb:124:in `with_friendly_errors'
	/usr/local/lib/ruby/gems/2.5.0/gems/bundler-1.16.2/exe/bundle:22:in `<top (required)>'
	/usr/local/bundle/bin/bundle:23:in `load'
	/usr/local/bundle/bin/bundle:23:in `<main>'
ERROR: Job failed: exit code 1

So I looked up some of the discussions on the issue tracker on Hanami’s github and I found this still open issue with Hanami still requiring a local postgres instance :|. Anyway, cart before the horse, I ended up using the postgres service while manually installing postgres in the ruby image just so I could run my specs proper.y

Here is my `gitlab-ci.yml` now

image: ruby:2.5

services:
  - postgres:latest

variables:
  DATABASE_URL: 'postgresql://postgres:postgres@postgres/budget_tracker_test'
  HANAMI_ENV: test

cache:
  paths:
    - vendor/ruby

before_script:
  - apt-get update -qq && apt-get install -y -qq postgresql postgresql-contrib libpq-dev cmake
  - gem install bundler  --no-ri --no-rdoc
  - bundle install -j $(nproc) --path vendor --quiet 

rspec:
  script:
  - bundle exec hanami db prepare
  - bundle exec rspec spec

After pushing this to gitlab, viola!

Use PRY with rails console

I love pry.

Aside from prettifying the output of your terminal when debugging, it is a bit more handy thanks to it’s extra features. Here’s a railscast to see what you can do with pry.

If you want to use pry as the default shell for rails console you can simple open up your config/development.rb file and add:

MyApp::Application.configure do
  # start copying here
    silence_warnings do
        begin
            require 'pry'
            IRB = Pry
        rescue LoadError
        end
    end
   # end copying here
end

and ensure that pry has been added to the Gemfile.

or if you want a one liner approach (one line of config and a bundle install to be clear), just add the pry-rails gem to your Gemfile

gem 'pry-rails', :group => :development

DRYing HTML using content_for and helpers

I recently encountered a scenario where I needed to dry up some HTML code for a navigation snippet that needed to appear on both the top and bottom of my main content. Here’s a snipped version of the code

<div class="tablenav top row">
   <div class="somenavigationfunction"></div>
   <div class="anotherfunction"></div>
   <!-- 
      Some code for the navigation here
    -->
</div>
<div class="display row">
   <!-- 
      Main display page here
    -->   
</div>
<div class="tablenav bottom row">
   <div class="somenavigationfunction"></div>
   <div class="anotherfunction"></div>
   <!-- 
      Some code for the navigation here
    -->
</div>

The code that I need repeated divs with tablenav classes. The usual way to go about this is using content_for and yield:

<% content_for :tablenav do %>				
   <div class="tablenav top row">
      <div class="somenavigationfunction"></div>
      <div class="anotherfunction"></div>
      <!-- 
         Some code for the navigation here
       -->
   </div>
<% yield :tablenav %>
<div class="display row">
   <!-- 
      Main display page here
    -->   
</div>
<% yield :tablenav %>				

A bit DRY-er now right? The problem with this approach is that both instances of the yielded output sports the same set of classes. This is good most of the time but in my current usage, I need the top instance to use a “top” class while the bottom one needed a “bottom” class for proper padding. I could simply add another div to wrap each of the yield lines but that’s requires me to edit the css file to reflect the change. Here’s the solution I came up with using content_for and helpers:

<% content_for :tablenav do %>				
   <div class="tablenav top row">
      <div class="somenavigationfunction"></div>
      <div class="anotherfunction"></div>
      <!-- 
         Some code for the navigation here
       -->
   </div>
<%= nav_block("top") %>
<div class="display row">
   <!-- 
      Main display page here
    -->   
</div>
<%= nav_block("bottom") %>

And the code for the helper

def nav_block(location = nil, &block)
  content_tag("div", content_for(:tablenav), :class => "tablenav #{location} row").html_safe
end

Just fire up the page in your browse and watch it work :). Now how exactly did this works? Turns out that content_for can also be used to output it’s contents. If you’re wondering why yield wasn’t used is because it simply doesn’t work with helpers. If you tried to use yield, you’ll end up with the following LocalJumpError: no block given (yield).

Important Note: I’ve only tested this on Rails 3.x, Rails 3.2 to be exact.
Hope that helps.

ArgumentError: invalid byte sequence in US-ASCII

If you’re on Ruby 1.9.2 and have started getting this error when trying to install gems (either by gem install or bundle install), your environment is simply missing the LANG variable and is loading up US-ASCII by default.

To fix this, simply run the command below before installing anything

export LANG=en_US.UTF-8

or to make it more streamlined, add it to your .bashrc or zshrc (if you’re using the zsh shell).

uninitialized constant Rack::Test (NameError)

Cucumber-rails 0.4.0 was released for Rails 3.x. If you try to use it with anything below that (Rails 2.3.x), you’ll encounter the error:

uninitialized constant Rack::Test (NameError)

Is the rack-test driver missing? Nope. Well you still need that installed but the root cause of the breakage is lack of a proper test environment for Rails 2.3 whereas Rails 3.0 has this covered.

The solution? Simple.

Use an older version of cucumber. If you missed that from the first two sentences of the post then… :(.

For me it works using this configuration for the config/cucumber.rb file (that’s our environment file, you can also opt to place this in your test.rb file instead):

config.gem 'cucumber-rails',   :lib => false, :version => '0.3.2'

or if you’re using bundler:

gem "cucumber-rails", "~> 0.3.2"

or if you’re really lazy and don’t have anything to automatically install gems for your environment:

gem install cucumber-rails -v=0.3.2

Resize or reprocess all Paperclip attachments

Update: This post was written based on an older version of paperclip which didn’t have a default rake task for this.

I’ve been using the Paperclip plugin/ gem for image attachment in several of my apps and I’ve encountered a scenario wherein I needed to change one of the styles configured in the model to accommodate the client’s request. At that point, there are already a bunch of images in the project so I need to resize or in Paperclip’s terms reprocess all of them to fit the new configuration.

Here’s how I did it:

If you have paperclip installed as a plugin

If Paperclip is installed as a plugin, you can do this:

rake paperclip:refresh:thumbnails CLASS=Attachment

Just replace Attachment with whatever classname you are using for with Paperclip

If it’s installed as a gem, do this inside script/console:

Attachment.all.each {|s| s.logo.reprocess! if s.logo}

Just replace Attachment with whatever class name you are using for with Paperclip and logo with whatever attribute name you are using for the image.

And you’re done ๐Ÿ™‚

Hurrah! A new server

I decided to move this blog together into a new VPS to host my personal rails projects :). Now, I’m not sure if this’ll be a permanent thing since I sort of jumped on the offer upon impulse but so far, I’m liking the service.

This server is running Ubuntu 10.4 with Pushion Passenger, Nginx, Ruby Enterprise Edition and PHP-FPM.

So why Nginx and not Apache? Well, aside from having it bundled with the latest version of Passenger, nginx historically has consumed less memory than Apache. The trade off of course is that I’ll still be running ruby 1.8.7 but I guess that’s fine since some of the plugisn I’ve been using have conflicts with 1.9.x.

I’ll be pushing a post detailing how I configured this server in a bit.

Installing the mysql gem on OS X 10.6 (Snow Leopard)

The first thing on my developer itinerary after getting my MacBook Pro is to install my development tools. That includes upgrading the ruby and rails gem versions packaged with OS X 10.6 and installing Xcode which is included on Snow Leopard’s install DVD. Things proceed smoothly until I tried to install the mysql gem.

Ruby threw a fit and dumped this message:

$ sudo gem install mysql
Building native extensions.  This could take a while...
ERROR:  Error installing mysql:
ERROR: Failed to build gem native extension.

Gem files will remain installed in /Library/Ruby/Gems/1.8/gems/mysql-2.8.1 for inspection.
Results logged to /Library/Ruby/Gems/1.8/gems/mysql-2.8.1/ext/mysql_api/gem_make.out

After some google-fu, I found out that when installing the mysql gem on OS X, you need to point it to where your mysql_config file is placed. Below is the complete guide on how to how to install the mysql gem on Snow Leopard.

  • Download your preferred MYSQL version from the community download site. If you’re on Snow Leopard, you may want to install the 64-bit version.
  • Install mysql via dmg or compile it from source.
  • Type ‘which mysql_configโ€™ on the terminal to locate said config. Take note of this location as we’ll use it on the next step.
  • Install the mysql gem with the command below. If the location for your mysql config is different with the one below, use that instead.
     sudo env ARCHFLAGS="-Os -arch x86_64 -fno-common" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
    

    Note that if you’re using the 32-bit version, you have to use:

     sudo env ARCHFLAGS="-Os -arch i386 -fno-common" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
    
  • And success!
    $  sudo env ARCHFLAGS="-Os -arch x86_64 -fno-common" gem install mysql -- --with-mysql-config=/usr/local/mysql/bin/mysql_config
    Building native extensions.  This could take a while...
    Successfully installed mysql-2.8.1
    1 gem installed
    Installing ri documentation for mysql-2.8.1...
    ...
    

If you are having problems, or have any suggestions, please post a comment.

On Rails and Loving it :D

I started out my official, programming career as a Java developer for my current company.ย  At the time, the design team was moving their development interests from purely desktop applications to a a more web-eccentric playing field, ergo web-based applications.ย  The itinerary was to find out if the web was a viable platform (don’t laugh, we’re being headed by a bunch of old peeps who are still touchy about the current computing trends) for development.ย  My answer of course was yes, so I took up training as a Java Web developer.

Things were great but like most things Java, the going was SLOW but steady.

ruby_on_rails_logoThen came Rails.

At first, I was really hesitant.ย  Strong typing (READ excessive typing) was the foundation of a good programming language; at least that’s what countless Java books that I’ve read told me.ย  So how does a language that puts the fun back in development catches attention?ย  Well, it might be cliche but…

It all started with Hello World

Nearly all programming languages starts with this old and tired way of displaying the text “Hello World”. Ruby got me interested by it’s simplicity:

puts ‘Hello World’

and that’s it ๐Ÿ˜€

Of course that really doesn’t say much about the language’s capability but you have to admit that it’s bound to turn heads :D.

So why switch?

At first it was really curiosity… although I will admit that I did already have Ruby experience prior to this via the gem WATIR (don’t ask why:D) but really, at one point I did ask myself, what’s all the fuss about Ruby on Rails? So I started reading, reading… reading and then read some more until I decided that my first rails application would be the project we had for our Software Development lab subject back in college. The result? I’m in love ๐Ÿ˜€

I’ll try sharing the project some time in the future but I have some re-writing to do ๐Ÿ˜€ย  It’s currently in workprint mode… it’s full of notes, comments and rants right in the source code so.. yeah I need to clean it first :D.

– to be edited.ย  Need to sleep for now ๐Ÿ˜€