Ruby 2.7 introduced numbered parameters for blocks

Since Ruby 2.7, it is possible to use numbered parameters in blocks additionally to named parameters.

This is an example of a block with named parameters:

my_array.each { |element| element.do_something }

And this is the same line with numbered parameters:

my_array.each { _1.do_something }

This works with multiple parameters too:

# named parameters
my_hash.each_pair { |key, value| puts "#{key}: #{value}" }

# numered parameters
my_hash.each_pair { puts "#{_1}: #{_2}" }

Browsers' IndexedDB are shared across domain

I was working on a major refactor for a PWA which basically changed the DB schema by reducing the amount of versions, nothing outstanding. BUT, I didn't change the DB name.

I was puzzled why whenever accessing the previous version I had to delete the data to have the app load correctly, then I realized that despite the PWA being located at different URL paths, both versions were using the same IndexedDB because of the same domain policy.

Using Upsert with Rails

Some DBMS support natively something that behaves like update or insert, Rails recently added the method Upsert that can take advantage of this method.

It is useful to update information that do not need to run validations, meaning, in a super performant way, here's an example:

# We usually do this:
activity = current_user.activity
if activity 
  activity.update(last_seen_at: Time.current)
else
  current_user.activity.create(last_seen_at: Time.current)
end

But if you see, it does not need to run any validation, it just needs to update last_seen_at if exists or create a new one, it performs two queries: one to instanciate the activity object and a second one that performs the real update/insert statement.

That can be replaced with the following code and it will perform just a single query and it will take care to either create the record or update an existing one

Activity.upsert({ last_seen_at: Time.current, user_id: current_user.id}, unique_by: :user_id)

To make this really work, considering you use Postgresql, you have to add a unique index on user_id and modify default value on created_at and updated_at in a migration like this:

query = <<-SQL
  ALTER TABLE #{Activity.table_name}
  ALTER COLUMN created_at SET DEFAULT CURRENT_TIMESTAMP,
  ALTER COLUMN updated_at SET DEFAULT CURRENT_TIMESTAMP
SQL
execute(query)

What is your car color?

Did you know that your car color can say a lot about how you want to be perceived by other people? Here is a list of some colors and their own meanings.

White: This color evokes freshness, cleanness, youth, and modernity.

Black: This is the most popular color in luxury vehicles. Black can be described as a sexy, powerful, and mysterious color.

Silver: This color is linked to a sense of innovation and modernity, that is why a lot of high tech products go for silver.

Red: This is a bold color, if your car is red this might mean you want to show an image of power, action, and confidence.

Blue: Blue is often described as the color of stability and safety. If your car is blue this might mean you are a trustworthy person.

Yellow: If you drive a yellow car might mean that you are a happy person or maybe a person who likes to take risks.

Gray: If you have a gray car this could mean you are a person who does not want to stand out, and prefers something a bit more ¨subtle¨ instead.

Better usage of Rails logger

Logging usefull data is a hard task, but there's one specific method that helps to improve the experience of logging actual useful information: tagged. It adds extra tags to the log message making it easy to debug:

Rails.logger.tagged('Super App') do
  Rails.logger.info('Log Message')
end

This will result in somethin like this:

[Super App] Log Message

If you can see, it prepends usefull information, you could add personalized data to trace logs, for example:

class ApplicationController << ActionController::Base
  around_action :add_logger_tags

  def add_logger_tags
    Rails.logger.tagged(logging_tags) do
      yield
    end
  end

  def logging_tags
    [
      "Request Id: #{request.id}",
      "Session Id: #{session.id}",
      current_user && "User id: #{current_user.id}"
    ]
end

And you will have super nice logs to read

How to use my local browser and get access to the server on Circle CI with port-forwarding

This helped me to debug a failing test, that was only happening on the CircleCI Server.

How to do it?

  1. Go to Details Job Page on the Circle CI app and re-run the job as Rerun Job with SSH. image

  2. You should be able to find an additional step called Enable SSH, just expand it to see a command similar to this ssh -p 64625 ubuntu@54.221.135.43 but with minor differences (the port number and IP address will be different). Copy the command into your terminal.

  3. Paste it and append this -L 3000:localhost:4000. With this, every request happening on the port 4000 (CircleCI server) will be forwarded to my local computer in the port 3000, so my local browser can reach the CircleCI server directly.

    $ ssh -p 64625 ubuntu@54.221.135.43 -L 3000:localhost:4000

  4. Lastly, change of directory, go to your application folder and serve your app in port 4000.

    $ cd my-app-directory && <command to serve your app>

    In this example, I ran yarn run dev which runs a server on the port 4000.

  5. Go to the browser and visit the localhost:3000.

Is it possible to render a "sidecar" partial for a ViewComponent?

Let's say I have

class MyComponent < ViewComponent::Base
end

and 2 view files in

app/components/my_component/my_component.html.erb
app/components/my_component/_some_partial.html.erb

In my_component.html.erb, I want to be able to do:

render "some_partial"

But without a special configuration, that looks under the views directory for said partial. I don't want to extract that partial to its own component, nor do I want it floating by itself in the view directory.

The first step is to tell Rails it can look for templates in the view components directory

class ApplicationController < ActionController::Base
  append_view_path "#{Rails.root}/app/components"

Keep in mind that view contexts are based on the currently executing controller, so <%= render :some_partial %> in a PostsController (even within a ViewComponent class) will look for a partial in a subdirectory /posts or /application.

To make sure Rails finds your partial, use an absolute path when you render it:

<%= render "/my_component/some_partial" %>

Hat tip to Roli in the StimulusReflex discord

More about randomness

If you want to generate random but predictable sequences of numbers, then the rand command and the srand are not enough, you have to use a trick to save the state of the variable. Fibers are primitives for implementing light weight cooperative concurrency in Ruby. Basically they are a means of creating code blocks that can be paused and resumed, much like threads. The main difference is that they are never preempted and that the scheduling must be done by the programmer and not the VM.

require 'rspec'

#i = pseudo_random 10
#p i.resume => 37
#p i.resume => 12
#p i.resume => 72
#
def pseudo_random num
  srand 1

  fiber = Fiber.new do
    num.times do
      Fiber.yield rand 100
    end
  end
end


describe 'Pseudo Random number generator' do
  it 'creates the same sequence of random numbers' do
    random_sequence = pseudo_random 3
    expect(random_sequence.resume).to eq(37)
    expect(random_sequence.resume).to eq(12)
    expect(random_sequence.resume).to eq(72)
  end
end

Quasi-Random numbers in Ruby

I was interested in random sequence because I was in need to test the Montecarlo Method for getting Pi digits.

One method to estimate the value of π (3.141592…) is by using a Monte Carlo method. This method consists of drawing on a canvas a square with an inner circle. We then generate a large number of random points within the square and count how many fall in the enclosed circle. Pi

So, if you need a random sequence, you can use Sobol for quasi-random numbers.


require 'gsl'

q = GSL::QRng.alloc(GSL::QRng::SOBOL, 2)
v = GSL::Vector.alloc(2)
for i in 0..1024 do
  q.get(v)
  printf("%.5f %.5f\n", v[0], v[1])
end