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

Updating ActiveRecord models without loading an instance using Postgresql

There're sometimes that we need to update an ActiveRecord Model but it is not necesary to load an instance, the normal flow would be the following:

profile = UserProfile.find_by(user_id: id)
profile.update(last_seen_at: Time.now)

The problem with this is that we load a useless instance of UserProfile, it is not needed, in a high traffic sites, an extra select query can count a lot, but luckly, Rails has addressed this with upsert command:

UserProfile.upsert({ last_seen_at: Time.now, user_id: id }, unique_by: :user_id)

This will use native Postgresql upsert command to update a record if it exists or insert a new one and no select will be performed, everything in a single query instead of two.

To make it really work, you need to modify your created_at and updated_at columns to have default current_timestamp

NIX node manager

Use n, an extremely simple Node version manager that can be installed via npm.

Say you want Node.js v12.10.0 to build Ghost template.

npm install -g n   # Install n globally
n 12.10.0          # Install and use v12.10.0
Usage:
n                            # Output versions installed
n latest                     # Install or activate the latest node release
n stable                     # Install or activate the latest stable node release
n <version>                  # Install node <version>
n use <version> [args ...]   # Execute node <version> with [args ...]
n bin <version>              # Output bin path for <version>
n rm <version ...>           # Remove the given version(s)
n --latest                   # Output the latest node version available
n --stable                   # Output the latest stable node version available
n ls                         # Output the versions of node available

Using Rails to migrate columns from JSON to JSONB in Postgresql

Postgres offers data type json to store any structure easily, but one dissadvantage is that filtering by properties stored in the json column are super slow, one simple fix before refactoring the whole implementation is to migrate the column to be jsonb, since it is stored in binary form, it supports indexes, a easy and safe way to do it is as follows:

class ModifyJSONDataDataType < ActiveRecord::Migration[6.0]
  def up
    add_column :table_name, :data_jsonb, :jsonb, default: '{}'

    # Copy data from old column to the new one
    TableName.update_all('data_jsonb = data::jsonb')

    # Rename columns instead of modify their type, it's way faster
    rename_column :table_name, :data, :data_json
    rename_column :table_name, :data_jsonb, :data
  end

  def down
    safety_assured do
      rename_column :table_name, :data, :data_jsonb
      rename_column :table_name, :data_json, :data
    end
  end
end

Then, using another migration(due the ability to disable transactions), add an index to it

class AddIndexToDataInTableName < ActiveRecord::Migration[6.0]
  disable_ddl_transaction!

  def change
    add_index :table_name, :data, name: "data_index", using: :gin, algorithm: :concurrently

    # You can even add indexes to virtual properties:
    # add_index :table_name, "((data->'country')::text)", :name => "data_country_index", using: 'gin', algorithm: :concurrently
  end
end

The slice_when method in Ruby

Creates an enumerator for each chunked elements. The beginnings of chunks are defined by the block.

This method splits each chunk using adjacent elements, elt_before, and elt_after, in the receiver enumerator. This method split chunks between elt_before and elt_after where the block returns true.

The block is called the length of the receiver enumerator minus one.

The result enumerator yields the chunked elements as an array. So each method can be called as follows:

enum.slice_when { |elt_before, elt_after| bool }.each { |ary| ... }

For example:

Return adjacent elements from this array [1, 2, 3, 5, 6, 9, 10] in chunked elements as an array.

[1, 2, 3, 5, 6, 9, 10].slice_when {|i, j| i+1 != j }.to_a
=> [[1, 2, 3], [5, 6], [9, 10]]

The each_cons method in Ruby

Iterates the given block for each array of consecutive <n> elements. If no block is given, returns an enumerator.

irb(main):001:0> [1,2,3,4].each_cons(2).to_a
=> [[1, 2], [2, 3], [3, 4]]

irb(main):002:0> [1, 2, 3, 5, 6, 9, 10].each_cons(2).to_a
=> [[1, 2], [2, 3], [3, 5], [5, 6], [6, 9], [9, 10]]

Print any two adjacent words in a given text:

def print_adjacent_words(phrase)
   phrase.split.each_cons(2) do |words|
     puts adjacent_word = words.join(" ")
   end
end
irb(main):025:0> print_adjacent_words("Hello Darkness my old friend")
Hello Darkness
Darkness my
my old
old friend
=> nil

Optional Chaining Operator (?) and Nullish Coalescing Operator (??)

Optional Chaining Operator(?) (**)

//Car object
const car = {
  attributes: {
   year: 2021,
   model: "Ferrari"
  }
}

Before in javascript to validate that the attributes of an object exist, it was necessary to use the And operator (&&) to validate if the attributes of the object existed.

See the following example:

if (car && car.attributes && car.attributes.model) {
  console.log('Exist',  car.attributes.model)
} else {
  console.log('Do not exist')
}

# => "Exist Ferrari"

Now with Optional Chaining Operator (?) We can validate if the property exit will return undefined if the property attributes or model doesn’t exist.

if (car?.attributes?.model) {
  console.log('Exist',  car.attributes.model)
} else {
  console.log('Do not exist')
}

# => "Exist Ferrari"

Nullish Coalescing Operator(??) (**)

//Car object
const car = {
  attributes: {
   year: 2021,
   model: "Ferrari"
  }
}

If we want to get the car model then we would like below:


console.log(car.attributes.model);
# => "Ferrari"

Now the new car object does not have the model property, so we get an undefined value

//Car object
const car = {
  attributes: {
   year: 2021,
  }
}
console.log(car.attributes.model);
# => "undefined"

To avoid the undefined value the OR (| |) operator can be used, It will now return the value BMW because the property model is undefined. But what if the name property is empty like below example

console.log(car.attributes.model | | "BMW" );
# => "BMW"

Now the problem is when the property model exists but has an empty, undefined or null value we will get the BMW value and this is not right.

//Car object
const car = {
  attributes: {
   year: 2021,
   model: ""
  }
}
console.log(car.attributes.model | | "BMW" );
# => "BMW"

The solution for this problem is to use the Nullish Coalescing Operator (??), Which will print the result as an empty string.

console.log(car.attributes.model ?? "BMW" );
# => ""

Ruby Double star (**)

def hello(a, *b, **c)
  return a, b, c
end

a is a regular parameter. *b will take all the parameters passed after the first one and put them in an array. **c will take any parameter given in the format key: value at the end of the method call.

See the following examples:

One parameter

hello(1)
# => [1, [], {}]

More than one parameter

hello(1, 2, 3, 4)
# => [1, [2, 3, 4], {}]

More than one parameter + hash-style parameters

hello(1, 2, 3, 4, a: 1, b: 2)
# => [1, [2, 3, 4], {:a=>1, :b=>2}]