SQL Query Strings with Node.js

PHP was my backend language of choice before I became interested in Node.js.  PHP has some wonderful ways to interact with SQL such as PDO (PHP Data Objects).  In addition, it is easy to pass literal strings as query strings to the SQL implementation of your choice using libraries such as MySQLi and MSSQL.  My favorite part of using PHP with literal strings is that the literal strings can span multiple lines, making it easy to write neat and tidy queries.

Obviously, this example is trivial, but if you have spent any time writing SQL queries I am sure you can imagine a scenario where your SQL query might be much longer.  If you have to put everything on the same line your query will eventually become a spaghetti string of unreadable code that requires endless amounts of scrolling left and right to read in its entirety.  Before you know it, you will be back at the doctor asking them to prescribe whatever drug it was they gave you to help cope with the trauma of miles long HTML snakes produced by MS FrontPage 2003.

By now you are probably wondering, what does this have to do with Node.js?  Well, unlike PHP, JavaScript cares about where you put your line breaks, and you can’t pass a query string like the $tallQuery example from above.  Instead, you need to join your strings with the infix operator, also known as the plus sign.

In the first example, I try to apply PHP practices to JavaScript and I am rewarded with a syntax error.  In the second example, I succeed in creating a valid multi-line query.  This is certainly more readable than a big long query, but I can’t help but feel that it sucks in my heart of hearts.  The infix operators are inconvenient to type, and now I have to worry about properly concatenating my strings, which is also inconvenient and less robust as I could forget one and cause the app to fail with another syntax error.

This small hiccup nearly ruined Node.js for me.  It just seemed so silly.  I wasn’t alone either, and a number of libraries were created to work around it.  One of my favorites is Squel, which allows you to build query strings by stringing together a series of functions prefixed the dot notation.  Check out the link to see what I mean.  Amusingly, when Squel was introduced on r/javascript back in 2013 it received some alarmed comments regarding how unsafe it is to pass query strings in the browser.  Node.js is server side.  You know that, I know that, but some people didn’t so now you can feel smug about something on your bus ride to work.

Anywho, Squel requires that you learn a somewhat esoteric API, as do solutions like node-sql by Brian Carlson, the sharp guy behind the node-postgres library.  I suppose that if you aren’t much of a SQL fan, you will prefer the OOP look and feel of Squel and node-sql.  But, if you are like me, you actually like SQL, and you don’t mind writing SQL queries one bit.  In fact, you might even feel that writing SQL queries is easier than writing code for other languages thanks to the declarative syntax of SQL.  You don’t define functions and assign values to variables, you SELECT things WHERE equality EXISTS.  It is easy to wrap your head around.

Enter ES6 template literals.  From MDN:

Template literals are string literals allowing embedded expressions. You can use multi-line strings and string interpolation features with them. They were called “template strings” in prior editions of the ES2015 specification.

How do you use a template literal?  It’s easy, just wrap your string with backticks, also known as the grave accent, also known as the angled dash under the squiggly (also known as the tilde), instead of single or double quotes.  Then your strings, ahem, literals are free to span as many lines that please you.

It’s so new that even my syntax highlighting plugin doesn’t support it yet.  I’m sure you can see where this is going.  Now we can have multiline strings without using the infix operator, which is a huge relief.  The folks on the steering committee are going in the right direction.

What if you need to pass a variable to your string?  Your first instinct might be to concatenate your string to a variable containing another literal.

JavaScript will let you do this, but this is bad.  What if the variable contains something you didn’t expect?  For example, “;DROP TABLE users” (relevant xkcd).  That would ruin your day.  You could write a whole mess of code to sanitize your inputs.  This would also ruin your day as soon as you discovered that the effort wasn’t necessary.  Instead, you can take advantage of the built in parameterization features included in Node.js database drivers and take advantage of the ability to embed expressions in template literals using a library such as sql-template-strings.

The text wrapped with ${} is the embedded expression.  Thanks to sql-template-strings, this is equivalent to passing a parameterized query in your favorite library.  This helps to protect you from nasty injection attacks like ‘1234;DROP TABLE users’.  I’ll leave the rest of the explanation for why you should use parameterized queries and how you should implement them (for Postgres, at least) to Brian Carlson (there’s that name again).

So there you have it, multiline query strings have a simple interface in Node.js assuming you are using an ES6 compliant version.  If you are familiar with JavaScript, but are just now learning Node.js, I recommend the learning tool known as learnyounode to help you get started.  Happy querying!

Simplify Code Deployment and Your Life with Vagrant

Several months ago I stumbled across a deployment automation tool called Vagrant.  Admittedly, I did not appreciate the value of what Vagrant had to offer at the time, but I have since become a fanatic for automation.  I nearly forgot about Vagrant until a few days ago when I encountered the kind of scenario that Vagrant was built to simplify.  I was on the hunt for a Selenium framework for node.js and settled on webdriverIO because I like the syntax of the API.  I started working my way through the getting started guide.  The getting started example is simple enough, just a few lines of code to get the contents of the <title> element from www.google.com with Selenium using firefox as the client.

This looks pretty simple.  But, there is a catch.  You need to start Selenium Standalone Server independently.  No biggie, following the directions in the getting started guide I launched Selenium

And executed the code above.

Well, dang.  But the error message seems pretty straightforward.  I snagged a copy of the geckodriver executable by following the link in the message, launched it, and executed the test code again.  Still the same error message.  Eventually I determined that the path to the executable needs to be set when launching Selenium Standalone.

Note that in the example above, I am indicating that the path is in the directory I am launching Selenium from with -Dwebdriver.geckodriver.driver=./geckodriver, where ./geckodriver is the path to the executable.

The maintainers of webdriverIO make it simple to propose updates to their documentation by placing a call to action on each page that creates a pull request for whatever page you are viewing.  I wanted to share share what I had learned so that the next person did not stumble in the same place, but I needed to be be able to demonstrate how my solution was correct.  The trouble is, I had already fixed the problem on my machine.  The path to geckodriver only needs to be set once.

The initialization command for Vagrant immediately sprung to mind.

Vagrant makes it easy to spin up new instances of a virtual machine fully provisioned with exactly what you need.  Check out their getting started guide, which takes about 15 minutes to complete, and shows you how to provision a basic Ubuntu box running a simple apache file server with forwarded ports so that you can access the server from your host machine.

The great thing about Vagrant is that the configuration of your virtual machine is portable, and can be destroyed and recreated again and again.  All that you need is a install of Vagrant and Virtualbox on your host, a file to bootstrap the machine, and a Vagrantfile to define the machine.  Feel free to clone a copy of my virtual machine that I created for this project so that you can follow along.  There are instructions to install and run the machine in the readme.md file.

My goal was to specify the requirements for the virtual machines that would emulate the machine state of my current problem, and emulate the machine state required to solve the problem, and automate running the test so that anyone could download a copy of my solution and test it in a virtual machine with a single command.  Vagrant allows you to do exactly that.

After installing Vagrant and VirutalBox, the next step is to create a Vagrantfile and place it in your project directory.  You can create one yourself, or you can use the init utility by running it from your project directory.

I didn’t need anything more complicated than what was provided in Vagrant’s getting started guide.

Vagrantfiles use Ruby syntax, but you don’t need to know much (or anything) about Ruby to get started.  In the code above, I am declaring what the configuration of the machine is.  I am using the hashicorp/precise64 box, which includes Ubuntu.  I am also specificying the relative path to my boostrap.sh file, which will be used to provision the machine, and I am forwarding my ports, which wasn’t really neccisary but whatever.

Most of the complexity for my virtual machine is in the boostrap.sh file.  This was significantly more work than I anticipated, but seems really simple in retrospect.  Surprisingly, the biggest challenge that I faced was installing Java to meet the needs of my use case.  Not only does my boostrap.sh file provision my machine with all of the software that it needs, it also automatically runs my test code.  Pretty neat!

The bootrap.sh file is simply a list of bash commands to execute, listed in the appropriate order.  It may have made sense to edit the file system permissions rather than using sudo for a number of commands.  Vagrant can simplify that by allowing you to declare the commands one time in the bootstrap.sh file.

After setting up my Vagrantfile and boostrap.sh file, I was ready to test again by running the vagrant up command.

Success!  I removed some key commands to create a counter example to my test code, which demonstrates what happens if you do not set certain dependencies such as installing geckodriver, and declaring the path to its executable.  It is included as a subdirectory of the main repository.  If you want to see it in action, vagrant up in that directory to watch the code execute and reproduce the error that I encountered before.  You will need to vagrant ssh into the machine and access the log.txt in /vagrant to see the error logs from Selenium Standalone, because I am redirecting the output of Selenium Standalone to that file.

The best part of all of this is that I was able to share my results with the maintainers of webdriverio along side my pull request to update their guide to make validating the proposed changes easy.

Happy  automating!

The Fall and Rise of I

An interesting question was asked the other day regarding the apparent decline in frequency of the word I in English language books included in Google Books Ngram viewer.  From the 1900s to the 1960s, the use of the word I appeared to be in steady decline.  By 1965, the use of I had seemingly declined by 49.5% from its previous peak in 1901.

The plot above is generated by Google Books Ngram viewer, which allows users to aggregate short phrases from Google Books.  Three things stand out in this data.  First, the use of the word I in the English language was consistent for 100 years, second the use of the word I experienced a steady decline for 60 years, and third, almost as soon as the use of I reached its lowest, the trend reversed twice as fast as it happened in the first place.

What happened?  Why did I fall out of favor and then come back?  Perhaps Google’s optical character recognition algorithms are simply unable to differentiate between I and 1 or lowercase l due to the typography that was popular during that time?  Perhaps the English grammar in published works simply declined from 1901 to 1960 and people began using me instead (e.g. me and my friends).  Of course, if that were true it would mean we have entered a golden era of English grammar in published works, which seems unlikely.

If either of the scenarios presented above are true, we should see the use of the word me either stay the same or increase considerably.  However, as you can see in ngram plot above for the word me, the trend is nearly identical to the word I.  Perhaps the public education system simply began to discourage writing in the first person from 1900 until 1960, and then reverse that policy starting in the 1970s onwards?  If this were true, we should see a complementary increase of third person nouns such as the word he and she.

Oddly enough, the ngram plot for he and she show a similar trend to I and me.  The word she is less common in general, but saw a decline starting in 1940, and a reversal of that trend in the 1970s.  The frequency of the word he sharply declined starting in 1900, just like the word I, and did not begin to become more frequent until the late 1990s.  It is safe to say that the decline in the frequency of I and me were not caused by public school policies.  If they were, we should have observed an increase in nouns associated with third person writing.  Instead we observed the exact opposite.

It might feel like we are at a loss for explanation at this point.  However, there is still something to take away from the ngrams that we have examined so far.  For example, since I, me, she, and he all declined in frequency and then became more frequently used around the same time, it is reasonable to assume that those words were simply displaced.  What if these plots do not tell us about the fall and rise of I, but rather the rise and fall of something else altogether?

The ngram plot above shows the frequency of the phrases technical manual, technical publication, and repair manual.  Now, unlike the words I, me, he, she, and her, these phrases are significantly less common.  However, the increase in the use of those phrases is an important reminder of why it is important to understand the dataset that you are working with.

Beyond being library-like, the evolution of the corpus throughout the 1900s is increasingly dominated by scientific publications rather than popular works. 1

The Google Books Ngram corpus does not represent the true popularity of a word or phrase.  Rather, the Ngram corpus is comprised of books mostly provided by libraries.  In addition, the corpus is contains one of each book, giving equal weight to popular and obscure publications.  Rather than representing the frequency of words or phrases in the popular vernacular, Google Books Ngrams represents what University libraries choose to include in their collection.

Unfortunately, the Ngram corpus does not contain any information about the popularity of the publication such as published copies or copies sold for the books that the ngrams were extracted from.  There is also no obvious way to relate the ngrams back to their original publications using the published corpus.

Although it is not useful for analyzing the popularity of words and phrases, it does provide interesting insight into trends in what libraries choose to collect.  As for the fall and rise of I, the cause was librarians displacing their frequency by adding more scientific and technical publications to their collections.  These publications simply do not use the word I, or he, she, him, her, you, or me for that matter.

Plot the FHFA House Price Index With R

FHFA House Price Index

 

R is a great tool for creating data visualizations like the one above.  The learning curve is a little bit steeper than a low code alternative such as Microsoft Excel.  However, R makes it easy to transform certain types of data such as a csv file with data points represented as column headers rather than row data.  For example, the data that is supplied by the Fair Housing Finance Administration is organized by month and regional market, meaning that there is a column for each regional market in the data.  The reshape library makes it easy to transform this data into three column csv file where the columns represent the month, index value, and regional market.

View on GitHub

In the example above, we start by calling the ggplot2 and reshape libraries.  Then we read the House Price Index csv data and add that data to the class ‘d’.  Afterwards we declare a new class called ‘month’ and format the month column from our csv as m/d/y.

Next we declare a class called ‘df’ and append a data frame to df which includes the data from our csv organized by column header.  Note that to make things simple, I altered the column headers in the csv to make it easier to add the data to the data frame.  After our data frame has been added to df, we use the melt method from the reshape library to transform the grid style data structure into a linear data structure that stores the month as time, market name as series, and index value as value.  Imagine taking an 10 column horizontal spreadsheet in Excel and turning it into a 3 column spreadsheet by copying the values from each column header and pasting them as new rows.  After pasting each row, you also add the column header to the third row.

After this we create a class that contains labels and a class that contains the colors for each label.  Libraries like ggplot will handle labels and colors automatically.  However, I wanted to have descriptive labels for the values represented in the plot.

Finally, we plot the data by assigning the ggplot function to ‘c’.  We also add in a title, x and y labels, and our label names and colors for the values shown in the plot.  In addition, we specify some additional theme parameters for our plot.

The source data can for this plot can be acquired from the FHFA.

How to remove a specific value from an array with Node.js

Let’s assume you need to remove values from an array.  You can build a simple function that will scrub specific values from an array of data that will return a scrubbed array in a callback using a few lines of code.

The function above accepts an array, deleteValue, and callback as arguments.  The array is iterated in a for loop.  Each time the loop runs, the value of the array at the index of the iterator is checked against the delete value.  If the value at the index of the iterator is equal to the delete value, the value at the index of the iterator is removed from the array using the splice() method where i is the index of the delete value and 1 is the delete count.  Finally, 1 is subtracted from i to ensure that the loop starts at the correct index in the next iteration.  After the array has been iterated through, the new array is passed to a callback.

Example Usage:

In the example above, we are declaring a function will use our clean() function to clean our array of values by comparing it the values in another array.  The function will pass the resulting cleaned array to a callback.  The advantage here is that you can remove multiple values from your array without blocking the event loop.  If you had an enormous array of values that needed to be scrubbed a solution like this might come in handy.

View this code on github.

Phishing Dark Waters: The Offensive and Defensive Sides of Malicious Emails 1st Edition

Do not let the human factor turn your castle into a fortress of glass.  Phishing in Dark Waters: The Offensive and Defensive Sides of Malicious Emails discusses why no corporate information security program is complete without addressing the human factor is security.  How do phishing scammers to use human nature to their advantage, and why do people fall for it?

I was at Barnes & Noble looking for a book to read for an upcoming camping trip when I came across this book.  I had actually gone to Barnes & Noble in a last minute search to find a good book on programing that delved into theory rather than practical application and how-to (they didn’t have anything like that).  I found Phishing Dark Waters: The Offensive and Defensive Sides of Malicious Emails nestled in with a heap of books with titles like “Teach Yourself Java in 24 Hours.”  The subject of the book caught my attention right away.  I flipped through the book and hem-hawed about the price ($35.00, but you can probably get it cheaper on Amazon).  I even took a couple more laps around the store, but kept coming back to this book.  Eventually, I decided to buy it, and I am glad that I did.

Christopher Hadnagy and Michele Fincher show us how email phishing plays on human emotional responses to get people to divulge valuable and sensitive information that can cost money, compromise security, and cause embarrassment for everyone involved.  Hadnagy and Fincher explain that phishers play on fear, greed, ignorance, gullibility, and respect for authority to convince people to take action that might not be in their best interests.

In this book, phishing attacks are categorized by their level of sophistication, from very low level attacks like the Nigerian 419 scam, all the way up to very sophisticated attacks known as spear phishes, which target executives and other high level individuals.  Then, Hadnagy and Fincher discuss how each type of attack can be identified by looking for common themes in each type of attack.  Hadnagy and Fincher show us how these different types of attacks have been employed successfully in real world situations, such as the Target payment systems breach.

After a thorough introduction to the common types of phishing schemes, Hadnagy and Fincher dive into the psychological aspects of how and why phishing works.  Namely, cognitive bias and a technique known as amygdala hijacking.  The authors point out that we are pre-programed by our environment to make certain types of decisions a certain way.  This is a cognitive bias.  It makes it easier for us to quickly make decisions.  Imagine if we had to weigh all of the facts every time we made a decision.  Trips to the grocery store would be agonizing.  This bread has more fiber, but this other bread has fewer calories per slice.  Which do we choose?  Our cognitive bias tells us we have always eaten Wonder Bread, so we grab a loaf.  We like the way the package looks.  Problem solved, and the outcome is harmless.

But what about an email that comes from our bank?  It has their logo.  They have never lied to us.  We follow the link and enter our credentials.  Except, this wasn’t a message from our bank and the page where we entered our credentials was actually a fake designed to ensnare us into giving away our login credentials.  Our cognitive bias blinded us to all of the warning signs because it was triggered by branding that we knew and trusted.  In this scenario, the outcome is definitely harmful.  Hadnagy and Fincher explain that phishing scammers employe cognitive bias to trick us into making decisions that have harmful outcomes.

Amygdala hijacking is the second major psychological factor in phishing that the authors discuss.  By generating an emotional response, phishers are able to short circuit our ability to think logically.  For instance, imagine you get an email that says someone has run a background check on you.  You haven’t done anything wrong, so you have no need to worry.  But you cannot suppress your emotional response.  Why is someone doing this?  What are they hoping to find out?  What if they know something that I don’t?  All of these are completely irrational questions when you consider that no background check agency has a responsibility to notify you if a check was run to begin with.  Hadnagy and Fincher share methods for overcoming a hijacked amygdala, and how to coach others to employ these methods.

After discussing how and why phishing works, the authors discuss methods to protect from phishing, such as sandboxing emails, hovering over links to reveal the URLs, and reading email headers.  For experienced IT folks, these methods might seem like no-brainers, but keep in mind that this book aims to show you how to teach others as much as it aims to teach you.  Admittedly, I found myself questioning what I really knew about emails and how they work as I read this book and came to the realization that like many people, emails are something that I take for granted and put very little thought into.

The real meat and potatoes of this book is the multi-chapter discussion of how to design and implement a penetration testing program which will help you evaluate the competency of the target group and train the members of the group to become better at spotting phishing attacks.  What I like most about this book was the emphasis on hands on training techniques by running live phishing simulations rather than endlessly sending volumes of policies and hours of computer based trainings to employees in the hopes that they will absorb something from it.  I have personally observed companies do little more than issue a new policy or a training after a phishing attack in the hopes that the policy or training will get their message across and resolve the problem once and for all.  The problem with this is that unlike a policy about time and attendance where it makes sense to put the burden of reviewing and understanding the policy on the employee, a phishing attack harms the entire company.  It simply is not good enough to place the burden of understanding the issue on the employee.  Companies need to do more to ensure that employees truly understand how to spot a phishing attack, and what to do.

Hadnagy and Fincher review how to design a phishing campaign, how to gather baseline data, and how to track progress with meaningful statistics.  I appreciate the author’s emphasis on ensuring that the experience is positive for everyone involved, and that every effort should be made to avoid embarrassing someone or causing them psychological harm.  Believe it or not, some people really do believe that embarrassment is an effective training tool, so this does not go without saying.

My only criticism of this book is the discussion of software choices for launching a phishing education campaign.  This chapter will be outdated in no time, and could have been left out altogether.  If you come across this review a few years after this book has been released and are trying to decide if you should pony up to buy the brand new second edition, or a used copy of the first addition, keep in mind that the most significant update to this book will be the discussion on software.  Hadnagy points out himself that many of the themes used by phishers have been around for hundreds of years.  They aren’t going anywhere, and the discussion of those schemes will still be relevant for years to come.

Do I recommend this book?  You bet I do, and I will be using the lessons that I have learned in this book to make myself, my family, and the organizations that I provide information security services to more secure from phishing attacks.  If you are an IT professional, business owner, or manager, do yourself a favor and get a copy of this book.  The day that it will take you to read this book will change your perspective on how to protect yourself and your business from phishing attacks.

learnyounode Unofficial Companion

This article is part of an unofficial companion for learnyounode, a teaching tool for node.js.  I wrote this to help myself understand node.js, and the learnyounode tutorials.  This walkthrough assumes that you will also read the lesson instructions and lesson hints, as well as any referenced documentation in each lesson.  This walkthrough contains both my solutions as well as the official solutions.  However, if one or the other is missing, you can find the solutions on github as well.  Lastly, at the time of writing this, I am far being any kind of expert, so take what I have to say with a grain of salt.

If you already have a good understanding of JavaScript (up to and including objects and prototypes), learnyounode is a great place to start learning node.js. If you are just diving into JavaScript, consider starting with the JavaScript module on codecademy instead. Node is JavaScript first and foremost. Starting with node before establishing a foundation in JavaScript is a lot like trying to sing in a language you don’t know. You might be able to make the noises, but you won’t really understand the meaning.

Additionally, it will be helpful to be familiar with the linux, OS X, or Windows command line.  Unlike JavaScript, which is tested using the browser console, node.js runs from the command line.  If you know how to launch the command line terminal and do simple tasks such as changing directories, you probably know enough to get started.

Getting Started

To get started, download and install the appropriate version of node.js for your operating system.  You can find it here.  If you are Windows user, you will need to restart your computer after you have installed node.  You should also consider using a text editor or IDE with syntax highlighting, but you probably already knew that.  I am partial to Atom (free) or Sublime Text (paid).

After you have installed node, launch the terminal and navigate to the directory you want to install learyounode to, probably ~/user/node-modules/.  Once you have navigated to your preferred directory, enter the following into the command line.

If you are a linux or mac user and your download fails, try this instead.

Enter your credentials when prompted.

If you are a windows user and your install fails, you are on your own for now (sorry).  If all else fails, try to google the errors you get.  You probably  aren’t the first to run into trouble.

After learnyounode is installed, you can get started by launching it from the command line.

You will know if you were successful when you see the learnyounode menu.

learnyounode

Woah!  Looks like an old DOS program or something.  It is actually a node.js app.  One of the great things about node is that not only can it be used as a server side scripting language, it can also be used to make nifty command line applications such as learnyounode.

Lessons

learnyounode Lesson 1 – Hello World!

learnyounode Lesson 2 – Baby Steps

learnyounode Lesson 3 – My First I/O!

learnyounode Lesson 4 – My First Async I/O!

learnyounode Lesson 5 – Filtered LS

learnyounode Lesson 6 – Make it Modular

learnyounode Lesson 7 – HTTP Client

learnyounode Lesson 8 – HTTP Collect

learnyounode Lesson 9 – Juggling Async

learnyounode Lesson 10 – Time Server

learnyounode Lesson 11 – HTTP File Server

learnyounode Lesson 12 – HTTP Uppercase

learnyounode Lesson 13 – HTTP JSON API Server

learnyounode Lesson 1 – Hello World!

The first lesson is time honored Hello World! tutorial.  This one is pretty easy, but in case you need a hint to get started, here are the steps to complete this lesson.

Create a new .js file called helloWorld.js in your text editor.  Add the following code to your file.

Save your file and verify it with learnyounode to complete the lesson.

That’s it!  You are ready to move on to the next lesson.

Lesson 2

Contents

learnyounode Lesson 2 – Baby Steps

In lesson 2 we need to write a program that accepts one or more numbers as command line arguments and then prints out the sum of those arguments.  Hmm…that’s a tough one, especially if you are accustomed to using JavaScript for browser applications.  You could spend a bunch of time researching how to build command line applications in node.  Fortunately,  you don’t have to.  Learnyounode give’s us a great hint to start with.

The hint tells us that command line arguments can be accessed from the process object.  One of the properties of the process object is argv, an array that contains the complete list of command line arguments.  If you like, you can see the contents of process.argv by creating a simple program that contains the code that follows.

You can run this from the command line the same way you ran your helloWorld.js application from the previous lesson.  If you run this code with a couple of numbers passed as arguments, you might notice that those arguments are stored as strings in the process.argv property.

The hint in learnyounode points out that we may need to convert these strings to numbers to complete the exercise by passing it to the Number() method, or by prepending it with the unary + operator.  Ah, that’s pretty simple after all.  Here is the official solution in learnyounode that ties all of the hints together.

Official Solution

Click to show/hide solution



Notice that the loop in the official solution starts at array index[2].  If it didn’t, we would get slapped with NaN instead of the sum of our arguments because the path to node and the path to your program are strings.  The official solution is really all you need to pass the lesson.  But, it isn’t the only way to pass the lesson, and it has a flaw that may be important to know about if you would like to build on this lesson in the future.

Let’s say that instead of passing only numbers as arguments, you are passing numbers and strings all mixed together.

Instead of getting the sum of our numbers, we get NaN because ‘a’ is a string.  The official solution is only valid if you will only pass numbers as arguments.  If you want to pass a combination of data types, but only sum the numbers without getting NaN (not a number), you will need to make your program a bit smarter.  Below is my solution for the baby steps exercise, which can handle a list of arguments has non number datatypes.

Alternate Solution

Click to show/hide solution



Instead of using a for loop, I am using the Array.prototype.reduce() method.  In my callback function, a is the previous value, b is the current value, and c is the index.  Note that I am prepending a and b with the unary (+) operator to coerce the process.argv string values into numbers.  One criticism of my solution is that the index start position is still hard coded (c >= 2).  Technically, it will only sum a list of arguments starting at index[2].  For the sake of accessing the process.argv property, this is probably fine as index[0] is always the path to node, and index[1] is always the path to your program.  However, you would need to modify this solution if you were going to use it for something other than accessing the process.argv property where the data type of index[0] and [1] might not be known.

Lesson 3

Contents

learnyounode Lesson 3 – My First I/O!

In this exercise we need to create a program that reads a file synchronously and prints the number of new lines in the file to the console, similar to piping the cat command to word count count command to count the number of lines in a file.

Wut?

If you aren’t familiar with these commands, cat reads a file and the pipe symbol ( | ) pipes the output of cat to the word count command (wc).  The line option (-l) counts the number of new lines in the file.

Let’s say these are the the contents of myFile.txt.

If we pipe the output of cat myFile.txt to the wc command, we get the result below.

Luckily, node has a filesystem module for performing tasks such as this.  To use it, we need to require the module so that we can use its methods.

After we require the fs module, we can use the readFileSync() method to read the contents of a file.  In this exercise, we want to read a file that is passed as the third argument on the command line.  Remember that in the baby steps exercise we used the argv property of the process object to sum values passed as argument.

We can access index 2 of process.argv to read the contents passed as the third argument to the command line.  The readFileSync() method returns the buffer object when the read is complete.

We can convert the contents of that buffer object to a string with the toString() method.  From there we can use the split() method to split the string at each new line (‘\n’) and get the length with .length.  Because our file will not will not have a new line delimiter at the end of the last line, we will end up with one extra new line in our count.  But we can just subtract one from our final value to get the correct count.  Is there a better way?  Probably, but you will have to do the heavy lifting to figure it out.

Official Solution

Click to show/hide solution



The solution is broken down into several lines for the sake of readability, but we can cram the solution into a single line if we want to.  However, this formatting may cause some to become nauseated, enraged, or both.  Use at your own risk.

Click to show/hide solution



If we run either of these solutions from the command line, we will get the result that follows.

Thats it!

Lesson 4

Contents