Transferring hard skills across industries

tl;dr
It took some time and distance from my career switch — I personally transitioned from the education world to the technosphere — to have a clearer perspective on the process. I’ve come to the perhaps unsurprising realization that the main similarities between coding and teaching are the hard skills and not the soft, and I’m convinced that this applies to all career changers or potential career changers.

There are different definitions extant for what constitutes a hard and soft skill; this quora post represents the two main viewpoints fairly well. For myself, rather than define hard skills as those which are immutable to a given industry, I’d prefer to define them as those which are immutable to you. After all, why should you have to do all the changing? Admittedly, there is already an existing industry out there, with more domain-specific vocabulary than you can ever hope to internalize, let alone parrot back to your coworkers in an attempt to sound informed. Yet at the same time, you bring your own domain-specific vocabulary with you wherever you go, and you can temper your own feelings of being an imposter by identifying and leveraging them.

For example, if you’ve worked as a barista, I can guarantee that you don’t just know how to serve coffee, and that you don’t merely know how to wear many hats in a demanding sales environment. Those skills may appear to vanish the minute you change your industry, but your experiences and abilities remain with you – they form the core of your transferrable hard skills, and help define your arc as a professional.

For myself, I am not content to leave behind my domain-specific knowledge and acquire new domains. I have a core of hard skills that I bring with me wherever I go, communication and facilitation, which stem from more personal qualities: patience, an open mind, and an ability to consider a problem from any angle. Rather than watering my previous skills down into their softer counterparts and then building them back up (as the received narrative often suggests), my commitment to change industries has only hardened my existing professional skills.

Configuring a backend Rails API

This post assumes you want to configure a new Rails app to use as a backend API. It will lead you through the following steps:

  1. using the rails new api command
  2. writing namespaced routes
  3. using the rails g serializer command
  4. setting up controller endpoints
  5. making the app JSON-API compliant
  6. changing CORS settings

Your first point of resource, before continuing any further, should always be to visit the relevant Ruby-on-Rails documentation. If you’d also like to read something that gets under the hood to detail exactly what makes a Rails API application more streamlined than its fuller counterpart, check out this article by Leigh Halliday. Let’s get started:

rails new –api -T

Pro Tip: Append a pretend -p tag to your command and Rails will mock and display the new resource so you can preview it before creating all those extra files.

This command will get your new API application up and running like magic, but let’s not take the magic for granted. Here’s a little glimpse of what it generates:

Pro Tip: You may need to remove some gems from your Gemfile, because they are unused or actively troublesome with the API configuration. I personally only had to uninstall turbolinks, but YMMV.

/config/routes.rb

If you have your resources and your basic endpoints, this part is pretty straightforward (don’t be afraid to revisit the documentation). Draw all your routes within an API namespace like so:

Rails.application.routes.draw do
namespace :api, defaults: {format: :json} do
namespace :v1 do
resources :words, only: [:index]
get '/words/:text', to: 'words#show'
post '/words/:text', to: 'words#create'
end
end
end

Just remember that, not only are you able to declare dynamic parameters to be carried within your app’s URLs, but you must declare them here if you want JSON payloads to be accessible to the relevant controller.

rails g serializer

Take a minute now to set up your models and attributes, otherwise you won’t know what to serialize — and make sure the namespacing is consistent. In the meantime, here’s the link to the serializer’s stable github repo. Add gem ‘active_model_serializers’ to your Gemfile and you’re all caught up!

I had two models with a has-many relationship, so I had two serializers:

Screen Shot 2019-06-12 at 2.32.31 PM

Screen Shot 2019-06-12 at 2.32.41 PM

Controller endpoints

You need to create a folder structure for your controllers that mirrors your routing namespace, such as: /app/controllers/api/v1/words_controller.rb

Don’t forget to whitelist your incoming params in a private method, and that those params match the namespaces you defined in config/routes.rb and app/serializers.

After you determine which endpoints you will need for your app, make sure they are declared as routes, and you are ready to interacting with your model data based on incoming params! This is the good stuff, and I can’t do it for you, but I can show you how I handled three basic requests:

Screen Shot 2019-06-12 at 2.43.37 PM
Screen Shot 2019-06-12 at 2.44.06 PM

Pro Tip: If you want to explicitly include model associations in the JSON rendered by your controller as I’ve done above, the workaround is to use Rails’ built-in to_json() method, inside of which you can specify the associations you want to include. Read more about it in this StackOverflow thread.

JSON-API compliance

Don’t you want your code to be compliant with international standards? Create a new file /config/initializers/active_model_serializers.rb and paste the following snippet, which tells the serializers to utilize a top-level object called data, as per the standard:

Screen Shot 2019-06-12 at 3.05.26 PM

CORS settings

Unfortunately, your shiny new app won’t work as a server unless you’ve configured it to accept cross-origin requests over the web. To fix this, personalize and include the following inside the code block in /config/application.rb:

Screen Shot 2019-06-12 at 2.56.15 PM

And that’s it! Congratulations, you’ve configured your new Rails app as a backend API.

Quick and dirty $BASH shell scripting to streamline your Learn.co workflow

One of the wonderful things about the Learn.co curriculum, and no doubt one of the reasons they’ve designed it this way, is that we have to interact with git and the command line on a daily basis in order to access the lessons, each of which resides in its own github repository. There is, of course, a necessary side-effect of this: a seemingly endless litany of terminal commands (directory-changing, lesson-forking, editor-opening, dependency-installing, etc.) Empowered by my growing intimacy and seeking to embody the DRY principle in my own programming practices, I began to look into a way to automate the series of commands that I, and most likely others like me, had to repeatedly run.

Without further ado, here are the contents of my bash script, with copious comments:


#!/bin/bash
# Note: the file must begin with the above line, telling the interpreter that it must be read in the bash environment
#
# Note: because the script involves running commands that change directories, it must be run with the source command.
# example/ if this file is titled `learn.sh` it must be run as a source script: `. learn.sh` or `source learn.sh`
#
read -p "Enter lesson url: " url
# the `read` command prompts the user for input and then assigns that input to a variable, in this case ‘url’ because we are expecting a string representing the url of a github lesson
#
git clone $url
# we can use the ‘$’ sign to access the variable inside the file
#
url=${url##*/}
# here we strip the inputted path of everything preceding the last backslash.
# note that if we operate on a variable while accessing it, we must wrap the whole expression in curly brackets
#
url=${url%%.*}
# here we strip the inputted path of its trailing file extension. the value of the url here should be equivalent to the name of the repository we are cloning, as well as name of the new directory created by the `git clone` command
#
# strip trailing carriage return
url="${url//'\r'}"
# for good measure, we strip of any trailing carriage returns because they were proving troublesome
#
echo "Moving into the lesson directory..."
cd ${url}
# change into the newly created directory, whose name matches the value of our ‘url’ variable
#
echo "Opening in atom..."
atom ./$url
# open the new directory in our favorite text editor
#
echo "Installing dependencies..."
bundle install
echo "Running 'learn' command..."
learn
echo "All set!"
#
echo "Note: opening in Atom currently generates a spurious blank file with the lesson name inside the lesson directory. You may safely close this generated blank file without saving."
echo "Note: if there are dependency compatibility issues you may need use rvm or npm where appropriate”

Those last comments, echoed out to the user’s terminal, provide me with a stark reminder that things always break and need recalibrating. As I enter more deeply into the javascript section of the curriculum, it becomes clear to me that I’ll have to continue to tweak this script to satisfy my penchant for DRY-inspired automation!

Setting up some basic calendar functionality in Rails

For my first RoR web application, I wanted to build a food intolerance tracker that allows users to keep a log of the foods they eat and the symptoms they experience, in order to help them correlate the symptoms with those foods. In the process of planning my models, the first thing I realized was that I would have to track the effects of foods and symptoms across two or more days (not only given the complex interactions between our diet upon our health, but also because it would be a good challenge).

So in order to keep track of the days in relation to each other, I needed something like the functionality of a calendar. Perhaps some instance methods like this:

@day.previous_day
—-> Day.find_by(id: self.id - 1)
@day.next_day
—-> Day.find_by(id: self.id + 1)

But while auto-generated IDs are unique and tell you the location and relative position of each object in the database, they have no correlation to human time-keeping scales. I needed date-relevant attributes, so I worked backwards from the schema that I wanted my days to have:

# db/schema.rb
create_table "days" do |t|
  t.integer "date"
  t.integer "month"
  t.string "month_day_year"
  t.string "day_of_week"
  t.string "comments"
  t.datetime "created_at"
  t.integer "user_id"
end

To do this, I turned to Ruby’s built-in Time.strftime method to generate further attributes from ActiveRecord’s built-in :created_at attribute.

Working backwards from the details I needed to display to the user, I wanted each Day object to exhibit the following behavior:

@day.date
—-> self.created_at.strftime(“%d”).to_i
@day.month
—-> self.created_at.strftime("%m").to_i
@day.month_day_year
—-> self.created_at.strftime("%m-%d-%y")
@day.day_of_week
—-> self.created_at.strftime("%A")

The glaring problem with this is that #created_at is generated AFTER valid object creation. Enter ActiveRecord callbacks, which enabled me to create a Day using standard parameters (in my case, an integer representing today’s date and a user_id) and then, after creation, setting the date-related attributes. In particular, the after_commit callback provides lots of options, and is worth saving for future notice.

# app/models/day.rb
after_commit do |day|
  day.set_date if day.date.nil?
  day.set_month if day.month.nil?
  day.set_day_of_week if day.day_of_week.nil?
end
def set_date
  self.date = self.created_at.strftime("%d").to_i
end
def set_month
  self.month = self.created_at.strftime("%m").to_i
end
def set_day_of_week
  self.day_of_week = self.created_at.strftime("%A")
end

At this point I could have refactored and set all attributes with Time.now upon object creation, but I was wary of object creation with too many variables and deemed it safer to assign attributes after creation, once the unique :date attribute has already been satisfied.

Now that I can set days up with date-related attributes, the next problem is: how do I know that I won’t be creating duplicate days with the same date attributes but different unique IDs? 1) There is no Days#create controller action, so users can’t create days.

# config/routes.rb
resources :users do
  resources :days, only: [:index, :update]
  resources :foods, only: [:index, :show, :destroy]
  resources :symptoms, only: [:show, :destroy]
end

So when is Day.create called in my app? Only once per day, in my #current_day helper method (more on that shortly). The very first time the app is run, I call create once in my initial seed file (using Time.now to establish the current day).

# db/seeds.rb
User.create(username: "username", password: "password")
month_day_year = Time.now.strftime("%m-%d-%y")
day = Day.create(month_day_year: month_day_year, user_id: 1, comments: "First day.")

2) Whenever a user logs in for the first time on a given day (recall that all my resources are nested under users), the root request involves a call to a #current_day helper method, which is only a #find_or_create_by query that, once again, uses Time.now to determine the appropriate date and month to use as search terms – in other words, it creates another day.

# app/controllers/application_controller.rb
def current_day(user_id)
  month_day_year = Time.now.strftime("%m-%d-%y")
Day.find_or_create_by(month_day_year: month_day_year, user_id: user_id)
end

Two workarounds for rack-flash with Sinatra

If you found this article, you’re most likely having issues with getting rack-flash to work in your Sinatra web app. Having spent more time on this issue than I would have liked, I would like to present two workarounds to prevent anyone from ever having to use rack-flash if they don’t want to.

When it’s working properly, rack-flash lets you load dynamic messages into your page views.

EDIT: While I like the simplicity of the workaround in this article, it appears that saving rack-flash’s functionality is even simpler: use Sinatra::Flash instead of Rack::Flash.

Here’s the error I spent too much time unproductively trying to debug:

/app/controllers/application_controller.rb:7:in '<class:ApplicationController>': uninitialized constant Rack::Flash (NameError)

Having had this issue in a previous lesson in my full-stack web development course, I took a look at the issues for that repository, and sure enough I found the same issue.

They suggest replacing the following code, suggested in the lab,

<% if flash.has?(:message) %> <%= flash[:message] %> <% end %>

to:

<% if !!flash[:message] %> <%= flash[:message] %> <% end %>

I think the double bang might be a better formulation than @has? anyway in this case, since it doesn’t rely on the `flash` object’s built-in methods. However, an even simpler alternative, if a tad clunky, would be to remove all dependencies and load them directly into your views by passing your messages as instance variables. Here’s a brief, excerpted example:

app/controllers/users_controller.rb:

get ‘/logout’ do
session.destroy
@message = “You have been logged out.”
erb :index
end

app/views/index.erb:

<% if @message != nil %>
<p><%= @message %></p>
<% end %>

This page has information.

To wrap up: if rack-flash is buggy, then passing your information as an instance variable is a safe and functional workaround, and one that preserves the separation of concerns between controllers and views.

Workflow for beginning coders

In the process of writing my first CLI and publishing it to Ruby gems, I came to realize two things: how naturally scattered my brain is, and how powerful of a tool it can be to simply write things down and check them off, one by one.

Not wanting to spend too much time researching, I tried to use the resources I had on hand to help my brain sort itself out.

1-by-1 visual checklist

Starting a project from scratch is easier said than done, because first you have to figure out what it is you need to do. I used a free productivity app called Trello to help me with keeping everything straight in my head:

Screen Shot 2018-07-18 at 10.33.28 AM

This **Kanban** board is a deceptively simple setup. For me it is powerful because it visually demonstrates that, no matter how many things you’re going to have to do, you can only do one of them at a time. I also like the ‘icebox’ feature, where you put ambitious ideas on ice until you’re ready to thaw them (though more often than not, they’ll stay there).

Editing a project in Atom

The bulk of my work was done in Atom, which has an intuitive folder tree layout:

Screen Shot 2018-07-18 at 10.35.13 AM

It is also compatible with git workflow: the files I edited since my last git push are highlighted in yellow, and then return to a neutral gray as soon as I have pushed.

Multiple terminal windows

One of the most productive strategies I used was to have a separation of concerns in the command line, so that I wouldn’t have to keep scrolling up or changing folders:

Screen Shot 2018-07-18 at 12.16.33 PM

It looks a bit messy, but each window has its own purpose. The window in the bottom middle is for testing my program’s functionality and reading its errors; the large window on the right, while keyed into the same folder, is exclusively for pushing to git. Because I was scraping a website using Nokogiri, I had a window open for accessing the @doc variable and for playing around with whatever results it fed me. I also had an **irb** shell running, just in case I needed to test the functionality of a method.

Atom as a Markdown text editor

After reading this article, I tried writing these blog posts in Markdown markup language so that I could start to get a feel for the tags:

Screen Shot 2018-07-18 at 11.47.11 AM

However, this blog is hosted by WordPress and I ended up having to reformat it manually. I will definitely try it again soon, and update this article on the results.

Should I decide to learn software development?

In answering this question for myself, I hope to reach others who are asking themselves the same thing.

Because I want a new career… without another degree

The field of software development has experienced rapid job growth over the past decade, though its continued growth over the next 10 years is debated (Here are some conflicting projections. The field itself is both wide and deep, with diverse opportunities in established companies of all sizes, eager startups, remote, free-lance or consulting work.

However, the contemporary job market is a grueling gauntlet, requiring you to arm yourself with a variety of specialized skills, resume padding, good fortune and good will if you are to have a chance to emerge victorious. In order to learn those specialized skills, you have to enroll in some sort of training program. How many people start medical school at the age of 50, or even 30? The barriers for entry are simply too high for most.

Computer programming has a refreshingly low barrier – in theory, you only need to demonstrate your abilities in a portfolio – especially when compared against other jobs of similar median base salaries. This provides an opportunity for people at any stage of life to learn a new skill and enter a new career. For myself, I trained to be a higher-ed teacher (and ultimately left because the job market was so stagnant), then trained to be a high school English teacher (and ultimately left because the job environment was unsustainable). When I sat down to consider my options, I crossed off everything that involved

Because I like failure, or at least don’t mind it

Avi Flombaum, co-founder of the Flatiron School (in whose Online Web Developer Program I am enrolled), said that we should “get comfortable with broken code,” because that is the default state of all code – each new feature you want to implement will be broken until it is fixed, and then when you want to change it, or add something else, it once again starts out broken and stays broken until the moment that it isn’t.

“By seeking and blundering we learn.”

 ― Johann Wolfgang von Goethe

This phenomenon is certainly not unique to the computer sciences, but it is particularly true that, in order to succeed at computer science, you need to learn to relish things being broken!

Because I like problem solving

There are two constants in this world: no one is perfect, and almost no one likes math very much. While the inherent beauty of mathematics is a topic for a longer article, I will say for myself – that I spent my entire education disliking and mostly failing at math, and came to the conclusion that I was just not very good at it.

Fortunately, computer programming is far more about logic than it is about math. There are certainly some mathematics involved (and increasingly so the more you specialize), but nowhere near as much as I had assumed. In my experience so far, the two biggest mathematical concepts that you need to grasp to succeed at programming are algebraic variables and the order of operations.

Just as in math, although it seems that it would be important to memorize the full list of HTML tags or of Ruby’s built-in methods, it is far more important to learn how to break down a problem into manageable steps. Methodical planning and sequential thinking are key skills that you should already be cultivating. If you’re not sure, try sampling some of the cornucopia of free online material and see where it takes you!