Karol Galanciak - Ruby on Rails and Ember.js consultant

Messages on Rails Part 3: RabbitMQ

In the first part of this series, we were exploring some potential options for communication between services – what their advantages and disadvantages are, why HTTP API is not necessarily the best possible choice and suggesting that asynchronous messaging might be a better solution, using, e.g. RabbitMQ and Kafka. We’ve already covered Kafka in the part 2, now it’s the time for RabbitMQ.

Messages on Rails Part 2: Kafka

In the first part of this series, we were exploring some potential options for communication between services – what their advantages and disadvantages are, why HTTP API is not necessarily the best possible choice and suggesting that asynchronous messaging might be a better solution, using, e.g. RabbitMQ and Kafka. Let’s focus this time entirely on the latter.

Messages on Rails Part 1 - Introduction to Kafka and RabbitMQ

Microservices, Service-Oriented Architecture (SOA) and in general, distributed ecosystems, have been on hype in the last several years. And that’s for a good reason! At certain point, The Majestic Monolith “pattern” might start causing issues, both from the purely technical reasons like scalability, tight coupling of the code if you don’t follow Domain-Driven Design or some other practices improving modularity, maintenance overhead, and also from organizational perspective since working in smaller teams on smaller apps is more efficient than working with huge team on an even bigger monolith which suffers from tight coupling and low cohesion. However, this is only true if the overall architecture addresses the potential problems that are common in the micro/macro-services world. One of these problems I would like to focus on is communication between apps and how the data flows between them.

How to Tell the Difference Between a Default and a Provided Value for Optional Arguments in Ruby?

It is sometimes required for the methods with optional arguments to be able to differentiate between its default value and the value passed from the caller. Passing nil might initially sound like a good idea since it represents “nothingness”. However, it might turn out that nil is a legit value and there might be cases where it is desirable for the caller to pass nil. In such a case, we cannot use it as a default value if we want to implement a special logic for the case of not providing that value.

Fortunately, there is an easy way to deal with it – use a special constant:

1
2
3
4
5
6
7
8
9
10
11
12
class SomeClass
  NO_VALUE_PROVIDED = Object.new
  private_constant :NO_VALUE_PROVIDED

  def call(argument: NO_VALUE_PROVIDED)
    if argument == NO_VALUE_PROVIDED
      handle_scenario_for_no_value_provided
    else
      do_something_with_argument(argument)
    end
  end
end

In call method, we allow to pass an optional argument with a default of NO_VALUE_PROVIDED, which is a private constant defined in that class that is an instance of Object.

By depending on the instance of Object that is initialized inside that class, we can avoid cases where the equality check returns true even if this is not an expected outcome, which could happen if we used strings or symbols. We could use some symbol that would be very unlikely to be passed from the caller, like :__no_value_provided__, but it arguably looks more like a workaround than a dedicated solution for the problem.

Also, a private constant ensures it is not used anywhere outside the class, which minimizes the chances that the passed argument would the same as our placeholder for no-value-provided scenario even more.

Inheritance and Define_method - How to Make Them Work Together

Imagine that you are implementing some form object because you are fed up with treating ActiveRecord models as such, and you need some extra flexibility. You start with a straightforward implementation for a base class of a form object where you can just whitelist attributes. That could look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class FormObject
  def self.attributes_registry
    @attributes_registry ||= []
  end

  def self.attribute(attribute_name)
    attributes_registry << attribute_name

    define_method(attribute_name) do
      instance_variable_get("@#{attribute_name}")
    end

    define_method("#{attribute_name}=") do |value|
      instance_variable_set("@#{attribute_name}", value)
    end
  end
end

Since the base class is ready, you can create a first form object that would inherit from this class:

1
2
3
class MyForm < FormObject
  attribute :some_attribute
end

Initially, it does the job, but then it turns out that you might need a default value if some_attribute turns out to be nil. So you try something like that:

1
2
3
4
5
6
7
class MyFormWithDefaultValue < FormObject
  attribute :some_attribute

  def some_attribute
    super || "Default"
  end
end

After checking if the default value works, this is what you get:

1
2
> MyFormWithDefaultValue.new.some_attribute
=> NoMethodError: super: no superclass method `some_attribute' for #<MyFormWithDefaultValue:0x007f84a50ae8e0>

Whoops! How did it happen? The method was defined in the superclass so it should be inheritable, right?

Well, this is not really true. However, the problem is easy to fix.

The Problems With Validating ActiveRecord Models and Why State Validation Is a Bad Idea

In the typical Rails application, you can find the most of the validations in the ActiveRecord models, which is nothing surprising – ActiveRecord models are used for multiple things. Whether it is a good thing, or a bad thing (in most cases it’s the latter) deserves a separate book or at least blog post-series as it’s not a simple problem, there is one specific thing that can cause a lot of issues that are difficult to solve and go beyond design decisions and ease of maintenance of the application, something that impacts the behavior of the model – the validations.

Just to give you a real-world example of what validation in ActiveRecord model looks like (as impossible as it seems, it really did happen) – when updating the check-in time of the reservation, which is a simple attribute on Reservation model, the record turned out to be invalid because… the format of guest’s phone didn’t match some regexp.

There are multiple ways to bypass this problem: use validate: false flag with save method: save(validate: false) or use update_columns method, but this is definitely not something that can be applied in a “normal” use case. In a typical scenario, this will be the error message displayed in the UI/returned to API consumer, and it will be confusing.

However, this is the expected behavior of ActiveRecord (or in general, ActiveModel-style) validations, which is a validation of the state of the model. And judging from this example, it’s evident that it leads to problematic scenarios. What kind of design then would be the most appropriate to prevent such issues?

Indexes on Rails: How to Make the Most of Your Postgres Database

Optimizing database queries is arguably one of the fastest ways to improve the performance of the Rails applications. There are multiple ways how you can approach it, depending on the kind of a problem. N+1 queries seem to be a pretty common issue, which is, fortunately, easy to address. However, sometimes you have some relatively simple-looking queries that seem to take way longer than they should be, indicating that they might require some optimization. The best way to improve such queries is adding a proper index.

But what does “proper index” mean? How to figure out what kind of index is exactly needed for a given query? Here are some essential facts and tips that should cover a majority of the queries you may encounter and make your database no longer a bottleneck.

Trolling in Ruby - Implementing JavaScript-like Maths With Implicit Conversion Hijacking

If you’ve ever worked with JavaScript, especially in pre-SPA/pre-frameworks era with just jQuery, you probably had a chance to see an “exotic” maths in action that looks similar to this:

1
2
"3" + 4
// => "34"

That kind of behavior usually comes as a big surprise and due to that fact, JavaScript has gotten some bad reputation (even though there is a rationale behind it). If we tried that in Ruby, we would get an obvious TypeError:

1
2
"3" + 4
# => TypeError (no implicit conversion of Integer into String)

Would it be possible though to obtain the same result somehow in Ruby?

Rails and Conditional Validations in Models

Adding consents for accepting Terms of Service/Privacy Policies must have been a top popular feature in the majority of the applications due to enforcement of GDPR in May ;). From the technical aspects that GDPR requires, there is a proof of consent for processing the personal information. In that case, you need to have some actual attributes in the database that would confirm the fact that some user has indeed accepted Terms of Service/Privacy Policy.

That makes a significant impact on how we approach this kind of features. However, in the past, such things were quite often not stored in a database at all – it just took some UI acceptance validation or maybe a validation of the virtual attribute on the backend to be on the safe side.

Let’s focus on the latter case where we don’t need to store anything in DB and see what the possible solutions to that problems are. As trivial as this problem initially sounds, it will get quite interesting ;).

The Case for Before_validation Callback: Complex State Normalization

Few months ago I wrote a blog post about ActiveRecord before_validation callback and how it is used for wrong reasons and concluded that in most cases this is not something we should be using routinely. However, I missed one appropriate use case for it which might be quite common in Rails apps, so this might be an excellent opportunity to get back to before_validation callback and show its other side.