Today I Learned Notes to self about software development

    Adding "breakpoints" to help you debug a Ruby program

    Sometimes when you are debugging a Ruby script, you want to do more than just print variables to debug. It’d be nice to pause the program at a particular moment and actually interact with all the variables that have been defined up until that point. Turns out, you can do this by adding breakpoints to your script.

    a breakpoint is an intentional stopping or pausing place in a program, put in place for debugging purposes. — Wikipedia

    Breakpoints can be added to your Ruby script using the pry library, which is a part of the standard Ruby library, but isn’t automatically loaded. You can load the library with require "pry".

    Pry basics

    Let’s say we have a program like this:

    list_of_people = [
      { :name => "James", :age => 16 },
      { :name => "Yolanda", :age => 26 },
      { :name => "Mel", :age => 15 }
    ]
    
    p "Enter an age and we'll tell you if we know a person who is that old:"
    
    age_to_find = gets.chomp
    
    list_of_people.each do |person|
      if person.fetch(:age) == age_to_find
        p "Found it!"
    	end
    end
    

    Even when I enter an age that I know should be found, like 16, my program doesn’t print "Found it!" like I expect.

    program-not-doing-what-i-want.png

    Using pry, I can use binding.pry to add a breakpoint before the if statement so I can interact more with the variables that were created.

    binding.pry will pause the runtime of the program and open an IRB console

    list_of_people = [
      { :name => "James", :age => 16 },
      { :name => "Yolanda", :age => 26 },
      { :name => "Mel", :age => 15 }
    ]
    
    p "Enter an age and we'll tell you if we know a person who is that old:"
    
    age_to_find = gets.chomp
    
    list_of_people.each do |person|
    	binding.pry
      if person.fetch(:age) == age_to_find
        p "Found it!"
    	end
    end
    

    Now when you run the program it doesn’t complete—

    adding-binding-dot-pry.png

    You can use an IRB console to interact with the code that has run so far.

    Now I can access variables like age_to_find and person that were defined before the breakpoint to see why the condition for my if statement never evaluates to true.

    debugging-with-pry.gif

    Ah, the ol’ forget-to-convert-a-String-into-an-Integer error. Gets me everytime 🤦. Now I know to convert age_to_find to an Integer.

    You can type exit when you’re done to un-pause the programs execution.

    Ruby on AWS Lambda

    I recently was looking into how to use Ruby with AWS Lambda for *reasons*, and it took a lot of time! I finally figured out how to do it and even test locally with containers.

    I already wrote a bunch of stuff up in this repository, which the README will be updated with any nice resources I find as I continue learning.

    OAuth vs SAML

    TIL, OAuth and SAML are not the same and do slightly different things. You would never use them both at the same time.

    OAuth

    OAuth is for authorization. The best example I have is when I used my Google account for Pokémon Go. After logging in with my Google account, the Pokemon Go app prompted me to ask if they could have permission to access a bunch of things in my Google account. I didn’t follow it, but there was a bunch of news about how Pokémon Go requested you grant too much access to the Google account. Anywho, OAuth is the protocol used to authorize other services to have access to things in your Google account. Facebook does the same. You may even see apps that say, “Login with your Facebook or Google account and we’ll import all your contacts into our system.” That’s OAuth being used by Facebook and a Google to authorize other services to access resources in your account.

    SAML

    SAML is a protocol for authentication. Basically, you have a service provider (Salesforce, G Suite, Box, etc) and you have an identity provider (Okta, OneLogin, Ping Identity, etc). You’ll have a user account in both systems, let’s say for Jane. When Jane goes to login to Box, she would typically provide a username and password, then Box would authenticate the user. But the IT admins have setup SAML with Box and Okta. So when Jane goes to Box to login now, Box sends a SAML request to Okta. Okta receives that request and may ask the user to login to Okta, if they haven’t already. Okta is essentially tasked with authentication. Okta then sends a SAML response to Box. Box accepts this and creates a session for the user and they’re now logged in. To Box, the SAML response they received is used instead of them providing a username and password.

    Markdown footnotes

    I look up how to do footnotes in Markdown everytime I need to use them. Maybe if I write this post, I’ll finally remember.

    It works like this:

    Here is a simple footnote[^1]. With some additional text after it.
    
    [^1]: My reference.
    

    Copying records

    When I was setting up Ruby assignment1 this week, I wanted to copy all of the exercises and specs from last quarter and associate them with the assignment for this quarter.

    I came up with a pretty nice solution using .attributes which returns a Hash of the existing attributes for a record that I can pass straight to the .create method.

    new_assignment = Assignment.find(...)
    old_assignment = Assignment.find(...)
    old_assignment.exercises.each do |e|
      copy = e.attributes
      new_e = new_assignment.exercises.create(copy)
    end
    

    BUT this .attributes includes the id too, so this doesn’t work yet. You can exclude key/value pairs from a Hash using .except. You can provide multiple keys at the same time as well.

    new_assignment = Assignment.find(...)
    old_assignment = Assignment.find(...)
    old_assignment.exercises.each do |e|
      copy = e.attributes.except("created_at", "updated_at", "id")
      new_e = new_assignment.exercises.create(copy)
    end
    
    1. This “assignment” is a Rails app, where an “assignment” is a model, and each assignment has many exercises, and each exercise has many specs.