Working with Rails has_one Association

Recently while working on a programming challenge, I came across a weird behavior when using a has_one association in Rails. It was one of those situations where I couldn’t help trying to figure out exactly why the code was behaving the way it was. In this blog post, I will briefly explain exactly what happened and how simple it was to solve it.

For this example, I will use a different domain than the one I was actually working with to respect the privacy of the actual challenge. However, the association is exactly the same.


class Team < ApplicationRecord
has_many :players
has_one :coach
end
class Player < ApplicationRecord
belongs_to :team
end
class Coach < ApplicationRecord
belongs_to :team
end

view raw

associations.rb

hosted with ❤ by GitHub

Here we are dealing with a sports domain in which a team has many players, but only one coach. For the sake of simplicity, we will assume I’m talking about the head coach, without assistant coaches and the rest of the coaching staff that normally makes up the coaching of an actual sports team. But I digress…

Here is what the corresponding schema looks like:


ActiveRecord::Schema.define(version: 20170308221615) do
create_table "coaches", force: :cascade do |t|
t.integer "team_id"
t.string "name"
t.integer "experience"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "players", force: :cascade do |t|
t.integer "team_id"
t.string "name"
t.integer "number"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "teams", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end

With the associations set up in this way, after running migrations let’s fire up the Rails console to make sure the associations are working as expected.

team has many players (1)

The above ensured that the has_many association linking Team and Player was working as it should. Straightforward enough. Now let’s give the Warriors a head coach.

team has a coach (2)
Alright, the Warriors have hired Steve Kerr.

Now it’s been a few years and the Warriors aren’t doing so well. They’re looking to hire a new coach. Let’s say they bring back Mark Jackson (seriously, there are many teams that could use him!). They first have to fire Kerr in order for Jackson to take over the team. This is where things get interesting. Back to the rails console.

team has new coach (3)

Here we create a new coach and immediately associate it with the Warriors (using .create_single_association). Of particular interest, however, is what happens right after that. Pay attention the yellow line. This SQL query gets fired right after the new record gets persisted. If you look closely, all it’s doing is updating the record’s team_id attribute to a nil value.

Notice that when I look at Coach.all the previous record’s team_id is in fact nil. Interesting…

The person I was pair programming with and I were both a little perplexed by this. After exercising some Google-fu, looking for an explanation, I came across this Stack Overflow answer which clarified things for me.

From the answer, I was able to learn that by default, the has_one association executes a nullify. This is now evident to me looking carefully at the yellow SQL query in the screenshot above. In addition, according to the answer, the way to prevent this behavior is to add a dependent: :destroy option. Let’s try that!

https://gist.github.com/fidelscodes/cba05a337bc1490acafd6168e9b61748

First, we update the Team model by adding the dependent: :destroy option to the `has_one` association.

Now, to the Batmobile! Err… I mean, to the rails console!

team has the goat (4)

As you can see by the red line of SQL, this time after the new record is created, the previous one is being deleted from the database. This is the behavior I was actually aiming for!

When would we want this default behavior over dependent: :destroy?

Well, this sports domain is a great example where it actually makes sense to go with the default.

We fired Mark Jackson as the Warriors head coach when we hired Michael Jordan. However, we also lost all information regarding Mark Jackson. If another team were to hire him, we would have to create a brand new record.

By relying on the default way that has_one works, his record simply would have been updated to nullify its team_id attribute (just as it happened with Steve Kerr in our first example). This means that if another team wanted to hire Mark Jackson, we would already have access to his information, we’d simply need to associate his record’s team_id with the new team’s id.

Conclusion

Going through the challenge that led to this blog post was a lot of fun. In particular, because I was able to learn something new from the experience.

It turns out that when used the right way, a has_one association can be a very powerful tool to be aware of when modeling a domain. Just make sure you’re aware of the way you want it to work ahead of time. It will save you from asking yourself “but why isn’t it working?” many times over.

Helpful Resources

http://stackoverflow.com/questions/36893028/has-one-relation-automatically-set-nil-if-more-than-one

http://guides.rubyonrails.org/association_basics.html#choosing-between-belongs-to-and-has-one

http://stackoverflow.com/questions/861144/difference-between-has-one-and-belongs-to-in-rails

Uploading Attachments with Ajax

For the past two days, my Rails Assessment partner and I have been working on revamping our project, ArtMart, in order to complete the Rails and JavaScript assessment. One of the requirements is to create a new resource and render the response without a page refresh using our existing Rails API and Ajax.

At first, this seemed like a very simple task. Especially since most of the labs leading up to the assessment provide practice using Ajax. However, once I started to implement this functionality, I quickly ran into a problem neither of us had ever encountered before.

The Problem

How to upload form data, including a file, and submit it via Ajax while preventing the page refresh, and then render the created resource from the response.

In a previous lab, I learned how to take all the form data and serialize it using jQuery’s  .serialize() function. Hence, my initial notion that adding the functionality would not be too challenging. Well, I was wrong.

The code I had looked something like this:

function attachFormListener() {
  $( "form" ).on( "submit", function(e) {
    e.preventDefault();
    let url = $(this).attr('action');
    let data = $(this).serialize();

    $.ajax({
      url: url,
      type: 'POST',
      data: data,
      success: function(response) {
        let artwork = new Artwork(response.artwork);
        let html = artwork.renderHTML();
        $('.artwork-new').html(html);
      }
    });
  });
}

This worked for all regular form input fields, but not for the file input field. The Ajax was was working and posting to the right action, but params was missing a key piece of information: the actual image data.

without-image-key

Because of this, the transaction was being rolled back and the resource just wouldn’t get created.

Looking for answers on how to handle file submission via Ajax using Rails, it seemed to be a problem that would require some workarounds. I tried a few of them but was unsuccessful. By this point, I don’t think my brain was processing right anymore.

Okay, So What Worked?

Using the FormData API.

The FormData interface provides a way to easily construct a set of key/value pairs representing form fields and their values, which can then be easily sent using the XMLHttpRequest.send() method. It uses the same format a form would use if the encoding type were set to "multipart/form-data".

Source: Mozilla Developer Network

This was actually one of the first things I had tried. Until I learned from a classmate (thank you, Gordon) that I was simply using it wrong! The code was actually very close to what I tried,  but I was missing two key pieces of the puzzle.

For everything to work, I had to set processData and contentType both to false inside of the Ajax call.

So this is what the working code looks like now:

function attachFormListener() {
  $( "form" ).on( "submit", function(e) {
    e.preventDefault();
    let url = $(this).attr('action');

    $.ajax({
      url: url,
      type: 'POST',
      data: new FormData(this), // compile 'this form' into key/value pairs
      processData: false,
      contentType: false,
      success: function(response) {
        let artwork = new Artwork(response.artwork);
        let html = artwork.renderHTML();
        $('.artwork-new').html(html);
      }
    });
  });
}

 

After submitting the form this way, now params looks like this:

with-image-key

So with that, Paperclip can do its job and the resource can be created as normal and finally sent back to the client as JSON.

Conclusion

What I thought would be a simple feature to add, turned out to be a lengthy process leading to what felt like hours wasted. I remember at one point I almost gave up, and thought of satisfying the requirement in another way. However, I just couldn’t leave it alone, and I’m glad that I didn’t.

Although the solution ended up being very simple, further adding to that feeling of wasting so much time, I choose to look at this as just another learning opportunity on my journey toward becoming a web developer.

 

Resources:

Getting Acquainted With JavaScript

As I work through the JavaScript labs on Learn.co I have been confused with how to write proper JavaScript. What is the proper place for brackets? What about conditionals? Most importantly, what is the deal with this annoying semicolon? This is all more confusing since we are going through a curriculum that’s split between the last two versions of ECMAScript, ES5 (used on the older track) and ES6 (which the new track is based on).

In this  blog post, I aim to provide a brief guide for some of the more common things we’ll be dealing with when writing JavaScript. Keep in mind that everyone usually settles into their own style of programming, and this guide is only meant to assist with some of the lower level decisions such as when to use const vs. let.

The rules:

Use 2 spaces for indentation

Most style guides and code examples I come across follow this rule. This is something easy to take care of by going to the configuration settings of your chosen text editor.

Use single quotes for strings

The exception to this rule should be if you need to escape apostrophes or other quotes. Although not strictly enforced by the language, pick one preference and stick by it.

console.log('Hello world... Now in JavaScript!');
console.log("He's using double quotes to escape ' ");

Add space after keywords

// good
if (condition) { ... }

// bad
if(condition) { ... }

Brackets open on the same line

function sayHello(name) {
  console.log('Hello, ' + name);
}

Else, else if follow after closing bracket for the previous condition

// good
if (true) {
  // do something here
} else {
  // do something else
}

// bad
if (true) {
  // do something here
}
else {
  // do something else
}

Use parentheses for conditions

This is one where I wasted approximately 20 minutes in one of the early labs, all because I had been spoiled by Ruby’s friendly syntax.

Make sure to always wrap your conditions inside parentheses. I believe the only exception to this rule is when using the ternary operator, which in Javascript looks the same as in Ruby:

condition ? expr1 : expr2
       // if true : if false

Use === instead of ==

While the double equals operator has its uses, it’s better to be on the safe side and check for strict equality using triple equals to avoid some unintended behavior.

The == operator allows for type conversion before checks, while === checks for strict type equality.

'1' == 1; // true because '1' is converted to a number before comparison
1 == 1; // true

'1' === 1 // false because the types are different

Like in the above examples, use !== instead of != to check for non-equality.

Write each variable declaration in its own expression

// good
let a = 'hi';
let b = 'hello';

// not necessarily bad, but it's harder to follow
let a = 'hi', b = 'hello';

While the second example works, separating each variable assignment makes the code easier to read.

Const, let, or var?

ES6 introduced const and let as ways to declare variables. Prior to them, there was only the use of var. I’m still not 100% sure that my usage of these new identifiers is correct all the time, but I try to force myself to use them in any lab that supports ES6 as a way to practice their use.

In a nutshell, use const when the variable you’re declaring isn’t going to be reassigned. For example, the endpoint of an API. Otherwise, opt for let.

Both const and let are block scoped, meaning that they are only available within the block they’ve been declared in.

Avoid using var. According to Eric Elliot:

`var` is now the weakest signal available when you define a variable in JavaScript. The variable may or may not be reassigned, and the variable may or may not be used for an entire function, or just for the purpose of a block or loop.

His point is that proper use of const and let is more expressive of what each variable is intended to do. Their use lets other developers know whether a variable is going to change or not later on in the code.

Arrow functions

Probably the biggest feature introduced in the ES6 specification are arrow functions. In fact, according to this 2015 article from 2ality, arrow functions topped the list as developers’ favorite JavaScript ES6 feature. And guess, what? The more I use them, the more I agree.

Arrow functions provide cleaner syntax and are especially handy as callback functions. Compare the following two examples:

// extracting names out of a json object

function extractNames(tracks) {
  return tracks.map( function(track) {
    return track.name;
});

// arrow function passed as callback to .map()
function extractNames(tracks) {
  return tracks.map( track => track.name );
}

 

$.ajax({
  url: url,
  dataType: 'jsonp',
  success: function(response) {
    callback(response);
  }
});

// arrow function passing response to the callback
$.get(url, response => callback(response) );

I know, I know, the second one is cheating a bit because of the switch to $.get() but the syntax would still be cleaner if you were set on using $.ajax() along with arrow functions.

Some key things to keep in mind when using arrow functions are:

  1. Parentheses are optional when there’s only one parameter
  2. A function with no parameters requires parentheses:
    () => { some code here }
    
  3. Arrow functions can have either a “concise body” or the usual “block body”. In a concise body, the return is implicit. When using a regular block body a return must be specified.
    var a = [
      "Hydrogen",
      "Helium",
      "Lithium",
      "Beryl­lium"
    ];
    
    var a2 = a.map(function(s){ return s.length });
    
    var a3 = a.map( s => s.length ); // return is implicit in this case
    
    source: <em><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" target="_blank">MDN</a></em>
    

Do use semicolons!

Okay, it seems these days this is more of a personal preference rather than a strict rule. Even a lot of the solutions to the labs omit the use of semicolons. The reason why it seems that semicolons are optional is because JavaScript uses something called Automatic Semicolon Insertion (ASI), which is a feature of the ECMAScript specification.

From the specification:

Certain ECMAScript statements must be terminated with semicolons. Such semicolons may always appear explicitly in the source text

But it goes on to state:

For convenience, however, such semicolons may be omitted from the source text in certain situations.

In order to avoid errors caused by a missing semicolon, I would highly encourage its use.

Linters

Tools like JSHint, JSLint and ESLint allow for safer coding with fewer errors. These are tools that check your code real-time and point out any possible mistakes or things that could cause issues.

They are available as plugins for most of the popular text editors. Just do a search for them using the plugin/package manager for your preferred editor.

Here’s an example of JSHint in action inside Atom:

screen-shot-2016-10-23-at-8-07-23-pm

As you can see, it’s a very handy tool to have so you can focus on the actual errors with your code, as opposed to errors caused by its syntax.

Conclusion

Just like Ruby, and I’m sure any other programming language, seems like there  is a lot to learn when it comes to JavaScript. I encourage you to at least skim through the resources listed below if you want more in-depth coverage of the topics discussed in this post. In addition, get acquainted with the Mozilla Developer Network. It is an amazing resource for JavaScript documentation.

Hopefully, this short guide provided an introductory primer to those who are brand new to the language.

 

Resources

http://www.bradoncode.com/blog/2015/08/26/javascript-semi-colon-insertion/

Semicolons in JavaScript: A preference

JavaScript Standard Style

var, let or const?

exploringjs.com – Arrow functions

Keep Application Secrets A Secret With Figaro

As web developers, we will most likely come across the need to use third-party services in the apps we create. These services typically require us to access them with our credentials. For example, username and password for a Gmail service, or in the case of using a gem like Omniauth, an application and secret ID.

The problem is that we don’t want to include those credentials in our actual app if we’re going to be pushing code to an open-source Github repository, where others can see this sensible information.

It wasn’t too long ago that I presented my Sinatra assessment, which included mail sending functionality. Although I tried taking precautions against showing everyone my credentials for one of my Gmail accounts, mistakes were made, and the entire class was able to see my information. Newbie mistake…

Going through the Omniauth labs, I was introduced to the concept of environment variables. These are variables that you can set in your environment and then can reuse throughout your app. For example, using the ominauth-github gem requires the following:


# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :github, ENV['GITHUB_CLIENT_ID'], ENV['GITHUB_SECRET']
end

view raw

example1.rb

hosted with ❤ by GitHub

From the Readme for that lab:

The ENV constant refers to a global hash for your entire computer environment. You can store any key value pairs in this environment, so it’s a very useful place to store credentials that we don’t want to be managed by Git or stored on GitHub (especially if your GitHub repo is public). The most common error we see from students here is that when ENV[“PROVIDER_KEY”] is evaluated in the initializer it returns nil. Then later when you try to authenticate with the provider you’ll get some kind of 4xx error because the provider doesn’t recognize your app.

To set the environment variables we add them as keys to the ENV hash by typing the following into the terminal:

$ export GITHUB_CLIENT_ID=<your_key>

$ export GITHUB_SECRET=<your_key>

You can verify that it worked by jumping into the rails console and checking that ENV[‘GITHUB_CLIENT_ID’] and ENV[‘GITHUB_SECRET’] return your keys.

But being that we are in the Rails ecosystem, of course there’s a gem for that!

Figaro

Figaro is  a gem that makes it easy to create and manage environment variables. To use it you add the gem to your Gemfile, run bundle to update, and then run:

$ bundle exec figaro install

That command creates a new file: config/application.yml and automatically adds it to the .gitignore. You add your secrets to this file and you’re done! That simple.

Looking at the example above for using it with omniauth-github, application.yml might look like this:


# config/application.yml
github_key: '9pl129837ll2406n8765761'
github_secret: 'aaaaa04e56cca7887d0ab1c0809896876876bf76786'
# Add configuration values here, as shown below.
#
# pusher_app_id: "2954"
# pusher_key: 7381a978f7dd7f9a1117
# pusher_secret: abdc3b896a0ffb85d373
# stripe_api_key: sk_test_2J0l093xOyW72XUYJHE4Dv2r
# stripe_publishable_key: pk_test_ro9jV5SNwGb1yYlQfzG17LHK
#
# production:
# stripe_api_key: sk_live_EeHnL644i6zo4Iyq4v1KdV9H
# stripe_publishable_key: pk_live_9lcthxpSIHbGwmdO941O1XVU

view raw

application.yml

hosted with ❤ by GitHub

And now we can use those variables in config/initializers/omniauth.rb:


# config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :github, ENV['github_key'], ENV['github_secret']
end

view raw

omniauth.rb

hosted with ❤ by GitHub

Voila! Now your ultra secret keys can remain confidential.

Conclusion

As you can see, storing your credentials securely is actually simple with either the use of Figaro or local environment variables. There are other gems that accomplish the same task,but Figaro automates most of the process while providing a straightforward solution to  this common problem.

Keep in mind that Figaro has some extra features that I didn’t mention in this blog post because I haven’t had a chance or need to use them. Please make sure to visit the official repo located in the resources below for more information.

 

Resources

Figaro – Simple Rails App Configuration

Rails Environment Variables

Aliasing and Options in Rails ActiveRecord Associations

The Sinatra track on Learn.co introduced us to the powerful – and almost magical –  ActiveRecord ORM. ActiveRecord (AR) association methods simplify the process of creating the right links between our models by handling a lot of work behind the scenes. This allows us to focus on more important aspects of our apps, such as the logic and behavior.  However, these same association methods can become even more powerful once we start associating them with options.

Through the use of these options, we can come up with complex associations that give us access to more methods than we would otherwise have. All without needing to add too many extra models and/or extra tables to our app and database.

In this blog post, I hope to explain (while at the same time test my own understanding) of aliasing active record associations, and the use of options such as :class_name, :foreign_key, :through, and :source.

The domain we will be using contains User,Post and Comment models. Assume their associated tables have been migrated and the schema looks like this:

screen-shot-2016-09-13-at-11-36-54-pm
Database schema

 

Let’s get started!

A post belongs to a user, and a user has many posts


# app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :user
end
# app/models/user.rb
class User < ActiveRecord::Base
has_many :posts
end

WAIT! Didn’t we name the foreign key in the posts table as author_id? We don’t even have an Author model…

If we try to create an association between user and post, it won’t work:


post = Post.create(title: "Best Post Evaaaar!")
user = User.create(name: "Someone Important")
post.user = user
#=> can't write unknown attribute 'user_id'

So, let’s try to fix the association in Post:


# app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :author
end
# However, this now leads us to another error when we try the following:
post = Post.first # returns first record from posts table
user = User.first # returns first record from users table
post.author = user
#=> NameError: uninitialized constant Post::Author

This error lets us know that Post still doesn’t know what we are talking about.

Using the option :class_name

We can tell it what we are referring to with the option :class_name.


# app/models/post.rb
class Post < ActiveRecord::Base
# alias the user association as "author"
belongs_to :author, class_name: "User"
end

We are letting Rails know that when we call .author on a post, we want the return to be an instance of User. The above is what is referred to as an aliased association.

OK. But Why?

The beauty of aliasing as we did above, is that we don’t need to define a separate class – for example, Author and then have it inherit from User . We also don’t need another table in our database.

Now in Post, we want to make sure the User (aka, Author) has many authored_posts as an author . So we have to let the User model know what foreign key to use to find the right posts.

As you may have guessed, we accomplish that by using the :foreign_key option…


# app/models/post.rb
class User < ActiveRecord::Base
has_many :authored_posts, class_name: "Post", foreign_key: :author_id
end
# The above is an example of an aliased has_many association
# And thanks to it, we can now do the following:
jk_rowling = User.find_by(name: "J.K. Rowling")
jk_rowling.authored_posts
#=> [collection of posts by this particular author]

With the above we are telling Rails to go to the posts table and retrieve all posts that are associated with this user id, but to make sure to look for the id in the column named “author_id”.

The norm is for the foreign_key in the has_many table to be named after the model that it belongs_to. This means a user would be looking for “user_id” in the authored_posts table.

Note that more we use aliases, the more explicit we have to be with telling AR how things are actually associated.

Now let’s look at the Comment model, which on top of containing content, will act as a join table.


# app/models/comment.rb
class Comment < ActiveRecord::Base
belongs_to :commentor, class_name: "User", foreign_key: :user_id
belongs_to :post
end
# Without adding the foreign_key: :user_id we get the following error
# when trying to set a user as a comment’s commentor:
jk_rowling = User.first
comment = Comment.create(content: "Still 10 more books left in the Harry Potter universe!!!")
comment.commentor = jk_rowling
#=> ActiveModel::MissingAttributeError: can't write unknown attribute 'comment_id'

In order to complete the association between User and Comment, we need to say that a User has many Comment(s)…

Using the option :through


# app/models/user.rb
class User < ActiveRecord::Base
has_many :authored_posts, class_name: "Post", foreign_key: :author_id
has_many :comments
has_many :commented_posts, through: :comments
end

With that last addition, we can now say jk_rowling.comments, which will return a collection (array) containing all of the comments left by J.K. Rowling herself.

But what happens if we want to know about all the posts where J.K Rowling has left a comment?

As it currently stands, calling .commented_posts on an instance of User, results in an ActiveRecord error:


jk_rowling.commented_posts
#=> ActiveRecord::HasManyThroughSourceAssociationNotFoundError:
# Could not find the source association(s) "commented_post" or :commented_post in model Comment.
# Try 'has_many :commented_posts, through => :comments, source => <name>'. Is it one of commentor or post?

Look at that! ActiveRecord is nice enough to let us know where we are going wrong. It is trying to figure out which of the two models that a Comment belongs_to (commentor or post) represents a commented_post. What is the source of this association?

The :source Option

In order to fix the error, we have to do the following:


# app/models/user.rb
class User < ActiveRecord::Base
has_many :authored_posts, class_name: "Post", foreign_key: :author_id
has_many :comments
has_many :commented_posts, through: :comments, source: :post
end

We can read that last relationship as a user has many commented posts, through comments and the existing relationship between comments and posts.

With the above, we have basically created an extra join table, even though we didn’t hard code a join table for commented_posts into our database. However, because of the way the relationships are set up between these models we get to reap the benefits of one. What kind of magic is this!?

Another benefit of aliasing like we did above, is that we get to decide what we want to call this virtual join table. We can make sure our code still reads well.

Now we just need to complete the relationship that a post has many comments and many commentors by adding the following to Post:


# app/models/post.rb
class Post < ActiveRecord::Base
belongs_to :author, class_name: "User"
has_many :comments
has_many :commentors, through: :comments, source: :commentor
end

And thanks to the this we can ask a post for all its commentors using post.commentors

Conclusion

Although active record and all its magic can make a lot happen on its own, proper usage of these association options, along with aliasing can extend that functionality even more. Learning how to use these isn’t  easy at first (I am still struggling with it all), but I feel like it’s one of the better tools we can add to our tool belt as aspiring Ruby on Rails developers.
If you’re also struggling with this topic, I highly recommend checking out the links in the resources section below.
Lastly, I just want to point out that there is another syntax for using associations with options. It looks like this:
has_many :commented_posts, :through => :comments, :source => :post
I haven’t figured out which one adheres to best practices. Personally, I find it more readable and concise to do it the way I have coded the examples on this post.

Resources:

Rails Guides – Association Basics

Building a URL Shortener Using Sinatra

I’m not sure how to start this blog post, so I’m just going to say, maybe shout, scream the following:

WHOO! I ACTUALLY DID IT!

Image

As I approached the second assessment for the Flatiron School WebDev Fellowship, I didn’t have much confidence going in. For some reason, I had a lot of trouble grasping some of the new concepts and terms being introduced. Terms like actions and routes left me looking like this most of the time:

Image

Things didn’t get any better once I got to the final three labs leading up to the actual assessment. The names of those labs, Playlister, Sinatra NYC, and Fwitter will continue to haunt me for the foreseeable future – I’m sure of it. In fact, I didn’t even have to reference the curriculum to make sure I had their names right.

After spending a full day on Playlister (which was pretty much the case for the other two as well,) I felt completely defeated. My confidence took another hit and thoughts of not being good enough started to get a foothold in my head.

At the same time, I was brainstorming something to build. I knew I didn’t want to go for any of the domains we had been practicing during the Sinatra track. It was actually discouraged to do so in the instructions for the assessment.

And then it hit me… A URL shortener. If anything was going to test my understanding of actions and routes, this was as good a candidate as anything else. I took my inspiration from Bit.ly and TinyURL.com.

Keeping in mind that I was still struggling with the previously mentioned labs, I decided I was just going to build this as barebones as I could. Once it was successfully shortening a link, I didn’t care if the thing looked hideous. I just wanted to pass the assessment and finally, move on to Rails. Sinatra didn’t know it, but it was my sworn enemy!

Image

Goals

My original goal list looked somewhat like this:

  • A user can shorten a link. Period.

The first only bullet-point on that crazy list was to randomly shorten a long link. I wasn’t sure how to tackle that. My first instinct was that I’d have to use some RegEx, but I keep reading that programmers are lazy, so I decided to do my best impersonation of a good programmer and went to The Oracle for some advice…

Image

SecureRandom

While asking The Oracle (okay, it was Google) some questions, I came across SecureRandom, a Ruby library that felt like an answer straight from the programming Gods (if there is such a thing).

This library is an interface for secure random number generator which is suitable for generating session key in HTTP cookies, etc.

The ::urlsafe_base64 method was exactly what I needed. As the name suggests, it generates a random URL-safe string.

p SecureRandom.urlsafe_base64 #=> "b4GOKm4pOYU_-BOXcrUGDg"

You can shorten the output by passing lower integers as an argument.

p SecureRandom.urlsafe_base64(3) #=> "WtMt"

After getting that basic feature working, it felt like the project snowballed from there on. I decided to make use of user stories to plan out the rest of the application:

As a User, I should be able to:

  1. Have many links
  2. Add, edit, and delete a link
  3. Give a name (optional) to a link if I want to, for remembering what a link is about
  4. Be able to click on a shortened link and be redirected to the proper URL
  5. Be notified upon successful link creation, edition, and deletion
  6. Be notified upon successful signup and login/logout

Programming features 1-6 took me less than I thought they would. Apparently, things were clicking better than I thought, after all! A very barebones version of the app was fully working after just a few short hours.

I spoke to my one-on-one instructor, Antoin to run a few ideas by him and to get a sense whether or not the app would meet the requirements. He seemed excited about what I had so far, and actually sort of challenged (read encouraged) me to add some of the extra features I had in mind.

So the following two stretch goals got added to the features list:

  • Have a button to easily copy links without the need to select link text (Stretch goal #1)
  • Be able to easily share a link (Stretch goal #2)

Flash? In 2016?

Since I got my inspiration from Bit.ly, I went to check out how they  handled copying to the clipboard. To my surprise, they are using some obscure, ancient technology of days past. Something called Flash or something…

 

adobe-flash-animate-cc
Flash isn’t actually dead; it’s just renamed – Image Credit: THN

I was under the impression that HTML5 and JavaScript are working hard to make Flash obsolete, but it seems like it is the cockroach of the web – it just won’t die.

Clipboard.js

After getting the suggestion that I should be able to handle that feature using JavaScript (thanks again, Antoin,) The Oracle revealed Clipboard.js.

Image

This JavaScript library made adding the functionality for copying to the clipboard very straightforward. Even better, it was readily available via a few CDNs (Content Delivery Networks.)

Using it is simple. You add the following to the bottom of the view where you want that functionality:


<!-- Link to the jsDelivr CDN for Clipboard.js -->
<script type="text/javascript" src="https://cdn.jsdelivr.net/clipboard.js/1.5.12/clipboard.min.js"></script>

<!-- Below is the actual function that gets called when the button is clicked -->
<script>
 var clipboard = new Clipboard('.btn');
 clipboard.on('success', function(e) {
 console.log(e);
 });
 clipboard.on('error', function(e) {
 console.log(e);
 });
</script>

Then, you have to make sure to set a target in your HTML.


<button type="button" class="btn btn-success" data-clipboard-target="#link-id-<%= link.id %>">Copy to Clipboard</button>

The important part of the code above is the ‘data-clipboard-target=”#link-id-1″‘ which is what sets the target to link-id-1 in this case. As each link is created, embedded Ruby takes care of assigning the proper id for each target.

With that feature taken care of, I moved on to the second stretch goal of making links shareable…

Sinatra and Pony

Reading through the Sinatra FAQs, I came across Pony, a gem for handling sending of emails from a Sinatra application.

Its usage is easy, we can send parameters from a form via a POST request, and then handle the actual sending of the email from the corresponding action in the controller.

The code in the controller looks like this:


# Action for handling sharing via email, using Gmail
post '/email' do
Pony.mail ({
:to => params[:send_to],
# :from => params[:send_from],
:subject => params[:subject],
:body => "#{params[:link]}\n\n#{params[:email_body]}",
:via => :smtp,
:via_options => {
:address => 'smtp.gmail.com',
:port => '587',
:enable_starttls_auto => true,
:user_name => 'gmail-account-name', # in this case my Gmail account
:password => 'some-password', # as well as my Gmail password
:authentication => :plain, # :plain, :login, :cram_md5, no auth by default
:domain => "localhost.localdomain" # the HELO domain provided by the client to the server
}
})
redirect '/'
end

One problem that I ran into while working on this functionality was that I had to provide credentials for Gmail to be able to send email from my account. Another thing is that the password is currently visible. I have chosen not to push this part of the code to GitHub until I learn more about storing API keys and other personal data in a way that won’t be a security risk.

Rucchi and Alex both mentioned a gem that can handle all that, which basically automatically adds files and folders you specify to the .gitignore file. However, I felt like for the time being, I just wanted to prove to myself that I could get the app working the way I wanted to – and I feel I accomplished about 95% of it.

Conclusion

One feature that I still want to figure out is how to make the modal that displays the email form automatically populate the link field so that a user doesn’t have to copy/paste the link. Maybe for version 2.0.

All in all, this project was incredibly fun to build. I thought I hated Sinatra, but looking back, I think it was all a simple misunderstanding. Going through this assessment, provided me with a thrill while coding that I haven’t had while going through the labs, or even the first assessment.

The hours seemed to fly by, and bugs and issues were actually something I cherished. They meant there was some more work to be done. More knowledge to be gained. (Also special thanks go to Raycent for his amazing ability to break my app in all the ways I couldn’t think of. It forced me to make the app that much better.)

At the moment, I’m feeling pretty good. I know the feeling probably won’t last more than a week until I run into another difficult lab that makes me feel like I’m one of the stupidest humans all over again. But for now I’ll just let Drama convey how I feel:

Image

A Simple Way to Get a Date Using Ruby

date-time

One of the early labs in Sinatra that I was working on yesterday requires that you make a route for /date, which will write the current date to the web page when a request is made to http://somegreaturl.com/date. Thanks to this lab’s readme, I learned about a new Ruby library for working with time and date. That library is called DateTime.

I immediately remembered struggling with the Time class in one of the very early labs where the date and time had to be outputted in a very specific format.

Previously, if you asked me to output the current date as Friday, August 5, 2016, I would have done something like this:

days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
"Friday", "Saturday"]

# Setting first index to nil for easier match with return from
# Time.month (1-12)
months = [nil, "January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"]

time = Time.new
year = time.year
month = months[time.month]
weekday = days[time.wday]
day_of_month = time.day
hour = time.hour
minute = time.min

puts "Today is #{weekday}, #{month} #{day_of_month}, #{year}"
#=> Today is Friday, August 5, 2016

Little did I know that both the Time class and DateTime can make this task almost trivial.

easy button

Enter #strftime and Time Formatting Directives

Both Time and DateTime have a variety of methods for working with time, but the #strftime method is one I found particularly useful and one that I know I’ll make use of anytime I need to work with either date or time from here on.

This method takes in a string as an argument, which allows you to be very precise with how the date/time will be formatted. Within the string argument, you use % signs coupled with different letters, to target individual parts of the current date and/or time. These are called time formatting directives.

These formatting directives provide many options for formatting in pretty much any way you would want to. For example, here are some of the things you can target individually if you want to work with dates (year, month, day):

Date (Year, Month, Day):
%Y - Year with century (can be negative, 4 digits at least)
-0001, 0000, 1995, 2009, 14292, etc.
%C - year / 100 (round down. 20 in 2009)
%y - year % 100 (00..99)

%m - Month of the year, zero-padded (01..12)
%_m blank-padded ( 1..12)
%-m no-padded (1..12)
%B - The full month name (``January'')
%^B uppercased (``JANUARY'')
%b - The abbreviated month name (``Jan'')
%^b uppercased (``JAN'')
%h - Equivalent to %b

%d - Day of the month, zero-padded (01..31)
%-d no-padded (1..31)
%e - Day of the month, blank-padded ( 1..31)

%j - Day of the year (001..366)

Using the above, we can replicate the output from earlier like this:

DateTime.now.strftime("Today is %A, %B %d, %Y")
#=> "Today is Friday, August 05, 2016"

Notice that this time, we can be much more specific with how we want to format the date, and also, that we are working with a string. This means we can easily change the return.

DateTime.now.strftime("Today is %a, %b%e, %Y. Current time: %T %p")
#=> "Today is Fri, Aug 5, 2016. Current time: 09:25:05 AM"

 

What’s the Difference Between DateTime and Time?

After learning about DateTime, I went back to the Time class documentation and realized I just never went through all of its available methods. Funnily enough, Time has access to the same #strftime method! So what is the difference between the two? When should you use one over the other?

Well here’s an excerpt from an answer to just such a question posted on Stack Overflow:

Newer versions of Ruby (2.0+) do not really have significant differences between the two classes. Some libraries will use one or the other for historical reasons, but new code does not necessarily need to be concerned. Picking one for consistency is probably best, so try and mesh with what your libraries expect. For example, ActiveRecord prefers DateTime.

Apparently, they can be used interchangeably unless you’re using a library that expects or prefers a specific one.

 

Conclusion

Formatting date and time should now be much easier thanks to #strftime. Thanks for reading.

 

Resources

Main Takeaways From Building a CLI Gem

The first assessment from Learn.co had me build my own CLI gem using everything I had learned up to that point. I teamed up with another student, Raycent Tan, who had an idea for a gem that would gather stock market information from the top industries, as well as be able to access individual companies. Although relatively simple, the main usage for the gem would be to be able to display useful information to aid researching possible investments.

The whole process took us about 3 days and we hit our share of roadblocks while trying to build this project. Nothing came easy, and there were plenty of learning moments. The following are my personal takeaways from going through it all.

Using Gems to Build Gems

I thought building a simple gem would require little effort and that we would be able to accomplish the task by writing all of the code ourselves. However, we came across  some useful gems that simplified and sped up our work.

We needed a solution to deal with JSON data, both for making the request, as well as returning the information in the right format. That’s when I came across HTTParty. This gem makes it extremely simple to make a request to an API and working with JSON all at once.

Another gem that proved extremely useful was Command Line Reporter. This made it almost trivial to display our output as we wanted in a structured table format. In addition, it has support for adding colors to your tables, which was a nice extra feature. We took advantage of this by displaying positive changes in industries in a green color while using red for negative numbers.

Git and GitHub – Learn the Flow

Even though I make use of Github every day while going through the Learn.co labs, it wasn’t until collaborating on this project that I really began to see the beauty that is Git.

During our coding sessions, we pushed a few times a day and made sure our work was always backed up. The feature that I came to enjoy the most while using Git was branching. After the first day, we already had a working version of the gem, albeit a very barebones version. From that point on, I started creating branches to work on things like formatting the output and debugging issues.

Branching always seemed like such a simple concept to understand, but it wasn’t until I made use of it that I finally see the flexibility it allows.

Merging branches, however, is another topic. We did not feel confident with the merging process and we were apprehensive about trying to merge our features and debugging branches into our master. The solution was for me to create a test-merge branch to merge Raycent’s code and my code into, and if all went well, then we’d simply merge that into the master. We ended up with some merge conflicts which I cleaned up on the text editor and then was able to seamlessly merge into the master branch.

Lesson learned here: more practice with branching and merging is required!

Using an API versus Scraping

Before getting the project underway, my pair and I debated whether we should use .csv’s downloaded from Yahoo! Finance, scrape for the information, or just use an API. We decided against scrapping because working with Nokogiri elements can get overly confusing. I’m not sure if it’s just me, but working with Nokogiri elements feels rather counter-intuitive. Or maybe I just need more practice with it…

The other option, using .csv files had us wondering where we would store the data downloaded, and how we would handle reading from .csv’s. We thought we’d have to make use of Ruby’s File class. It wasn’t until we were finished with the project that we found out there’s an actual class in Ruby to handle CSV’s.

In the end, we opted to go with using an API. I had some prior experience of working with one and suggested we go that route because of how simple it is to work with JSON data.

Big mistake!

Finding a financial API was much more difficult than we’d originally thought it would be. It turned out that Google Finance had shut down their API a long time ago, and Yahoo! Finance wasn’t officially supporting their own anymore. The API we were using via the YQL (Yahoo! Query Language) was unstable. This caused all sorts of headaches and issues while trying even the simplest requests from it.

There were times when the API would work flawlessly, and return all the data we asked from it; Othertimes it would become unresponsive and had us going through our code with a fine-tooth comb as if that was the problem.

We dealt with the issue to the best of our ability by making multiple successive requests every time any of the fields we were targeting returned with a value of nil.

Conclusion

Thanks to this project, I have learned my lesson, as I’m sure my partner did as well – never willingly work with an unsupported, unstable API if we can avoid it! I believe if we had to do the project over, we’d rather deal with Nokogiri.

At least it would be consistent in returning XML objects that sort of behave like arrays, but aren’t really arrays – yet still, accept array methods…

The Quirks of Ruby Method Arguments

As I make my way through the learn.co curriculum as part of the Web Development Fellowship, I find myself supplementing the content with various resources. Currently, I’m slowly reading through The Well-Grounded Rubyist (TWGR) by David A. Black in an effort to get more comfortable with the language.

While reading chapter 2, which is titled “Objects, methods, and local variables”, there was something that stood out to me… Apparently method arguments are more complex than they appeared at first glance. It turns out there is a specific order, as well as certain rules that apply when supplying parameters during a method definition. Read on for a beginner-friendly overview on the behavior of method arguments.

Required and Optional Arguments

During method definition, you can make arguments required by simply supplying a parameter for it. If you provide more (or less) arguments than the number required, Ruby will throw up an error:

example1

This is Ruby’s way of letting you know you have provided too many arguments. The #awesome_method needs to be provided exactly one argument for the method to work.

Just like you can require a predetermined amount of arguments, you can also make them optional. To accomplish this all you have to do is provide a default value for any parameters you want to make optional. This is done during the method definition like so:

example1

As you can see, when we call #greet_programmer without an argument, the default value is used for the name parameter.

The Splat Operator

The what operator? Yes, that’s what I thought as well when first introduced to an asterisk placed before a parameter.

example4
This example is not from the actual lab on Learn.co

Although I was able to pass that particular lab on Learn, the Ruby splat still felt like a complete mystery. It wasn’t until going through this chapter of TWGR that I finally gained more of an understanding as to what it’s actually happening.

In a nutshell, the splat allows you to include any number of arguments in a method. Mr. Black uses a sponge metaphor to explain its behavior – the splat sponges up any remaining, non-required arguments, and turns them into an array.

Using p instead of puts shows that arguments refers to an actual array:

example5

Mixing And Matching – What Gets Assigned To What?

This is where things start to get a bit more complicated (read interesting). When you mix required with optional arguments, how do you know what argument is getting each value? Well, there is a specific order that arguments must follow for Ruby to make sense of everything that’s happening.

example6

In the above method call, you can see a and b were required arguments, and therefore, got assigned the first two values of “apple” and “banana”; *c took the rest of the arguments and turned them into an array as expected.

But what about when you have the following:

example7

Notice that this time after a and b receive their required values, *x only gets two values – “grape” and 15 – while y gets the last value passed in.

In addition, if we take this same example a bit further:

example13

Passing two values and mixing in a default value for b makes things more confusing. This time, there are just enough values to satisfy all the requirements that will allow the method to still work.

The argument assignment for the above call on #mix_and_match goes like this:

variable_assignment

If you pass only one argument to #mix_and_match as coded in that last example, Ruby throws up the following error:

terminal error

Order Please!

While it looks like you can do almost anything mixing and matching required and optional arguments, the reality is that there is one rule you must always follow – pay attention to the order of optional parameters and default value parameters in your method definition.

The main thing to keep in mind is that default value parameters must come before optional parameters. Otherwise, Ruby responds with a syntax error.

correct_vs_incorrect - example 10

terminal error 2

If you think about it, it doesn’t make much sense to have an optional argument before the one that carries a default value. Just like it doesn’t make sense to have more than one splat operator in your argument list.

The order in which Ruby assigns priority to arguments goes like this: required arguments get assigned first, regardless of whether they are on the left-end or right-end of the argument list, and are followed by optional arguments taking up anything that is left in the middle.

Hopefully, this post was helpful in any way! Comments are welcome!