JACOB SILVER

web developer | musician | venue booker

A Few Brief Words About CSS Modules and Create-React-App v2

I’m a huge fan of Create-React-App. I pretty much use it for every React project I make. I’m also a big fan of CSS modules. For those who don’t know, CSS Modules allow you to scope a CSS file to a javascript file, so you don’t need to worry about duplicate class names or anything like that. It also helps to keep your CSS leaner and smaller, because you’ll be writing many CSS files. One per file, really!

In previous versions of Create-React-App, you had to run “npm eject” in order to enable CSS modules. That can pose a bit of a problem, and the developers only recommend doing that if you really need to. From there you had to go into some settings files and alter all sorts of code, which was not fun either! I kept a pretty long checklist reminding me how to do the step-by-step process, and I always managed to mess a thing or two up every time.

But now, with the release of Create-React-App v2, CSS modules are now fully supported without having to run npm eject. All you need to do now is name your css file “your-file.module.css”. That’s it! Doesn’t get much easier than that. Good times!

Creating a Daily Project Template in Omnifocus 3 with Varying Tasks Depending on the Day of the Week

As an avid user of Omnifocus for both Mac and iOS, I was super excited when the OmniGroup released version 3 of Omnifocus last week. Though it has many awesome changes and new features, all that release really did for me was re-inspire my automation brain, now equipped with more coding skills and experience than ever before. I decided to set out to create a script which I would run every morning that would create a new project for the day with all the tasks I planned on accomplishing that day.
The complicated part was that there is never one day where every task is the same. Let me explain…as a booker for two music venues in New York City, I have tons of emails to write and bands to book. But there’s more than that. I need to send out confirmation emails (I have a detailed confirmation email system involving sending emails out 3 weeks before show date, 2 weeks before show date, and 1 week before show date), do reporting for the night before, setup Evernote notes for the evening’s events for the staff to do reporting on, and much more. Some days I don’t need to send out confirmation emails. This is because at both venues, there is no music booked on certain nights, meaning I don’t need to send out confirmation emails on those dates.
So I set out to make the ultimate script which was able to make a new project every day with day-specific tasks. Here we go:

Set Date Variables

First of all, we’ll need to create the date variable for the title. It will need to be a string, not a date object.

set theDate to date string of (current date)

Next we’ll need to get the day of today (you know - Monday, Tuesday, etc…)

set theDay to weekday of (current date)

And lastly, we’ll need to get today’s date as a date object, and then change the time to 11pm, which will be the time all these tasks will be due.

set dueDate to (current date)
tell dueDate
    set {its hours, its minutes, its seconds} to {23, 0, 0}
end tell

This is some oddball syntax if you ask me. I guess “its” is something akin to Javascript’s “this” keyword, but I dunno, maybe not?

Create Task Variables

I’m sure there’s a cleaner way to do this, likely involving Applescript’s odd way of using subroutines (functions), but this works, and the nice thing about this is that if I need to change anything, I know exactly where to look. Though if this were a javascript app, I’d probably spread most of this code over the span of at least a few files and do imports/exports, React.js style. Anyways, I’m making 14 different arrays. Two arrays per day. Two music venues, so separate arrays per venue. Like this: set petesSun to {"Clear Inbox", "Send 2 week confirmation email", "Send 3 week media request email", "Send 1 week promo email", "Log last night's evernote notebook to BusyCal", "Enter last night's show data to the BusyCal Events", "Make daily Evernote Entry", "Email bands who did well last night"} set pineboxSun to {"Clear Inbox", "Send 2 week confirmation email", "Enter last night's show data to the BusyCal Events", "Make sure every band has submitted show info for tonight's show and email the bands who haven't"}

set petesMon to {"Clear Inbox", "Send 2 week confirmation email", "Send 3 week media request email", "Send 1 week promo email", "Log last night's evernote notebook to BusyCal", "Enter last night's show data to the BusyCal Events", "Make daily Evernote Entry", "Email bands who did well last night"}
set pineboxMon to {"Clear Inbox", "Send 2 week confirmation email", "Enter last night's show data to the BusyCal Events", "Make sure every band has submitted show info for tonight's show and email the bands who haven't"}

set petesTues to {"Clear Inbox", "Send 2 week confirmation email", "Send 3 week media request email", "Send 1 week promo email", "Log last night's evernote notebook to BusyCal", "Enter last night's show data to the BusyCal Events", "Make daily Evernote Entry", "Email bands who did well last night"}
set pineboxTues to {"Clear Inbox", "Enter last night's show data to the BusyCal Events"}

set petesWed to {"Clear Inbox", "Log last night's evernote notebook to BusyCal", "Enter last night's show data to the BusyCal Events", "Make daily Evernote Entry", "Email bands who did well last night"}
set pineboxWed to {"Clear Inbox", "Make Evernote tables for next Thursday-Monday", "Send an email to all bands who have not submitted tech info"}

set petesThurs to {"Clear Inbox", "Send 2 week confirmation email", "Send 3 week media request email", "Send 1 week promo email", "Log last night's evernote notebook to BusyCal", "Make daily Evernote Entry"}
set pineboxThurs to {"Clear Inbox", "Send 2 week confirmation email", "Make sure every band has submitted show info for tonight's show and email the bands who haven't"}

set petesFri to {"Clear Inbox", "Send 2 week confirmation email", "Send 3 week media request email", "Send 1 week promo email", "Log last night's evernote notebook to BusyCal", "Enter last night's show data to the BusyCal Events", "Make daily Evernote Entry", "Email bands who did well last night"}
set pineboxFri to {"Clear Inbox", "Send 2 week confirmation email", "Enter last night's show data to the BusyCal Events", "Make sure every band has submitted show info for tonight's show and email the bands who haven't"}

set petesSat to {"Clear Inbox", "Send 2 week confirmation email", "Send 3 week media request email", "Send 1 week promo email", "Log last night's evernote notebook to BusyCal", "Enter last night's show data to the BusyCal Events", "Make daily Evernote Entry", "Email bands who did well last night"}
set pineboxSat to {"Clear Inbox", "Send 2 week confirmation email", "Enter last night's show data to the BusyCal Events", "Make sure every band has submitted show info for tonight's show and email the bands who haven't"}

What’s also confusing is that the syntax uses curly braces for arrays. Very un-JS!

I’ll also make three more task arrays, one for coding, one for exercise, and one for music. Most of the time I won’t know exactly what I’ll be doing for those until the week-of, or even the day-of, so I’m content to get more specific with the tasks after the project is generated. set codingTasks to {"Work On Coding Project"} set exerciseTasks to {"Exercise at least 45 minutes"} set musicTasks to {"Practice at least 30 minutes"}

Create the New Project and Make Some Tags

Now we can finally do something with Omnifocus. Here we’ll create the new project, and also assign some tags (new with OF3) to some variables to set to the new tasks a little later in the script.
Keep in mind the tags must exist first in Omnifocus, or else AppleScript will throw an error saying it can’t find these tags!

tell application "OmniFocus"
    activate
    tell default document
        -- Set Tag Variables
        set petesTag to first flattened tag where its name is "Pete's Candy Store"
        set pineBoxTag to first flattened tag where its name is "Pine Box Rock Shop"
        set codingTag to first flattened tag where its name is "Coding"
        set musicTag to first flattened tag where its name is "Music"
        set exerciseTag to first flattened tag where its name is "Exercise"


        -- Make a new Omnifocus Document
        set theProject to make new project with properties {name:theDate, due date:dueDate}

Great! Now we have a new project whose name is the current date, and is due at 11pm today.

Make Parent Tasks

I like to have “parent” tasks. Meaning, for Pete’s Candy Store (one of the venues I book), there will be a task called “Pete’s Candy Store”, and beneath it will be all the tasks for Pete’s Candy Store. Same with the other venue, Pine Box Rock Shop, as well as Coding, Music and Exercise.

tell theProject

            -- Make Parent Tasks
            set petesParentTask to make new task with properties {name:"Pete's Candy Store", primary tag:petesTag}
            set pineboxParentTask to make new task with properties {name:"Pine Box Rock Shop", primary tag:pineBoxTag}
            set codingParentTask to make new task with properties {name:"Coding", primary tag:codingTag}
            set musicParentTask to make new task with properties {name:"Music", primary tag:musicTag}
            set exerciseParentTask to make new task with properties {name:"Exercise", primary tag:exerciseTag}

So now in our project we have 5 tasks, all with 11pm due dates and tagged accordingly. Nice!

Create Child Tasks

Now for all the fun stuff. This will create new tasks from the items in the arrays defined above, and will designate them as “children” to whatever parent task we set it to. Like so: -- Make Tasks Depending On Day Of Week if weekday of (current date) is Sunday then repeat with theItem in petesSun set petesTask to make new task with properties {name:theItem, primary tag:petesTag} move petesTask to end of tasks of petesParentTask end repeat repeat with theItem in pineboxSun set pineboxTask to make new task with properties {name:theItem, primary tag:pineBoxTag} move pineboxTask to end of tasks of pineboxParentTask end repeat

else if weekday of (current date) is Monday then
                repeat with theItem in petesMon
                    set petesTask to make new task with properties {name:theItem, primary tag:petesTag}
                    move petesTask to end of tasks of petesParentTask
                end repeat
                repeat with theItem in pineboxMon
                    set pineboxTask to make new task with properties {name:theItem, primary tag:pineBoxTag}
                    move pineboxTask to end of tasks of pineboxParentTask
                end repeat


            else if weekday of (current date) is Tuesday then
                repeat with theItem in petesTues
                    set petesTask to make new task with properties {name:theItem, primary tag:petesTag}
                    move petesTask to end of tasks of petesParentTask
                end repeat
                repeat with theItem in pineboxTues
                    set pineboxTask to make new task with properties {name:theItem, primary tag:pineBoxTag}
                    move pineboxTask to end of tasks of pineboxParentTask
                end repeat


            else if weekday of (current date) is Wednesday then
                repeat with theItem in petesWed
                    set petesTask to make new task with properties {name:theItem, primary tag:petesTag}
                    move petesTask to end of tasks of petesParentTask
                end repeat

                repeat with theItem in pineboxWed
                    set pineboxTask to make new task with properties {name:theItem, primary tag:pineBoxTag}
                    move pineboxTask to end of tasks of pineboxParentTask
                end repeat


            else if weekday of (current date) is Thursday then
                repeat with theItem in petesThurs
                    set petesTask to make new task with properties {name:theItem, primary tag:petesTag}
                    move petesTask to end of tasks of petesParentTask
                end repeat
                repeat with theItem in pineboxThurs
                    set pineboxTask to make new task with properties {name:theItem, primary tag:pineBoxTag}
                    move pineboxTask to end of tasks of pineboxParentTask
                end repeat


            else if weekday of (current date) is Friday then
                repeat with theItem in petesFri
                    set petesTask to make new task with properties {name:theItem, primary tag:petesTag}
                    move petesTask to end of tasks of petesParentTask
                end repeat
                repeat with theItem in pineboxFri
                    set pineboxTask to make new task with properties {name:theItem, primary tag:pineBoxTag}
                    move pineboxTask to end of tasks of pineboxParentTask
                end repeat


            else if weekday of (current date) is Saturday then
                repeat with theItem in petesSat
                    set petesTask to make new task with properties {name:theItem, primary tag:petesTag}
                    move petesTask to end of tasks of petesParentTask
                end repeat
                repeat with theItem in pineboxSat
                    set pineboxTask to make new task with properties {name:theItem, primary tag:pineBoxTag}
                    move pineboxTask to end of tasks of pineboxParentTask
                end repeat

            end if

And finally, we’ll do the same with Coding, Exercise and Music:

repeat with theItem in codingTasks
                set codingTask to make new task with properties {name:theItem, primary tag:codingTag}
                move codingTask to end of tasks of codingParentTask
            end repeat


            repeat with theItem in exerciseTasks
                set exerciseTask to make new task with properties {name:theItem, primary tag:exerciseTag}
                move exerciseTask to end of tasks of exerciseParentTask
            end repeat


            repeat with theItem in musicTasks
                set musicTask to make new task with properties {name:theItem, primary tag:musicTag}
                move musicTask to end of tasks of musicParentTask
            end repeat

…and then we’ll close off the tell blocks.

end tell
    end tell
end tell

And voila! We now have a killer everyday template to use and abuse. The full code can be downloaded on my GitHub page at: https://github.com/jacobsilver2/OmniFocusDailyProjectTemplate

Thanks! Jake

React Context API

React’s new Context API is great way to access properties from nested components without having to send down props from one component to another, and another, and another… It works a bit like Redux. I’m thinking it’s best to use for apps that might not need all the power of Redux, but still need some basic central “store”. It works like this:

First of all make a new React project with create-react-app. Then once you’ve cd’ed into your new react app, make sure you’re using the latest version of React. Do that by typing into your terminal npm install react@next react-dom@next.

In order to use Context, you’ll need to make a new React component to hold the “store”. So first, we’ll make our app component.

class App extends Component {

    render() {

    return(
        <div>
        <p>Hello</p>
        </div>
    )}}

And then we will create the store, or the “provider”. We will store our state in here.

//make sure to make a new context from React
const TheContext = React.createContext();

class TheProvider extends Component {
    state = {
        user: 'Jacob',
        posts: 0,
    }

    //you need to return a context provider

    render() {
        return(
        <TheContext.Provider value={{
            state: this.state
        }}>
        {this.props.children}
        </MyContext.Provider>
        )}
}

And then after that, you need to wrap your App component in the new provider component. Don’t forget to import it!

class App extends Component {

    render() {

    return(
        <TheProvider>
            <div>
                <p>Hello</p>
            </div>
        </TheProvider>
    )}}

After that, any child will be able to access the data within the provider! So, if we made another component called, User, and rendered it from our App component, like so:

class User extends Component {
    render() {
    return(
        <div className="user">
            <TheContext.Consumer>
                {(context) => (
                //note that you need to use React.Fragment when rendering multiple pieces of state!
                <React.Fragment>
                    <p> User: {context.state.user}</p>
                    <p> Posts: {context.state.posts}</p>
                </React.Fragment>                
                )}
            </TheContext.Consumer>
        </div>
    )}}

class App extends Component {

    render() {

    return(
        <TheProvider>
            <div>
                <p>Hello</p>
                <User />
            </div>
        </TheProvider>
    )}}

Pretty cool! In another post I’ll demonstrate how to update/remove, or anything really via the Context Api. Hint: It works a lot like dispatch/reducers/actions.

Fetch

fetch() is a javascript function which allows you to make network requests. It uses promises, which allow for asynchronous requests.

A basic fetch request looks like this:

fetch('./api/party.json')
.then(response => { // do something here }

The response that it returns is actually just the status of the request. We need to convert the body to JSON before we can do anything with the response. For that, we use resonse.json to convert. For example, to get a list of all my repos in my GitHub repository, it would be like this:

fetch('https://api.github.com/users/jacobsilver2/repos')
    .then(response => response.json())
        .then(data => {
            console.log(data)
})

Easy! Now, if you want to post data, it’s not a whole lot different either. You just need to make sure you add a few other parameters (options). It’s like this:

let myData = { data: 'data' }

fetch('./api/party.json', {
    method: 'post',
    headers: {
        'Content-Type': 'application/json'
    },
    body: JSON.stringify(myData)
})

Awesome! And it’s not a whole lot different for patch, put, or delete requests either.

It’s also a good idea to have some sort of error-handling as well, because there are many reasons why a fetch request would fail, like, for example, if the internet is down, or if a record doesn’t exist, etc. For that, you need to add a little bit more code at the end. Like this:

fetch('https://api.github.com/users/jacobsilver2/repos')
    .then(response => response.json())
        .then(data => console.log(data))
            .catch(error => console.log(error)

Though…it’s actually not that simple. Mostly because fetch mostly just cares if there is a response returned or not. If there is no response, it will go to the catch portion of the code. But if the response is something like record does not exist, that is technically a response, so it won’t get to the catch. So what I like to do is write a separate function to deal with the response. Like this:

function handleErrors(response){
  if (!response.ok) {
    throw Error(response.statusText);
  }
  return response;
}

There are other bloggers who have written much more elaborate response functions, for example, at css-tricks.com, they use:

function handleResponse (response) {
  let contentType = response.headers.get('content-type')
  if (contentType.includes('application/json')) {
    return handleJSONResponse(response)
  } else if (contentType.includes('text/html')) {
    return handleTextResponse(response)
  } else {
    // Other response types as necessary. I haven't found a need for them yet though.
    throw new Error(Sorry, content-type ${contentType} not supported)
  }
}

function handleJSONResponse (response) {
  return response.json()
    .then(json => {
      if (response.ok) {
        return json
      } else {
        return Promise.reject(Object.assign({}, json, {
          status: response.status,
          statusText: response.statusText
        }))
      }
    })
}
function handleTextResponse (response) {
  return response.text()
    .then(text => {
      if (response.ok) {
        return json
      } else {
        return Promise.reject({
          status: response.status,
          statusText: response.statusText,
          err: text
        })
      }
    })
}

But however you decide to do it, your initial fetch request would have to be slightly refactored to something like:

fetch('./api/party.json')
  .then(handleResponse)
  .then(data => console.log(data))
  .catch(error => console.log(error))

But however you decide to do it, know that it is now MUCH easier than the previous method of using XMLHttpRequest or jQuery!

React-Redux-Rails Portfolio Project

EventTracker

EventTracker is my Flatiron Portfolio project for React/Redux. It uses Create-React-App, as well as a Rails backend to serve the API. It incorporates React Router, along with Thunk middleware to handle asynchronous API calls.

It is a simple to use event creator. It allows the user to create events, inputting name, date, time, location and notes, and have them save to the backend and displayed on fancy cards! The user is then able to add more events, edit events, and delete events.

Setting all of this up was the real challenge. There are so many little things all working together. I imagine once you do this a few times you start getting the hang of it, but little things like hooking up Rails to React, and making sure CORS was not an issue or anything presented itself to be quite challenging right from the get-go. But once that was setup, as well as the script to run rake start in the terminal and have it boot up the rails backend at localhost:3001 and then boot up the npm server at localhost:3000, we were in business!

On the React-Redux side, it felt good to finally get my actions and reducers both working hand in hand. Again, that is something that probably takes a bunch of projects to really get the hang of, so for me, this was difficult from start to finish. There were many syntax problems in both the actions and reducers that prevented the app from working all throughout the project that took me many hours to get through!

But once that all was sorted out, I was able to get the app looking a little nicer, and was able to build out more functionality. That felt good.

Overall, it was a huge learning experience and I can’t wait to get back into the it and make more stuff.

There are still a few bugs that I’d like to fix. First of all, deleting an event requires a refresh in order to show on the page. Not sure why that is, but I’d like to fix that, of course! I’d also like to be able to edit and delete directly from the cards, and not have it done on separate pages.

In future versions, I’d like to be able to add user accounts, OAuth, as well as be able to query popular event websites like Eventbrite and add them to the database of events.

var, let, const, hoisting, scope, and functions

Variables

Javascript has three ways of defining variables: var, let, and const. They have sometimes subtle, other times dramatic differences. Below I will explain the basic functionality of each.

var is the oldest method of defining variables in Javascript. It is able to be redefined and updated. For example, if you define var name = "john" and later define name = "tim", and then console.log(name), the result should be tim.
var variables are also scoped to the function they are initially declared in. Meaning, if you declare this function

function createName() { 
    var name = "john"; 
    console.log(name)
    }; 
createName()

, and later in your code write console.log(name), you will get an error because the variable name is only defined within the scope of the function it was declared in. The only way for that example to work would be if you declared the variable name outside of any function, therefore making it global, and then accessible via any scope, like this:

var name = "john"
function createName() {
    console.log(name);
};
createName(); //log: 'john'
console.log(name) //log: 'john'

This can sometimes create some unexpected problems though, as var variables are not “block scoped”. For example, in this code

var name = "john"; 
if (name === "john") {
    var lastName = "smith"; 
    console.log(`${name} ${lastName})
}; 
console.log(lastName)

, your last console.log statement would return “smith”. This is because the var variable is not block scope. Enter let

let is the newer variety of variable declaration in Javascript. It serves a similar purpose as var, but has a few advantages, one of which being that it is “block-scoped”. Another interesting thing about let, is that if you declare the same variable name with let, but define them in different scopes, it will actually create two separate variables (because it is block scoped), whereas let will re-assign the already declared variable.

const is the newest of the three types of variables. Const is short for, you guessed it, constant. Meaning, it can’t be changed. However, one aspect to note is that if you define a const variable and assign it the value of an object, the properties within that object can change. So in that sense, const is changeable, but it’s value still can’t be re-assigned.

Hoisting

[W3Schools.com] https://www.w3schools.com/js/js_hoisting.asp defines hoisting as:

Hoisting is JavaScript's default behavior of moving all declarations to the top of the current scope (to the top of the current script or the current function)

Meaning that no matter where the function is defined within the document, it will be “hoisted to the top”. Note that this only hoists the function declaration, not the function initialization.
This allows you to do something like this (not advised though!)

myFunc();

function myFunc () {
  return 'Hello, world!';
}

//returns 'Hello, world'

This works because the function declaration was hoisted to the top. However, if we do something like this:

function myFunc () {
    console.log(name);
    var name = 'john'
}

myFunc();  //undefined

It will return undefined. This is because even the though function was hoisted to the top, the variable declaration didn’t happen until after the console.log statement. The solution would be to move the var variable to the top of the function declaration, or to take it out of the function and instead make it global. However, the best method would be to use let or const instead.

Named functions, anonymous functions, and arrow functions

Before ES6, there were essentially two ways to define a function: Function declarations and function expressions. A function declaration is like this:

function functionDeclaration() {
    console.log("hi");
)

And a function expression is like this:

var functionExpression = function () {
    console.log("hi")
}

The biggest difference between the two is that a function declaration will be hoisted to the top, whereas a function expression will not.

Arrow Functions

ES6 introduced a new way to create functions: the arrow function. It looks a little different, and also behaves slightly different as well. An ES6 function is written like this:

const helloWorld = () => 'Hello World!';

Besides being more concise, and easier to read, there are some key differences, mainly, with the this keyword. Because we so often use nested functions (functions within functions), it is necessary to make sure the this keyword gets carried over to the lower function. In previous versions of javascript, this was done using the .bind() method, and binding to self. Because arrow functions now allow you to retain the scope of the calling function, that is no longer needed, which makes things like making api calls more clearer and more concise.

JS-Rails with jQuery and Ajax Requests

For me this project was a great way to experience the wonderful world of “refactoring”. The refactoring process for this project was really a three-stage process.

The first stage involved creating the homepage markup to allow for content to be inserted dynamically. For that, I created a new home controller. I edited the routes.rb file so that the root directory would be home#index, and created the index.html file inside views/home. In there, I created a pretty basic markup structure with only a few div elements, container, message, shows, and acts.

The second stage was where the real work occurred. It involved firstly, creating event listeners and handlers on the existing div elements, and secondly, changing the get and put requests from the existing Rails style to jQuery. Getting the event listeners coded properly, as well as the get/put requests to do the right things was a little challenging, as it involved careful creating of the flow of object ids. For example, if I was to create a new Act, which was to be associated with a specific show, that put request would have to know the show id. Most of the time this could be coded within the id element of the html markup.

The third stage involved creating Javascript class methods. To be honest, it probably would have been easier to create these class methods first, as it is easier to visualize the passing of class/object parameters then it is via html id elements (or, at least it is now, having spent so much time with Rails over the past few months).

I created two method prototypes within the Show class, the first one is renderShowButton(), and the other was viewShow(). These methods allowed me to render html elements without having to pass in any other data, which was great!

There are a few bugs and todos still remaining, which I will fix at a later date. First of all, Facebook Oauth seemed to stop working. I believe it might be because Facebook recently changed its privacy policies. I opted not to fix it for this lab, and instead spend the time on the actual requirements of the lab. Also, in the previous portfolio project, I used a gem called combined-time-select, which didn’t seem to work very well with all the new jQuery additions. In fact, it consistently reported show times as five hours early than selected. In a future revision, I will remove this gem, and instead use the bootstrap dateTime picker. Also, my functions are primarily the older method, not the new ES6 style. And lastly, I’d like to include full CRUD functionality with the jQuery/Ajax style. For now, it’s only create and read.

Rails Portfolio Project

# Rails Final Project

Working on this project was by far the biggest challenge I've worked on since enrolling at the Flatiron School.  It took me about two weeks and probably around 30-40 hours to complete, and I still feel like there's lots more work to be done.  There were many features I had hoped to put into this project that I eventually had to scrap, mostly because in the end I decided it was more important to submit something that works instead of working for 2 months on something that might work, might not!  Plus, even at the state that it is at, I do believe it satisfies the requirements of the project.

The app has 3 models, plus one more which operates as the join table via a has many through association.  The three models are User, Show, and Act.  The join model is called ActShow.  The User has many shows, the Show has many Acts through the ActShow, and the Act has many Shows through the ActShow.

Upon successful login (via a local login system or Facebook), the user is given the option of creating a new show.  Once that new show is created, the user can create acts which will be added to the newly created show.  Validations ensure that there aren't two shows on the same date, or that an act is created without a name or contact email address.  The user can add as many acts as they wish to the show.  From there, the user can edit the acts (including selecting an act to be the "headliner", which is an attribute residing on the join model), delete acts, or even delete the show entirely, which also deletes the associated acts.  

There are two additional views which allow the user to view either today's show, or all the shows occurring this week.

# Issues
The main issue I faced was dealing with acts.  I was hoping to have the option of adding an already-created act (in a different show), to a new show, but eventually had to scrap this feature after many, many hours of coding, and more than a few sessions with instructors, which led nowhere.  In a real booking application, this would be a necessary feature which I hope to one day learn how to implement properly.
Another issue I faced was with validations.  I attempted to enforce much stricter validations, but was met with mismatched join-table records, params not passing, and other frustrations which ultimately led me to stick with a lighter validation system.  Again, this is something I really hope to one day get a much better grasp on.

# Conclusion
All in all, this was incredibly rewarding, but was equally frustrating, for every time I fixed one thing, it broke 10 other things.  I guess that's part of programming!  I can say that I learned TONS about Rails in this process, and can't wait to jump back in and do more projects.

Ways to Learn the Most From Video Reviews

The video reviews can be a challenge.  Often times the pace is WAY too fast, and you need to go back 100 times to see what the instructor did, or other times, the video is 2 hours long, and you don’t really feel like sitting the the whole lecture :).  Here are a few tips for maximizing your learnin’ while watching these videos.

First, download the videos!  The is not the most straightforward process, but since we’re all coders, it shouldn’t be too bad.  I use a great tool called Youtube-dl.  It can be downloaded with Homebrew on the Mac.  Just enter the following command into your terminal. `brew install youtube-dl.`.  From there, navigate in your browser to the video you’d like to download, right-click and choose “copy video url”.  Then go back into your terminal and type in `youtube-dl + The URL of The Video You'd Like To Download`.  Give it a few minutes and you’ve downloaded the video!  (Btw, make sure you are currently in the directory where you’d like the video to download to).  
From there, I like to open the video in VLC.  VLC let’s you watch the video at different speeds, so if you need to speed up or slow down the video, it’s super easy.

Another important tip is to really try and follow the train of thought by the instructor.  Understanding that is one of the keys to programming.  Try to truly understand why the instructor did something a certain way, and how he or she came to that conclusion.  If they didn’t know how to do a certain thing, pay close attention to how they figured it out: What they googled, code they tried, etc.  It’s inspiring to see someone not get frustrated, and to just solve the problem!  Also pay close attention when they get errors and can’t figure out how to fix it.  That is such a common problem, and one of the most important aspects of programming, and to see techniques for how to dig yourself out of that hole are invaluable!

I used to try and code along with the instructor.  Now I believe that’s not the best technique.  I think it’s more important to just watch closely, take a few notes if you have to, but coding along will probably mean you’ll end up with tons and tons of typos in your code, and you’ll spend too much time trying to fix those little errors, and you won’t internalize whatever programming concept the instructor was trying to teach.

Good luck!

Struggles with Logic and Conditionals

Struggles With Logic and Conditionals

A beginning is a very delicate time. Know then that it is the year 2018, and understanding conditionals is one of the most important aspects of learning to code.

It really does seem easy when someone gives you a real-world example of a conditional. Like, "If the milk is green, don't drink it. Otherwise, drink up!". That makes sense. But somehow in the early days of understanding the logic and the flow of coding, conditionals can get really, really confusing.

One of the toughest parts of understanding conditionals was all the 'opposite ' conditionals. Like, in the milk example, it might make more sense in code speak to say something like, "If the color of the milk equals green, do whatever the inverse of drinking is. Something like !drink would be how it might look. So it can be quite common to have to do all these little bits of logical acrobatics in order to understand why something would evaluate one way or another. 

Another example, more in line with something you might actually see deep within the folds of code , would be something like this:

if a <= b && b <= c

    puts "do this"

else

    puts "wait, do this"

end

In this statement, the code is making two evaluations, and if they are both true, the code in the first block will execute. Otherwise, the code in the else block will execute. So, if a is equal to or less than b , AND b is equal to or less than c, then you are free to pass safely within the mines of Moria (random LOTR reference).

For the most part conditionals are that simple. Of course, with all things coding, it can get really complicated, really quickly. Nested conditionals can add extra layers of confusion upon first glance, but usually if you stop and slow down, you'll get the logic of it all.

There are also many ways to write a conditional. I suppose most coders develop habits over time and start writing the conditional statements which are most comfortable to them, and upon seeing new ones can get freaked out. I know, because it's happened to me! Just take your time, go slow, and make sure to google everything you don't understand!

 

Showkeeper

I had an idea early on during the Flatiron section on ActiveRecord and Sinatra to  design an app which would be based on my job as a music venue booker.  A booker constantly needs to create new shows at the venue he or she books at, and needs to modify that event many times throughout the booking process.  So I decided to create an app that does just that.  Because I'm still a little early on in my understanding of relational databases, I chose to not implement all the functionality I would actually need to use this tool, but to create more of a starter project for something I might eventually create as my skillset and knowledge for the subject increases.  Basically, I kept it simple.  A user(or, booker) is able to create an account, choose the name of the venue they book for, and create and modify shows.  
In terms of what that means in ActiveRecord speak, it means a User(venue) "has many" shows, and that shows "belong to" a user.  I created two databases: One to manage the users(venues), and another to manage the shows and the users(venues) they were associated with.  
The user is then able to go in and create as many shows as they'd like.  They can input relevant information for that particular show, including the headlining act, support act, start date, start time, a short description of the show, and a website for the headliner.  The user is then able to view all the shows in their database, and modify any of the shows.
The app uses restful routes and uses the CRUD method to create shows, read shows, modify (edit) shows, and destroy (delete) shows.  Hopefully we won't have to use that last method too much, because venue bookers hate cancellations!

Comparing Basic Programming Fundamentals To Music

Often times when I get stuck with a particularly vexing programming dilemma, I'll try and think how I can relate the issue to music, something I'm quite comfortable with.  For example, when I was first learning about the concept of functions and methods, and how they took arguments passed into them, I would think about how I hook up my studio gear.  The way sound gets passed through one component to another is a slightly similar concept (ok, there are actually many differences when you really think about it, but that's fine).

Another fun thing I like to think about is how there's so many ways to do the same thing in programming.  The different ways you can iterate over collection sometimes reminds me of all the different ways you can play the same thing on an instrument.  Like, on bass, I could play one baseline in like 5 different spots on the neck.  Each one would sound slightly different.  Similar concept with enumerables, only the results don't necessarily sound different...but they do produce different results!

For a beginning to intermediate programmer, relating core concepts to things you are already familiar and comfortable with is a good idea.  It helps to make programming less scary and more friendly.

CLI Data Gem Project

CLI Data Gem Project

For this project, I decided to create a CLI Gem that would scrape vintagebassworld.com, to give the user data about many different vintage bass guitars. Since I am a bassist, I found the project to actually be super informative and actually really helpful! 

My original approach to coding this was based on Avi's video, CLI Gem Walkthrough. At first, everything was going great, but because I was perhaps a little too ambitious about how I wanted the data to be structured, I hit a wall pretty hard. I was assuming it was going to be easy to be able to search by Brand, Model, or Year. That proved to be very difficult, because searching by year would have to be a massive web scrape of over 100 websites within the vintagebassworld.com domain. So after a full day of coding, I decided to scrap everything and start over with a simpler, more top-down approach.

After watching Avi's second video, https://www.youtube.com/watch?v=Y5X6NRQi0bU, I decided to model my 2nd attempt after this structure (with some of the original structure as well). This worked out well, and was much simpler for me to see the data flow, as it was more in line with the code I've been working with in previous Flatiron lessons. My top-down approach made sense too. The user is presented a list of 5 brand to choose from (this was hard-coded. I didn't see it necessary to scrape the website for the brand names). Once the user makes their selection, a new instance of the Scrapermethod is created, which in turn creates a new instance of the of the Brand class. Once that happens, all the other Scraper methods are able to do their thing. The #scrape method is able to return a list of all the available models of that particular brand, and at the same time, make new instances the Model class, and add those newly created classes to the Brand instance. The user chooses which model they are interested in, from there the #scrape_instruments method is called, which returns a list of every year that particular brand was manufactured. It also creates a new instance of the Instrument class, and adds each instance to the Modelsobject.

Once the user chooses which particular year they are interested in (or, as it is defined within the code, Instrument, the scrape_description method is called, returning the description, as well as adding the description to the instance of Instrument. 

I had some major challenges doing the scraping, because the website I was scraping from is old, and has all sorts of weird drop-down menus, and menus within menus and all that confusing stuff. Also, the site was not coded with specific CSS class names. At best there were 3 or 4 CSS classes to start from. Eventually I determined the best way to get the data was via XPATH. Not ideal I guess, but it did work. After a few refinements, I was able to get data via iteration. One big challenge I had was string interpolation within an XPATH. When finding XPATH links on Chrome, quotes for CSS classes are single quotes. It took me some time to realize why my string interpolations weren't working: Because the #{}syntax only works with double quotes!!! I also learned about escape sequences within a string. Like, when you need to actually have a quote inside a string. So I learned about ` and all that good stuff. 

All in all, a great project! I was great to go out on my own and learn how to do things without the option of asking a question on learn.co. All that trial and error throughout the process, as well as all the research, is what it's really all about.

Why I Decided To Learn Software Development

I first got excited about software development when I learned how to automate computers.  As a booker for music venues, I found that I could cut down my time doing tedious, repetitive tasks by at least half.  Doing this allowed me to focus my energy on booking good music.  It also created a more stable system of booking. It meant less typos, double bookings, miscommunications, and cancellations.  At some point, I started keeping track of every little thing I had to do more than once.  Anything that made that list would be automated.  I got every piece of software that could help with the automation process.  I learned AppleScript, and used it to control just about everything.  
I was so proud of all my scripts, I showed them to a few of my programmer friends.  The response I got was basically, "Dude, you're about 3 steps away from being a programmer.  You should just learn programming!"
It was around that point that I realized that I really enjoyed the process of scriptwriting and automation, not just because of all the time I was saving, but because it was really fun and challenging- I got a kick out of it!
So I started messing around with JavaScript, HTML, and CSS.  I took a few starter courses online, and had a really good time with it.    After doing a few of those courses, I realized I wanted to take it a step further and really learn how to use these tools.  I tried the Flatiron Bootcamp Prep course.  It was definitely the most challenging of all the programming courses I had tried.  But again, I really enjoyed the challenge and loved working my brain in that way.