Optional Chaining in JavaScript

The Optional Chaining Operator ? allows you to read the value of a property located deep within an object without having to validate each property in the object. It works in a similar way than the chaining operator ., except that instead of causing an error if a reference is nullish, the expression will return a value of undefined.

A common way to validate properties was to do something like this:

const player = {
  stats: {
    stamina: 40
  }
}

let stamina
if (player && player.stats) {
  stamina = player.stats.stamina
}

This was done because calling player.stats.stamina directly could led into an error being thrown if stats didn't exists, and sometimes even the execution would stop.

Using the Optional Chaining Operator, we could do something like this:

const player = {
  stats: {
    stamina: 40
  }
}

const stamina = player.stats?.stamina

The result is shorter and simpler, and in case stats didn't exists the value would be undefined, without an error being thrown.

Remove Rails model's fields without crashing on production

If you are experiencing problems after removing an attribute from a Rails model it is probably because ActiveRecord has cached that field, it is something normal is intended to help to improve performance on production environments but when removing a field may cause errors because Rails is training to read/writer a column that doesn't exist anymore, so for Rails 5 and newest we have the ignore_columns setting to fix this issue, simply add it to your model something like:

class MyModel < ApplicationRecord
  self.ignore_columns = %w[field_to_ignore]
end

And you are good to go! if you want to be warned or remind to your team you would like to consider using the strong migrations gem https://github.com/ankane/strong_migrations

Native Pub/Sub in Rails with ActiveSupport::Notifications

If you want to use pub/sub design pattern inside your rails app, there's no need to add extra dependencies, you can use ActiveSupport::Notifications to do the job

Example:

class Order
  # methods

  def complete
    update(complted_at: Time.zone.now, etc: 'some')
    ActiveSupport::Notifications.instrument("order_completed", { number: order.number })
  end
end

module Subscribers
  class SendConfirmationEmail
    def self.subscribe!
      ActiveSupport::Notifications.subscribe("order_completed") do |_name, _start, _finish, _id, params|
        order = Order.find_by number: params[:number]
        OrderMailer.confirm_order(order).deliver_later
      end
    end
  end
end

module Subscribers
  class UpdateCustomerCRM
    def self.subscribe!
      ActiveSupport::Notifications.subscribe("order_completed") do |_name, _start, _finish, _id, params|
        order = Order.find_by number: params[:number]
        CrmIntegration.update_customer(order.customer.email, order.total_amount)
      end
    end
  end
end

# etc

Measuring memory utilization

Ruby comes with the cool module Benchmark, but the only downside is that it only provides the time taken for each task.

A simple approach to get how many memory the ruby process is consuming is to call: ps -o rss:

memory_before = `ps -o rss= -p #{$$}`.to_i
Utils.heavy_memory_consumming_process
memory_after = `ps -o rss= -p #{$$}`.to_i

puts "The process took #{memory_after - memory_before} KB"

THE HOOK IS IN EXPERIENCE

When working with brands, yep, its image and its communication are essential. But, TODAY I LEARNED: EXPERIENCE IS THE REAL HOOK!! People will forget what you say, people will forget what you do, but they will never forget HOW YOU MAKE THEM FEEL!!! Right???

In life, sometimes I tend to observe and analyze stuff that would help me to improve something, especially at work. There is a local fashion brand I used to follow (as a fan, I must say) because -besides their clothes are cute- I loved their branding and how they work with their social media communication. Well, I am working with my own fashion brand and I tend to look at the mentioned one as a visual reference. But I wanted to know how their logistics works and I tried to buy something to learn about it, BUT THE EXPERIENCE WAS TERRIBLE! They made me feel ignored and even stupid with their election of some words...

I must say this post is not about talking sh** about a brand and complain about it. Is about expose a case so we can understand why EXPERIENCE is the real value. Even if you have the most beautiful, luxurious, good vibing brand, if you gave a negative experience YOU WILL LOST a follower and probably A CLIENT!

Consumers will transmit their experience: positive or negative. It could become viral and have a huge impact. So, if you really want to capitalize with it, GIVE THE BEST EXPERIENCE EVER TO YOUR AUDIENCE! You could even create brand ambassadors by doing it!

xoxo

Use discard_on to discard the job with no attempts to retry

Discard the job with no attempts to retry, if the exception is raised. This is useful when the subject of the job, like an Active Record, is no longer available, and the job is thus no longer relevant.

You can also pass a block that'll be invoked. This block is yielded with the job instance as the first and the error instance as the second parameter.

Example: 1

class SearchIndexingJob < ActiveJob::Base
  discard_on ActiveJob::DeserializationError
  discard_on(CustomAppException) do |job, error|
    ExceptionNotifier.caught(error)
  end

  def perform(record)
    # Will raise ActiveJob::DeserializationError if the record can't be deserialized
    # Might raise CustomAppException for something domain specific
  end
end

Example: 2:

class UserNotFoundJob < ActiveJob::Base
  discard_on ActiveRecord::RecordNotFound



  def perform(user_id)
    @user = User.find(user_id)
    @user.do_some_thing
  end
end

Source

When to eager load relationships in Rails and when it is not that good

Rails provides a way to eager load relationships when fetching objects, the main idea is to avoid queries N+1, but, when isn't a good idea when to do it?

Good

When rendering unique results that can not be cached, for example: table reports

Why? Most of the times you need to display related information

orders = Order.includes(:user, :line_items).completed

Try to avoid

When you use fragment cache

Why? Eager load is executed before the rendering, regardless the final result is already cached or not. If using eager loading, it will always be executed, but when allowing queries n+1 that query will be executed once to fill the cache, and that's it

products = Product.includes(:categories, variants: [:price]).search(keywords)

Use product.id & updated_at to fill a fragment cache and fetch the data from database only when needed, no extra info needed such as variants, categories, prices, etc

Test Rails log messages with RSpec

Have you wondered how to test your Rails log messages?

Try this:

it "logs a message" do
  allow(Rails.logger).to receive(:info)
  expect(Rails.logger).to receive(:info).with("Someone read this post!")

  visit root_path

  expect(page).to have_content "Welcome to TIL"
end

Or this:

it "logs a message" do
  allow(Rails.logger).to receive(:info)

  visit root_path

  expect(page).to have_content "Welcome to TIL"
  expect(Rails.logger).to have_received(:info).with("Someone read this post!")
end

Source