RobL

upgrading Rails 3 to Rails 4 and try

In a Rails project I am using the ZendeskAPI gem to integrate with Zendesk. It’s a simple integration with Hash-like objects representing the remote data.

e.g. ZendeskAPI::User #- is a kind of Hash with magic methods

Subtle differences between Rails 3 and 4 make Jack a dull boy.

Rails 3

user.try(:id)  # just calls send on source if it is not nil

def try(a, &b)
if a.empty? && block_given?
yield self
else
send(
a, &b)
end
end

Rails 4

user.try(:id) # just calls send on source if it isn’t nil and responds to ‘id'

def try(a, &b)
try!(
a, &b) if a.empty? || respond_to?(a.first)
end

user can potentially be nil at any point we when we call try on it, it will always return nil because the ZendeskAPI::User does not respond to the those methods. So in cases where you might be overriding method_missing try most certainly won’t work.

However, ‘try’ takes a block…so I discovered quite by accident that I can do this instead

*source.try(&:id)*

This works because if the first argument is empty it simply instance_evals the block I gave it, which calls ‘id’. And relax.

The Mad Katter - Boardgame Cafes Interactive Map

A really nice little project http://www.themadkatter.co.uk/cafes not to mention give us a clue on where to go on holiday next.

Calling rake task within other rake tasks

and blocking non-test environments for safety…

namespace :db do
  desc 'Rebuild test database and load seeds'
  task rebuild: [:environment] do
    fail ArgumentError, 'Test Environment required' unless Rails.env.test?
    Rake::Task['db:drop'].invoke
    Rake::Task['db:create'].invoke
    Rake::Task['db:schema:load'].invoke
    Rake::Task['db:migrate'].invoke
    Rake::Task['db:seed'].invoke
  end
end

Can't install Ruby 2.3.0 because of CURL

deployer@www:~$ rvm reinstall ruby-2.3.0
ruby-2.3.0 - #removing src/ruby-2.3.0..
ruby-2.3.0 - #removing rubies/ruby-2.3.0..
Searching for binary rubies, this might take some time.
Found remote file https://rubies.travis-ci.org/ubuntu/14.04/x86_64/ruby-2.3.0.tar.bz2
Checking requirements for ubuntu.
Requirements installation successful.
ruby-2.3.0 - #configure
ruby-2.3.0 - #download
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
curl: (60) SSL certificate problem: self signed certificate in certificate chain
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
/home/deployer/.rvm/scripts/fetch: line 105: log: command not found
Checking fallback: ftp://rubies.travis-ci.org/ubuntu/14.04/x86_64/ruby-2.3.0.tar.bz2?rvm=1.26.11
Checking fallback: http://www.mirrorservice.org/sites/rubies.travis-ci.org/ubuntu/14.04/x86_64/ruby-2.3.0.tar.bz2?rvm=1.26.11
No fallback URL could be found, try increasing timeout with:

    echo "export rvm_max_time_flag=20" >> ~/.rvmrc

Downloading https://rubies.travis-ci.org/ubuntu/14.04/x86_64/ruby-2.3.0.tar.bz2 failed.
Mounting remote ruby failed with status 2, trying to compile.
Checking requirements for ubuntu.
Requirements installation successful.
Installing Ruby from source to: /home/deployer/.rvm/rubies/ruby-2.3.0, this may take a while depending on your cpu(s)...
ruby-2.3.0 - #downloading ruby-2.3.0, this may take a while depending on your connection...
ruby-2.3.0 - #extracting ruby-2.3.0 to /home/deployer/.rvm/src/ruby-2.3.0....
ruby-2.3.0 - #configuring..........................................................
ruby-2.3.0 - #post-configuration..
ruby-2.3.0 - #compiling.................................................................................
ruby-2.3.0 - #installing...........................
ruby-2.3.0 - #making binaries executable..
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.
There was an error while trying to resolve rubygems version for 'latest'. 
Halting the installation.

I am pretty sure the last this happened I had to apt-get install ca-certificates.

Ah, just skipping secure check finally did it.

echo insecure >> ~/.curlrc

Benchmarking String Matching in Ruby

I am very prone to writing string matching as ‘string’.match(/ing/), which is very readable, however it is not always necessary to capture the matching part of the string. Having seen alternative syntax from a colleague I’ve used the following benchmark to test what is the most efficient syntax/method.

Robs-iMac:benchmarks$ irb
2.2.2 :001 > require 'benchmark'
 => true 
2.2.2 :002 > 
2.2.2 :003 >   "cloudfront.net" =~ /cloudfront/
 => 0 
2.2.2 :004 > 
2.2.2 :005 >   Benchmark.measure{ 1000000.times { "cloudfront.net" =~ /cloudfront/ } }
 => #<Benchmark::Tms:0x007fdea2288ee8 @label="", @real=0.30020256410352886, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.30000000000000004, @total=0.30000000000000004> 
2.2.2 :006 > 
2.2.2 :007 >   "cloudfront.net"[/cloudfront/]
 => "cloudfront" 
2.2.2 :008 > 
2.2.2 :009 >   Benchmark.measure{ 1000000.times { "cloudfront.net"[/cloudfront/] } }
 => #<Benchmark::Tms:0x007fdea24785a0 @label="", @real=0.36411550105549395, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.36, @total=0.36> 
2.2.2 :010 > 
2.2.2 :011 >   "cloudfront.net".match(/cloudfront/)
 => #<MatchData "cloudfront"> 
2.2.2 :012 > Benchmark.measure{ 1000000.times { "cloudfront.net".match(/cloudfront/) } }
 => #<Benchmark::Tms:0x007fdea2350920 @label="", @real=0.967038004193455, @cstime=0.0, @cutime=0.0, @stime=0.0, @utime=0.9600000000000001, @total=0.9600000000000001>

I would appear that =~ is the outright winner, being at least three times faster. Keeping an eye out for unnecessary overuse of .match from now on. Referencing Stack Overflow http://stackoverflow.com/questions/11887145/fastest-way-to-check-if-a-string-matches-or-not-a-regexp-in-ruby

petty annoyance of alias_method_chain

So it appears you can’t alias_method_chain []=. Rightly so you’d end up trying to do something like

def []=_with_rescue
  []=_without_rescue
end
alias_method_chain :[]=, :rescue

The resulting method names are of course invalid. So you have to do it longhand

require 'action_dispatch/middleware/cookies'
# action_dispatch/middleware/cookies.rb
module ActionDispatch
  class Cookies
    class SignedCookieJar
      def assign_with_overflow_rescue(name, options)
        assign_without_overflow_rescue(name, options)
      rescue ActionDispatch::Cookies::CookieOverflow => e
        SiteMailer.delay.error(e, key: key, original_options: original_options, encoded_size: options[:value].size)
      end
      alias_method :assign_without_overflow_rescue, :[]=
      alias_method :[]=, :assign_with_overflow_rescue
    end
  end
end

grab Ruby Objects by object_id

Are you ever frustrated that you cannot just grab objects in the console to see what the hell they are and what methods you can call on them?

2.2.3 :001 > ArticlesController
#<ActiveSupport::Callbacks::Callback:0x007fdb1e58a010>
70289541845000
#<ActiveSupport::Callbacks::Callback:0x007fdb1e3104d8>
70289540547180
#<ActiveSupport::Callbacks::Callback:0x007fdb1ed30058>
70289545855020
#<ActiveSupport::Callbacks::Callback:0x007fdb1e30b708>
70289540537220
=> ArticlesController 
2.2.3 :002 > ObjectSpace._id2ref(70289541845000)

Lazy...

It is my aim in 2016 to stop being lazy. It’s all too easy to let your skill set slide, and while I enjoy what I do every day I haven’t explored every language, framework or technology enough to know whether I am missing out on anything I am interested in. So starting from tomorrow morning I’ll be taking a stab a some new projects to advance my skills in probably the following, Python, R, Java / Android app development, Swift for iOS, AngularJS for Desktop Development with Electron, Unity / C#, Corona SDK / Lua, Raspberry Pi PSX Emulation, Arduino development to measure how much our cats are using their cat wheel (no really). Expect the Lab to fill up with guff. Wish me luck or don’t.

Three things that were invaluable today

Quick and dirty database migration on the console

When a database migration failed to roll back properly, stripping one column but not all, we had to put back the original column without changing the migration and re-running. It always feels very dangerous when a multipart migration fails halfway through. So….you can actually call migration commands on ActiveRecord::Migration directly, just be careful to test in development first as accidents can and will happen.

Rails pro >> ActiveRecord::Migration.add_column :somethings, :thing_file_name, :string, before: :thing_file_name
-- add_column(:somethings, :thing_file_name, :string, {:before=>:splash_content_type})
   (4838.6ms)  ALTER TABLE `somethings` ADD `thing_file_name` varchar(255)

Cherry picking changes in a different branch with Git.

I had to give up on a recent branch because refactoring had caused more problems than it intended to solve. Without wanting to start over I was able to pick the files that I cared about individually rather than sifting through and reverting parts of a previous commit.

git checkout feature/somefeature -- config/blah.yml

While I’m there, ever wanted to ditch your local changes in a conflict over the merged in changes from another branch?

git checkout --theirs config/routes.rb

Rails partials as layouts

Ever had a Rails partial and wanted to re-use it in a specific situation but with a small change? A partial can also be used as a layout, it appears a partial can be a layout that takes a block.

app/views/somethings/_dave.html.haml

= form_for(@dave) do |f|
  = f.text_field :full_name

app/views/somethings/thing.html.haml

= render partial: 'dave'

I really want to add an way to to re-use the form and add to it. How about this?

app/views/somethings/_dave.html.haml

= form_for(@dave) do |f|
  - if block_given?
    = yield
  = f.text_field :full_name

app/views/somethings/thing.html.haml

= render layout: 'dave' do
  %p A MESSAGE TO PLONK AT THE TOP OF THE FORM

TBG Secret Santa

Another mini-project. A Secret Santa app, Facebook login, address data collection, will then select a suitable Gift Recipient, mark gifts as shipped and reciprocol gifts received.

http://www.themadkatter.co.uk/secret_santa

Hosted on http://www.themadkatter.co.uk