“...I've been working since 2008 with Ruby / Ruby on Rails, love a bit of Elixir / Phoenix and learning Rust. I also poke through other people's code and make PRs for OpenSource Ruby projects that sometimes make it. Currently working for InPay...”

Rob Lacey
Senior Software Engineer, UK

Cross Domain Fonts with Nginx?

Having seen a few issues with cross domain web fonts with Firefox and a report of the same in Chrome. This small addition to an Nginx server config allows access from any origin, in this case for a fonts in a Rails asset pipeline. This config solves the problem of another site pinching our fonts. However, more importantly this allows cloudfront to sit in front of our origin server and for our site to serve fonts over cloudfront.

location ~ "^/assets/(.*/)*.*-[0-9a-f]{32}\.(woff|ttf|eot)$" {
  gzip_static on;
  expires     1h;
  add_header  Cache-Control public;
  add_header  Access-Control-Allow-Origin *;
  # debug to check this is being caught.
  add_header  X-Braindeaf-Pipeline true;
}

With the right syntax, we should probably limit the origin to *.cloudfront.net domains, and to our specific distrubitions in a more complete solution.

Static Google Maps

Since we’re heading off to Germany in the morning, here’s a quick stab at the Google Maps Image APIs Static Maps . Looks fairly straight forward if you have the Lat/Long of the places you want to create markers for.

https://maps.googleapis.com/maps/api/staticmap?zoom=6&size=900×500&maptype=roadmap&markers=color:blue|label:Brighton|50.84274,-0.106829&markers=color:green|label:Essen|51.450001,7.016700

Redirect / to another path in Nginx

I needed to tweak my Nginx config to redirect / (slash) only on a Wordpress site to a completely different location but leave all other routing intact. There we have it.

server {
  listen 80;
  server_name here.robl.me;
  root /var/www/wordpress;
  index index.html index.htm index.php;

  location = / {
    rewrite ^ http://there.robl.me permanent;
  }

  location / {
    try_files $uri $uri/ /index.php?$args;
    # auth_basic "Restricted";
    # auth_basic_user_file /etc/nginx/.htpasswd;
  }

  location ~ \.php$ {
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
  }
}

Wrote some PHP for the first time in about 8 years.

I think I liked it. Maybe. Associative Arrays and the like

<?php
$array = array(
  'units' => array(
    '1117411' => array(
      'is_shipped_at' => 'true',
      'shipped_at'    => '2014-10-14 T14:56:55+00:00'
    )
  )
);
var_dump($array);
?>
Robs-iMac:snarf rl$ php -f data.php
array(1) {
  ["units"]=>
  array(1) {
    [1117411]=>
    array(2) {
      ["is_shipped_at"]=>
      string(4) "true"
      ["shipped_at"]=>
      string(26) "2014-10-14 T14:56:55+00:00"
    }
  }
}

JBuilder extensions


class Jbuilder

  # don't repeat yourself. when WillPaginate
  def paginate!(collection, &block)
    if collection.respond_to?(:page)
      set! :total_entries, collection.total_entries
      set! :page, collection.current_page
      set! :per_page, collection.per_page
    else
      set! :total_entries, collection.count
      set! :page, 1
      set! :per_page, collection.count
    end
    set! :entries, collection, &block
  end

  # don't return null, should should be an empty string
  def _set_value(key, value)
    raise NullError, key if @attributes.nil?
    unless @ignore_nil && value.nil?
      if value.nil?
        @attributes[@key_formatter.format(key)] = ''
      else
        @attributes[@key_formatter.format(key)] = value
      end
    end
  end
  
  # when you want to skip a record when iterating over a collection
  def _map_collection(collection)
    return [] if collection.nil?

    collection.map do |element|
      _scope{ yield element }
    end.reject(&:blank?)
  end

end

Resetting counter cache

Ran into a problem whereby the counter cache on one of our associations was out of sync. Simple …just update the counter cache with the count of the association?

rails >> u User.find(1)
rails >> u.update_attribute(:roles_count, 1)
ActiveRecord::ActiveRecordError: roles_count is marked as readonly
	from /data/app/shared/bundled_gems/ruby/2.1.0/gems/activerecord-3.2.18/lib/active_record/persistence.rb:194:in `update_column'
	from (irb):17
	from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands/console.rb:47:in `start'
	from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands/console.rb:8:in `start'
	from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands.rb:41:in `<top (required)>'
	from /data/app/current/script/rails:6:in `require'
	from /data/app/current/script/rails:6:in `<main>'
rails >> u.update_column(:roles_count, 1)
ActiveRecord::ActiveRecordError: roles_count is marked as readonly
	from /data/app/shared/bundled_gems/ruby/2.1.0/gems/activerecord-3.2.18/lib/active_record/persistence.rb:194:in `update_column'
	from (irb):17
	from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands/console.rb:47:in `start'
	from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands/console.rb:8:in `start'
	from /data/app/shared/bundled_gems/ruby/2.1.0/gems/railties-3.2.18/lib/rails/commands.rb:41:in `<top (required)>'
	from /data/app/current/script/rails:6:in `require'
	from /data/app/current/script/rails:6:in `<main>'
rails pro >> User.readonly_attributes
=> #<Set: {"roles_count"}>

Seems you can’t update the value, I was surprised that update_column wouldn’t work either. I guess it makes sense to protect this value since it’s supposed to be kept in sync and only in rare occasions should it be out of sync. However, you can use the reset_counters class method.

rails >> u = User.find(1)
rails pro >> User.reset_counters u.id, :roles
  User Load (0.5ms)  SELECT `users`.* FROM `users` WHERE `users`.`id` = 1 LIMIT 1
   (0.4ms)  SELECT COUNT(*) FROM `roles` INNER JOIN `role_users` ON `roles`.`id` = `role_users`.`role_id` WHERE `role_users`.`user_id` = 1
   (0.9ms)  UPDATE `users` SET `roles_count` = 1 WHERE `users`.`id` = 355411
=> true

Calling super with no arguments

Suppose I want to overwrite a method an apply a optional argument that the original method didn’t accept.

class Something < ActiveRecord::Base

  def to_s(or_other = nil)
      if or_other
        Other.new.to_s
      else
        super
      end
  end

end

Seems fine. However, when you call to_s you’d get an error like wrong number of arguments (1 for 0). The reason is because without supply arguments to super they, by default, use the arguments passed to the overridden method. Since the original method didn’t accept any arguments previously then this fails. In order to avoid this you must call super() to deliberatly call it without arguments.

class Something < ActiveRecord::Base

  def to_s(or_other = nil)
      if or_other
        Other.new.to_s
      else
        super()
      end
  end

end

Created a new OmniAuth Strategy for PledgeMusic

Just wanted to test out OmniAuth by plugging into PledgeMusic authentication.

github. braindeaf/omniauth-pledgemusic

Well it works and you get an access token out, nice and simple. Wouldn’t mind re-styling the OmniAuth::Form to be a bit more in keeping with the decor.

Extending RedCloth to use custom tags.

After finding the GitHub jQuery Repo Widget I want to embed the widget in my blog posts. The body of which uses RedCloth So I needed to add a custom tag which could turn.

github. JoelSutherland/GitHub-jQuery-Repo-Widget

into

<div class="github-widget" data-repo="JoelSutherland/GitHub-jQuery-Repo-Widget"></div>

You can extend RedCloth’s HTML formatter by placing something like this in config/initializer/redcloth_extensions.rb for example.

require 'redcloth'

module RedCloth
  module Extensions
    def github(options)
      html = %Q{<div class="github-widget" data-repo="#{options[:text]}"></div>\n}
    end
  end
end
RedCloth::Formatters::HTML.send(:include, RedCloth::Extensions)

And there you have it.

github. JoelSutherland/GitHub-jQuery-Repo-Widget

Ruby Time#to_i and MySQL UNIX_TIMESTAMP

In a recent project I wanted to use a date to be a component of a hashed string in order to create a unique hash for a password reset page. I want the hash to expire when the user’s password is reset, in this case when the user’s last_logged_in datetime changes. I can generate the hash simply.

class User < ActiveRecord::Base
....
  def password_token
    unless new_record?
      Digest::SHA1.hexdigest([id, password_hash, salt, last_logged_in.to_i].join)
    end
  end
....
end

I don’t want to store this hash in the database (we might want to in the future to optimise the look up). So I need to generate the hash in SQL, but how to I do the equivalent to Time#to_i in SQL.

[29] pry(main)> Time.parse('2014-10-03 01:17:21 +0100').to_i
=> 1412295441

I initially thought I was looking for TO_SECONDS as per the MySQL Date and Time functions it seems it should be UNIX_TIMESTAMP

mysql> SELECT TO_SECONDS('2014-10-03 01:17:21 +0100');
+-----------------------------------------+
| TO_SECONDS('2014-10-03 01:17:21 +0100') |
+-----------------------------------------+
|                             63579518241 |
+-----------------------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> SELECT UNIX_TIMESTAMP('2014-10-03 01:17:21 +0100');
+---------------------------------------------+
| UNIX_TIMESTAMP('2014-10-03 01:17:21 +0100') |
+---------------------------------------------+
|                                  1412295441 |
+---------------------------------------------+
1 row in set, 1 warning (0.00 sec)

Found the answer at HOW TO GET THE CURRENT EPOCH TIME . And now I can write the finder method.

class User < ActiveRecord::Base
....
  class << self
    ....
    def with_password_token(password_token)
      where("SHA1(CONCAT(users.id, IF(users.password_hash IS NOT NULL, users.password_hash,''), IF(users.salt IS NOT NULL, users.salt, ''), IF(users.last_logged_in, UNIX_TIMESTAMP(users.last_logged_in), ''))) = ?", password_token).first
    end
    ....
  end
....
end
GPK of the Day Mad DONNA