Skip to content

Instantly share code, notes, and snippets.

@pepesenaris
Last active July 7, 2018 19:54
Show Gist options
  • Save pepesenaris/2c19d185a56bb4f1eefaccc853dc16fd to your computer and use it in GitHub Desktop.
Save pepesenaris/2c19d185a56bb4f1eefaccc853dc16fd to your computer and use it in GitHub Desktop.
Thinkful assestment

JavaScript

This is a good example of the fact that most of our Javascript code is not executed in the moment is "read" by the browser rather than at some point later in time, usually as a callback triggered by a browser event or user interaction.

The problem here is that each loop interation defines a new function but each function share the same scope. Let's consider scope as the set of variables that are accesible from a piece of code, for example the function body in this case.

Given how Javacript works we are able to use the btnNum variable that was declared in an outer scope, ie outside the function. The tricky part is that each function points to the same btnNum variable and when those functions are executed, the btnName always holds the same value. In this case the value is 3, which is not a valid offset for the array of prizes, so we obtain undefined as a price.

The key here is to remember that functions in Javascript define a new scope and we can treat functions as any other primitive values such as integers or strings. This means we can assign functions to variables and also return them from other functions.

A common pattern that can help is:

  • Create a function A to define a new scope.
  • Return a function B that performs the work.
  • Execute function A passing the values we need to "remember".

This is commonly known as Immediately-invoked Function Expression or simply IIFE.

I'll add an example of how I would solve the problem but I'll encourage you to try it yourself first:

SPOILER ALERT AHEAD

for (var btnNum = 0; btnNum < prizes.length; btnNum++) {
      document.getElementById('btn-' + btnNum).onclick = (function (index) {
      // Here each function has its own scope, so index will be always a different value
        return function () { // This is the function that does the actual work and is assigned as the onclick event handler 
          alert(prizes[index]);
        }
      })(btnNum); // By inmediatly executin the function and passing the btnNum variable we can remember the correct value
    }

Rails

The has_many :through form is recommended for many-to-many associations over the similar has_and_belongs_to_many. Using has_many :through allows us to defined a join table for a many-to-many relation and adding columns to that new entity, which is a common case.

Take for example:

 class Doctor < ActiveRecord::Base
  has_many :appointments
  has_many :patients, through: :appointments
end

class Appointment < ActiveRecord::Base
  belongs_to :doctor
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  has_many :appointments
  has_many :doctors, through: :appointments
end

Here we can express the fact that a doctor A may have 3 patients B, C, D but each of those patients can have many other doctors as well, given that the relationship is recorded in the appointments table as different rows. The Appointment model allows us to add extra information, unique to a pair of Patient and Doctor, for instance the date of the next meeting.

By simply using has_many we loose flexibility for future changes in the codebase, ie we won't be able add/remove data in the intermediate model, and can not be as precise when modelling an scenario where the relation between entities is not exclusive.

Regarding has_one :through, this can be useful to easily reference the inverse relationship. For example if we have

 class Doctor < ActiveRecord::Base
  has_many :clinics
  has_many :patients, through: :clinics
end

class Clinic < ActiveRecord::Base
  belongs_to :doctor
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  has_one :clinic
  has_one :doctor, through: :clinic
end

A Patient can have a single doctor assigned in his Clinic, but we still have the ability to work with all the Patient of a the same Clinic that belongs to the same Doctor.

SQL

For the most concise and funny SQL injection description ever check this xkcd comic. Otherwise keep reading below... :-)

SQL injection refers to a common attack made in web applications backed by a SQL database, where a malignant user tries to execute SQL code that does not belongs to the application in order to gain access or corrupt the data.

It typically works by adding pieces of SQL to input data provided by the user, for instance given a query that looks for a specific username:

"SELECT * FROM `users` WHERE `username` = '$name'";

If the user input is blindly added to the query, an attacker could send a string with an empty username followed by a 2nd SQL snippet that deletes the users table:

"SELECT * FROM `users` WHERE `username` = ''; DROP TABLE `users`";--";

The simplest way to prevent SQL injection attacks is to AVOID mixing SQL code and user-input data. For example, the above query written with SQL prepared statements read like this:

"SELECT * FROM `users` WHERE `username` = '?'";

In this case the database knows it expects a single value and will throw an error with a malicious SQL code payload.

The most popular programming languages, libraries and frameworks provide battle-tested tools that follows best practices to avoid SQL injections attacks. For example Ruby on Rails applies built-in filters for special SQL chars like ',' or 'NULL' so a query generated using Rails will automatically sanitize its inputs values.

User.where(login: entered_user_name, password: entered_password).first

React/jQuery

React is a library and Angular is a framework. A library goal is to solve a specific problem so it usually has a small size and less functionalities when compared to a framework, which is usually composed of many libraries that work together to solve a bigger problem. According to the official documentation React is A JavaScript library for building user interfaces so it focus on how to render a User Interface using a declarative component based approach leaving other concerns such as how to get data from an external source or how to organize your project file structure to the programmer.

React and jQuery solve different problems. jQuery provides a group of functions to manipulate the DOM, easing out browser inconsistencies, plus some handy utilities, for example to perform AJAX requests. On the other hand React only generates HTML.

If the goal is to enhance a site with a few interactive snippets of JS probably jQuery is the best choice. On the advantages of React is that the view (your HTML in this case) becomes a function of the state. Consider state as all the data that the user sees and interacts with in the application. When the complexity of the app logic grows, React gives us an easier to use way to express how the application should look like given the current state of the app, as opposed to jQuery that mingles together DOM nodes with the app state.

Algorithms

Big O notation is a mathematical model used to describe the complexity of an algorithm, in terms of amount of operations (running time) or memory space, according to the size of the input. In that sense an algorithm does not use a notation rather than we select one of the possible notations to analyze the behavior of the algorithm. When it comes to Big O, it gives us an idea of the worst case scenario of the algorithm performance.

Let's see a couple of examples.

An algorithm that search for a value in a list.

bool ContainsValue(IList<string> elements, string value)
{
    foreach (var element in elements)
    {
        if (element == value) return true;
    }

    return false;
}

In this case the element could be the last one in the list, so we need to iterate over all the elements to find out wether the value is present or not. As the amount of items in the list grows, the number of steps needed to find an answer grows linearly with the size of the list, hence this algorithm is O(n).

If we are trying to find a duplicate of an element in the list we can proceed like this:

bool ContainsDuplicates(IList<string> elements)
{
    for (var outer = 0; outer < elements.Count; outer++)
    {
        for (var inner = 0; inner < elements.Count; inner++)
        {
            // Don't compare with self
            if (outer == inner) continue;

            if (elements[outer] == elements[inner]) return true;
        }
    }

    return false;
}

Here we have a couple of nested loops that iterate through the full list of elements. Again in the worst case (only the last item is duplicated) we need to do NxN comparisons to finish the algorithm. For a list of size 2 we need at most 4 comparisons, for size 4 we could need 16 operations and so on. The complexity of the algorithm grows proportionally to the square size of the list size. In this case we have a O(n^2) complexity

CSS

In order to properly place the content it's easier to use CSS flexbox properties. Let's see in details:

a) We can remove the explicit width of the .pricing section and define a flex container with centered children:

    display: flex;
    justify-content: center;

b) The previous step allows us to remove the margin and width properties from .pricing-tiers that were causing an horizontal scroll to appear. We can ensure that the content in .pricing-tiers is shown horizontally by setting:

  display: flex;
  flex-direction: row;

which allows us to remove the float: left in .tier class.

c) To fix the missing margin in the last .tier we simply remove the corresponding rule:

  .pricing-tiers>.tier:last-child {
    margin-right: 0px;
  }

Finally we can remove the bullets from the list items and adjust paddings/margins in the .tier boxes.

.tier ul {
  list-style: none;
  padding-left: 0px;
  margin: 0;
}

.tier {
  padding: 5px;
}

.tier h1 {
  margin-top: 0;
}

The full styles are:

<style>
    header {
      width: 100%;
      height: 60px;
      background-color: #333;
    }

    .pricing {
      padding: 20px;
      background-color: tomato;
      display: flex;
      justify-content: center;
    }

    .pricing-tiers {
      display: flex;
      flex-direction: row;
      background-color: #ddd;
    }

    .pricing-tiers .tier {
      width: 260px;
      margin: 20px;
      padding: 10px;
      background-color: white;
    }

    .tier {
      padding: 5px;
    }

    .tier h1 {
      font-family: "Helvetica", sans-serif;
      font-weight: bold;
      font-size: 2em;
      margin-bottom: 20px;
      margin-top: 0;
      text-align: center;
    }

    .tier ul {
      list-style: none;
      padding-left: 0px;
      margin: 0;
    }
  </style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment