I Wrote an Elixir Thing Today

20. June 2016 Uncategorized 0

I’ve been playing with Elixir for a few weeks now. I’ve really enjoyed it. But most of what I’ve been doing has just been programming exercises. Specifically over at exercism. That’s been great, it’s made me think in Elixir for a while. But at the end of the day, it reminded me of my Intro to Computer Programing 101 course at Rolla. The exercises were fun because it was programming, but also frustrating because it was just a discrete group of exercises.

Last week I started playing with Phoenix to get an API up and running, but even that wasn’t really getting me up in the morning. Sure, it was fun to have it auto-deploy to Heroku, but at the end of the day, it was just a CRUD API.

This morning, however, I had an idea.  I wanted to periodically tweet out my courses from Pluralsight.  Not constantly, mind you, just throughout the year send out reminders about topics I’ve covered. I could do this in TweetDeck, but that seemed like a lot of work to go out and set up each individual tweet to be tweeted in the future.

So I had an idea, what if I created a text file with a handful of tweets, and then randomly selected one and sent it out every few weeks?

So I set out to write that elixir app.  You can see the source code on my github page (minus my twitter keys, of course.)

I’d say within about 30 minutes or so, I had all the logic except actually tweeting done. And it’s some of my favorite code.

https://gist.github.com/taylonr/4e7b20cb10b9eaaf236fe4f42b2dfa39

I created a function called get_line that took a file path.  Then, I used Elixir’s pipe functionality. The way this works is that it takes the output from the previous function and passes it to the next function as the first line. That is, line 2 & 3 from the first part of the gist, could also have been written as line 1 of the second gist.

Why does this matter? Because it solves you either adding a bunch of temp variables or nesting your functions.  For example, String.split(File.read!(path), ~r{\n}). That’s not horrible for 2 functions, but for the 5 functions I have in the first gist, it would become unreadable.

So let’s look at what this gist does:

  • Read the file specified (this returns a string with all the contents.)
  • Split the string on every new line (this creates an array)
  • Map over the array, and strip away all empty spaces. E.g. ”   hello    ” becomes “hello”
  • Filter the list so that only strings that have <= 140 characters are preserved. No point in trying to tweet out something with 150 characters.
  • Take a random element from that array

There’s a few reasons I really like this function.  First, reading top to bottom it tells me exactly what’s going to happen.  Next, I didn’t have to do any looping or anything of the sort. I didn’t have to keep track of whether I’d reached the end of the file or not.  Instead, I just dealt with simple little functions.  Finally, and this is a big deal with Elixir, all I did was transform data.  I still don’t fully grasp that, or think that way. However, instead of thinking “what objects should I create” a lot of time in Elixir seems to be spent on “How do I need to transform this data?”  It’s an interesting thought. And, to me, it makes sense. After all, that’s what I’m doing most of the time as a developer, transforming data.

In fact, the core of my application was essentially written as 3 lines of code:

https://gist.github.com/taylonr/fcb39675669181d4c7226f6eb25b4ccf

The first line takes the filename passed in and looks it up in the priv folder of my application (a common place for data files.)  It then passes that data to the function above to get me the line I want tweeted out, and then it sends that to the Twitter library’s update method, which tweets it.

Imagine if File.get_line was some library that I pulled in through hex (Elixir’s package manager) then I’m simply translating data between libraries.

Like I said, I had the get_line working in about 30 minutes or so.  It did take me some time to play with the ExTwitter library and get my bearings.  But all-in-all, I probably had this working manually in about 2 hours time.  I then spent a lot of time trying to make it run as a service. In the end, I found a cron job library for Elixir, and I got it running locally. I had it tweeting out a random number between 1-6 for about 5 minutes (I’ve since deleted the tweets.)

The longest part of the process was making this run like a service. That is, not dying after the first tweet got sent out. That’s not a problem with Elixir, it’s a problem with me reading. I tend to jump around and skim articles instead of actively reading them. That means, I jumped over the part of the code I needed to make this stay alive after tweeting. In fact, I probably jumped over it about 6 or 7 times before I finally thought “Maybe that’s the line that’s important.”

The only challenge I have left right now is deploying it. I’ve gotten web apps deployed to Heroku (even Elixir ones) but I’m struggling getting this to work.  So I’ll put a pin in it for a few nights, and come back later in the week.