Christopher
Stoll

Changing Dev Stacks: Ruby on Rails to Elm on Feathers

Changing Dev Stacks: Ruby on Rails to Elm on Feathers

From the fourth quarter of 2017 through the first half of 2018 I was almost exclusively creating Ruby on Rails applications. After the excitement of mastering a new toolset wore off, I started to feel that I was working on a dated platform. There’s nothing inherently bad about Ruby on Rails, it is a time-tested and validated approach for creating reliable monolithic web applications. But, having just previously worked at a shop where we figured out how to build actual microservices, building monolithic applications simply felt dated.

I certainly wasn’t going to use microservices out of the gate for my side projects, but I at least wanted to abstract the presentation layer from the data access layer. So, I needed a set of tools which made creating SPAs (single page applications) and APIs as easily as it was to create views and models with Rails. Where I landed isn’t quite as easy, but it is fairly enjoyable, and I really don’t even know what I’m doing yet. The stack I landed on was Elm for the front end and, for now, FeathersJS for the backend.

On one hand, I don’t expect people who have only worked on monolithic applications to completely understand why I feel the need to split the code base. On the other hand, I’ve seen what happens when a monolithic development shop is asked to make an app work on mobile. In the best case scenario, their monolithic application has a responsive user interface and the client doesn’t need any off-line capabilities. As soon as the client needs off-line capabilities a SPA is probably required, unless the client is ready to spend for native app development. The reality is that web application development has become intertwined with mobile application development. Established shops like Basecamp can implement a native-heavy hybrid mobile strategy, but that strategy may not be best for a shop trying to quickly get market traction.

Even if we ignore the entanglement of web and mobile applications, web application users have certain expectations of modern web interfaces. A certain amount of JavaScript is required for almost all modern web applications, that’s why the creators of Rails built the Stimulus Javascript framework. Ruby on Rails has tools which make adding Javascript to the asset pipeline easy, but it still has to be managed inside of a view, and it always has that bolted on feel to it.

It may seem like I am picking on Ruby on Rails or DHH, that’s not my intent. I respect the Rails contributors and what they have created. Having created server-side web applications using Python (Django), PHP (Cake, Laravel), and even ColdFusion, I think Ruby on Rails is best in-class. (I’m ignoring enterprise class platforms which have a different set of constraints and objectives.) I’m using Rails as my example because it’s harder to dismiss my core argument about the datedness of monolithic applications by blaming the toolset.

So, if monolithic applications are dated, why isn’t every shop switching to JavaScript SPAs? I think it’s because almost everything about the JavaScript ecosystem is, to put it nicely, fragile.

Sigh, Javascript (via @Sh1bumi)

Everyone who has significant expose to the language knows it is basically garbage. They may not call it garbage, but in their hearts they know it is. JavaScript programmer interviews often just come down to summing up how many pitfalls the candidate knows about and whether they can avoid the biggest ones.

The package system for the language is getting better. But, it’s hard to forget the time that one developer pulled packages from npm and prevented everyone from deploying for a day. Ohh, there’s also the lack of a standard library which made everyone dependent upon a library that just left-pads strings.

There have been and continue to be many attempts at providing tools to make developing with Javascript better. But, in the end they are mostly thin wrappers that can be bypassed, intentionally or otherwise. I like Typescript, but it’s way to easy to type something as ‘any’. And, in order to gain traction, many of these wrappers use existing Javascript libraries, so you never really get away from it. I am willing to give up the few good parts of Javascript to work with something that will be better in the long run.

Javascript is clearly not what I want, so what am I looking for? First, I want static types. I’ll give up the flexibility of being able to assign arbitrary data to a variable for less headaches and higher quality in the long run. I swear that at least half the value of creating unit tests is for discovering problems caused by lack of clarity around parameter and return types.

I really want something that allows me to write fewer tests. My agile friends and colleagues will gasp at that, but tests are overhead. I see tests in the same light as scaffolding – a necessary evil. I don’t write tests for the business value, because they provide none. I don’t write tests for fun, because it isn’t. I write tests to make refactoring the application easier. A statically typed language with an intelligent compiler should reduce the need for many classes of tests. A functional language would reduce the need even further.

After searching and trying a lot of front-end web technologies, I decided to invest time in learning Elm. I was skeptical, but it most closely matched my desired requirements. I started by following the guides and then evolved that application into a score keeping app. Everything was going well with the single page, so I added a router to created a more useful single page application.

Next, I needed a backend to work with. There is no server-side version of Elm, it is in-browser only at this point. My original intent was to use Elixir for the back-end, but I was already learning a lot of new things. I decided I would concentrate on learning Elm, and focus on Elixir at a later date. I grabbed FeathersJS, which makes creating simple API servers easy. I know, it’s still Javascript. The nice thing with Feathers is that minimal Javascript is required to get a basic RESTful service up and running.

To get the two pieces talking to each other requires getting a better understanding of the Elm architecture, but it wasn’t too difficult. The hardest part was setting up the JSON decoding pipeline inside of Elm. Some of the difficulty was simply due to the nature of adding type information to the JSON data. Some of the difficulty was due to the awkwardness of the patterns Elm uses for decoding.

With the web application stack up and running, I turned my attention to adding in authentication. I use Auth0 as my default authentication service because it is easy to get a secure process up and running. So, I started out by attempting to add the Auth0 code directly into the Elm application. That approach still requires the use of ports and flags, so it seemed to be easier to keep the Auth0 code on the Javascript side and just send the resulting auth information into Elm.

I pushed all of my code up to GitHub, as is the custom. The frontend is named scoredy-os-frontend, and the backend is named scoredy-os-backend. The app itself is available at scoredy.com.

Unfortunately, since I started writing this post elm has been updated from 0.18 to 0.19. I would update my example code to use the latest version, but it uses sockets and elm 0.19 currently lacks support for websockets. There’s nothing inherently wrong with this demo using elm 0.18, but there have been some significant changes, so not all the code there applies in an elm 0.19 environment.

Besides for unexpectedly loosing websocekts, I have enjoyed using elm. Ruby on Rails developers will appreciate the enjoyment factor, since their platform is at least partially driven by developer happiness. So, if you are a Rails developer who feels like they are getting left behind the times, maybe give elm a try.

Published: 2018-08-30
Ruby on Railselmfeathers