Today I Learned

A Hashrocket project

47 posts by jasoncummings @jasoncummings86

Advanced Google Queries

You can use various techniques to narrow your Google queries:

To start, open a new tab, and google hashrocket.com. Compare those results to the following:

site:hashrocket.com This will only return resources that have a reference to this website.

site:hashrocket.com admin Same as above, but only containing resources that contain the word admin. In this case, it shows all of the TIL posts containing admin.

link:hashrocket.com Only pages that have links to hashrocket.com

related:hashrocket.com Sites that are similar to hashrocket.com (other dev shops).

source: ‘The Web Application Hackers Handbook 2’ - Dafydd Stuttard & Marcus Pinto

Ruby Object Reference in blocks

Usually when I want to set the value of a variable by yielding to a block, I will explicity set it

  x = 'something'
  x = yield(x)
  #....

Turns out ruby will treat different types of objects different when yielded to a block (remember everything is an object). If you are yielding an Integer, or String for (a contrived) example:


def do_stuff_by_val
  do_block_stuff_by_val do |name|
    name += 'rocket'
  end
end

def do_block_stuff_by_val
  company_name = 'hash'
  yield(company_name)
  puts company_name #prints 'hash', not 'hashrocket'
end

If we wanted the company name to change to “hashrocket”, we would need to explicitly set the variable to the result of yielding:

company_name = yield(company_name)

Other types of objects do not behave this way (hash or array). If we yield a hash and set a key, the hash in the calling method will be updated:


def do_stuff_by_object_reference
  do_block_stuff_by_object_reference do |company|
    company[:name] = 'hashrocket'
  end
end

def do_block_stuff_by_object_reference
  company = {}
  yield(company)
  puts company # { name: 'hashrocket'}
end

Cascading function calls

Cascading function calls can be useful for building up properties on an object. We can simply return this at the end of each cascading function so that we always end up with the object when we’re done.

Example - building a flash message after an ajax request in rails:

$.ajax({
        method: 'DELETE',
        url: url,
        contentType: 'application/json',
        error: function(status, data, jqxhr){
          var message = JSON.parse(status.responseText).error;
          var flash = new FlashBuilder('div');

          flash.text(message)
            .addClass('notification-error')
            .append('.flash-messages', '#some_container');
        }
      });
function FlashBuilder(el){
  this.element = $('<' + el + '>');

  this.text = function(text){
    this.element.text(text);
    return this;
  };

  this.addClass = function(klass){
    this.element.addClass(klass);
    return this;
  };

  this.append = function(target, container){
    if(container){
      $(container).find(target).append(this.element);
    } else {
      $(target).append(this.element);
    }

    return this;
  }
}

e.target vs this in delegated events

When attaching click handlers to elements, I used to think I could use e.target interchangeably with this. That is not true when we use event delegation.

Given the following JS:

    $('body').on('click', "[id^=delete_thing]", function(e){
      // do stuff
    });

And the following HTML:

<a href="javascript:void(0)" id="delete_thing_184">
      <img  src="/assets/ui/icon_delete.png">
      <strong> Delete Thing </strong>
</a>

When we click this link, we’re actually clicking either the <strong> or the <img>. When the event e is passed to the callback, e.target is the element we actually clicked, and this is the element the click event bubbled up to, so use this instead of e.target.parent.

rel attribute for performance and security

The rel attribute on HTML links need to be set to noopener if you’re using target=_blank in your links, otherwise the new tab contains a reference to the other tab’s window object, and can redirect, manipulate dom, etc.

Read more and see a demo here: https://mathiasbynens.github.io/rel-noopener

There are also some performance benefits: https://jakearchibald.com/2016/performance-benefits-of-rel-noopener/

Shell ! command

!! is well known to repeat the last shell command in a *nix terminal, it turns out there are other useful variants:

Given a shell history:

$ history
10034  echo $PATH
10035  history
10036  type ruby
10037  which ruby
10038  history
10039  ls

!n - execute a specific item:

$ !10039
ls
Applications
Desktop
...

!?<match>?: matches a pattern and runs the first command that matches:

$ !?uby?
type ruby
ruby is /Users/jason/.rvm/rubies/ruby-2.2.2/bin/ruby
````

Ruby XOR operator

The ^ acts is a boolean XOR operator in Ruby when the arguments are boolean. It wants only one true value in an expression in order to be considered true:

true ^ false ^ false
# => true

true ^ false ^ true
# => false

Let’s look at 5 trues:

true ^ true ^ true ^ true ^ true 
# => true

How is this true? Each ^ is evaluated one at a time. Since true ^ true is not exclusive, it is false. So after the first evaluation, we have:

false ^ true ^ true ^ true

# false ^ true is true

true ^ true ^ true

#true and true is false
false ^ true
# true

Using this same logic we can see why true ^ true ^ true ^ true is false.

non recursive find

The find command is recursive by default. Let’s say you want to find all the screen shots on your ~/Desktop, but ignore any screens in the directories in Desktop. Setting the maxdepth flag will tell how far to recurse, using the value 1 only searches the directory you specified, using 2 would go into each directory, but only not search any sub directories, and so on.

#this will recurse by default
$ find ~/Desktop -name "*Screen*"

#this will only search the Desktop and it's immediate subdirectories
$ find ~/Desktop -maxdepth 2 -name "*Screen*"

Pipe into operators

Since Elixir operators are macros defined on Kernel or in a submodule of Kernel, we can pipe into them when we call the function on Kernel:

true |> || false # this raises a syntax error

true |> Kernel.||(false) # valid Elixir

Real world example from the Phoenix source: https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/router/helpers.ex#L31-L36

alias is lexically scoped

Aliases are lexically scoped, allowing you to alias a module inside of a function and that alias will only exist in that function’s scope. Also TIL: You can even alias over Elixir standard lib module names.

defmodule Cartography do
  def north_america do
   alias Earth.NorthAmerica.Map
   #Map is now Earth.NorthAmerica.Map
   # You can get to the normal Map module using Elixir.Map
  end

  def foo do
    #Map is still Elixir.Map
  end
end

Change resource param in Phoenix routes

Phoenix, like Rails, gives you the option to specify a resource in your routes in order to generate the typical CRUD actions we deal with in a controller. The dynamic segment which identifies the resource is :id by default.

resources "orders", OrderController

The update route would look like this if we run mix phoenix.routes.

order_path  PATCH  /orders/:id    MyApp.OrderController :update

If our table doesn’t use “id” as a primary key, or we want to change the field we use to find our resource, we can specify it as an option in our route:

resources "orders", OrderController, param: "some_field"

Now our route is updated:

order_path  PATCH  /orders/:some_field    MyApp.OrderController :update

https://github.com/phoenixframework/phoenix/blob/master/lib/phoenix/router.ex#L482

.cert vs .pem

Fellow Rocketeer Dillon Hafer had the explanation for my SSL issue mentioned at https://til.hashrocket.com/posts/c38666d448-react-native-heroku-and-ssl-heroku- reactnative -

“DNSimple gives you a cert and a pem file. The cert file is just the certificate, while the pem file is actually 4 certificates mushed into one file. The 3 extra certificates are the intermediate certificates required by some operating systems that only include Root Certificates. Hope that helps explain why the pem from DNSimple works while the cert doesn’t.” - Dillon Hafer

React Native, Heroku, and SSL @heroku @reactnative

I recently switched over a Phoenix app from the paid Heroku SSL add on to the new SSL beta. Everything seemed to work great, until I noticed all Network Requests from the Android side of my React Native mobile app were failing, however iOS, curl, postman, etc were all fine.

I banged my head around for a while and went back to check my SSL set up. During the beta setup, Heroku tells you your certificate is usually a .pem or a .cert. I have both. Without much though, I uploaded the .cert. I went back and uploaded the .pem, and everything works fine.

I don’t know why the .pem worked and the .cert didn’t, but I’ll do some digging and post a follow up to this when I know why.

Ecto 2.0 ownership timeout #myelixirstatus

Ecto 2.0, gives us concurrent testing against the DB by allowing an Elixir process to own a database connection. The default time releases the connection pretty quick, so it’s not suitable for debugging anything thats non-trivial.

We can change the timeout in our config/test.exs

config :my_app, MyApp.Repo,
  adapter: Ecto.Adapters.Postgres,
  #...
  ownership_timeout: 60_000

https://twitter.com/josevalim/status/686598666078023680

InteractionManager smooth scene transitions

If you have an expensive scene to render with a lot going on in the constructor, or componentDidMount, etc, your navigator animation will likely by choppy because the Javascript thread is blocked executing that code. Use the InteractionManager API to execute that code after the transition ( and render a placeholder if necessary).

https://facebook.github.io/react-native/docs/performance.html#slow-navigator-transitions

Compose functions

Clojure’s comp function allows you to give it a set of functions, and return a function that is the composition of those functions.

;without comp

(defn inc-and-to-string [num]
  (str (inc num)))

(inc-and-to-str 2)
; "3"

;with comp
(def inc-and-to-string-with-comp (comp str inc))

(inc-and-to-string-with-comp 2)
;"3"

The with-comp version returns a function, which when called, applies inc to the argument passed in, then applies str to the result, the same as the other version.

Refinements

In Ruby 2.1 and later, you can require monkey patching to be explicitly active inside of a class/module by defining your method inside of a refine block. You can activate the changes with the using keyword.


​module Confusion
  refine String do
    def length
      "Yes"
    end
  end
end

module BadString
  using Confusion
  def self.count(string)
    string.length
  end
end

module GoodString
  def self.count(string)
    string.length
  end
end

BadString.count("four") # => "Yes"
GoodString.count("four") # => 4

Use array.[] instead of array.@each

In Ember, I knew array.@each, array.length, and array.[] would all work in my computed properties, but it turns out array.[] and array.length are much more performant, and should be used over array.@each in almost every case.

Use array.@each when you need to know about a property/properties on a member of the array changing, for example: array.@each.{foo,bar,baz} will watch for changes to the foo, bar, and baz properties.

https://blog.eladshahar.com/performant-array-computed-properties.html

Always triggering the model hook in a route

In a link-to helper, many times you already have the model you’re linking to in the Ember Data Store, so you pass in the model directly to the link-to. This will cause the route to skip the model hook because Ember Data already knows what the model is. If for some reason you want to ensure the model hook is always called, pass in model.id instead of model.

Just remember that this is done intentionally for performance, link-to model is always going to be faster than link-to model.id, because the model is already loaded.

Uncover monkey patched methods

Due to Ruby’s open classes, anyone can monkey patch any thing at any time, which could lead to confusion if you aren’t aware of the patched methods. You can check a method to see if it’s been monkey patched in irb/pry/byebug without exiting and grepping the source code.

class Array
  def length
    "MONKEY PATCHED!"
  end
end
arr = []
suspect_method  = arr.method :length
method = arr.method :size

Here we create some references to the length and size methods on Array. When you call source_location on one of these, if the method is defined in native Ruby, it will return nil, if it has been monkey patched, it will return the file name and line number where it was defined.

suspect_method.source_location
# ['some_file.rb', 2]

method.source_location
#nil

Auto remove trailing whitespace

Copy this in your .vimrc.local, and any trailing whitespace will be highlighted, and automatically removed when you write the file.

"highlight trailing whitespace
match ErrorMsg '\s\+$'
" kill trailing whitespaces automatically
autocmd BufWritePre * :%s/\s\+$//e

Yes, I totally stole this from someone else’s vimrc on github. https://github.com/rwz/dotfiles/blob/master/vim/vimrc

V8 Optimizations

V8 will not define variables that would normally be within JS function scope until they’re actually called.

test('visiting /foo/bar', function(assert){
  var foo = server.create('foo');
  var bar = server.create('bar');

  andThen(function(){
      var someProp = foo.callProperty;
      debugger
  });
});

When the console opens, foo will be in scope, while bar will be undefined