RubyConf AU 2017
Functional in the Front, Rails in the Back: Give Your App An Elm Mullet

http://www.rubyconf.org.au

You want to keep up with new and exciting technologies, but rewriting your monolith in the language du jour is too daunting a task, and you're not sure a microservice split is right for you. Why not experiment with a purely functional, powerfully typed language in your existing Rails app? Elm is a new language that compiles to JavaScript and has lots of great mind-bending features. In this talk we'll look at the basics of Elm and how you can integrate it into an existing Rails app, even alongside your existing JavaScript code.

RubyConf AU 2017

00:00:12.360 My name is Louis. I'm a technical aid at Rea. Hey, I'm Rahul. I'm a technical aid at Rea as well.
00:00:19.119 In our day jobs at Rea, we mostly work on domain-driven microservice architectures using Ruby. But we're here today to talk to you about Elm.
00:00:25.119 That's just something that we've taken a big interest in recently, and so I'll try and answer your first question: what is Elm?
00:00:30.720 If you go to the Elm website, what you'll be told is that Elm is a delightful language for reliable web apps that generates JavaScript with great performance and no runtime exceptions.
00:00:42.320 To illustrate what Elm is, I want to run through those statements quickly. Elm is delightful; you'll have to take my word for that for now, but I assure you it is truly delightful.
00:00:55.399 Elm is a programming language—it's not a library or framework that you add to your apps; it's a whole new programming language for reliable web applications.
00:01:07.000 We want our apps to be reliable, so I kind of take this one as a given and move along. Elm is specifically for writing web applications that run in the browser.
00:01:19.680 Elm compiles into JavaScript, so you write Elm code, turn it into JavaScript, and then send that into your web pages.
00:01:31.960 Regarding performance, similar to reliability, we want our apps to have great performance.
00:01:37.720 Elm uses a virtual DOM implementation, which is similar to React, and in benchmarks, it performs very well compared to React.
00:01:48.479 Finally, and I think this is the most interesting part, Elm promises no runtime exceptions. It guarantees you will write code that will never throw a runtime exception in the browser.
00:02:02.680 Most of us are very familiar with runtime exceptions in Ruby and, of course, also in JavaScript.
00:02:08.720 If that answers the question of what Elm is just enough to give you a framework to understand the rest of the talk, the next question is: why should I care?
00:02:20.480 I want to spend a little bit of time saying why we think Elm is really interesting and worth your time, both in general and specifically for the Ruby community and for Rails programmers.
00:02:39.120 Going back to the idea of no runtime errors: this seems fascinating. Let's talk about that a little.
00:02:49.720 To explain this, I'm going to dive into one particular language feature in Elm. It’s not the only thing preventing runtime errors in Elm, but it's one of the key aspects.
00:03:03.400 I'm going to show you a quick example to give you an idea of how Elm achieves no runtime errors.
00:03:10.799 Here’s some Elm code I’m defining a type of a user. It has a name, state (both strings), and a phone number which is also a string.
00:03:22.519 I’m defining a list of area codes—a dictionary, which is similar to a hash in Ruby. Although the syntax for defining it is weird, think of it just like a hash—not to worry about that.
00:03:40.760 So, I'm mapping states to area codes.
00:03:47.439 Finally, we have a function `displayPhoneUser`. This is how you define functions in Elm; you don't use 'def,' parentheses, or anything—just the name of the function with the parameter list. The function gets a user, uses the dictionary to get the area code, and concatenates it with the phone number using the '+' operator to display the phone number.
00:04:15.799 I pointed out there's a bug in this code, which many of you might have spotted, and yes, I forgot Tasmania. I want to clarify that this is purely a hypothetical example, and I'm sure no one has ever forgotten Tasmania in production code.
00:04:39.160 If you had this code in Ruby, you would try to get the user's area code from that hash using the state, get nil back, and then try to call '+' on nil, resulting in a 'no method error' and crashing at runtime, blowing up for your users.
00:04:52.320 The interesting thing about this code in Elm is that it simply will not compile. I can't convert this code into JavaScript to run in the browser. When attempting to compile, I receive an error message highlighting how amazing Elm's error messages are.
00:05:12.240 The error message states that the '+' operator is expecting an appendable, which can be a string or a list, but what I actually received is a 'Maybe String.'
00:05:30.199 For those familiar with typed functional programming languages, you're aware of the 'Maybe' concept. So what is 'Maybe'? Glad someone got that. When calling the 'display' function here, I’m pulling a value, but I don't know if I got a string or if it failed and returned nil.
00:06:03.680 In Ruby, we assume it succeeded because you get back a string and can start operating on it right away. In Elm, what I get is a 'Maybe,' which means I have to unbox that value before using the string inside it.
00:06:35.160 So, I need to handle both possibilities where I may have a string or nothing. This is something Elm enforces to avoid runtime errors.
00:06:54.760 Here’s how it looks: I use a case statement. If 'maybe' could either be 'just string' or 'nothing,' then I handle those cases by matching either result. If it's just a string, I bind it; if not, I return a placeholder indicating an unknown area code.
00:07:10.800 This way, it’s a lot better than a stack trace or crashing at runtime. I know you can safely concatenate nil in JavaScript, but it serves as a placeholder for any situations where you'd typically encounter a function call or object access that could lead to issues.
00:07:34.159 All of this leads back to the original question of why you should care. It's great to know you can write applications for the browser that just won’t crash. There are a couple of things that I find particularly appealing for the Ruby community.
00:07:47.760 One is programmer happiness. The idea that programming languages should be fun to use, and I feel like Elm has a very similar design aesthetic. Even though I couldn't find a direct quote to that effect, you can observe this throughout the various components of the language.
00:08:09.119 Another thing I appreciate about Elm, which is particularly interesting for those from a Rails background, is the cohesive model. I prefer everything to fit together without needing to make many decisions about how to wire everything.
00:08:20.760 Elm tends to do that well, as evidenced in its components, which are all included except for one, 'elm-test.' There are ongoing talks about integrating it into core to make it included as well.
00:08:30.679 Another appealing point for Ruby and Rails programmers is Elm's low barrier to entry. You don’t have to learn a brand new application or apply a new portion of code. You can simply integrate it with your existing application.
00:08:48.480 While using something like Elixir represents a shift—writing less Ruby—instead, Elm replaces your JavaScript within the existing Ruby framework.
00:09:05.760 With all that out of the way, I hope I have provided some reasons why we think Elm is cool and interesting for our community. I'm going to hand it over to Rahul to give you a crash course in Elm syntax.
00:09:30.399 Elm does not crash! Elm gets many features from academic languages but is designed to feel very manageable. Programmer happiness and friendliness is a key aspect that they focus on.
00:09:40.800 This is going to be a brief course on Elm syntax, just after lunch, so please bear with me! Since we’re at a Ruby conference, we'll introduce Elm using some Ruby concepts.
00:09:58.640 For example, we can define numbers in Elm and we get a type back. So, '42' is a number. We can also define decimal places similarly and receive a float back. In Ruby, strings can be represented with double quotes.
00:10:17.880 However, in Elm, single quotes indicate a character type, and you can also define strings with double quotes.
00:10:24.720 In Ruby, lists are arrays denoted by square brackets, while in Elm, you can define lists and Elm will provide the types back, e.g., list of numbers.
00:10:39.600 We can perform operations on lists like mapping to add one to each member and get a new list in Elm—this is similar to Ruby’s array mapping.
00:10:55.040 However, Elm does not permit heterogeneous lists (having differing types) as Ruby allows. You cannot mix different types; Elm will give you a type mismatch error because it enforces strong typing.
00:11:01.680 To avoid runtime errors, Elm makes design choices that prevent illegal operations. Records in Elm can be defined similarly to open structs in Ruby, providing strong guarantees about their structure and type.
00:11:18.320 In Elm, everything is immutable, meaning you can't change it after its creation. Instead, when you change a value, it returns a new copy.
00:11:34.360 When defining functions in Elm, you simply start with the name of the function, pass the parameter list, and define the body. For example, calling a function with parameters follows straightforward syntax.
00:11:49.760 The Elm compiler deduces types for you typically, minimizing the need for explicit typing. If you want, you can also be explicit and define your types at the beginning of function definitions.
00:12:15.360 Elm implements currying, which is a technique where a function taking multiple parameters can be transformed into a sequence of functions taking a single parameter each.
00:12:31.240 This means, for example, if you have a function that accepts two arguments, you can call it with just one and receive back another function expecting the second parameter.
00:12:44.639 Additionally, Elm’s typing provides aliases for complex records to improve code readability, allowing you to create simpler signatures for frequently used types.
00:13:01.240 Union types are especially powerful in Elm. They allow you to define types that can hold multiple possible shapes, enhancing your program's ability to handle complex scenarios cleanly.
00:13:18.440 For instance, you can define a user type that can either be anonymous or have a name using a union type. This effectively encapsulates various states that a user might have.
00:13:35.240 When handling user actions, you write case statements to handle each possible user type. If the user is anonymous, show a default photo; otherwise, use their actual profile photo.
00:13:54.280 The 'Maybe' type is another union type that indicates instances where a value could either be present or absent. Elm encourages developers to handle these cases explicitly.
00:14:12.520 For example, a database can have nullable values that can be safely worked with when errors are heavily reduced.
00:14:30.600 Finally, Elm treats errors similarly. Instead of throwing exceptions, it uses a result type that can either represent success or failure, making error handling more transparent.
00:14:52.800 We can define a function to convert a string to an int, where we manage the possible errors with simple pattern matching.
00:15:06.760 The main takeaway is that Elm ensures reliability and safety in your applications through its strong typing and enforced patterns.
00:15:23.280 Now, moving forward, to demonstrate how all these pieces fit together, we developed a simple shopping cart application using Rails for the backend.
00:15:39.040 We used Elm for the front end, creating a basic interface where users can change item quantities. The app functions with an API built in Rails, demonstrating how Elm integrates with existing systems.
00:15:57.200 While I can't cover every line of code in the app today, I encourage you to visit GitHub to explore the implementation on your own.
00:16:12.080 The shopping cart allows users to adjust quantities dynamically, send requests to the Rails API, and receive updates reflected in real time.
00:16:29.360 If using JavaScript libraries like Stripe is necessary, Elm ensures smooth integration with front-end JavaScript while keeping type safety intact.
00:16:45.760 You can use Elm with Rails either by compiling to JavaScript and adding it to the public directory or through gems that integrate Elm into the asset pipeline.
00:17:03.600 Using the gem allows you to avoid worrying about integrating a front-end build pipeline while focusing on Elm's features and architecture.
00:17:21.440 Now, let's talk about building applications in Elm. Elm offers a beginner program, which is a simplified way of creating applications without side effects.
00:17:41.600 The model in an Elm application encompasses the entire application state, which could include everything from items in the shopping cart to UI state.
00:18:00.440 The view function transforms the model into HTML, while the update function handles changes and returns a new model, making everything part of a single loop.
00:18:21.920 In the most straightforward Elm applications, everything is done through pure functions, ensuring predictability and ease of testing.
00:18:42.560 You can build a counter app using a simple integer for the model, allowing for straightforward increment and decrement actions using messages.
00:19:00.640 Elm functions return types and can be pure in nature, which promotes code cleanliness and promotes a smooth flow of data through the application.
00:19:20.480 Extending to a shopping cart app, the initial model contains hardcoded data, eliminating the need to request server data in the beginner program.
00:19:36.000 The update function can change quantities, utilizing Elm’s built-in capabilities to handle real-time web activities, guaranteeing type safety throughout.
00:19:53.920 When transitioning to a full Elm program, it becomes simple because you can add necessary parameters and the Elm compiler provides guidance on any type mismatches.
00:20:10.200 Implementing subscriptions allows you to listen for events occurring outside of Elm, seamlessly integrating with external actions like user interactions.
00:20:28.480 With commands, you can also execute asynchronous actions, where Elm communicates with external systems while maintaining purity.
00:20:48.000 Applying these principles in your shopping cart, you define commands that trigger database interactions, allowing updates based on AJAX responses.
00:21:06.760 In summary, Elm grants powerful pattern matching and type systems that ensure you can build efficient and reliable applications.
00:21:25.120 The integration with Rails through Elm ensures you can create dynamic, interactive front-end experiences linked directly to Rails applications.
00:21:44.079 I'm happy to have shared this overview and hope you feel inspired to dive into Elm, possibly exploring a new realm of programming happiness.
00:21:57.760 Thank you!