If you happen to develop API for non-trivial app with complex business logic beyond CRUD directly mapped to the database tables (i.e. typical Active Record pattern) you were probably wondering many times how to handle these cases and what’s the best way to do it. There are quite a few solutions to this problem: you could add another endpoint for handling given use case, add non-RESTful action to already existing endpoint or you can add a magic param to the payload that would force non-standard scenario in the API. Let’s take a closer look at the these solutions and discuss some advantages and disadvantages of each of them.
Having some kind of
type attribute in your models is a pretty common thing, especially in applications with more complex domain. How do you handle such cases? Is it with multiple conditionals /
case statements in every method dealing with the type attribute? If you’ve been struggling with organizing and maintaing code for such use cases then say hello to your new friend: type delegation.
In the previous blog post we were exploring a new wonderful feature coming with ECMAScript 7: decorators. This time we are going to learn about
async / await, which is at this moment at Stage 3 in TC39 process, which means it’s already a release candidate that passed Proposal and Draft stages. Just like decorators, it’s already available in Babel. Let’s see what kind of benefits does it offer.
Recently I’ve been repeatedly asked how to get started with programming, especially Ruby and Rails. To keep things DRY and make sure I always include all great resources for learning, I decided to write this blog post. Most of people who asked me had never programmed before or had done some coding before in other languages, but are not (yet) proficient developers, so if you are a total beginner or just started learning Ruby / Rails and you are not sure what the next step is then you came to the right place.
In many Rails applications the modeling is limited only to creating classes inheritng from
ActiveRecord::Base which are 1:1 mapped to database tables. Having AR models like
Project doesn’t tell much about the domain of your application. Well, you can add some domain logic to the models but that way you will easily end up having giant classes with thousands lines of code, so let’s just use models for database-related stuff only. Other option would be to create service objects for every usecase. That’s a good and clean way, but it’s merely the interaction layer between different parts of your application. You may end up easily with all logic encapsulated within service objects that will start looking more like procedural programming rather than proper OOP and not real domain API at all. The good news is that you can easily counteract it: time to use composed models.
There’ve been a lot of discussions for several months about “The Rails Way” and problems associated with it - huge models with several thousands lines of code and no distinguishable responsibilities (User class which does everything related to users doesn’t tell much what the app does), unmaintainable callback hell and no domain objects at all. Fortunately, service objects (or usecases) and other forms of extracting logic from models have become quite mainstream recently. However, it’s not always clear how to use them all together without creating huge classes with tens of private methods and too many responsibilities. Here are some strategies you can use to solve these problems.
You’ve started developing new app and need server to deploy it. You can choose hosting platform like Heroku or Shelly which may turn out to be quite expensive if you want to host multiple apps. You can also set up your own server. Going with the latter option can be quite time consuming, especially if sysadministration is not you main responsibility and you have multiple servers to provision. I that case automation beyond simple Bash scripts is a must - time to meet Chef.
You are working currently on that awesome app and just started thinking about implementing new feature, let’s call it feature X. What’s the first thing you do? Rolling your own solution or… maybe checking if there’s a magical gem that can help you solve that problem? Ok, it turns out there’s already a gem Y that does what you expect. Also, it does tons of other things and is really complex. After some time your app breaks, something is definitively not working and it seems that gem Y is responsible for that. So you read all the issues on Github, pull requests and even read the source code and finally find a little bug. You managed to do some monkeypatching first and then send pull request for a small fix and solved a problem, which took you a few hours. Looks like a problem is solved. And then, you try to update Rails to2 the current version. Seems like there’s a dependency problem - gem Y depends on previous version of Rails…
Last time, in part 1, I was giving some advice about testing - why to test at all, which tests are valuable and which are not, when to write acceptance tests and in what cases aim for the maximum code coverage. It brought about some serious discussion about testing ideas and if you haven’t read it yet, you should probably check (it) it out. Giving some general point of view about such broad topic like Test Driven Development / Behavior Driven Development is definetely not enough so I will try to apply these techniques by implementing a concrete feature. I wanted to choose some popular usecase so that most developers will have an opinion how they would approach it. In most applications you will probably need: