Code Reading - Learn ❤️ GraphQL

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

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

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

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

Notes from day one, day two and day three.

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.

Regional rules

...
Read More

Dev Ops Crash Course - Day Three

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

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 /etc/cron.d. Why Read More

Dev Ops Crash Course - Day Two

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

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 go in every...
Read More

Dev Ops Crash Course - Day One

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

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 options: +cmd ;; Got...
      
Read More

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

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

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 Form...
      
Read More

React and Redux Crash Course with Steven Nunez PART DEUX

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)
  9. ...
Read More

React and Redux Crash Course with Steven Nunez

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

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

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

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, email:...
      
Read More

BASH Tips and Tricks

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 display the on-line manual...
      
Read More

React Code Talk Notes

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

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

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

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

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

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

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

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

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

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?

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

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

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

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

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?

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

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

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

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 --no-color 2>...
      
Read More

Using Github for Lecture Notes

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

###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