Code Reading - Learn ❤️ Domain Driven Design

Published Thursday, June 14, 2018

Challenge: introducing DDD in a legacy codebase

What is DDD?

Domain

“Sphere of knowledge…”

Model

Model domain in our software

Muggles

  • Informed by people who actually do the work (stakeholders)
  • Domain experts are key for bridging gap between domain and software

Goals

  • Better code
  • Better product
  • More happy

What is DDD in Learn?

  • It’s always kind of been there
  • DDD encompasses a lot of general best practices, some of which we’ve already been following (ex. ubiquitous language)

First attempts: LearnApps

  • Not true DDD
  • Doesn’t follow all the core principles

Then DDD “Lite”

  • Domains directory
  • Closer to setting up microservices in our monolith
  • Aggregate domain module for each domain
    • Insulation around implementation
    • Provides clearer context
    • Minimize reaching across domains
    • Primitives in, primitives out
  • Still encourages collaboration
    • Not just a tool for engineers
    • Use company-wide ubiquitous language (talk to product, stakeholders)

Gotchas

  • Domains are NOT project namespaces
  • Domains should map to business departments (in general)
  • Watch out for early abstraction
  • Different names for the same things
  • vs. Same name for different things
  • Rails autoloading
Read More

Code Reading - JWT

Published Thursday, April 26, 2018

A code reading by @spencer1248

JSON Web Tokens

Website: jwt.io (maintained by private company AuthO)

JWT Basics

Base64 endcoding

JWTs use base64 encoding.

Why?

  • Normalizes data into set of known characters
  • No collisions with heading encodings
  • Doesn’t break JSON parsers
  • Signature is binary
  • Take binary data and convert into this common character set

Base64 basics

  • 1 character, 64 different permutations
  • 6 bytes with 4 characters
  • When encrypting, keep in mind going from 6 bytes to 8 bytes increases size of data by 33%

Structure

Start with Base64 string

3 parts:

  • header
  • payload
  • signature

<header>.<payload>.<signature>

Example - period delimited JWT with Base64:

{"typ": "JWT", "alg": "HS256"}.{"aud": "learn", foo": "bar"}.<signature> (signature is a binary string)

  • Signed with key and algorithm (ex. HS256)
  • Public and private claims
  • Private claims are registered (ex. expiry)

General Concerns

  • Don’t use JWTs for sensitive information
  • Don’t use JWTs as a session replacement [post]

2Learn and JWTs

There are public JWT Devise strategies.

We didn’t use any of those because:

  • Too much custom stuff in our codebase and 2U’s codebase
  • Will allow us to be more...
Read More

JS Testing with Jest and React

Published Thursday, April 05, 2018

A code reading by @gj

Jest

  • New hotness for testing React
  • More or less a superset of Jasmine
  • Backed by Facebook
  • “Just works” out of the box
  • Started as a wrapper around JSDom, evolved into its own thing

Hopes and dreams: Jest makes test writing fun and easy => we write more tests

Helpful features

  1. Watch mode (--watch) - runs test on code changes (similar to guard on server-side)
  2. Coverage metrics (--coverage) - out of the box
  3. Notifications mode (--notify) - native OS notification when test runs completes
  4. Tracks test failures - runs failed tests first on next run (shorter feedback loop)
  5. Tracks test suite run time - suites run in parallel across processes
  6. Fully sandboxed - tests are strictly scoped, so no globals pollution

Suggestions

  1. Enzyme’s shallow over mount for rendering components

WIP… more to follow after next week’s code reading.

Read More

Ops Roadmap for Learn.co

Published Thursday, March 22, 2018

Outline

  1. Review current setup
  2. Share upcoming challenges/priorities
  3. Share roadmap + new concepts/tools

Priorities

  1. Ensure new collaborative ventures are successful
  2. Support our team as we grow (make ops more automated + manageable)

Requirements

  • Move to AWS for hosting
  • Need high amounts of infrastructure + environment automation and orchestration (Terraform)
  • Scaling
  • Security
  • Lower maintenance costs as our team grows

Current Setup

  • Hosted on Digital Ocean
  • Self-hosted services:
    • Postgres
    • Redis
    • Elastisearch
    • Memcached
    • Pushstream
  • Our virtual servers are on private network in DO region

Pain points

  • Communication between services is not automated (no robust tooling available)
  • Our servers are “pets not cattle”
  • High maintenance costs
    • Lots of outages
    • Infrastructure is not self-healing (no robust tooling available)
  • Low security
  • Noisy alerts (Nagios)
  • Relying on manageable (aka more brittle) deployment and provisioning processes (Chef)
  • Our virtual servers are on shared machines, so vulnerable to leaks / attacks

Roadmap

Security

Guiding principle: Principle of Least Privilege (limit surface area / attack vectors)

  • GitHub 2FA
  • Remove root AWS keys
  • ...
Read More

Phil Sturgeon - A No-Nonsense GraphQL and REST Comparison

Published Thursday, March 15, 2018

Notes from Phil Sturgeon’s code talk at Flatiron School, 3/15/2018.

Slides available at philsturgeon.uk/speaking.

What is GraphQL?

GraphQL = FQL + (REST - Hypermedia)

A little FQLish, a little RESTish.

What is REST?

  • REST != CRUD API
  • REST == state machines over HTTP
  • Nice wrapper for models (keep logic in controller)
  • State machines can power Hypermedia controls (see below)

What is Hypermedia?

  • State machines over JSON
  • Misused
  • Misunderstood
  • Hypermedia links are not just for related data

More on HATEOS:

Level 1: string containing URL

  • no guarantee of success
  • make url respond to options

Level 2: add metadata to options payload

  • use JSON schema to detail fields
  • use JSON Hyperschema to detail potential actions
  • plus another optional layer of strictness
  • might to ignored/unnoticed by clients

Level 3: Add Hypermedia controls in response

  • Siren / HAL
  • Just send back everything (but end up with potentially huge response size)

Other protocols

  • SPARQL (2008) - not popular
  • FIQL (2008) - flexible, but not popular

Some things GraphQL is bad at

  • Caching
    • Query langagues are bad at caching
    • Each...
Read More

Pattern Matching in Elixir

Published Wednesday, March 14, 2018

Pattern Matching Hearts Elixir

At the Flatiron School, our mission is to help people learn how to code. That means that as a member of the engineering team, my work reminds me almost every day of that important, universal truth: learning new stuff is hard.

Take learning to play a musical instrument, for example, like guitar. When you start, you have these lofty aspirations. You wanna be the next David Bowie. But when you’re first starting out, that dream is so, so far away. It takes a ton of hard work to get there, and it’s easy to get discouraged. Without some early wins, you might give up.

You need to learn that one cool riff that gets you hooked, where you don’t wanna put the guitar down, because now you’re in it.

It’s kinda the same thing with Elixir.

Lots of folks are excited about the language because of all the great things you get from using it - concurrency, fault tolerance, scalability - the hype list goes on and on. But none of these are things you can enjoy right away. You pretty much have to build and ship...

Read More

Code Talk - How the Test Lights Work on Learn.co

Published Thursday, March 08, 2018

aka The Little Submission That Could

by @talum

Submissions take a long, multi-step journey from learn-co gem to Learn.co.

Step 1: learn-co gem

Collection of open source gems (one parent gem with buncha child gems)

Focus for this talk is learn-test

  • figures out what kind of test strategy to use
  • runs tests
  • turns test results into JSON payload
  • show student human readable results (written to results.json)
  • sends payload to Ironbroker V2
    • user info
    • repo info
    • test success/failure info

Step 2: Ironbroker V2

Message broker app written in Sinatra.

Handles all webhooks from variety of sources

  • FlatironUnitTest
  • FlatironRspec
  • GitHub
  • ScheduleOnce

By “handle”, specifically this means process and publish to topic exchange

  • parse
  • save
  • validate
  • resolve event name
  • resolve ampq topic
  • resolve ampq routing key
  • publish
  • handle bugs
  • publish trackable
  • save (again)

Step 3: RabbitMQ

Message broker over AMQP.

Payload arrives at topic exchange, then routed to specific queue (based on routing key). In this example, the local_build queue.

Step 4: Worker

Messages are peeled off by consumers (powered by Sneakers, a high performance RabbitMQ background processing...

Read More

Code Talk - Refactoring Retriable Actions

Published Thursday, February 22, 2018

A Story About Asynchronous Actions, Dynamic Workers and Queues, and RabbitMQ

To standardize running asynchronous services, we’ve created a number of “Base” objects:

  • AsyncBaseService, just introduced (inherits from BaseService)
  • BaseWorker

Worker queues are managed by RabbitMQ.

Problem to solve:

  • Sometimes services fail and need to be retried
  • We need a reliable way to retry jobs, keep records of attempts, eventually fail after a specified number of attempts, and log error on max-out failure
  • To fulfill above, we built our own Retriable system, which has done more harm than good

New solution:

  • New queues and workers are spun up dynamically for each AsyncBaseService-backed service
  • Safety through encapsulation: if one service goes sideways, problems won’t impact any other queues
  • Three queues for each service: standard queue, retry queue, error queue
  • Config with SNEAKERS_DEFAULT_OPTIONS

Replacing Retriable system with built-in RabbitMQ tooling, most importantly, Dead Letter Exchanges. With Dead Letter Exchanges, messages can be passed to another queue on failure (aka our retry queue).

When message is rejected in original queue, gets pushed to retry queue. Retry queue waits (10s TTL), then passes back to original queue. Every message will be retried...

Read More

Code Talk - Networking

Published Friday, November 03, 2017

Low level talk about how information moves across the internet.

Why? Because we’re moving to AWS and Scot wants to try teaching this.

Types of addresses:

IP address Mac address
Dynamic Static
Related to geolocation (network location associated with physical location) Hardwired to computer’s network card
Higher level (IP layer, layer 3) Lower level (ethernet, layer 2)
32bit, example: 10.10.2.2 48bit, usually represented in hex, example: F1:4F:AF:FF:FF:FF

ifconfig - shows IP address, netmask, and more

$ ifconfig lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 16384 options=1203<RXCSUM,TXCSUM,TXSTATUS,SW_TIMESTAMP> inet 127.0.0.1 netmask 0xff000000 inet6 ::1 prefixlen 128 inet6 fe80::1%lo0 prefixlen 64 scopeid 0x1 nd6 options=201<PERFORMNUD,DAD> gif0: flags=8010<POINTOPOINT,MULTICAST> mtu 1280 stf0: flags=0<> mtu 1280 en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500 ether a4:5e:60:d0:47:85 inet6 fe80::4b4:2f9:9d8c:bc76%en0 prefixlen 64 secured scopeid 0x4 inet 10.9.97.112 netmask 0xfffff800 broadcast 10.9.103.255 nd6 options=201<PERFORMNUD,DAD> media: autoselect status: active 

ipcalc <ip address> <netmask> - tells...

Read More

Code Reading - Learn ❤️ RabbitMQ - Part 1

Published Thursday, August 31, 2017

A code reading by @joshrowley, part 1.

Concepts

Fuzzy overview of stuff we’ve heard about RabbitMQ

  • Written in Erlang
  • Queues, Exchanges, Channels, Subscriptions
  • Publishers, Consumers
  • Connections
  • Fanouts
  • Self-healing
  • Distributed

Actual overview

  • Message broker originally built by JPMorgan Chase. Built 2004, released 2007.
  • Designed as a way to solve problems with integration points between many different bank systems. Needed standardized way of sending messages between apps.
  • Goals: reliability, guaranteed message delivery between apps, uptime
  • Solution: AMQP (protocol)

What is AMQP?

  • Runs on Erlang OTP
  • Queues where you persist messages
  • Consumers who consume messages
  • Acks inform queue when message is processed
  • Whole thing ensures streams of data are processed as intended
  • Any client can use AMQP, so why roll your own?
  • Decouples publishers from consumers
Producer - app that publishes messages (Ironbroker, Ironboard, Flatchat) | | - TCP Connection (ongoing 2-way connection) V Broker (RabbitMQ) - Queues ("mailboxes"): hold messages, wait for consumer to connect and take message off queue, load balances - Exchanges: publishers publish message to exchange, exchange routes to queue(s) - Bindings: rules you define for how exchanges publish messages to queues - Connections:...
      
Read More

Code Reading - Learn ❤️ Domain Driven Design

Published Thursday, August 10, 2017

Introducing DDD into Existing Codebase

Risky to experiment with existing “domains”. Better to experiment with something new.

Our test case: “Compliance” and “Notifications” domains

  • small
  • isolated
  • wouldn’t affect existing code

Test Case

Didn’t add any new has_many or other associations

Domains

Communicate with domain through top level domains/:domain modules (ex. domains/compliance.rb).

Gives us bounded context. Send messages to bounded contexts, not the subdomains directly. All requests should be funneled through top level module.

That said, we’re not being strict about this convention. You still can call models directly. We may change this in the future to be stricter, but we’re trusting our team to self police for now.

# domains/compliance.rb module Compliance def self.get_requirements_with_document(requirement_ids) Requirement.includes(:document).find(requirement_ids) end def self.requirement_complete?(requirement_id) Requirement.complete.where(id: requirement_id).exists? end # etc... end # models/requirement.rb module Compliance class Requirement < ActiveRecord::Base end end 

Fun...

Read More

How My Bash Color Settings Broke edeliver

Published Wednesday, July 12, 2017

Yep, you read that right. My bash color settings broke edeliver, the tool my team uses to deploy our Elixir apps.

Now, anyone who’s tinkered with their .bash_profile knows there’s an infinite number of ways to totally bork your system. But this bug was well camouflaged, hiding inside a common, seemingly-benign bash setting I’d had in place for over two and a half years without issue - a bash setting you, too, might have on your machine RIGHT NOW 😱

But don’t worry, I tracked down the little bugger, so read on to save yourself the same hassle I went through. And for those of you in a rush, here’s the tl;dr.

The Problem

I’d just started working on one of our Elixir projects, doing my best to learn a new codebase and a new language all at once. Things were going well until it came time to deploy changes. I could build a release, no problem, but I couldn’t deploy; the command would fail every time with the following output:

Read More

How to Run Ecto Migrations on Production

Published Thursday, July 06, 2017

You’d think the answer to this question would be a simple Google search away. Unfortunately, that wasn’t the case for me this afternoon, working on a Phoenix project with a newly-added Ecto backend. In an effort to save others (and let’s be honest, future me) the same frustration, here’s the most straight-forward solutions I found.

What Doesn’t Work

Mix. Mix tasks aren’t compiled into your deployed release, and as evidenced in this exciting discussion, there’s no plans to change this any time soon.

So don’t try using your trusty local mix ecto.migrate task on production. Not gonna help you here.

What Does Work

1. Ecto.Migrator

Ecto ships with Ecto.Migrator, a first-class module for Ecto’s migration API.

Run it manually by ssh’ing onto your app server, attaching to your Phoenix app, and running the following:

path = Application.app_dir(:my_app, "priv/repo/migrations") Ecto.Migrator.run(MyApp.Repo, path, :up, all: true) 

Ideally, you’d wrap up the above in its own task that can be called during your build and deployment process. Check out Plataformatec’s blog for a nice example.

2. eDeliver

Our app uses edeliver for deployments, and it has...

Read More

How to Work with Developers

Published Wednesday, June 28, 2017

Software developers, have you ever felt misunderstood by your non-developer teammates? It happens to most of us, which is why I wrote this post to help clear up some of the most common misunderstandings, miscommunications, and missed opportunities. Feel free to pass it along to anyone who’d love to have an easier time working with developers.

Below, I’ll be sharing my (completely unbiased 😉) perspective on how to work with software developers. My goal is that after reading this article, every reader feels confident they can work effectively with their development team thanks to some proven tools and strategies we’ll review together.

Developers: They’re Just Like Us… or are they?

So why is this discussion necessary? Are developers really so different from your average co-worker?

Yes. Yes, we absolutely are.

Take Flatiron School’s engineering team, for example. Here’s a picture of us from last summer, happily hacking away in the park outside our office.

Flatiron School engineers outdoors

Why are we in a park? Well, this was moments after our building was evacuated during a fire (a literal dumpster fire, turns out). When the alarms went off, the rest of the office...

Read More

Code Reading - Learn ❤️ GraphQL

Published Thursday, June 22, 2017

What is GraphQL?

  • “Graph Query Language”
  • Alternative to REST pattern
  • Making your data queryable through a single endpoint

Why use GraphQL?

  • More declarative
  • More consumer focused
  • Simplified endpoints
  • Fewer requests
    • With REST, request count grows w/ more data you need
    • With GraphQL, only request as much data as you need => more efficient

In use in the wild

  • Github API
  • Shopify

Stuff to Think About

  • Due to HTML limitations, super long queries get sent via POST request
  • Mutations

Demo

  1. Spin up new rails app: rails new graphql-demo
  2. Add graphql-ruby gem to Gemfile
  3. Run rails generate graphql:install
    • gives you graphql directory with sub-directories for mutations, types, new controller, new route graphql-rails
  4. Lookit /grpahiql loader dev tool
  5. Lookit /app/graphql/graphql_demo_schema.rb
  6. Lots of demo boilerplate-y examples generated for us
  7. Add more field queries to Types::QueryType
 field :course, Types::CourseType do description "This will return a single course" argument :id, !types.Int 

      Read More
    

Code Reading - Learn ❤️ Docker

Published Thursday, June 15, 2017

Prereqs:

  • Watch this Youtube playlist (~90 min)
  • Clone down existing Rails app (in our case, the Learn codebase)
  • Set up account on Docker Hub

Intro

What is Docker?

  • Tool for managing and creating containers

Why use Docker?

  • Maintain a stable, consistent environment
  • Encapsulate all pices of an app
  • Uniformity and consistency
  • Step towards better deployments and auto-scaling infrastructure (Swarm, Kubernetes)
  • Lighter than a VM (no hypervisor)
  • One of the more mature tools available

Basics

Docker image:

  • Pre-packaged layer
  • Can stack layers on each other
  • Result of running Dockerfile
  • Can create containers off of image

Docker container:

  • Running isolated container of your app’s code

Docker networking:

  • Built-in
  • Allows containers to talk to each other over same network

Docker volumes:

  • Take local files and put them into your container
  • Edit locally, see changes in container

Docker compose:

  • Toolset for coordinating containers

Docker Hub:

  • Store and access repositories (images)

Practice

Run an image: docker run -it ubuntu (creates container with interactive terminal)

Build Dockerfile: docker build -t wget...

Read More

Code Reading - Capistrano

Published Thursday, April 20, 2017

A fascinating glimpse into Spencer’s server config process.

Impetus:

Contractor working on our marketing website CMS needs a staging environment to deploy changes to.

Context:

We set up a one-click droplet on Digital Ocean. But we use chef for server management, so we need to custom configure this setup.

Requirements:

  • Wordpress
  • MySQL
  • Varnish (service that sits in front of web applications like Wordpress, handles caching, kinda like nginx with caching)

What we did:

First step was looking at our existing chef cookbooks and seeing if there’s anything we can reuse. Turns out we have fis-msql cookbook already - but why? We don’t use MySQL on production. So look for a corresponding droplet on Digital Ocean; can’t find one.

Git blamed cookbook, and it was added in March around the same time this marketing site CMS project was originally kicked off (later put on paused, restarted now).

Side note: Spencer is using the Elflord color scheme for VIM. Loves it.

Diving into fis-msql cookbook code:

  • see our base cookbook
  • setting up msql v5.6, so update to latest v5.7 (bc why not)
  • rm mysql2_chef_gem (don’t need it)
  • rm Read More

Dev Ops Crash Course - Day Five

Published Friday, March 24, 2017

Notes from day one, day two, day three and day four.

Chef Chat

What is Chef?

  • Scripts written in Ruby to provision a server.
  • Server setup
  • Infrastructure automation
  • Server configuration management

What’s important to manage?

  • Software versioning
  • Uniformity and consistency across machines
  • Reproducability
  • Idempotency

What problems are we solving?

  • Efficient setup
  • Preserves history
  • Prevents environment issues resulting from inconsistencies among envs

Alternatives to Chef?

How We’ve Structured Our Cookbooks

Rely on inheritance. All cookbooks include base cookbook, which makes sure we always have security standards, base stuff in place on all boxes.

Wrapper cookbooks let us have a general template we can extend with app-specific details.

Idiosyncracies of Chef

Conventions aren’t very clearly defined. Easy to define attributes all over the place (ex. in your recipes, in attributes directory, etc.)

Cookbooks have many recipes, but in our chef repo, we tend to only have one recipe per cookbook (the default recipe).

Community cookbooks

When using community cookbooks, probably want to wrap rather than fork. After a certain amount...

Read More

Dev Ops Crash Course - Day Four

Published Thursday, March 23, 2017

Notes from day one, day two, day three, and day five.

Learn IDE

Load Balancers

Using haproxy for load balancers. Config lives in /usr/local/etc/haproxy

IDE config is using slightly different approach than Learn. Not using cookie. Instead using hashed token from user (as url param).

DNS

In general, SSL certificate needs to match what IP address the web request resolves to (resolves to DNS entry). DNS entry is for floating IP. So you can use the same certificate for multiple servers, depending on what server floating IP points to. That allows us to SSL terminate at load balancer server. Certicate is on load balancer.

We have load balancers in front of each region AND a super load balancer to handle delegation. Has 3 different A records, one per load balancer.

We’re using traffic management service on Dynect. This service allows you to set address pools and service controls.

Address Pools

Pools are preset by Dynect. We plugged in our servers where it made sense.

Global pool has all 3 main regional load balancers. Monitor and obey are active.

Serve mode off for US Central, so people get routed to closest region.

...
Read More

Dev Ops Crash Course - Day Three

Published Wednesday, March 22, 2017

Notes from day one, day two, day four, and day five.

Year in Review Review (continued)

Notifications

Nagios repo w/ full documentation: https://github.com/flatiron-labs/nagios

Nagios API that powers our Learn.co status page: https://github.com/zorkian/nagios-api

Status page lives on nagios01 server: root@nagios01:/usr/local/nagios/nagios-api. There’s a cron job that runs updates: crontab -l to view, crontab -e to edit.

Automated SSH Key Propagation

Cron job that runs every 30min that runs chef user_setup recipe on every host.

Every 30min too often? We should scale this back.

Automated Server Provisioning Tools

Script that uses Digital Ocean, Dynect, and Chef APIs to provision the host automatically. New host in under 2 min.

Note: script is a little dated now. DO has since made its own CLI tools that do a lot of this (doctl). There’s also tugboat gem.

DO tools probably better suited since they incorporate all DO’s latest features.

Faster Deploys

Drew and Devin put work in to speed up server-side only deploys. More work needs to done on speeding up asset compilation.

Weekly DB Migrations

See qa-support server. Runs cron job: root@qa-support...

Read More

Dev Ops Crash Course - Day Two

Published Tuesday, March 21, 2017

Notes from day one, day three, day four, and day five.

Year In Review Review

Q: What is DevOps?

A: When first created, more of a concept than a well-defined position. Even today, the term is still fairly broad, but in general refers to:

..a set of practices emphasizing the collaboration & communication of both software developers and operations professionals, while automating the process of software delivery and infrastructure changes.

Postgres Database Replication

  • Read-Only replica: all transactions are mirrored to 2nd server
  • Hot standby in case of failure
  • Easy failover strategy
  • Lowers risk of downtime

Backups stored in /var/lib/postgres along with backup config.

How restore works:

  • WAL-E (continuous archiving) takes base image of our database once a day and stores in S3.
  • Postgres creates binary transaction logs (write-ahead logs) that have to complete before transaction succeeds. That way, can re-run if database crashes before completing transaction. Over the course of the day, we send up these write-ahead log files to S3.
  • For restore, first imports base image to db, then applies deltas (write-ahead logs).
  • WAL-E has interface for deleting backups. We...
Read More

Dev Ops Crash Course - Day One

Published Monday, March 20, 2017

Notes from day two, day three, day four, and day five.

Internet 101

Videos: https://www.khanacademy.org/computing/computer-science/internet-intro/internet-works-intro/v/the-internet-wires-cables-and-wifi

Some vocab:

  • Bandwidth: capacity to receive information
  • Bitrate: speed of sending information (bits per second)
  • Latency: drag / delay when sending information

Internet is a design philosophy expressed through agreed upon protocols:

  • IPv4 - current protocol (32bit)
  • IPv6 - new protocol to provide more IP addresses (128bit)

IP addresses have A, B, and C classes.

DNS

How DNS works: https://howdns.works/

In local network settings, DNS is set to Google Public DNS.

  • better performance
  • better security

Anatomy of a URL: https://doepud.co.uk/blog/anatomy-of-a-url

protocol subdomain domain
https:// www. google.com

DNS records

Record types:

  1. A record: address, maps hostname to physical IP address
  2. PTR record: pointer, maps IP to name (helpful when scanning logs)
  3. CNAME record: alias, map domain name to another domain name

Can use multiple records for redundancy strategy. For example, you want multiple MX records for mail servers. Config priority on each record.

DNS lookup

$ dig learn.co ; <<>> DiG 9.8.3-P1 <<>> learn.co ;; global...
      
Read More

How Object-Oriented Design Saved Our CSS (and Site Performance)

Published Monday, February 20, 2017

Back in January 2016, our CSS was easily the messiest part of the Learn.co codebase… something that probably sounds familiar to many other web developers out there. Last spring, we budgeted time and resources to overhaul it. I led that project. Here’s what we learned.

Before diving in, let’s clarify what we’re talking about when we talk about object-oriented design. Object-oriented code is:

  • Modular: reusable
  • Encapsulated: self-contained with minimal dependencies
  • Maintainable: easy to work with, which is especially important for smaller dev teams like ours

Learn.co is built on a Rails backend, and Rails strongly encourages writing code in an object-oriented paradigm. But how does that apply to stylesheets? As good Rubyists, we tried to follow object orientation with our CSS, but we were doing it wrong. To illustrate, let’s take a look at our old stylesheets directory tree.

Stylesheet Directory Tree

Very similar to the Rails boilerplate setup, we had one stylesheet per view, with styles namespaced under a top level ID. This approach is fine when you’re starting out, but over time, it can get out of hand. Just look at where ours was pre-rewrite:

Stylesheet...
      </div>

      <a href=Read More

Code Reading - Learn.co Shared React Form Library

Published Thursday, January 12, 2017

Presenter: Seiji

Problem

React is not an opionated library

  • too many options for building forms
  • we ended up with a bunch of different implementations / approaches

Forms are omnipresent in our app

  • lots of repeated code
  • need to DRY this up

Solution

  • Build out library to manage form state + validation + submission
  • Build reusable form component specific to our domain

Process

  • Reviewed all our current approaches
  • Melded into single, shareable component

Shared Component Library

Can be used for controlled + uncontrolled inputs

  • examples at /admin/react/forms
  • documentation on ironboard wiki

Robust test coverage

Default styles can be overridden

Acts as building block / starting point for new form

  • won’t just magically build your entire form for you
  • use lego blocks to build lego set

Alt Form: existing library, but outdated and not super functional, so Seiji rebuilt one specific to our app

Uses Curring pattern

  • Referred to in React community as “high order component”

3 Objects:

  1. Form Object
  2. Form Component
  3. Form Connector
Form Object Form Component \ / \ / Form Connector || \/ React...
      
Read More

React and Redux Crash Course with Steven Nunez PART DEUX

Published Tuesday, December 20, 2016

Instructor

Steven Nunez, Lead Instructor/Developer at Flatiron School

Goals:

  1. Build on what we learned last week
  2. Set up some tests

Exercise: Hacking on Our Chat App

Last time: closed out talking about Middleware (Thunk, specifically). Today we’ll make some more progress towards a nice lil chat app.

We’ll start out with by building some functional components.

  1. create new files:
    • ./components/app
    • ./components/RoomList
    • ./components/RoomDetails
  2. render RoomList and RoomDetails from App
  3. render an unordered list of Rooms (aka channels) in RoomList
  4. RoomDetails will render an individual room:
    • messages back and forth from each room member
    • also the textarea input where you can compose new messages
  5. Add some styling (lil flexbox, lil custom fonts, etc.)

Next up, set groundwork for testing. Use this post for reference: https://keita.blog/2016/02/08/javascript-unit-tests-in-a-phoenix-application/

  1. npm install --save-dev mocha
  2. npm install --save-dev chai
  3. npm install --save-dev babel-register
  4. in .babelrc, set preset: { "presets": ["es2015"] }
  5. in package.json, update scripts: "scripts": {"test": "mocha --compilers js:babel-register test/js/**/*.js"}
  6. mkdir -p test/js/reducers
  7. touch test/js/reducers/RoomReducerSpec.js
  8. write some tests (see example repo)

Let’s pause and talk about immutability.

Redux is trying...

Read More

React and Redux Crash Course with Steven Nunez

Published Tuesday, December 13, 2016

Instructor

Steven Nunez, Lead Instructor/Developer at Flatiron School

Goals:

  1. Learn through doing
  2. Knowledge up on cool new tech

Why Redux?

  1. “Surprisingly simple” says Steven
  2. Very specific purpose
  3. Supes popular
  4. Lots of high quality curriculum available from Flatiron School
  5. They hired Dan Abramov

What is Redux?

  1. State Management

The end.

  • Has nothing to do with the web.
  • Has nothing to do with React.
  • Nice and simple.

Is it Flux?

Not really. Flux has a very specific set of parts: dispatcher, actions sent by dispatcher, etc. Redux has a lot of the same players, but follows slightly different pattern.

Why Redux was hard for Steven

Seems like a lot of stuff at first.

The part that’s Redux is actually fairly small. Redux covers Reducers, Dispatch, middleware. The rest is mostly Redux+React. And then conventions like ALL_THE_CAPS and Action Creators are separate conventions (oof).

Exercise: Simple Chat App

Building a chat app

code lives at: https://github.com/StevenNunez/redux_chat_hedgehog

  1. brew install elixir
  2. mix phoenix.new redux_chat_hedgehog (using phoenix bc it has nice tools for modern web workflow)
  3. comment out db username and password in Read More

CSMess to OOCSS - Refactoring CSS With Object Oriented Design

Published Monday, October 17, 2016

Presented at Fullstack Toronto Conf. 2016

Slide deck

Text (no video available, unfortunately)

Back in January 2016, our CSS was easily the messiest part of the Learn.co codebase… something that probably sounds familiar to many other web developers out there. Last spring, we budgeted time and resources to overhaul it. I led that project. Here’s what we learned.

Before diving in, let’s clarify what we’re talking about when we talk about object-oriented design. Object-oriented code is:

  • Modular: reusable
  • Encapsulated: self-contained with minimal dependencies
  • Maintainable: easy to work with, which is especially important for smaller dev teams like ours

Learn.co is built on a Rails backend, and Rails strongly encourages writing code in an object-oriented paradigm. But how does object orientation apply to stylesheets? As good Rubyists, we tried to follow object orientation with our CSS, but we were doing it wrong. To illustrate, let’s take a look at our old stylesheets directory tree.

Stylesheet Directory Tree

Very similar to the Rails boilerplate setup, we had one stylesheet per view, with styles namespaced under a top level ID. This approach...

Read More

Flatchat Code Talk

Published Thursday, September 29, 2016

Flatchat is our in-house replacement for Slack, which we’ll be moving our users off soon.

Stats

  • maxing out at ~350-500 unique websockets
  • avg 200ms room load time

Check /pghero for db query diagnostics.

ssh into flatchat server for PM2 monitoring.

  • logs are rolled over every 7 days
  • pm2 monit for live resource usage
  • pm2 list for quick summary

Handling Message

  1. Validate inputs (flatchatter and room member)
  2. Check room policy
  3. Write message to db
  4. Add more stuff to message object (decorator?)
  5. Broadcast msg
    • to other users in room
    • to other rooms
  6. Send msg info to rabbitmq for processing

Details:

  • Room stored in session
  • User bounced if no access to room / no room
Read More

Get Fuzzy with LEVENSHTEIN

Published Friday, September 16, 2016

Discovered a super handy Postgres extension tonight: fuzzystrmatch. This lil cutie is a real godsend when dealing with potentially crummy user input, such as, oh say, for a Rails project where you’re requiring your less-than-tech-savvy relatives and future inlaws to input their email address in order to access your wedding website. Note: said website is badass, built-from-scratch, and open source.

Here’s a visual:

Login Modal

Imagining that scenario, one might be concerned about poor conversion due to typos, misspellings, or any other of the myriad problems that plague “uncontrolled” user input. And extra sadly, poor conversion here translates to a sparsely attended wedding and future full of angry inlaws… no bueno.

Enter fuzzystrmatch. Adding this extension to your Postgres database gives you some super handy fuzzy string matching functions, my favorite of which so far is levenshtein. levenshtein calculates the difference between two strings, aka the “edit distance”, and it’s based on this metric named after this guy.

You can use it to make some extra forgiving ActiveRecord queries, as laid out below.

> User.find_by('levenshtein(lower(email), lower(?)) <= 3', 'test@email.c') => #<User id: 1,...
      
Read More

BASH Tips and Tricks

Published Thursday, September 01, 2016

All tips courtesy @devinburnette

Basics

$ w

see who else is on box

$ w 14:15 up 5 days, 19:23, 7 users, load averages: 1.47 1.56 1.82 USER TTY FROM LOGIN@ IDLE WHAT ktravers console - Mon11 3days - _mbsetupuser console - Mon11 3days - ktravers s000 - Mon11 1:35 gulp ktravers s001 - Mon11 - w ktravers s002 - Mon11 4:10 node /Users/ktravers/.nvm/versions/node/v6.2.2/bin/sails lift ktravers s004 - Mon11 3days /usr/local/Cellar/rabbitmq/3.5.1/erts-6.1/bin/../../erts-6.1/bin/beam.smp -W w -K true -A30 ktravers s005 - Mon11 3days redis-server *:6379 

$ write [user]

send message to specific user

$ wall

broadcast to all users on box

$ whoami

get your current user

$ whoami ktravers 

$ who am i

verbose get current user

$ who am i ktravers ttys001 Aug 29 11:06 

$ clear

put command line at top of window

$ man [whatevs]

get manual for [whatevs] command

$ man man man(1) man(1) NAME man - format and...
      
Read More

React Code Talk Notes

Published Monday, August 01, 2016

Overview

  • library that renders data to the DOM
  • can add Flux architecture after you’re comfortable with React

Setting up a React app in our codebase

General Notes

  • avoid using jQuery so we can remove that dependency
  • use vanilla JS where possible instead
  • Gulpfile is not watching these files, so will need to re-compile manually after making changes

Setup

1. Add _src file (_src/code-reading.js)
// _src/code-reading.js var React = require('react') , ReactDom = require('react-dom') , AppComponent = require('code-reading/app.jsx') ; document.addEventListener('DOMContentLoaded', function () { ReactDom.render(<AppComponent/>, document.getElementById('js-main')); }); 
2. Create manifest (javascripts/code-reading.js) and require src file in via sprockets
// javascripts/code-reading.js //= require _bundles/code-reading 
3. Add to asset pipeline (application.rb) and blacklist
4. Create AppComponent (/javascripts/code-reading/app.jsx)
  • React.createClass(){} requires render function
  • React can only return one...
Read More

Best Ways for Beginners To Contribute to Open Source

Published Saturday, November 07, 2015

When I first started out learning to code, the idea of contributing to an open source project was really intimidating. I got that advice from everyone - “Contribute to open source! It’s so easy! Employers love it!” - but I was still hesistant. I’d only been writing Ruby for a couple months; how was I going to contribute anything useful to someone else’s project?

Well, I’m happy to report from the other side, it’s actually pretty painless and fun for beginners at any level to make meaningful contributions to open source projects.

So shake off that imposter syndrome; the open source community needs you. They need everyone, in fact. Open source projects depend on a large and diverse community of contributors to really robustify their codebase. That includes people from all skill levels and all areas of expertise. Plus, the benefits are reciprocal. You’ll get to know the community better, build your support system, and get your name (and your code) out there in a really positive way.

Getting started

So where do you smart? The two best pieces of advice I got in this department were to 1) start small and 2) (in the immortal words of...

Read More

Code Talk Notes - Javascript Testing and Analytics

Published Thursday, September 24, 2015

Javascript Test Updates

jsdom: npm module

  • load into node environment
  • recreate DOM
  • run inside of node using Jasmine

Jade templating

  • require in templates
  • doesn’t need to rely on Rails asset pipeline

Spies:

  • PushStreamSpy
  • spyOnBackboneHistory
  • can have it substitute the function, wrap the function then delegate to function
  • Note: mocks, spies & stubs are all very similar (functionally, conceptually)

Can write specs for Marionette views, Backbone models

  • run in node (npm t)
  • load in view (same as front end)
  • stub out fixtures
  • create view then test view

** eval(locus) == binding.pry for node **

Analytics

Tracking should be done client-side; inconsistent if tracked from backend

  • in our system, controller will delegate to client-side
  • concept of current_visitor bc we don’t have a user yet

To have access to Segment system, be sure to include analytics script call (helper method)

Use aliasing to transfer data from before user is logged in to when after user has logged in

  • data stays attached to same user
  • alias vister::user

Sequence:

  1. alias
  2. identify (updated from current visitor traits)
  3. track

Stats on Mixpanel

  • can create/view funnels
  • see...
Read More

Code Talk Notes - Librato and Ironbroker

Published Thursday, September 10, 2015

Librato Update

Librato has two stats types: counter vs gauge

When using counter (aka #send_increment), be sure to set summary function to sum and check Service-Side Aggregation.

Librato counter

Ironbroker Refactor

Payload == immutable
State == mutable

Validation for each source

RabbitMq handler - rescue channel failure by creating new channel

begin
  # do bunny stuff
  # if channel closes, rescue
rescue
  @channel = @bunny.create_channel
  # bunny keeps hopping
end

Oj: much more efficient JSON parser

Checkout Source model for some cool meta-programming

New Hierarchy Builder

Structure determined by depth level

Query uses Postgres’s WITH RECURSIVE method

  • give it an initial SELECT statement which is run once
  • give it another SELECT statment that it calls recursively until it runs out of results
  • then combines the SELECT statement

Holds a path array while building, so you can see how you got to your final result

Test failures were a nightmare, but solved by creating a rollout_helper support method.

Read More

Code Talk Notes - Promises and Asynchronous Code

Published Thursday, August 20, 2015

Callback Hell

Promises are a pattern for managing async callbacks.

Calling then() generates another promise object, when then resolves at the end of the chain. When promise object resolves, it resolves with the data coming back, which can then be passed to the next promise in the chain. Helps maintain the idea of a return value to asynchronous code - brings return values back.

jQuery

jQuery has promises built in, but not fully up to true A+ promise spec.

When.js

When.js is a much more robust promises library.

When.js library provides many additional helper methods for promises. You can call return when.promise(function(resolve, reject){...}) to return a promise object and pass resolve and reject functions into the promise chain.

Use tap() to add in something asynchronously to the chain.
Use catch() at the bottom of the chain to handle an error at any point in the chain.
Use delay() to add in a delay at any point.
Use timeout() to throw an error if promise isn’t resolved after a certain amount of time. Use with() to pass in a context (usually Read More

Sublime Text Key Bindings

Published Tuesday, August 18, 2015

Keyboard shortcuts are a programmer’s best friend, and Sublime Text lets you write your own. I use these five below on a daily basis, and you’re going to want to, too. Here’s the setup:

  1. Open Sublime Text
  2. Type command + shift + p to open your Command Pallette (aka super+shift+p in Sublime lingo)
  3. Select Preferences: Key Bindings - User
  4. Insert the following into this file:
[ { "keys": ["super+shift+w"], "command": "close_all"}, { "keys": ["ctrl+alt+shift+down"], "command": "goto_definition" }, { "keys": ["alt+c"], "command": "insert_snippet", "args": { "contents": "console.log(${1:}$SELECTION);${0}" } }, { "keys": ["alt+d"], "command": "insert_snippet", "args": { "contents": "debugger;" } }, { "keys": ["alt+b"], "command": "insert_snippet", "args": { "contents": "binding.pry" } } ] 

Quick summary of each key binding:

super+shift+w => close_all

Closes all open tabs.


ctrl+alt+shift+down => goto_definition

Navigates to selected method or class definition (based on your cursor’s position).


alt+c => insert_snippet ‘console.log();’

Inserts console.log(); at your current cursor position.


alt+d => insert_snippet ‘debugger;’

Inserts debugger; at your current cursor position.


alt+b => insert_snippet ‘binding.pry’

Inserts binding.pry at your current cursor...

Read More

POODR Recap, or How I Learned To Stop Injecting Dependencies and Love OO

Published Wednesday, July 22, 2015

I’ll keep this concise, in the spirit of less is more.

Reading POODR has been one of the most beneficial things I’ve done in my long, illustrious career as a programmer (clocking in at approx $("Feb 02 2015").timeago();). It’s been recommended to me since ~week 2 of my immersive program at Flatiron School, but I’m glad I put it off until I’d built some un-POODR-like apps of my own. That context helped me draw connections between the abstract principles discussed in the book and very real production code I’m working on now. So without further ado:

Main takeaways from POODR:

1. Think about code in terms of objects and messages, not procedures

As Chapter 2 emphasizes, classes (and methods, really) should have a single responsibility. If you find your class carrying multiple responsibilities, break each one into its own separate class. You should conceptualize a class as an object that passes and receives messages, not something that executes some long procedure. Objects that execute a procedure can find themselves performing multiple responsibilities.

One strong example of this is a Ruby Code Challenge feature I’m currently working on, conveniently written entirely in Javascript. Its basic functionality...

Read More

Monkey Patching truncate_html

Published Monday, July 06, 2015

The truncate_html gem is a really useful tool for clipping off a string of html at a designated point. It has some nice customizeable config options, and best of all, zero third party dependencies. Per its docs, it even does the unthinkable:

This library…parses HTML using regular expressions.

Today I discovered I could extend its usefulness even further with a small monkey patch. Now, before the haters come out in full force, YES - I understand that monkey patching is dangerous and needs to be handled with deft and delicacy. That said, the small size and limited dependencies of this gem make it a prime candidate for practicing safe patching, Justin-Weiss style.

Moving right along…

Desired functionality:

1. Multiple break tokens

Per truncate_html’s docs, you can truncate your html after a after a certain number of characters (options[:length]) or at a designated piece of content, like <!-- break --> (options[:break_token]).

Setting a single break_token is great if I’ve created the HTML and set my own unique break_token wherever necessary. But what about situations where I want to pass in any old HTML and...

Read More

AcademyAwardable Polymorphic Associations

Published Monday, June 08, 2015

If you ever find yourself in a Rails-situation where you need one model to belong to multiple other models, consider using an ActiveRecord polymorphic association. Don’t let the multisyllabic name fool you; polymorphic associations aren’t as complex to build as they might seem. You can do it.

Meryl Streep Can Do It

Let’s consider a completely relatable and engaging example: The Academy Awards. Maybe you’re building an Oscar ballot app for a family member who’s particularly obsessed with this time-honored, hallowed awards show. Your app at minimum would need to contain Actor, Movie, Director, and Vote models (plus all those technical award categories, but we’re going to ignore them for now - just like the Academy). We’ll need some savvy schema design to keep things simple and DRY.

Let’s start by trying to set up our schema the old-fashioned, non-polymorphic way first. Actor, Movie, and Director would all have_many Votes, which means Vote would belong_to Actor, Movie, and Director. Here’s how that would look in our CreateVotes migration:

class CreateVotes < ActiveRecord::Migration def...
      
Read More

It's `document.write(new Date().getFullYear());` - Update Your Footer

Published Friday, May 08, 2015

As I was updating some content on my personal website today, I noticed the copyright date in the footer still read “2014”. Yeah, it’s May. Go me.

Sadly, I believe future-me from 2016 would probably make this same mistake, so to help myself out, I did a quick google search for “How to auto update year website”, which yielded this extremely helpful site: UpdateYourFooter.com. It offers Javascript and PHP solutions, with JS being the easier option for my needs.

Just add the following wherever you want the year displayed:

<script>
  document.write(new Date().getFullYear());
</script>

You can find more info on the Javascript Date object here. And best of all, this solution is supported in all browsers except IE8. Finally, there’s (of course) a longer discussion about this on StackOverflow, for anyone who wants some additional reading.

Read More

Rendering from a Model with ActionView::Base.new => WAT?

Published Sunday, April 26, 2015

I’m a firm believer in the “make it work” philosophy - solve problems first, then refactor. That said, my team may have gotten a little too creative making our last project work. Just take a look at this gnarly method we cooked up:

class Recipe < ActiveRecord::Base def recipe_card ActionView::Base.new( Rails.configuration.paths['app/views'] ).render( partial: 'menus/recipe', format: :txt, locals: { recipe: self } ) ###🙊🚷 W A T ☠😿### end end 

Yep. We instantiated a new instance of ActionView::Base in a model. And used it to render a view outside a controller. WAT?!

Before I go any further, let’s take care of the necessaries:

  • Yes, we know what we did was wrong.
  • Yes, we are deeply sorry for our crimes against MVC.
  • Yes, we’ll refactor and never repeat this grievous offense again.

But the thing is, it worked. And I’d like to explore how and why before purging this from our git history moving...

Read More

Dynamic Duos - Dependent Select Menus with JQuery and Rails

Published Saturday, April 25, 2015

The first time I tried to apply “dynamic selection” within a Rails form - where selecting an option in one select field dynamically updates the menu options in a second select field, I had a surprisingly hard time with it. I’d watched the Railscast and read multiple tutorials, but just couldn’t crack the code.

Problem was, I was trying to use a collection of model attributes in the first collection_select menu and a collection of model instances in the second menu, organized using the grouped_collection_select helper. What I learned after much trial, error and a deep dive into the documentation, was that the menu options should both be collections of model instances, where the models are associated through a join table. <– tldr: central lesson of this post.

I could have benefitted from more explicit discussion of those mechanisms, one with a slightly more complex example than countries and states. Towards that end, let’s walk through the steps I took to apply this solution in my Rails application, Parkster.

SECTIONS:

  1. Correcting the schema
  2. Updating the seeds file
  3. Adding appropriate ActiveRecord associations to models
  4. Updating the...
Read More

Sublime Linter Rubocop Reboot

Published Saturday, April 18, 2015

This week’s Ruby Weekly had a nice post from Matt Brictson on “Setting up Sublime Text 3 for Rails Development”. It reminded me to finally install the SublimeLinter-rubocop package. This package syncs your linter up with rubocop, highlighting “bad code” as you type (according to the community Ruby Style Guide). Great addition, right?

Well, word to the wise: don’t install a new linter package a couple hours before a technical interview. I didn’t have a chance to tweak the default settings, which as you’ll see below, are a bit…aggressive.

Mark Style Outline

I knew I’d be pair-programming with my interviewer, and no way was I gonna subject her to literally ugly code. I had to scramble to find a fix, and after jumping through a couple different sections in the SublimeLinter documentation, I found the solution. Here’s the lowdown.

Turns out you have 5 different linter mark styles to choose from. The package defaults to "mark_style": "outline". That style’s a little visually overwhelming with my current color scheme, so I decided to switch to the "mark_style": "none", so marks appear in the gutter only.

The...

Read More

Remote True is Magic

Published Sunday, March 29, 2015

I had a really fun time this weekend building a small side project with Sophie DeBenedetto, Jeremy Sklarsky, and Rachel Nackman. We learned a lot of very cool things that you can do with Rails + jQuery, but the coolest was easily remote: true. This one little option is crazy powerful. Case in point: by adding remote: true to our Search form, our searches.js file went from this:

$(function () { submitListener(); }) function submitListener () { $('#new_search').on('submit', submitSearch); } function submitSearch (e) { e.preventDefault(); var url = $(this).attr('action'); var $form = $('form#new_search'); $.ajax(url, { method: 'POST', url: url, data: $form.serialize(), dataType: 'script', complete: function(response){} 

      Read More
    

Listen Up - Tech Podcasts

Published Sunday, March 22, 2015

Back in my former life as an art historian / art shipper, it wasn’t enough to simply know about art. You had to know about the other people who know about art - the key figures shaping the field, your peers working on the same stuff you were - that was just as critical as being able to recite off Greek column types or the core members of the Arte Povera movement (which I can still do, thanks very much, humanities degrees).

Now that I’m joining this new realm of web development, I have a whole world of new people to get to know. Honestly, it’s been one of my favorite parts so far; the Ruby world especially has so many weird,wonderful voices, it’s been a blast reading up on and listening to the amazing cast of coders behind all these concepts I’m learning about.

One invaluable resource in this process has, of course, been podcasts. I pretty much only listen to podcasts these days (mostly comedy, with a dash of NPR and PRX staples), so it seemed natural to turn there for my tech education as well. Below are some of my favorites I’ve found so far....

Read More

Who's Ahead Now?

Published Sunday, March 15, 2015

After week one of learning Rails, I was eager to test out my new skills on a new side project. I wanted to build something fairly simple, that would utilize skills I felt comfortable with - JSON parsing, ERB, simple search and routing - while also pushing me into uncharted territory, like deploying on Heroku. I spent the afternoon brainstorming, circling around some sort of app that would answer a single simple question (like Is It Raining?, one of my fave single serving sites). I had a couple good ideas, but my partner came up with the best one: is Hillary winning?

Now obviously a website that just says “aw yass” every time it renders doesn’t have much utility. So I decided to expand the concept a bit and build a site that yields the current frontrunners for each party in the current presidential race. A quick rubygems search pointed me to HuffPost’s Pollster API, which is really nicely maintained. Armed with data and a plan, I started building.

Texts from Hillary

The app ended up being pretty simple:

  • One model (Search)
  • Three controllers (ApplicationController, SearchController, and WelcomeController,...
Read More

--no-test-framework

Published Thursday, March 12, 2015

Note to self:

Bart Simpson chalkboard

Why? Without the --no-test-framework flag, Rails generate will do the following:

a) overwrite any existing tests that you, your colleagues, or your instructors have already written for that particular object

b) generate unnecessary / unwanted tests (see Thoughtbot’s helpful post on diminishing test coverage returns).

Better to write your own tests. Here’s hoping repetition leads to retention…

UPDATE: my classmate Rachel Nackman wrote an excellent blog post on Rails generators, which included an extremely helpful tip for not overwriting tests. Just add the following code to your config/application.rb file:

module Testing
  class Application < Rails::Application
    ...
    config.generators.test_framework false
  end
end

Voila! Your generators are now auto---no-test-frameworked.

Read More

Flatiron Twitter CLI

Published Sunday, March 01, 2015

Last week, Avi pitched a pretty cool idea to the class: build an “auto-follow bot” for Flatiron student twitter accounts - something we could use to easily auto-follow everyone in the class.

Avi Flatiron Twitter pitch

I’d been looking for a side project to work on (inspired by my classmates who’ve built some very sweet side-projects already: ex.1, ex.2, ex.3, ex.4) and this seemed like a perfect opportunity. I’ve never built a bot, but I know how to build a CLI, so I put labwork on pause and spent my Saturday building the FLATIRON TWITTER CLI instead (available at your local github).

Let’s walk through the build, starting with setup. I tried to follow best practices, setting up bin, config, and lib folders, along with a Gemfile and README.

Right off the bat, my bin/run file almost sunk me. I wanted users to be able to initialize the CLI by simply cd’ing into the directory and running bin/run.

#!/usr/bin/env ruby require_relative '../config/environment' FlatironTwitterCLI.new.call 

I thought the code above would do it, but...

Read More

Refash Your Bash - Bash Prompt Customization

Published Monday, February 16, 2015

When I was just starting out learning to code, it quickly became clear I’d be spending a lot of time in Terminal. Never one to skimp on workspace feng shui - just ask my old art world colleagues - I set about post haste to fine tune the CRUD out of my bash profile, starting with the bash prompt.

Now, I’ll caution, there’s an endless plethora of resources out there on the ol’ internet about customizing your bash prompt, and my first time through, I think I read nearly all of them (really went down the .bash_profile rabbit hole, I’ll admit). To save you some time and tedium, I’ll summarize my specific mods below, with tl:dr links to resources for further customization.

Note for fellow rookies: My bash prompt is contained inside a nice little function at the top of my .bash_profile file. I’d recommend putting this function towards the top since 1) your terminal loads the prompt first and 2) that way it won’t interfere with any of the rest of your bash code below. Now without further ado …

###My Complete Bash Prompt Function

function parse_git_branch { git branch 

      Read More
    

Using Github for Lecture Notes

Published Sunday, February 15, 2015

Flatiron School has a great system for sharing lecture notes: a dedicated Github repo. I forked the repo during week one, thinking I’d pull down the files to my local, take notes on the notes (Inception-style meta-noting), then push back up to my forked repo. No sweat.

But then comes the scary part for us git-n00bs - getting updates. I felt real comfortable pushing to / pulling from my own repositories. But to get the next days’ lecture material, I was gonna have to add my instructor’s repo as a remote. Yikes. Now that’s a scary connection to make. Any mistakes, and I’m screwing up the lecture docs for Avi, who might have to redo them, and my classmates, who need this material asap for labs + projects. I needed to handle this delicate operation with extreme care.

Indiana Jones Raiders of the Lost Ark animated gif

As I now do in all these types of situations, I went straight to Github support. Here’s the solution, specific to our Flatiron repo.

1) Open Terminal and cd to whatever folder you want to use for lecture notes storage.

...
Read More

Adventures in DNS Configuration

Published Tuesday, February 03, 2015

###Or How I Stopped Worrying, and Learned to Love GitHub Support

One of the main tenants of the The Flatiron School is “Always be a beginner,”* which has been pretty easy for me to embrace so far, since I am the noobiest of coding noobs right now. Pretty much every day, I’m reminded of my beginner-dom, even in realms I thought I’d more or less mastered.

Case in point, this very blog.

Day one, we were asked to set up technical blogs, which we’d use to write about all the cool new concepts we’re learning. I was pretty excited to dive right in, especially since I’d just built my own portfolio site at my newly-purchased custom domain, kate-travers.com. When I found out GitHub offered free hosting through GitHub pages, I about flipped. This was gonna be great. I could build out my new site with a SEO-friendly blog feature, perfect my git skillz and gain all kinds of Github coder cred in one fell swoop. I was a subdomain and CNAME record away from blogging like hacker.

Now, this was not my first time at the DNS-configuration rodeo. I’d set up probably +10...

Read More