Been meaning to post about this for a while, but I recently learned about Generalized Inverted Indexes. According to the Postgres docs:
GIN indexes are “inverted indexes” which are appropriate for data values that contain multiple component values, such as arrays. An inverted index contains a separate entry for each component value, and can efficiently handle queries that test for the presence of specific component values.
I plan to write a longer post about my exploration into this, including the pros and cons of denormalization, but I’ll give a short overview of a problem I was trying to solve and how the GIN index came into play.
At Reflektive, I’ve been working on a user profile feature that gives each person a personalized newsfeed of the feedbacks they have sent or received.
Over time, the types of feedback we have in Reflektive has grown, and with each type of feedback, specific rules around who can see the feedback. For example, a user can give somebody private feedback, and only those two individuals should be allowed to see it. Or, Person A can write a private note about Person B, and not share it with Person B. While this is still stored as a Feedback in our database, and Person B is the recipient, Person B should not be allowed to see that Feedback.
In total, we have 9 different types of feedbacks, and unless the feedback is public, the feedback is private and shared with, at most, 3 people.
This post first appeared on the Reflektive Engineering Blog
If you’ve worked on any large Rails app, you’ve probably come across the service object pattern, a useful abstraction for handling business logic.
Recently, we’ve been playing with a particular implementation of this pattern using the Interactor gem.
To understand the benefits of interactors, it’s helpful to first talk about service objects and how they’re often used in Rails.
In the context of Rails, a service object is simply a Ruby object used for a specific business action. This code usually doesn’t belong in the controller or model layer, because it might involve multiple data models, or it hits a third-party API.
Today I learned that if you call a multiplication operator on a Ruby array, it duplicates each element of the array by the multiplier.
So for example:
>> [1,2,3] * 3
=> [1, 2, 3, 1, 2, 3, 1, 2, 3]
>> ['Jared Rader'] * 3
=> ["Jared Rader", "Jared Rader", "Jared Rader"]
Those that are against class inheritance entirely often favor composing classes with modules to add behavior. The funny thing here is that including modules functions pretty much exactly the same as class inheritance. If a method is not defined in the class, Ruby looks up the inheritance tree, starting with the modules included.
The favor for composition comes from the fact that composing classes with modules is more flexible than what a class hierarchy offers and classes can essentially achieve multiple inheritance through module inclusion.
I decided to take the idea to its extreme recently in a project at work. After students enroll in courses at Bloc, they are taken through an onboarding workflow where they create a profile, select their mentor, create a schedule of appointments, etc. We created a neat class called
OnboardWorkflow that defined a series of determined steps so that students would go through onboarding in the order we wanted them to.
Rails developers are familiar with the maxim “fat models, skinny controllers”. If logic starts creeping into our controllers, most developers seem content to push that logic into a model. But obese models can make for painful development. At Bloc, we’ve reached the point where this has become painful enough that I decided something needed to be done about it. After reading through Jim Gay’s fantastic Clean Ruby, I identified many areas in which our application could benefit from the DCI (data, context, interaction) design pattern.
DCI, according to that wikipedia link above, “separates the domain model (data) from use cases (context) and Roles that objects play (interaction)”. In Clean Ruby, Jim Gay illustrates this concept with transferring money between two accounts. The domain model is an account, which takes on the role of a transferrer of money from itself to another account, in the context of transferring money.
The situation I came across in the Bloc application involved populating a progress bar with data related to a student’s enrollment. This used to be fairly straightforward, but after introducing our Track products, in which students can take a track of two courses, it became a little more complicated.