Custom loggers in Ruby and Rails

File logger

If you need to log to a file you can use Ruby's Logger class:

require 'logger'

log = Logger.new('log/mylog.log')
log.info 'Some information'
log.debug 'Debugging hints'
log.error StandardError.new('Something went wrong')

Logger does a number of things well:

  • Message type (info / debug / error) is logged
  • Log entries are timestamped
  • Writing log output is synchronized between threads
  • Logged errors are printed with full backtraces

If you don't like the output format, you can define a custom formatter.

I ha...

Dusen (>0.5) now with "exclude from search"

Dusen (our search gem) is now capable of excluding words, phrases and qualified fields from search.
E.g. search for

  • included -excluded
  • "search this" -"not that"
  • topic:"Yes" -topic:"No"

This will soon also work in makandra cards!

Linux: Kill a process matching a partial name

This is useful to kill processes like ruby my-script.rb:

pkill -f my-script.rb

With great power comes great responsibility.

Slack integration for deployments via Capistrano

You can hook into Slack when using Capistrano for deployment. The slackistrano gem does most of the heavy lifting for you. Its default messages are unobtrusive and can be adjusted easily.

When deploying, it posts to a Slack channel like this:

Example

How to integrate

Integrating Slackistrano with Capistrano 3 is fairly simple.

  1. In your Slack, open menu → A...

Ruby: Removing leading whitespace from HEREDOCs

If you're on Ruby 2.3+ there's a <<~ operator to automatically unindent HEREDOCs:

str = <<~MESSAGE
  Hello Universe!
  This is me.
             Bye!
MESSAGE

If you have an older Ruby, you can use the String#strip_heredoc method from ActiveSupport. See Summarizing heredoc in ruby and rails for an example.

Technically...

Exporting to Excel from Rails without a gem

See this Railscast.

Basically you can simply write views like index.xlsx.erb:

<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:o="urn:schemas-microsoft-com:office:office"
  xmlns:x="urn:schemas-microsoft-com:office:excel"
  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:html="http://www.w3.org/TR/REC-html40">
  <Worksheet ss:Name="Sheet1">
    <Table>
      <Row>
        <Cell><Data ss:Type="String">ID</Data></Ce...

Ruby: Enumerable#partition

If you want to sort values from an enumerable into two arrays based on whether they match a certain criteria or not, Enumerable#partition can come in handy.

# Enumerable#partition returns two arrays, 
# the first containing the elements of enum 
# for which the block evaluates to true, 
# the second containing the rest.

(1..6).partition { |v| n.even? }  #=> [[2, 4, 6], [1, 3, 5]]

Works well with destructuring assignment, too.

even, odd = (1..6).partition { |n| n.ev...

How to coordinate distributed work with MySQL's GET_LOCK

The linked article explains how to get a database-wide lock without creating table rows:

This article explains how I replaced file-based methods to ensure only one running instance of a program with MySQL’s GET_LOCK function. The result is mutual exclusivity that works in a distributed environment, and it’s dead simple to implement.

Ruby implementation

An implementation as a Rubygem seems to be [with_advisory_lock](https:...

Using PostgreSQL and jsonb with Ruby on Rails

Postgres 9.4 introduces a new column type: jsonb. json and jsonb columns store data differently, so just compare the two when you want to store JSON data and choose the one that matches your use case best.

Rails 4.2 includes support for jsonb columns, too. The article outlines different ways on how to interact with the serialized object.

Ruby: Counting occurrences of an item in an array / enumerable

Enumerable#count can do three things.

  • With no argument provided, it returns the number of items.
  • With an argument, it returns the number of items matching the given value.
  • With a block, it counts the number of elements yielding a truthy value.
ary = [1, 2, 4, 2]
ary.count #=> 4
ary.count(2) #=> 2
ary.count { |x| x % 2 == 0 } #=> 3

Ruby: Flatten arrays by only one level

Array#flatten by default flattens an array recursively. To only flatten the array for e.g. one level, it takes an optional argument.

# Flattens the array recursively
>> [1, [2, [3]]].flatten
=> [1, 2, 3]

# Flattens the array the given number of times
>> [1, [2, [3]]].flatten(1)
=> [1, 2, [3]]

Fix error UDPSocket.open: wrong number of arguments (0 for 1)

I got the following error after updating the selenium-webdriver gem:

wrong number of arguments (0 for 1) (ArgumentError)
/home/pointoo-dev/.rvm/gems/ruby-1.8.7-p374/gems/selenium-webdriver-2.35.1/lib/selenium/webdriver/common/platform.rb:183:in `open'
/home/pointoo-dev/.rvm/gems/ruby-1.8.7-p374/gems/selenium-webdriver-2.35.1/lib/selenium/webdriver/common/platform.rb:183:in `ip'
/home/pointoo-dev/.rvm/gems/ruby-1.8.7-p374/gems/selenium-webdriver-2.35.1/lib/selenium/webdriver/common/platform.rb:196:in `interfaces'

It was caused...

grosser/rspec-instafail

Gem to show failing specs instantly.
Unlike the --fail-fast option it doesn't abort abort on the first failure, but keeps running other examples after print out the failure.

I haven't tried it with parallel_tests.

Beware: Coffeescript "in" is not the Javascript "in"

The Javascript in operator does what Hash#has_key? does in Ruby: Return whether an object has a property.
However, Coffeescript has its own in operator that checks for array inclusion. To check whether an object has a property, use of:

Javascript

'name' in {name: 'Horst'} # => true

Coffeescript

# wrong
'name' in {name: 'Horst'} # => false

# correct
'name' of {name: 'Horst'} # => true
1 in [1,2,3] # => true

True story.

Ruby: Find a hash key given it's value

To find a hash key by it's value, i.e. reverse lookup, one can use Hash#key. It's available in Ruby 1.9+.

Hash#key(value) → key
# => Returns the key of the first occurrence of a given value.
     If the value is not found, returns nil.

hash = { "a" => 100, "b" => 200, "c" => 300, "d" => 300 }
hash.key(200)   #=> "b"
hash.key(300)   #=> "c"
hash.key(999)   #=> nil

Delegating an instance method to a class method in Ruby

With ActiveSupport you can say:

class Robot
  def self.likes_humans?
    'Nope.'
  end

  delegate :likes_humans?, to: :class
end

Robot.likes_humans?
# => 'Nope.'

Robot.new.likes_humans?
# => 'Nope.'

Preview Github-flavored Markdown from the bash with ianks/octodown

Preview what your markdown would look like on Github. Helpful e.g. when writing or extending a Readme for your gem or projects.

Installation

sudo apt-get install cmake libicu-dev # required for building native extensions
gem install octodown

Know that this will install at least 12 other gems. However, the beautiful output should be worth it.

Usage

octodown README.md

octodown markdown preview

How to set up database_cleaner for Rails with Cucumber and RSpec

Add gem 'database_cleaner' to your Gemfile. Then:

Cucumber & Rails 3+

# features/support/database_cleaner.rb

DatabaseCleaner.clean_with(:deletion) # clean once, now
DatabaseCleaner.strategy = :transaction
Cucumber::Rails::Database.javascript_strategy = :deletion

Cucumber & Rails 2

The latest available cucumber-rails for Rails 2 automatically uses database_cleaner when cucumber/rails/active_record is required -- but only if transactional fixtures are off. To have database_cleaner work correctly:

  1. Add the at...

Github: How to find the Readme for a certain version of a gem

When a gem author releases a new version to Rubygems, usually a tag with the version number (e.g. v1.2.0) is created an pushed to Github, so everyone can check out or take a look at the source code at this point version release at a later time.

If you'd like to take a look at the Readme of a specific Gem version, you can easily switch to that git tag on Github.

Github: Checkout Git Tag

Refile: Ruby file uploads, take 3

Jonas Nicklas, the author of Carrierwave and Capybara, has released Refile, a gem for handling file uploads in Rails. It handles direct uploads (also direct uploads to Amazon S3) better than Carrierwave.

The story and reasoning behind some of the decisions in Refile, and how it's different from Carrierwave, by the author himself, is a good read before deciding which way you'll go.

Big Caveat: Refile only stores the original image and r...

Installing the typhoeus Rubygem on Ubuntu 14.04

Make sure you have libcurl3-dev installed:

sudo apt-get install libcurl3-dev
gem install typhoeus

Taking screenshots in Capybara

Capybara-screenshot can automatically save screenshots and the HTML for failed Capybara tests in Cucumber, RSpec or Minitest.

Requires Capybara-Webkit, Selenium or poltergeist for making screenshots. Screenshots are saved into $APPLICATION_ROOT/tmp/capybara.

Manually saving a page

Additionally you can trigger the same behavior manually from the test using Capybara::Session#save_and_open_page and [...

Databound

Databound provides Javascript a simple API to the Ruby on Rails CRUD.

Tries to expose a full model CRUD as an API. Not sure if this is useful for more refined requirements.

Active Record and PostgreSQL — Ruby on Rails Guides

Rails guide that covers PostgreSQL-specific column types and usages for Active Record.

You should especially keep in mind the special datatypes that PostgreSQL offers. \
Types like json and array take away a lot of the pain that you had on MySQL projects.

Example use cases for array are tags or storing foreign keys (instead of a join model). You can even index them.