Skip to content

Instantly share code, notes, and snippets.

@AlanBreck
Last active October 25, 2016 00:43
Show Gist options
  • Save AlanBreck/b7c44e7e1ab87a6ea6765e61227b990f to your computer and use it in GitHub Desktop.
Save AlanBreck/b7c44e7e1ab87a6ea6765e61227b990f to your computer and use it in GitHub Desktop.
Answers to sample Bloc student questions.

Javascript

Hi Student,

Your problem is one of scope. The question you have to answer is what is the value of btnNum when the onclick function is called.

Consider the following example:

var foo;

for ( var i = 0; i <= 3; i++ ) {
  foo = i;
}

console.log( foo ); // what is the value of foo?

Without running the code, what would you expect the value of foo to be? Try to reason this through before going on.

So, in the example above, we've declared a variable (var foo;) in the "global" scope (in other words, we haven't defined any scope other than the scope of the context in which we're working - if that sounds overly technical, don't worry about it for now). Then you're running a for loop which will iterate 4 times (since i starts at 0, it will go 0, 1, 2, 3). At each iteration, we're reassigning the value of foo to the most current value of i.

The following code example:

for ( var foo; foo <= 3; foo++ ) {
  // run some code
}

...could also be expressed as follows:

var foo = 0;

for ( ; foo <= 3; foo++ ) { // ignore the semi-colon, for now
   // run code
}

console.log( foo );

What would you expect to be output to the console in the above example?

The result would be 4, and here's why...

During the first loop, our computer asks, "Hey, is foo greater than or equal to 3?". Since foo is 0, at this point, it runs the code and increments foo to 1.

This process repeats three more times until foo is incremented to 4.

At this point, when our computer checks to see if foo is greater than or equal to 3, it returns false and stops iterating, but foo is still set to 4.

The fact that foo is still set to 4 is crucial to solving your problem.

Using the var keyword in the for loop, your btnNum variable is actually being declared in the "global" scope just like the foo variable in our example above. This being the case, when your onclick function reaches out to find the value of btnNum (prizes[btnNum]), it gets 3 since that was the that was the last increment for btnNum in your for loop. There is no index 3 in your array, thus your alert returns undefined.

In order to solve your problem, you have to properly "scope" the btnNum variable. This can be done in one of several ways...

  1. ES2015 (the newest spec for JavaScript) gives us the let keyword for declaring "block scoped" variables which means that the following would make btnNum scoped to your for loop and not the "global" scope: for ( let btnNum = 0; btnNum < prizes.length; btnNum++ ). Further reading: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
  2. The let keyword is widely supported in modern browsers, but a non-ES2015 way would be to use the .bind() method. An oversimplification of what .bind() allows you to do is pass arguments into a function without calling it yet. Read more here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind. Here's an example of how you could do that:
for ( var foo = 0; foo <= 3; foo++ ) {
  document.getElementById( /*some id*/ ).onclick = function ( foo ) {
    // some code
  }.bind( this, foo ); // "this" is a discussion for another day
}

I would love to talk with you more about this during our next session if you have any questions. I'd encourage you to read the following: https://github.com/getify/You-Dont-Know-JS/blob/master/scope%20&%20closures/README.md#you-dont-know-js-scope--closures. Don't worry if you don't understand everything, just try to follow the logic as best you can, and write down any questions you have along the way.

Best wishes!
– Jacob


Rails

Hi Student,

So, has_one, has_many, has_one :through, and has_many :through all have to do with defining relationships between your data models. In the case of both has_one :through and has_many :through, :through is there to say that the connection between two data models is defined by a third model.

Let's say we're modeling out the data structure for a university system:

We'll have the following data models:

  • University
  • College
  • Building
  • Janitor
  • Course
  • Professor
  • Student

Typically, a university has multiple colleges, so that will be a has_many relationship. The tables could look something like this:

universities

id name
1 LearnALot U

colleges

id name university_id building_id
1 College of Pyrotechnics 1 1

Since the colleges table contains the university_id, there's no need for a third model, so it's simply a has_many relationship.

Now, each professor has multiple courses and each student has multiple courses. Our professors, courses, and students tables could look like this:

professors

id name
1 Left Ear

students

id name college_id
1 Wesley Crusher 1

courses

id name professor_id student_id
1 Basics of Implosion 1 1

Now, we want to be able to see which professors any given student has, and which students any given professor has. Since neither the students nor professors tables contain the ids for the other, we'll need a has_many :through relationship with the Course model as our connection. So, for example, the professor class could look like this:

class Professor < ApplicationRecord
  has_many :courses
  has_many :students, through: :courses
end

The same principle can be said for the has_one :through relationship: if the relationship between two models can't be made using those two models alone, you'll need to use through.

Being a small university, each college only has one building and each building only has one janitor. Let's say you wanted to find the janitor assigned to a given college. Well, the colleges table doesn't store a janitor id, but it does store a building id, and the buildings table stores a janitor id:

colleges

id name university_id building_id
1 College of Pyrotechnics 1 1

buildings

id name college_id janitor_id
1 Building A 1 1

janitors

id name building_id
1 Vincent Freeman 1

Therefore, we can use a has_one :through relationship, using our Building model as the connection, to find which janitor is assigned to any given college. Our college class could look something like this:

class College < ApplicationRecord
  has_one :building
  has_one :janitor, through: :building
end

Hope this helps!
– Jacob


SQL

Hi Student,

I'm glad the lecture was helpful!

SQL injection is when SQL code is inserted into a SQL statement where it was not intended. This typically happens in a web form, of some sort, where a user is able to enter a value into a text box and that value is then inserted into a SQL statement which then gets executed. A general rule of thumb is that user input through forms should always be viewed as a potential vulnerability. Obviously, this doesn't mean you avoid user input altogether, but it's important to make sure doing so doesn't compromise your security.

An obviously dangerous situation would be SQL statements which interact with a users table containing passwords, etc. I'm going to borrow an example from an article which I'd recommend you read: http://www.w3schools.com/sql/sql_injection.asp. Let's say you have a login form with a Username field and a Password field. Behind the scenes, you have a SQL statement which will contain the values from those two fields once the user submits the form:

$username = $_POST("Username");
$password = $_POST("Password");

$sql = 'SELECT * FROM users WHERE username ="' + $username + '" AND password ="' . $password . '"'

If your code doesn't validate the input, in some way, a hacker could submit a value like " or ""=" (""="" will always return true). The resulting SQL statement which will get executed with that input would be SELECT * FROM users WHERE username ="" or ""="" AND password ="" or ""="". In other words, select all fields for each row in the users table where the username is blank ("") or where "" equals "". Well, "" will always equal "", thus all rows will be returned and and provide the hacker with all of your users' credentials. Not good.

The best way to avoid this is to rely on your framework's or language's methods to build and execute SQL statements. In Ruby on Rails, your base class to use is called ActiveRecord.

Let me know if you have any further questions!
–Jacob


Angular/jQuery

Hi Student,

Great question! The classification for the various tools in JavaScript can sometimes be fuzzy due to what they're capable of doing, how people talk about them/use them, etc. So while there is some overlap, a basic difference between a library and a framework is that while a library gives you a bunch of different tools that you can use in a whole bunch of different ways, a framework is giving you a more opinionated structure with which to build your website, web app, etc.

By opinionated, I mean that a framework not only gives you the tools, but cares about how you use those tools and structure your app. Angular, for example, is an MVC - Model, View, Controller. A lot more could be said here, but with an MVC framework, the decision of how to structure code is made for you: the model is the "layer" that interacts with your database and prepares your data for use in the app. The view is the "presentation" layer – in other words, it's the code that gets presented to the user (so that's where your HTML templates go). The controller is kind of the "central command" for the app – responding to requests (like submitting a form, or navigating to a new page) and then determining what needs to happen next, like fetching data through the model layer, or serving up a new view.

So, in terms of the drawbacks/benefits, it's somewhat apples and oranges. A good rule of thumb, though, is to start with the most minimalistic approach and add complexity (like an MVC) as needed. If you're just building a simple little static website with no database, you can probably get away with just using jQuery (or vanilla JavaScript, for that matter). But if you're building a more complex website or app with a database and multiple pages, an MVC will provide consistent, more maintainable structure, whereas something like jQuery would be too "loosey goosey" for a complex, scalable app.

Let me know if you need further clarification!
– Jacob


CSS

Hi Student,

Your primary need in this example is something called a clearfix hack. When floating child elements within a parent element, the parent element will often collapse since the float makes it as if the child elements no longer exist (or at least don't take up any space). What you need the parent element to do is "self-clear" it's children. There are multiple snippets to do this, but essentially you need to include a utility rule in your CSS, like the one below, and apply it via a class to parent elements with children that are floated.

<style type="text/css">
	.clearfix:after {
		content: "";
		display: table;
		clear: both;
	}

	.child {
		float: left;
	}
</style>

<div class="parent clearfix">
	<div class="child"></div>
	<div class="child"></div>
	<div class="child"></div>
</div>

Read more about floats and problems with floats here: https://css-tricks.com/all-about-floats/

Another problem that you'll want to address is in the rule for .pricing:

.pricing {
  width: 100%;
  padding: 20px;
  background-color: tomato;
}

When you have width: 100%; and padding: 20px;, that's adding an additional 40px to the width of 100%. Setting the width to 100% is actually unnecessary, in this case, and I would recommend removing it.

Hope this helps!
– Jacob

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment