CLI Data Gem Project: True Crime Documentary "Database"

At last, I am complete with my project.  It took exactly two weeks.

Overview

The name of my project is True Crime Documentary Database. It offers a list film and television documentary film titles in the True Crime genre. 

Screen Shot 2018-06-23 at 7.03.36 PM.png

(Note: Although it indeed is not a database, its functions point in the direction of a database. The term "database" is used here loosely.)  

I used the Nokogiri gem to scrape the site crimedocumentary.com.  

Screen Shot 2018-06-23 at 7.20.39 PM.png

I created an application that scrapes the category names, the URLs, and the documentary attributes that exist within each URL path.  I had to scrape these link (image below).

Screen Shot 2018-06-23 at 7.22.56 PM.png

The program should deliver a menu of options: to browse the documentaries by category or to see a full listing of documentary titles.  

Screen Shot 2018-06-23 at 7.03.47 PM.png

Selecting category delivers a list of documentaries displayed with their title, year, category, synopsis, and full synopsis URL.  

Screen Shot 2018-06-23 at 7.04.09 PM.png

Otherwise, if list all documentaries is chosen, then the user is taken to a submenu from which to select a title.  Similarly, the selection displays the documentary’s details.

Screen Shot 2018-06-23 at 7.04.27 PM.png
Screen Shot 2018-06-23 at 7.04.41 PM.png

Building The Project

Now, based on my initial review of the HTML I felt assured that I could achieve this project based on what I had learned in the previous labs leading up to my CLI data gem.  What I hadn’t given better attention to was the layout of the site and how it delivered the data.  The categories of a film are front and center, while the documentaries generate (no HTML to scrape) in many places, except inside of category link paths in the right sidebar.  Sadly, I hadn’t noticed this quirk until long after getting approval and having coded my scraper class. (With respect to object orientation, this presents some coding challenges. It would be hard to maintain the has a/has  many object relationship that I planned.)  

IMG_20180621_174802.jpg

In the scraper class is when I realized I might run into trouble when I’d have to connect these objects in the CLI controller class.  Sure enough, that difficulty arose. I worked hard to refactor the entire project from start to finish and ended up with a better product.

Something I encountered was that the number of links I decided to scrape tacked on at least 15 to 20 seconds of load time at the start of the program. Coincidentally, in one of my recent study groups, the instructor mentioned how it might sometimes be a better option to have the data load (scrape) upon selection by the user. I thought it was an excellent idea!  However, given how far I had come and that I was already in the middle of rebuilding my program from scratch (I created a branch and merged later), it would have proven difficult timewise.  So again, the layout and coding of the site presented a hurdle that made any new idea unfeasible.


Overall, I believe that I have met the requirements of the project by demonstrating that I have a good grasp of object orientation and working confidence in coding in Ruby.  

Some Afterthoughts

  •  Simple ideas are still complicated when it comes time to code them!
  •  What you think is simple may not be simple enough.
  • *Projects fan the flames of enduring appreciation for Google search! :)
  • *This project was, *hard*! However, it I love it! 
  • *Coding is fun. Learning to code is fun and uncannily cathartic. O_O

Bottom line: The CLI data gem was a challenging project, while also gratifying!

Access the repository here.
 

CLI Data Gem Project Complete...mostly

I'll explain how it works later in the week.  But for now I'm just celebrating having made it through the toughest part, which was building it and getting it to work.  It took me a week.

Screen Shot 2018-06-20 at 1.48.20 AM.png
Screen Shot 2018-06-20 at 1.48.49 AM.png
Screen Shot 2018-06-20 at 1.49.29 AM.png

Object Oriented Ruby Final Projects: Music Library CLI

I am one lab away from the CLI Data Gem Project. Although, I have gone over it to evaluate what I need to do to complete it.

Object-oriented Ruby has been one heck of a challenge so far, and I’ve enjoyed every moment, including the parts where I was stumped. I enjoyed the Music Library CLI project the most. However, the CLI Data Gem Project appears to be the most fascinating and open! By open, I mean that I like that I get to choose the content of my project, albeit with some training wheels still attached. But I digress… What the Music Library CLI project brought to bear regarding object relation is where I struggled the most. It was hard to quickly wrap my brain around the intricacies of how the objects were to be linked via methods. Moving forward my takeaway is to draw diagrams with a flowchart of objects to get the big picture. And since I am a big picture thinker, this is almost a must! I am a visual-kinesthetic learner. I must see and touch my solutions, or at least have some physical association with what I am learning.

On the more technical side of the house, these are the methods in the Music Library CLI project that gave me the most significant challenge:

Song Class Song.new_from_filename: Learned that I had to instantiate a new instance of Song.

Artist Class artist#add_song: The key to getting this to pass was the unlessconditional statement, which is the inverse of the if conditional. It just proved to be a far more elegant and efficient means of defining the method.

Music Library Controller Class All of the trigger methods took some careful reading of the test specs and greater thinking along the lines of iterating with an index–that is, Ruby’s each_with_index method, to be more specific. It saved the day! Also, I later realized that I’d be sorting objects, which reframed my entire plan of approach to elegantly and adequately coding specific list methods. It is important to remember that we are to take advantage of the object attributes to maintain well abstracted and efficient code throughout the entire project. So I called on the list of objects stored in the @@all class variables so that I could sort them, then call on their respective attributes to define specific list methods.

Overall, everything that I have learned has challenged me to think broadly–far more than I thought I already could. And the fact that I can learn to think more broadly than I ever have with coding has nurtured both a growing excitement and hunger to learn more.

A Way to Learn As a Flatiron School Student

I began my journey as a FS Web Development student in the first week of April. I am a quarter of the way through the curriculum and would like to share some patterns that I have noticed in my learning in hopes that it will be of some help to any other beginning FS student.

What I have learned about my learning:

  • Get comfortable with being uncomfortable with broken code.  In fact, get comfortable with breaking and redoing or refactoring code to higher efficiency. In a phrase, think in drafts. Writing code is not unlike writing a paper that is too wordy, uses overused terms, or is poorly formatted.  Working code is not necessarily "good" code.  All of this is part of the ongoing process of programming.  Think: Less is more. Simplest or abstract code is the good code.  Although, I grant that for beginners that the "efficient" is relative to our experience and what little we know.  So be patient with yourself.
  • Read test specs carefully and plan accordingly.  As great as it is to have pre-written test specs, don't make the test specs a crutch.  Remember this is a learning environment intended to simulate and teach; that is, to train as you fight, figuratively speaking. This is to say, you need to learn the way a programmer is expected to program in the real world or learn  by doing as programmers do. However, Learn.co is still a teaching environment and not the real world.  Therefore, plan and think, as opposed to slipping into autopilot--because it is possible up until a big challenge comes along and appears wholly unfamiliar on top of whatever labs are supposed to be challenging all their own. Don't get me wrong! These lessons and labs are scaffolded to comprehensively challenge you.  But this does not rule out the personal responsibility to review, take some notes, and make connections to prior knowledge; assimilating knowledge, while consistently taking in entirely new experiences.
  • Strategize, strategize, strategize!  Object-oriented ruby, for example, will begin to introduce you to more realistic interaction with code, where you will code in one file while having to pause work on that file to accomplish some working code in another to enable the prior file to work.  The implied task is that you will need to understand what to code in some necessary order.  This makes the previous steps crucial.
  • Think about your thinking and approach. For example, when you make an error, and whether you are able to resolve it quickly or not, take a moment to understand how you got to that point, whether your code is passing or failing the tests specs.  In terms of a failing spec, think:  What am I missing in this method/class/lab?  What does the test spec say?  Does my code address every facet of what the spec requires? (On the latter, all but a missing piece of code could be causing an error to be thrown, demonstrating while you have to think both with and beyond the given test specs! Stated inversely, all your code is set to work if one piece of code weren't missing.)  So you kind of have to be a Sherlock who must really observe your code to embrace the possible problem that just isn't popping out at you despite having run yourself through several loops to figure out why your code is not working.  And in terms of a passing spec, ask yourself:  How did I accomplish this?  Do I know and understand what I did to achieve this success?  Implied task:  Take time to evaluate your learning, even if you are a high-speed FS student with previous experience.
  • Evaluate and document (summarize in your own words) what is being asked of you to  accomplish a particular specification(s). Although Learn.co has built-in tests for you, you still have to do the work of thinking. As you progress through the curriculum the tests will become less and less specific. There will be gaps in the logic of the test specs that require you to fill in the blanks for how you get from one end of a problem to its expected outcome or output. 
  • Remember that computer programming's technical and essential purpose:  To solve real-world problems.  You should be excited by the presentation of a problem to solve, as opposed to feeling bothered by problems.  So to further break a broken record, learn to love problems so that you can get to the place to appreciate how your work as a programmer can improve people's daily lives, because that is what it's all about at the end of the day.

Dig deep. Think. Code. Evaluate. Adapt. Keep going. :)

Originally published at http://wayofthecode.com/.

Why I Decided to Learn Software Development

It was a long time ago actually that I took a nascent interest in coding at all.  In the spring of 1996, I completed my high school freshmen enrollment schedule before graduating middle school.  The fall came, and I found myself in a computer programming class learning BASIC.  At the time I felt intimidated by not only the programming language, but especially the other students who seemed to have prior experience and were keeping up with the teacher. It didn't click for me at that time. I visited my guidance counselor and got out of it. It would be years before I'd ever seriously look at code again. Instead, I took a serious interest in music for the remainder of my high school years, all the way through college and meanwhile harboring a deep love of tech. 

In 2005, I graduated from the University of Florida as a music educator. Five years later the county cut my music position after I enlisted in the U. S. Army Reserve in 2010. So from 2011 onward  I spent years on and off active duty, bouncing between the Middle East and the United States from 2012 until the present.  Throughout all of these years I really wanted to code. In fact, it grew to the point that I knew I didn't want to teach anymore. I still felt that it was beyond my ability until I met my good friend, Staff Sergeant Myers, who encouraged me to take the plunge because he had seen my raw potential in tech whether as an information technology professional or software developer.

In short, while I deployed to Kuwait in 2016, that year proved to be what I consider the most crucial year for tech and my country (US), whether one was a systems administrator, cybersecurity professional, and/or a coder. In my eyes, 2016 was a pivotal year where the virtual world and the real world coalesced, or maybe even collided, in perhaps a perfectly unintended way. I was both riveted and dismayed by the entirety of 2016, and the role tech had within it.  Something ignited within me that year, such that I formed a plan to get educated and experienced in tech some way, somehow.   

My values were ignited that year and were challenged! And my passion for tech suddenly had deepened with meaning and purpose. All I needed was the means to act on my vision to create, that is, to code and collaborate on health-conscious technologies. Why? 2016 was a call to action. That year showed me that the unintended consequences of things we develop without any ethical foresight and preemption could have real-world implications--particularly in the areas of privacy, security, and epistemology or truth. That year also proved that software developers (or engineers) have a philosophical imperative to create with a conscience. Apple made a subtle but powerful video advertisement titled, "Designed by Apple in California."  One portion of the video asks the following: "Will it make life better? Does it deserve to exist?" One can hate Apple's high-walled ecosystem of products, but we certainly cannot doubt their intention and caring thoughtfulness about user experience.

Finally, the current business model for the most popular web platforms enlivened me to the importance of the way web technologies are designed. For instance, I would encourage moving away from user interfaces and experiences that are inherently meant to commoditize the user. What do I mean? Perhaps define and create better social media platforms that do not psychologically and physiologically exploit the user's baser instincts (e.g., dopamine-fueled scrolling on bottomless feeds and a token economy of "Likes.")  To wit, I think existing web and mobile technologies are amazing!  But I believe that we can do better, and I would like to be part of shaping a future that cares about the mental and social well-being of the user.  I believe learning software development enables me to have a seat at the table and even perhaps help to remake the table for a better social web and real-world experience.

OO Tic Tac Toe In Ruby Complete!

Shortly after writing my previous blog post I jumped headlong into my final Intro to Ruby Lab (OO Tic Tac Toe) and completed it.  I think it didn't take me long to refactor the code because I have prior experience with creating objects with classes in Java. (Cringe? LOL)  In case, you haven't already read my about page, I completed an Introductory and intermediate course in Java at the University of Maryland University College online between the timeframe of Fall 2016 and Spring 2017. So it was basically a matter of a transliterated understanding of how Java classes work uniquely compared to how Ruby classes work.  

Screen Shot 2018-04-14 at 11.22.20 AM.png
Screen Shot 2018-04-14 at 11.22.30 AM.png

Procedural vs Object Oriented Ruby

This is a lab the requires that I refactor all of my procedural code for a Tic Tac Toe game to object-oriented programming. This entails removing certain arguments from many of the methods I created due to the lossy and buggy potential of continuously passing around the same value. Also, the procedural code makes scalability a nightmare; to expand functionality and behavior. You'd essentially have to re-write old code and then write entirely new code to expand the application. Conversely, using an instance variable wrapped within a class method is a better and less buggy practice.  This is what I understand so far from my reading and labs in Learn.co

I just started this lab.  I'll show you my results later.

Screen Shot 2018-04-14 at 9.43.49 AM.png

Walk Away And Return

Short and sweet.

I was working on the Tic Tac Toe Game Status lesson in Learn.co and got stuck on a particular method--the #winner method.  I got frustrated because I was just not able to abstract what was needed to solve the test problem.  So I got up and watched television.  

"David! Isn't that irresponsible and a time waster?"

Ordinarily, you'd be right.  But no, it was not a waste of time.  And it was a mature and responsible response to the moment of frustration.  I got up and walked away to do something completely different.  And on top of that the very show I watched hit on the very thing I was struggling with from quite an esoteric angle. (The show was HBO's "Here and Now," by the way.) 

When I was done, I plopped back down in front of my computer and in under two minutes, I solved what I had initially toiled over for about an hour prior to walking away from it.

Life is not all logical and clean and neat. It's ugly and beautiful and random and scary and amazing, and so much more.  Sometimes you have to let go in order to learn real control and discipline.

Take it or leave it. :)

Lastly, I did ask for help with other things earlier on in the lesson.  You gotta let go and ask for help. This is a form of strength and maturity!

Fizz Buzz Test

While reading my lesson called Rspec Fizzbuzz, I learned about the Fizz Buzz Test.  It's intriguing!  Check it out here:  Fizz Buzz Test.

Description from the site:

"The 'Fizz-Buzz test' is an interview question designed to help filter out the 99.5% of programming job candidates who can't seem to program their way out of a wet paper bag.  The text of the programming assignment is as follows:

Write a program that prints the numbers from 1 to 100.  But for multiples of three print "Fizz" instead of the number and for the multiples of five print "Buzz".  For numbers which are multiples of both three and five print 'FizzBuzz'."

The site's author is pretty snarky, but his sentiment is well-heeded.  A computer programmer should be able to problem-solve beyond wrote skill knowledge and proofs.  Here is a blog post talking about it and an excerpt below:

"FizzBuzz was presented as the lowest level of comprehension required to illustrate adequacy. There's no glory to be had in writing code that establishes a minimum level of competency. Even if you can write it in five different languages or in under 50 bytes of code.

The whole point of the original article was to think about why we have to ask people to write FizzBuzz. The mechanical part of writing and solving FizzBuzz, however cleverly, is irrelevant. Any programmer who cares enough to read programming blogs is already far beyond such a simple problem. FizzBuzz isn't meant for us. It's the ones we can't reach – the programmers who don't read anything – that we're forced to give the FizzBuzz test to."

With all this said, it is my plan to complete at least one coding challenge per week.

Full Stack Web Developer, Begin!

I enrolled in Flatiron School on Monday of this week, and the learning has been smooth sailing thus far. To I completed my 30-minute video conference with my non-technical coach, which is a free resource that FS offers to its students.  The non-technical coach is a means of keeping the students accountable if they want it, and to stay on track with their end-state learning goals.

As far as the learning is concerned, a good portion of it is prior knowledge for me due my both my self-taught background and education through University of Maryland University College.

I'm off to a great start!

Screen Shot 2018-04-06 at 10.54.21 AM (3).png

Flatiron School's Bootcamp Prep and the Case of the Missing IDE

The bootcamp prep course through Flatiron School is phenomenal...so long as it allows you to continue.  My excitement and enthusiasm to work on the coursework have been atmospheric. Today I was on a role until I got a special little notice at the bottom of the browser stating that I've made enough progress to just go ahead and apply.  So now the IDE doesn't launch, preventing me from coding.

Progressing won't be happening although I actually wanted to blast through the prep before I begin in April to work through the actual web development course online.

At any rate, I have applied to FS and therefore will not be enrolling with Bloc simply because I like the platform, the support, and progress that I have already made with FS.  What's also awesome is how FS incorporated an online IDE and terminal into the learning platform called Learn.co.  I can also jump right into Slack from my Learn.co account as well as push and commit all of my labs to GitHub, which is also incorporated into Learn.co via an API.

I'm not even an official student yet, and love how FS works!

Stay tuned!

centuryFromYear [Code]

I'm hungry for coding!  So I joined a site called CodeFights.  It's a really neat place to put one's coding skills to the test and to just get dirty.  It is a perfect place in which to experiment, research, and learn new things.  As a beginner, I am gaining problem-solving skills as well as familiarizing myself with JavaScript.  The CodeFights (here forward referred to as CF) allows the user to choose a language of choice with which to complete the coding challenges or the coding interviews.  Yes!  CF has an option to practice for coding interviews! 

Anyway, here is my code for the Arcade challenge called centuryFromYear. Let me know how I could have coded better. 

Questions:

  1. Is there a simpler way to code the function?
  2. Do you see a possible test case that would fail?
  3. Is my code readable or unnecessarily complex?
  4. How did I do with following coding conventions (variable names, indentation, brackets, parentheses, etc)?

centuryFromYear

Description:  Given a year, return the century it is in.  The first century spans from the year 1 up to and including the year 100, the second - from the year 101 up to and including the year 200, etc. (In other words, I am to create a function that will achieve this.)

Language:  JavaScript

My code (51 lines; not including the test code far below):

(The following was accepted by CF as a working solution. It passed all 9 test cases far below.)

function centuryFromYear(year) {
var yearToString = year.toString();
var century = 0;
var strCentury = 0;

//Checks for four-digit year.
if (yearToString.length === 4) {
    //Checks for final year of the century to prevent adding
    //a century.
    if (yearToString.substring(1) === "000") {
        century = yearToString.substring(0,2);
        century = parseInt(century);
    }
    else if (yearToString.substring(2) === "00") {
        century = yearToString.substring(0,2);
        century = parseInt(century);
    }
    //Otherwise adds century and parses the string to initialize
    // the variable century with the proper number of centuries.
    else {
        century = Number(yearToString) + 100;
        strCentury = century.toString();
        strCentury = strCentury.substring(0,2);
        century = parseInt(strCentury);
    }
}

//Checks for a three-digit year.
else if (yearToString.length === 3) {
    //Checks for final year of the century to prevent adding
    //a century.
    if (yearToString.substring(1) === "00") {
        century = yearToString.substring(0,1);
        century = parseInt(century);
    }
    //Otherwise adds century and parses the string to initialize
    // the variable century with the proper number of centuries.
    else {
        century = Number(yearToString) + 100;
        strCentury = century.toString();
        strCentury = strCentury.substring(0,1);
        century = parseInt(strCentury);
    }
}

//Checks for two-digit year.
else if (yearToString.length === 2 || 1) {
    century = 1;
}
return century;

}

Tests (custom test code I wrote):

//Runs through nine test cases to ensure the function returns the proper //century for any given year. var testArray = [1905, 1700, 1988, 2000, 2001, 200, 374, 45, 8];

//Iterative loop for testArray. for (var i = 0; i < testArray.length; i++) { document.write("Test Case " + (i + 1) + ": " + centuryFromYear(testArray[i]) + " century" + "<br>");
}

Output:

Test Case 1: 20 century
Test Case 2: 17 century
Test Case 3: 20 century
Test Case 4: 20 century
Test Case 5: 21 century
Test Case 6: 2 century
Test Case 7: 4 century
Test Case 8: 1 century
Test Case 9: 1 century

JavaScript: Strings and Numbers

Since having started my search for a coding school, I have taken full advantage of Flatiron School's free online Bootcamp Prep course.  It appears to provide a lot of the fundamental requisites for success in the developer track

HMLT & CSS

To review, I have gone over HTML and CSS, with which I have a good deal of experience already.  I did, however, gain some additional knowledge that was unknown to me.  Rather, I have worked with these things through raw experimentation, without knowing them by name./

  • Compound Selector
    • h1, h2, #box {...}
  • Descendant Selector
    • #nav li {...}
  • Child
    • #list > li {...}
  • Adjacent Sibling
    • h3 + p {...}
  • General Sibling
    • h2 ~ p {...}
  • Universal
    • * {...}
  • Attribute Selectors
    • img[alt="Cat"] {...}
  • Pseudo Selectors
    • a:link {...}

JavaScript (JS) and the Document Object Model (DOM)

As for JS and the DOM, I have prior experience with this from introductory resources that I've utilized across the web. The bootcamp prep course has been a focus on utilizing the inspector tool with the Google Chrome Developer Tools and how to select certain elements within a page by using JS. For example, in order to find a CSS ID, such as "#height", I would type the following into the inspector Console:

document.querySelector("#height")

This might return something like this:

<p id="height">74</p>

And if I want to get the sole value from the elements returned with the previous code, I can add innerHTML to it.

document.querySelector("#height").innerHTML

This might return something like this:

"74" Now, let's say that I want to add two additional inches to the height. Note that the innerHTML value immediately above is a string and will need to be converted to a numerical value. This can be achieved by using the parseInt() function. Otherwise, if we simply attempt to add 2 to document.querySelector("#height").innerHTML , it will simply return a concatenation of "74" with the 2 , returning a new string value of "742" instead of the number 76 .

Here is an example using parseInt() :

parseInt(document.querySelector("#height").innerHTML)

This will return the following:

"76"

Instead of typing all of the code in the previous example, it can be stored in a variable for easier use and less code in the future.

var heightSelector = document.querySelector("#height").innerHTML

Then we can utilize the parseInt() function again and add two inches to it.

parseInt(heightSelector) + 2 will return the same value as the previous example: "76" .