Iacutone.rb

coding and things

ENV Variables in XCode

| Comments

Setting ENV variables in XCode in not straighforward. I have broken down how to accomplish setting up an ENV variable in the following videos and code example.

Make a new conifuration file and set any ENV variables you need.

In the debug environment, use the debug.xcconfig file. Then, assign the value to something, in this case, SignUpUrl corresponds with the SIGN_UP_URL, which is set to localhost:4567/sign_up.

SignUpController.swift
1
2
  var info:[NSObject:AnyObject] = NSBundle.mainBundle().infoDictionary!
  var sign_up_url = info["SignUpUrl"] as! String

The sign_up_url variable is set to localhost:4567/signup.

Helpful Links

Configuring ENV Variables in XCode

Shared Contexts With RSpec

| Comments

In the past, I used traits with my factories. Below is a simple example of defining a trait:

Using traits

donations_factories.rb
1
2
3
4
5
6
7
8
9
10
11
  FactoryGirl.define do
    factory :donation do
      trait :with_amount do
        amount 10
      end

      trait :no_amount do
        amount 0
      end
    end
  end

An example spec:

donation_spec.rb
1
2
3
4
5
6
7
8
9
10
  RSpec.describe 'Donation Matching', :type => :model do

    context 'with an amount' do
      let(:donation) { create(:donation, :with_amount) }
    end

    context 'with no amount' do
      let(:donation) { create(:donation, :no_amount) }
    end
  end

However, I believe that using a shared context is a clearer approach. Defining the amount in a shared context and overriding the amount allows more control over testing use cases.

Using a shared context

donation_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  require 'support/shared_contexts/donor_with_donation_context'

  RSpec.describe 'Donation Matching', :type => :model do
    include_context 'a donor with a donation'

    context 'with an amount' do
      // donation.amount == 10 (defined in the shared context)
    end

    context 'with no amount' do
      let(:amount) { 0 }
      // donation.amount == 0
    end

    context 'with a gnarly' do
      let(:amount) { 09709780 }
    end
  end
spec/support/shared_contexts/donor_with_donation_context.rb
1
2
3
4
5
  RSpec.shared_context 'a donor with a donation' do
    let(:amount) { 10 }

    let(:donation) { create(:donation, amount: amount) }
  end

I especially like the shared context approach because you can have shared context and redefine attributes as needed in specs.

Auto Layout Xcode for Navigation Bar

| Comments

Finding auto layout information is difficult. The steps below pin a navigation bar to the top of the screen for all iOS devices.

Steps

  • Make sure “Navigation Bar” is selected on the left menu
  • Click the “Pin” button on the bottom right corner
  • Click the top, left and right constraints
  • Click the Height constraint
  • Add the 4 contraints

The above steps “pin” the navigation bar object to the top of the view and stretch the navigation bar to the sides of the view. The height constraint keeps a static height for the navigation bar.

Helpful Links

Auto Layout Basics

Prototypes and Constructors in Javascript

| Comments

I usually do not need to write code using neither constructors nor prototypes in Javascript. So, I always forget how to write them when I need to use them.

Constructor

1
2
3
4
5
6
7
8
9
10
  Say = function(){
    this.hello = function() {
      return "Hello";
    }
  }

  var say = new Say();
  say.hello()

  // "Hello"

Prototype

1
2
3
4
5
6
7
8
9
  function Say() {}
   Say.prototype.hello = function() {
    return "Hello";
  }

  var say = new Say();
  say.hello()

  // "Hello"

Helpful Links

Use of ‘prototype’ vs. ‘this’ in JavaScript?

Advantages of using prototype, vs defining methods straight in the constructor?

Shell Function

| Comments

I have been using youtube-dl every week. The application is a “Small command-line program to download videos from YouTube.com and other video sites.” It’s super useful. However, it default downloads to the current terminal directory. Let’s write a simple shell script in order to place all downloaded files from youtube-dl in the same directory.

.zshrc
1
2
3
4
5
6
function mp3 {
  # Download all of the things to /Downloads

  youtube-dl --default-search=ytsearch: \
             --output="Downloads/%(title)s.%(ext)s" "$*"
}

The “$” signifies the string following mp3, the example below, “$” is the URL arument.

1
  mp3 https://www.youtube.com/watch\?v\=9fYeiGeuTFA

Now I can run the above script in order to download the video from the youtube URL.!

Helpful Links

youtube-dl

The Setter Method in a Rails Model

| Comments

At Fractured Atlas, we are trying to move away from the additional complexity of using callbacks. For example, let’s say we need to do something in a before_save callback such as lowercase a user’s email.

user.rb
1
2
3
4
5
before_save: lowercase_email

def lowercase_email
  self.email = self.email.downcase
end

How is this code implemented without using before_save? One method would be overriding the setter accessor.

user.rb
1
2
3
4
def email=(value)
 email = value.downcase
 super(email)
end

Now, when the email attribute is updated, my email setter method is called.

Currently, both implementations for downcasing an email are straightforward. However, as the application grows, the before_save callback is more difficult to test and maintain. The before_save is implicit and might have unexpected side effects. Here is a basic spec.

user_spec.rb
1
2
3
4
5
6
7
8
9
10
11
12
describe User do

  let(:user) { FactoryGirl.create(:user) }

  describe '#lowercase_email' do
    before { user.email = 'GNARLY@email.com' }

    it 'lowercases the email' do
      expect(user.lowercase_email).to eq 'gnarly@email.com'
    end
  end
end

Instead, let’s test the behavior of what we expect.

user_creation_spec.rb
1
2
3
4
5
6
7
8
9
10
11
describe 'User Creation' do
  let(:user) { FactoryGirl.create(:user) }

  describe ':email' do
    before { user.email = 'GNARLY@email.com' }

    'it returns a standardized email' do
      expect(user.email).to eq 'gnarly@email.com'
    end
  end
end

The first spec is directly testing the callback, whereas the latter spec is testing the behavior of the expected outcome. The latter spec is easier to reason about and change. This is an easy example, but as callbacks grow changing their behavior becomes more difficult. This is especially true if the callbacks are coupled with other models.

Helpful Links

What is the right way to override a setter method in Ruby on Rails?

Overwriting default accessors

Ruby's Fetch Method

| Comments

Checking for values in a Rails params hash is complicated. In this post we will use the #fetch method to ensure nil is not called on a params hash.

searches_helper.rb
1
2
3
  if params[:search][:organization_id].present?
    # do things
  end

The code above will call #present? on nil if params[:search][:organization_id] does not exist.

A better way to write the conditional:

searches_helper.rb
1
2
3
  if params[:search].present and params[:search][:organization_id].present?
    # do things
  end

Writing a similar conditional with #fetch:

searches_helper.rb
1
2
3
  if params.fetch(:search, {}).fetch(:organization_id, nil).present?
    # do things
  end

Let’s break this method down into simpler components:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  params = {}
  puts params.fetch(:search, {})
  // {}

  params[:search] = "searched!"
  puts params.fetch(:search, {})
  // "searched!"

  puts fetch(:organization_id, nil)
  // nil

  params[:organization_id] = 1
  puts params.fetch(:organization_id, nil)
  // 1

I like the ability to call #fetch with a default return value if one does not exist. This leads to better ways to handle nil or catch errors.

Swift Basics

| Comments

String Interpolation

1
2
3
4
5
var name = "Eric"

println("Hello, \(name)")

// "Hello, Eric"

Dictionaries

1
2
3
4
5
6
7
8
9
var response = ["id":14,"email":"test@email.com"]

let id = response["id"]

// 14

let email = response["email"]

// "test@email.com"

Tuples

Unnamed Tuples

1
2
3
4
5
6
7
8
9
10
11
var coordinates = (100, 999)

let (lat, lon) = coordinates

println("Latitude is \(lat)")

// "Latitude is 100"

println("Longtitude is \(lon)")

// Longitude is 999

Named Tuples

1
2
3
4
5
6
7
8
9
10
11
12
13
var response = (code: 200, message: "All good")

response.0
// 200

response.1
// "All good"

response.code
// 200

respsonse.message
// "All good"

Swift Classes

Creating a class

Person.swift
1
2
3
4
5
6
7
8
9
10
11
12
13

class Person: NSObject {
  var name: String
  var email: String
  var zip: Int

  init(name: String, email: String, zip: Int) {
    self.name = name
    self.email = email
    self.zip = zip
    super.init()
  }
}

Create data for Person Class

SampleData.swift
1
2
3
let personData = [
  Person(name: "Eric", email: "eric.iacutone@gmail.com", zip: 12345)
]

Instantiating Person Class

PersonViewController.swift
1
var person:Array = personData

Now, if you copy and paste the the files into a XCode Playground, you can call methods on your person object.

Playground.swift
1
2
3
4
5
person.count
// 1

person.first?.zip
// 12345

Enums

An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code. - Swift docs

Use an enum when you need a consistent data value.

1
2
3
4
5
6
7
8
9
10
11
12
enum CountryType:String {
    case UnitedStates = "United States"
    case Spain = "Spain"

    init() {
      self = .UnitedStates
    }
}

var type = CountryType.UnitedStates.rawValue

// "United States"

Structs

A struct allows you to create a structured data type which provides storage of data using properties and extending its functionality via methods. -Tree House

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct Person {
    var name: String
    var email: String
    var country: CountryType
}

var person = Person(name: "Eric", email: "eric.iacutone@gmail.com", country: CountryType.UnitedStates)

person.name

// "Eric"

person.country.rawValue

// "United States"

My Return to Blogging

The goal of this blog is to refine my writing skills. In order to fulfill this goal I will write about something interesting I learned on a weekly basis. I find that if I do not get into a routine, I will not fulfill my goal. So, every Friday after work I will post on this blog. I have no goals about the legth of posts, but to write something with clarity and thoughfulness.

Exceptions in Ruby

| Comments

I inherited some interesting code last week. A user has the ability to sign into the website with omniauth.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
def num
  puts "Enter a number"
  num = gets.chomp.to_i

  if num == 3
      puts "It's a 3!"
      else
          raise "Wrong number, you entered a #{num}"
  end
end

def num2
  num
end

begin
  num2
rescue Exception => ex
  puts ex
end

Reference

Ruby Exception Class