I have been doing web development with Ruby on Rails for a while, and though I really like it, I’m always looking for new things to try out, so when I heard about the Lucky web framework on the bike shed podcast it really caught my eye. It sounded like a blend of deep experience with Ruby on Rails and the novelty of the Crystal programming language, of which I had already heard interesting things.

On the other hand, while building an app for a client, I had run into the need (or rather the want) for an autocomplete of colleges and post secondary education institutions, which made sense to develop against a standalone API. In the end, we simplified this feature into a free text input, but for some reason this idea came back out of nowhere recently and it felt like a good small challenge to get started on Lucky and Crystal.

So I had some time in my hands this week, and I decided to take a stab at it. A sample client app is live, and you can hit the API (the sources are here: API, sample client). I won’t dive into too many implementation details because it’s a couple of very simple apps, but I wanted to share some impressions on using Lucky and Crystal for the first time.

Crystal

First, I think the ideas behind Crystal as a programming language are great, in part because they can be greatly simplified: be as awesome to use as Ruby, but with speed and type safety. There are, as always, tradeoffs. First, the feedback loop feels a bit clunky when testing out ideas, even accounting for my inexperience with it, but I’m sure this will eventually smooth out once the language is more mature and there are better error messages, better debugging tools, and a faster compiler.

The actual error here is that I’m trying to pass an integer as `ipeds_id` but a string is expected. Probably if I were more used to statically typed languages, this wouldn’t be as confusing.

Second, and kind of obvious, there isn’t as big a community around it as compared to other more mature languages, so it’s hard to get around blocking issues. This is true for both the language and the framework, but there is a silver lining: not having quick answers on Google and StackOverflow forces you to read some sources and dig into compiler errors more often, which I think is good for learning (although not so much for production work).

Lucky

The meat of the matter to me was Lucky, although it is even earlier stage than the language, and this shows, I see great potential in it, and I will try to put in a grain of salt towards it being successful. It did feel a bit counterproductive using the least mature of the Crystal web frameworks (there is also Kemal and Amber which are a bit older) but the ideas behind it were well worth it.

Actions

The first thing that caught my eye was defining Actions as whole classes rather than controller methods, which might sound a bit odd, but I can see this turning into a bunch of small classes, with small test files, which is a good thing to me. On the other hand, these Action classes also define the route and can even infer RESTful routes for you. This alone is what really hooked me.

From the class name (`Institutions::Index`), the route institutions is inferred. With the param macro, the parameters page , per_page and query are safely defined as methods. There are of course ways to define non RESTful routes for these actions.

Queries

Models in Lucky are very similar to those in rails, except with a lot less responsibilities. Queries live in a separate class, instead of being class methods on the same model, which affords you a nice separation, and a nicer way to define scopes (they are simple instance methods of the Query )

Queries end up being very simple objects, instead of being tangled with the model’s responsibilities.

Forms

Another responsibility extracted from the model are Forms. I didn’t use them much (only to seed the database) but I can see they are a very logical way to get rid of Parameter checking in controllers, and validations in models, which in my opinion are two small parts of the same thing, which is a Form so this makes a lot of sense.

For views, and serializers (which are akin to jbuilder views in Ruby on Rails), Lucky uses pure Crystal code, there are some obvious tradeoffs to not using templates, but for my use case (building a simple `json` response) this was more than enough

Deploying

Deploying was a breeze following the Heroku deployment instructions, but I still wouldn’t dare to do this on a bare bones server. I only ran into a simple issue, so I had to remove /public/mix-manifest.json from the .gitignore , but other than that it was all pretty straight forward.

Sample app

I built this little sample app to showcase the API, it is completely decoupled from the Lucky app, so not really in the scope of this article, but it was a nice practice for my front-end chops. For what it’s worth, it’s very basic React, using Parcel (which makes set up very easy and I’ve come to prefer it over Webpack) and it is deployed to Netlify, which is an awesome and very easy to use hosting platform for static sites.

You can check out the source on github. The only really interesting thing to it is the use of proxying for the API queries, to prevent CORS issues, so it takes a wee bit of configuration (Check out devServer.js and _redirects on the sample app’s source and to learn more, look at Netlify’s proxying docs and this Parcel issue too).

Testing

I didn’t get around to writing any tests, because it was such a simple app, so I don’t have much to add in this respect, though I feel the compiler had my back pretty good where tests would usually be in a Ruby on Rails project. When I write Ruby, I feel I’m writing too many tests sometimes, but I wouldn’t dare not writing them, maybe this is another significant improvement using Crystal will bring (needing a little less testing) but I’ll have to give it a try in the future.

Conclusion

It was a lot of fun to learn something new and put it to good use so easily. I can see both Crystal and Lucky becoming a very powerful platform in the coming years, but unfortunately there is still a lot of work left for these to be everyday technologies. That being said, I think Lucky has what it takes to become a serious contender to being the new “better Rails” and I will sure try to lend a hand.

I detailed some improvements that could make this a useful, production ready API, and I hope I can revisit this down the line, but that being said, it took me less than a couple afternoons to get a useful “product” up and running using this stack, which I think speaks very well of the potential it has.