Development Agency & Digital Product Superheroes
Apps | Software | Hardware

Let's work together

Rhabit

Live Video Coaching Sessions with top tennis coaches

Learn more

Product Super Powers

Product Design

We’ll help you refine your idea and roadmap it into a real solution.

Native Mobile Apps

Your mobile app will be ridiculously fast and extremely reliable.

Web Apps & Software

Everything we build for you will run seamlessly across different platforms.

Hardware Development

We’ll apply technology to your hardware and make it way cooler.

See All Services

Genevieve Theirs
CEO, NewFounders

SO MANY THANKS to 20Spokes, our amazing tech firm here in Chicago. We literally cannot say enough good things about 20Spokes.

Why 20spokes

Passion

We live and breathe design and development, and put that passion into every product we produce.

Transparency

You’ll know everything that goes into your product with status updates on a consistent basis.

Quality

Quality is top of mind. We work through a tailored approach to ensure that quality is consistent.

Fun

Turning your idea into a reality will not only be a rewarding experience that results in a high-quality product, but we guarantee you’ll have some fun.

From the Blog

Technology

7/6/18

Using Active Storage with Active Model Serializers

Attachment is the root of all suffering. If you’re a web developer, attachments are the root of all suffering.

Paperclip, a longtime go-to gem for managing file attachments, has been deprecated in favor of Active Storage, which is now officially part of Ruby on Rails as of version 5.2. So for a recent greenfield app, I took the dive into Active Storage.

Switching out dependable gems for new ones can be anxiety-inducing, but that’s web developer life. While Active Storage ended up being a breath of fresh air for many reasons, it came with a few of it’s own gotchas, particularly when dealing with querying data.

Active Storage and N+1 queries

Let’s say a user has one avatar. While Paperclip would add a few columns to your users table to store the avatar’s file data, file type, etc., Active Storage will create new tables that are solely responsible for keeping track of asset data and associating this data to your records.

These tables are called blobs and attachments. Blobs represent the actual metadata of the files, whereas Attachments are what join blobs (file data) to your application’s records (users). For every file you upload, a blob is created and associated to your record through an attachment.

These relationships are created when you attach a file through Active Storage using the has_one_attached shorthand:

class User < ApplicationRecord  
  has_one_attached :avatar

It’s important to understand these relationships between blobs and attachments when dealing with record queries that may have attachments.

For has_one_attached relationships, you can avoid N+1 queries by adding the with_attached_X method that Active Storage generates for you based on your attachment name:

User.with_attached_avatar.where(active: true)  

This is basically saying:

User.includes(avatar_attachment: :blob).where(active: true)  

I had to take special care of these relationships when using Active Model Serializers. Normally, when dealing with child records in a serializer, you can define a relationship using has_one or has_many:

class GameSerializer < ActiveModel::Serializer

  attributes :title

  has_many :users

If my User Serializer is using the avatar in any way, this would create an N+1 scenario:

class UserSerializer < ActiveModel::Serializer

  attributes :avatar_url

  def avatar_url
    ...object.avatar_url...

In order to avoid N+1 queries here, I had to ditch the built-in has_many and create a custom users method for the Game Serializer:

class GameSerializer < ActiveModel::Serializer

  attributes :title, :users

  def users
    User.with_attached_avatar.where(game_id: object.id)

Finding the right asset URL for serialization

When passing image urls through serializers, I had to search through some Active Storage Github issues and documentation to find the right url to use.

Creating images of smaller sizes is common for real-life use of your assets. Active Storage calls these variants. You’ll most likely use variants rather than the original asset in serializers.

If you want a url of the asset variant, include the Rails.application.routes.url_helpers module in your serializer, then use rails_representation_url in your url method:

class UserSerializer < ActiveModel::Serializer  
  include Rails.application.routes.url_helpers

  attributes :avatar_url

  def avatar_url
    variant = object.avatar.variant(resize: "100x100")
    return rails_representation_url(variant, only_path: true)
  end

If you want to use the original asset, use rails_blob_path instead:

return rails_blob_path(object.avatar, only_path: true)  

So there’s a little extra work when serialization is concerned, but overall I really enjoyed working with Active Storage and appreciate what a great thing this is for the Rails community.

Technology

7/6/18

React and its Less-Cool Cousin, Semantic HTML

One of the best and most meaningful features of HTML5 is its introduction of more “semantic” tags, or tags that help define the structure of a webpage. Tags like section, article, footer, nav, and aside are highly useful for improving the accessibility of a website for visually impaired users. They provide valuable information about your site to any screen readers that are processing it, allowing for easier browsing and less time wasted with repeated or irrelevant information. Semantic tags improve your site's SEO rankings for the same reason — they help search engines understand what your site is about. And on a more basic level, these tags make it easier for developers to understand what role each element plays on a particular page, increasing maintainability.

So where does semantic HTML fit into the React.js framework?

React requires that any render function returns a single parent element that contains the rest of the content. Depending on the complexity of your UI, this rule can result in an bulky Matryoshka doll of divs, divs, and more divs. The benefits of semantic HTML can get muddied by just how easy it is to stick another handy, neutral div in your component tree, especially when (out of habit) you start using divs in place of more semantically useful tags, like button or nav.

Enter React v16.2.0, released in November 2017, which introduced an awesome new feature called Fragments:

"Fragments look like empty JSX tags. They let you group a list of children without adding extra nodes to the DOM."

With this addition to the React framework, there’s no reason to bulk up the DOM with more div tags. There’s a handier, even more neutral tag in town that does exactly what we need.

render() {  
    return (
        <>
            <h1>Content title</h1>
            <p>Sample content</p>
        </>
    )
}

Fragments are a way not only to streamline your webpage, but also to get out of the habit of using a div when another, more specific tag would make sense. Let’s make the internet a more accessible place by remembering that for some consumers, semantic HTML isn’t just “nice to have.” It’s essential for navigating your UI.

And hey — no more sifting through divs to debug your front end, am I right?

Technology

5/17/18

When to Put Data in Redux

Lots of internet ink has been spilled over when to keep data in an application state management system (like Redux) versus in a React component's internal state. While I've mentioned benefits to Redux on this blog before, it's important to understand the tradeoffs.

Keeping state in components has pros and cons:

Pro: your data is cleared when the component unmounts!

Con: your data is cleared when the component unmounts.

Likewise, keeping data in app state has pros and cons:

Pro: your data persists between components!

Con: your data persists between components.

Personally, I err on the side of keeping data out of app state. If I'm creating a new component and I'm unsure where to store my data, I'll use internal state, then port to Redux when it becomes necessary.

It's helpful to conceive of your app state as a collection of global variables. Normally, global variables are to be avoided. You wouldn't add global variables willy-nilly in a Rails or Python app. Have the same precaution when adding globals client-side.

Like any other global variable, when you make the decision to move your data into the global app state, it is now up to you to manage it. For instance, you'll probably need to clear your app state when a user logs out. When a user exits a multi-step form, you may need to clear any data that user entered.

Constructing your React container components thoughtfully can help you avoid manually managing state like this. With multi-step forms, I typically create a wrapper component that's responsible for rendering each step of the form, keeping all user-entered data in its own state. From this container, I can pass any of its state and functionality down to each step as props. It's a simple solution, but an often overlooked one, especially when Redux is already in your app and you see other components using it.

When an app uses Redux, it's impossible to prevent future maintainers from simply adding everything to app state. You can mitigate this by stressing in your documentation how keeping state in Redux can be dangerous. You can also practice predictable state patterns in your own components (like the form wrapper), setting good examples for future developers. But ultimately it's a hard thing to enforce, and this should be considered when deciding to add Redux to your application.

View More Work

PupJoy

We automated PupJoy’s operation and gave back hundreds of man hours. (So we could all spend more time with our best friends)

Rhabit

Want to watch a video of player mechanics while streaming a video chat with your tennis coach? We made it possible with Rhabit.