“...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 GenieBelt who are based in Copenhagen, Denmark ...”

Rob Lacey
Senior Software Engineer, Copenhagen, Denmark

Google did a thing

I love PacMan but I am not good at it, not even if my own neighbourhood.

rewhere

Interesting problem requiring us to remove the where values on an ActiveRecord::Relation. The original heavy handed method seems to play havoc with chained where calls and the id of the original proxy_association.owner would get used in a later where. Here we can see that our for_me method seems to cause the else_id to be the same as our recipient_id

[5] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_7::Nested_1>)> user.somethings.where(else_id: something.else_id).to_sql
=> "SELECT `somethings`.* FROM `somethings` WHERE `somethings`.`user_id` = 20323 AND `somethings`.`else_id` = 6465  ORDER BY id DESC"
[6] pry(#<RSpec::Core::ExampleGroup::Nested_1::Nested_7::Nested_1>)> user.somethings.for_me.where(else_id: something.else_id).to_sql
=> "SELECT `somethings`.* FROM `somethings` WHERE `somethings`.`recipient_id` = 20323 AND `somethings`.`else_id` = 20323  ORDER BY id DESC

when in doubt read the Rails source

# remove user_id = proxy_association.owner.id from scope
    # so it can be reapplied by to_me or for_me
    def global_scope
-      s = respond_to?(:scoped) ? scoped : all
-      s.where_values = []
-      s
+      unscope(where: :user_id)
    end

which is the way that rewhere reassigns values in where rather than chaining again

2.2.2 :006 > Something.where(user_id: 1).where(user_id: 2).to_sql
=> "SELECT `somethings`.* FROM `somethings` WHERE `somethings`.`user_id` = 1 AND `somethings`.`user_id` = 2"
2.2.2 :007 > Something.where(user_id: 1).rewhere(user_id: 2).to_sql
=> "SELECT `somethings`.* FROM `somethings` WHERE `somethings`.`user_id` = 2"

I like ActiveRecord OR-ing

class Creature < ActiveRecord::Base
    scope :is_good_pet, -> {
        where(
            arel_table[:is_cat].eq(true)
            .or(arel_table[:is_dog].eq(true))
            .or(arel_table[:eats_children].eq(false))
        )
    }
end

ActiveRecord::Associations::CollectionProxy#many?

Nice…

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets.count # => 1
person.pets.many? # => false

person.pets << Pet.new(name: 'Snoopy')
person.pets.count # => 2
person.pets.many? # => true

Multiline Ruby String without interpolation

Whilst trying to clean up old blog posts. I thought I’d just re-assign the whole post on the console. However, the content of the post had code examples and these examples were being interpolated. This makes sense but isn’t what I wanted. These are all (nearly) equivalent other than the new lines.

s =<<-STR
#{Time.now}
STR
# => "2017-01-17 06:43:48 -0500" 

s = %(
#{Time.now}
)
# => "\n2017-01-17 06:43:48 -0500\n"

s = %Q(
#{Time.now}
)
# => "\n2017-01-17 06:43:48 -0500\n"

But what I really want it multi-line string assignment without interpolation.

s = %q(
#{Time.now}
)
# => "\n\#{Time.now}\n"

And without the new lines.

s = %q(
#{Time.now}
).lstrip.chop
# => "\#{Time.now}"

Instagram Subscriptions

Instagram Subscriptions

Loading development environment (Rails 5.0.1)
2.3.0 :001 > puts JSON.parse(Infectious::Instagram.subscribe('http://robl.me/instagram/subscriptions/callback','dave').body).to_yaml
ETHON: Libcurl initialized
ETHON: performed EASY effective_url=https://api.instagram.com/v1/subscriptions response_code=200 return_code=ok total_time=1.394347
---
meta:
  code: 200
data:
  object: user
  object_id: 
  aspect: media
  subscription_id: 0
  callback_url: http://robl.me/instagram/subscriptions/callback
  type: subscription
  id: 0

Method#call

Not sure what to make of this at all.

class Cat
  def call(*args)
    (args).join(' ^O^ ')
  end
end

Cat.new.(:samson, :smeagol, :gimmick)

Rails 4, ActiveRecord::Base, MySQL and DISTINCT

Interesting, ActiveRecord joins issues today. Recently upgraded to Rails 4.0 and working on clearing odd occasional bugs.

Mysql2::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'DISTINCT grapes.id, grapes.* FROM `grapes` INNER JOIN `tickets` ON `z' at line 1: SELECT `pledges`.`id` AS t0_r0, ...., DISTINCT grapes.id, grapes.* FROM `grapes` INNER JOIN `tickets` ....

We specifically need a DISTINCT in here so that we don’t end up with duplicate rows. However, overwriting the select for *eager_load*ed statements isn’t going to work, in fact it appears to just append our select causing the above error. So…

-        scope = scope.joins(:tickets).select('DISTINCT grapes.id, grapes.*')
+        scope = scope.joins(:tickets).distinct('grapes.id')

Don’t use .select(‘DISTINCT … when eager_loading is likely to kick in. You’ll end up with something like.

SELECT `grapes`.`id` AS t0_r0, ..... DISTINCT(grapes.id), grapes.* FROM grapes;

Which will break, since you can’t have two DISTINCT in a SELECT.

Do your columns contain Unicode Characters?

Want to work out if any of your columns contain Unicode Characters?

Something.where('LENGTH(data) != CHAR_LENGTH(data)').first

cannot remove 'v3.0': Directory not empty”

But it is empty???

rails@snarf:~$ ls -la /var/www/robl.me/releases/20160323235726/tmp/cache/assets/sprockets/v3.0
total 40
drwxrwxr-x 2 rails rails 36864 Dec 16 15:11 .
drwxrwxr-x 3 rails rails  4096 Mar 23  2016 ..
rails@snarf:~$ rmdir /var/www/robl.me/releases/20160323235726/tmp/cache/assets/sprockets/v3.0
rmdir: failed to remove ‘/var/www/robl.me/releases/20160323235726/tmp/cache/assets/sprockets/v3.0’: Directory not empty