omg polymorphic associations

Don’t worry, they really aren’t that scary, but it’s the sort of concept that slips away from you if you haven’t worked with it in a while. For a recent code challenge, I was asked to find a polymorphic use case for the upvotes table in my Graffito app. Currently, the table functions as a join between the user and graffiti models. There is a many-to-many relationship between users and graffiti and upvotes is the glue that binds them. The association declarations and schema look like this:

This is fine so long as we only want to allow users to upvote one model, Graffiti. But what if we expand that feature to favorite specific photo uploads that belong to a graffiti? At first glance, it might appear that a new upvotes tables is required: upload_upvotes. But that instinctually feels like overkill and a violation of the DRY principle.

How can we extend the upvotes table to handle relationships to not only graffiti but also uploads? Polymorphic Associations to the rescue.

According to Rails docs, “with polymorphic associations, a model can belong to more than one other model, on a single association.” This is achieved by abstracting the association naming more broadly, often just by adding able to the join model name, i.e., upvotable. Let’s take a look at the new associations and schema:

On line 16 above, we establish a polymorphic association, upvotable, which translates to two new columns in the upvotes table, upvotable_id and upvotable_type. Upvotes can now belong to more than one model on the single association; upvotable functions as an alias to any other model we attach it to, e.g., graffiti and uploads.

There’s one more thing I want to unpack. A user has many upvotes. But upvotes now attached to multiple models so we have to devise away to query the graffiti or uploads that users have upvoted. Once again we can take advantage of our polymorphic association and simply specifiy that source types we’re interested in (Graffiti and Uploads).

The great thing about polymorphic associations is that they scale really well. Imagine we decide to add upvotes to comments, drawings, or videos. That’s not a problem. The upvotes table can be extended to handle any number of models on our single abstract association, upvotable, and we don’t have to worry about managing a bunch of other upvote tables. Polymorphic associations are efficient and elegant if not a little confusing. They are well worth the effort.

Advertisements

Refactoring with let Block Scope

While I was refactoring a code challenge today, I learned something very cool about ES6 variable declarations via the let keyword vs. variable declarations via the var keyword. let is scoped to the nearest block while var is scoped to the nearest function. This is particularly important in the context of loops because let will create a new binding of a variable for each iteration; var will only create one binding.

When you have a callback inside a loop that relies on separate bindings at each step, using let saves you the headache of wrapping the callback in a closure to make copies of the variable at each increment. The canonical example is calling JavaScript’s setTimeout() function inside a loop to execute a function or code snippet after a specified period of time (delay) in milliseconds:

Let’s take a look at how this informed the refactoring of my code.

I was tasked with building a tool that takes a sequence of CSS styles as input and uses vanilla JavaScript to apply each step in the sequence to the DOM, animating an element over time.

The input consists of a 2D array of CSS styles, where each array has a time delay and any number of style objects.

To implement the animator, I looped over the input and set timers to update the style of an element in the DOM after a delay. let‘s block scope binding allowed me to refactor my code without a closure.

An integral part of the challenge is that each step is relative to the previous step. So it’s not enough to apply the styles at step 2 after 200 milliseconds (see input array above); step 2 must be applied after delay + delaySoFar milliseconds, or 300 milliseconds. Likewise, step 3 must be applied after 500 milliseconds.

To persist the cumulative delay, on line 29 above, I declare the variable delaySoFar outside of the loop. Inside of the loop, I set each step’s delay to the sum of the current delay (sequence[0]) and delaySoFarOn line 36, I invoke setTimeOut(), without a closure thanks to let‘s block scope binding. Inside each timer, I set the style of an element in the DOM after the current delay. Last, after the timer is set but before the next loop, I update delaySoFar. The result animates the element and each step’s delay is relative to the previous step.

I really enjoyed this code challenge. The efficiency of let‘s block scoping is nifty.

Some More Thoughts on React

I’ve been immersed in React for about three weeks now, and so far I’m finding it really easy to organize and maintain. Compared to Angular 1 (still haven’t tried Angular 2), my code is also much easier to read and understand. I like how JSX lets me embed HTML-like syntax inside JavaScript, instead of having separate HTML templates with Angular’s unique syntax embedded within. With React, you don’t have to learn all that new syntax.

An all-JavaScript approach not only feels intuitive but it has performance benefits. React achieves this by decoupling state from the DOM and storing it in a virtual DOM. When state lives in the real DOM you must traverse a sometimes huge tree structure to update a node (think jQuery), whereas with React’s virtual DOM, it keeps an eye on the state of a component via a diff algorithm, and whenever it changes, it simply converts the component to a React element and inserts it in the DOM. Imagine a DOM with thousands of child nodes – the virtual DOM approach results in far greater efficiency.

Furthermore, the idea of designing a code base in terms of reusable UI components instead of a larger MVC framework vis-a-vis Angular 1, cuts down significantly on my code base. Its principles encourage me to think more about the features and layout of my site.

Most important, I love the React environment. With webpack and the webpack-dev-server, debugging is a synch because it happens in real time; the server watches your source files and recompiles them whenever there is a change. If there’s a bug, the app will break and almost always yield a helpful error message because React is all JavaScript. On the other hand, because Angular embeds its own syntax in HTML templates, debugging can be more difficult.

I also love the object-oriented approach that React encourages. With ES6 classes, I can define state and the events that change it in the constructor of my component. That makes the code more succinct and maintainable for a colleague who might jump in on a project. Here’s an example of an ES6 class with a constructor function from a current project I’m working on:

Lines 7-9 above demonstrate how quickly one can get up to speed on what this component is responsible for: keeping track of a username in the DOM. Line 7 signifies that the username property is what we are watching. Line 8 tells us that there is an event that updates that property while line 9 shows there is a form submission event. A fellow developer jumping into this code would be off to a great start synthesizing its purpose. On a side note, it’s important to note that we must call .bind and pass in this on both of our events; otherwise this will be undefined in the method.

Let’s talk about line 5 as well. All React classes are initialized with a props object via calling super(props). Don’t be sidetracked by the super part. The only effect of calling super on props is so you can access this in the constructor. It’s probably redundant because we already have reference to props but the React docs encourage it: “Class components should always call the base constructor with props,” which is in keeping with object-oriented JavaScript’s standard of binding instance properties to this.

The props object allows you to access anything you pass in while “invoking” a component. Because I’m using React Router, my props object contains all sorts of useful information like routes, route params, and location, plus anything else I want to pass when I invoke the component.

Let’s take a look at my routes and compare it with the props object it yields.

On line 11, I “invoke” a route component and pass it three key/value params: path=’playerOne’, header=’Player One’, and component={PromptContainer}. component points to the class where all this information is headed.

Now, inside the constructor of PromptContainer, let’s log the props object to the console. A lot of useful information lives in props when you use React Router, but lets focus on what we manually passed in. The route object contains all the info we passed in and we can now access by call any of the keys on this.props.route.

screen-shot-2017-01-13-at-11-19-08-am

Finally, let’s demonstrate how we can use props, state, and the events defined in our constructor in the render method of our UI component:

On line 3, we access our header prop as the value of our tag. Line 5, binds the onSubmitUser event to the React onSubmit callback. Line 11 binds our onUpdateUser event to React’s onChange event (this watches for any changes to the input field). Last, on line 12 we set the initial value of the input field to the state of username defined in the constructor.

Check out this codepen to see a working example. Note that the app is incomplete. After you enter player two’s name, an alert will flash.

Functional React Components and Props

In this post, I’ll show how to build an avatar using functional React components. You can think of React components as isolated building blocks to reuse throughout an application. They accept inputs and return elements for updating the DOM.

Functional React components are pure. Just like pure functions in JavaScript their execution doesn’t depend on the state of the application, they don’t modify any variables outside their scope (no side effects!), and they always return the same result given the same arguments. Because of React’s adherence to pure components, learning React makes you a better developer. It also makes testing easier.

To start our avatar component, let’s think about what building blocks we’ll need to make it. An avatar has a user image, a user name and a probably a link to a user profile. Hmm, sounds like we need a user object. We’ll define one using an ES6 constant, call ReactDOM’s render method and pass it our forthcoming Avatar component.

ReactDOM’s render method takes two arguments — our avatar component that returns a UI object and the element in the DOM where the UI will be updated to. As we “invoke” the Avatar component we pass it the user as props, essentially parameters the component will use to create the UI. Now we can define an Avatar function and access the user object.

Our Avatar component is comprised of three other components: ProfilePic, ProfileName and ProfileLink. Each needs access to some part of our user object. As we “invoke” the child components, we pass in the necessary props. It’s important to note that the React component rendered in the DOM must be wrapped in a div.

With our child components we don’t need to worry about a container. Each child component can just return whatever element it needs to. And that’s pretty much all there is to building function react components. Nothing too fancy — it’s very similar to writing pure functions with JavaScript. The only difference is we’re returning JSX instead of primitive values.

Checkout the example on CodePen.

First React Component

In my last post, I showed how to set up the React environment — npm to download packages and their dependencies, webpack to minify and bundle code into one file for production, and Babel, a compiler that processes React into JavaScript the browser can understand.

I left off with using regular JavaScript to select an element and set its inner HTML to “Hello World!”. In this post we’ll use a React component to do that.

Writing a React component is so much easier than setting up the React environment, because React is really just JavaScript. If you are comfortable with JS, it follows that you’ll be at ease with React.

In index.js, set two variables equal to the two React modules we downloaded in my last post, react and react-dom. The syntax for loading a module is require(insert-module-name).

On line 4, we’ll define our first React component and set it to a new variable, HelloWorld. We’ll start without using ES6, in which case you can use the createClass helper to initialize a component class. Every React component includes a render function that returns the HTML you want to display in the DOM.

On line 12, we use the render method from the the ReactDOM module to update the DOM with the output from our HelloWorld component/function. We pass it the component first, the selected element last.

Next run npm run start to start the development server, visit http://localhost:8080/ and you’ll see “Hello World!” displayed.

It’s always worth using a web inspector to see what’s being rendered in the DOM.

screen-shot-2016-12-29-at-10-53-04-am

As expected, the HelloWorld component has rendered inside the app. Note how the div element we rendered was automatically assigned a data-reactroot attribute. This allows tools like react-detector to identify a React app without any hiccups.

In my next post, I’ll demonstrate how functional components and props are used to organize your UI into reusable, isolated building blocks. All react components are pure; they always return the same result given the same arguments and never change the state of variables outside of their scope (no side effects!). This makes React components easy to test.

React Environment: NPM + Webpack + Babel

Building a React component is easy. It’s setting up the environment that’s tricky — you’ll need npm, webpack and Babel to get started. Once set up, webpack will take all your files, compile them into JavaScript the browser can understand, and output them to one single file.

To start a new React project, create a new directory call webpack-test-project and cd into it. Run npm init. This will create a package.json file in the root of your project.

Next run npm install –save react react-dom. This will create a new folder in the root of your project call npm_modules and will download the react and react-dom modules to it, along with any of their dependencies. As well, package.json will be populated with a dependencies object that includes any downloaded modules. This is great because instead of pushing all your modules to GitHub, a teammate can clone your project, run npm install, and presto, react and react-dom will be downloaded to their npm_modules folder.

Next, you need to install webpack via npm. webpack is module bundler. It will take our assets and transpile them according to the specifications in our config file. In this case, we’ll be configuring webpack to use babel and babel-preset-react to compile our code. By compile, I mean that webpack will process our React code to modern javascript that the browser can understand. Babel can also process ES6 & ES7 to JavaScript the browser can understand.

To install webpack and Babel run npm install –save-dev html-webpack-plugin webpack webpack-dev-server babel-{core,loader} babel-preset-react. Notice that this time we used –save-dev because we will only be using these packages in development mode. All of these packages will now be listed in package.json:

Next run mkdir app && cd app and create an index.js and index.html file. Then, in the root of the project create webpack.config.js — we’ll use this file to configure webpack.

We configure webpack by building an exports object, with three important keys: entry, output, and module. Entry tells webpack which files to process; Output tells webpack to bundle your JS files into one new file called index_bundle.js that lives in a new folder /dist in the root of our project. Module tells webpack which loaders (processors) to use to compile our React code into JavaScript the browser can understand.

The Module object contains an array of loaders. In this case we only need one loader, babel-loader, to process our code. In the loaders array we tell webpack to take any file that ends in .js (except those in the node_modules folder) and process them with babel-loader.

But we aren’t finished yet, Babel has its on config file. Create a .babelrc file in the root of your project that tells Babel which presets/processors to run on your code, in this case react.

Ok, almost finished with configuration. The only outstanding issue is instruct webpack to create a new index.html file in the /dist folder and link to the bundled script, index_bundle.js. We will use the HTML webpack plugin to accomplish this task. Run npm install –save-dev html-webpack-plugin. This will update your dependencies in package.json and download the plugin to node_modules. Next, we initialize the plugin in webpack.config.js.

First, declare a new variable and set it to the HTML webpack plugin module. The object we pass to HtmlWebpackPlugin on initialization contains three properties: template, filename and inject. Template points to the file we would like to transform, filename specifies the name of our output, and inject specifies where in the output we want webpack to put the link to the bundled file, in this case the body tag. Then, at the end of the exports object, add a new property plugins and set it to our plugin instance, HtmlWebpackPluginConfig.

Phew, now all the architecture is in place but we still need to define scripts to run webpack. We’ll use two scripts, one for production, webpack -p, and one for development, webpack-dev-server, and put them in package.json. We’ve named our scripts production and start.

Scripts allow us to define shortcuts for common administrative tasks like bundling code. To bundle and compile our code for production as configured in webpack.config.js, run npm run production. After, you should have a new folder in your root project, /dist, with a new index.html file linking to a single compiled file, index_bundle.js, with all of our JavaScripts ready for the browser. You’re file structure should look like this after running the command.

screen-shot-2016-12-28-at-2-57-42-pm

Finally, let’s test this all out with some code. In index.html  create a div element with an id set to app.

And in index.js, fetch the app element and set its inner HTML to “Hello World!”.

Run npm run production one more time. Now when you open ./dist/index.html you should see Hello World! in the top left of your window, which means npm, webpack and Babel are all working properly!

And check out your dist/index.html file. It should be exactly the same except it will link to index_bundle.js in the body.

index_bundle.js will contain a minified version of index.js, transpiled to browser-friendly JS.

Finally, because we aren’t in production mode most of the time, it makes more sense to only compile our code when pushing to production. While in development mode, take advantage of the start script we defined about in package.json. Run npm run start and you can view your progress at http://localhost:8080.

Setting up the environment for React is a bit complicated but it gets easier with practice. I recommend building the environment a few times. In my next post, I will show how to build a React component to display “Hello World!”.

For further information on setting up the React environment, check out this amazing free tutorial which informed much of this post.

 

 

 

 

Learning React: The Environment – NPM scripts

I’m excited to be learning a second front-end framework, React, because I like the idea of writing ES6 JavaScript components with embedded HTML instead of embedding HTML in JavaScript, like with Angular 1.

A prerequisite to learning React is having a basic understanding of its environment, which includes npm, the package manager for JavaScript. npm allows you to easily install and update modules like jQuery.

To initialize an npm project, run npm init from the console. This will generate a package.json file in the root folder of your project.

To install a package like jQuery, run npm install jquery –save. This creates a new folder called ‘node_modules’ in your project and downloads the jQuery package to it.

The –save part of the command will include jquery under dependencies in package.json. This is nifty because when a colleague clones your project, they can simply run npm install and any dependencies in package.json will be downloaded to their node_modules folder.

Another cool feature of npm is scripts. Scripts allow you to store commands that would otherwise be cumbersome to type out in the console. For example,  instead of always typing karma start –singleRun to run your Karma tests, you can define a script like…

… and now you just have to type npm test to run your specs. This comes in handy as a project grows and files get deeply nested, as you deploy and have to manage ever more command line tasks.

When I first learned about npm scripts, I found it helpful to compare them with Rake tasks in Rails. Although Rake tasks are more substantive and involve functional code snippets, like npm scripts, they allow you to define administrative tasks and run them from the command line by their definition. Here’s a fallback Rake task I wrote to upload files to Amazon S3 that are older than 300 seconds:

To execute this task you would run rake:upload_jobs from Rails console, or use a scheduler to automate it every few hours.

Next I’ll be learning about the module bundler webpack and building my first React component!