TILs - Fueling Curiosity, One Insight at a Time

At Codemancers, we believe every day is an opportunity to grow. This section is where our team shares bite-sized discoveries, technical breakthroughs and fascinating nuggets of wisdom we've stumbled upon in our work.

Published
Author
user-image
Syed Sibtain
System Analyst
getBoundingClientRect() A crucial DOM method that gives us an element's position and size relative to the viewport, not the document.

Example:

JavaScript

const rect = container.getBoundingClientRect();


What getBoundingClientRect() returns?

Code

{
  top: 100,      // Distance from viewport top to element top
  left: 200,     // Distance from viewport left to element left  
  right: 400,    // Distance from viewport left to element right
  bottom: 300,   // Distance from viewport top to element bottom
  width: 200,    // Element width
  height: 200,   // Element height
  x: 200,        // Same as left (for compatibility)
  y: 100         // Same as top (for compatibility)
}


Real Usage Example: Image Comparison Slider:

Code

// User drags the slider to compare two images
handleDrag(event) {
  const container = this.getContainer(); // The image container
  const rect = container.getBoundingClientRect();
  
  // Convert global mouse position to slider position
  const x = event.clientX - rect.left;  // Mouse X relative to container
  const percentage = this.calculatePercentage(x, rect.width);
  
  // Update slider position (0-100%)
  this.sliderPosition = percentage;
  this.updateSliderPosition(percentage);
}


Step-by-Step Breakdown:
1. User drags mouse → event.clientX = 350 (global position)
2. Get container bounds → rect.left = 200 (container starts at 200px from viewport left)
3. Calculate relative position → 350 - 200 = 150px (mouse is 150px from container's left edge)
4. Convert to percentage → 150 / 400 = 37.5% (150px out of 400px container width)
5. Update slider → Move slider to 37.5% position
getBoundingClientRect() is the bridge between global coordinates and element-relative coordinates.

#CCT1JMA0Z #stimulus
Published
Author
user-image
Syed Sibtain
System Analyst
When we rewrite git history (like squashing commits, interactive rebase), our local branch diverges from the remote branch.
A regular git push will be rejected because the histories don't match. The first option is git push --force, which overwrites the remote branch with our local version.

The Usual Approach: git push --force

Code

# DANGEROUS - can overwrite other people's work
# We do it everyday though
git push --force origin <feature-branch>


The Safer Alternative: git push --force-with-lease

Code

# SAFER - includes safety checks
git push --force-with-lease origin feature-branch


How --force-with-lease works:
• Checks if the remote branch has moved since we last fetched it.
• Only overwrites if the remote is exactly where we expect it to be.
• Fails safely if someone else has pushed commits we don't have locally.
• Prevents accidental overwrites of other people's work.
PS: Might sound simple, but helps a lot when working with bigger teams.

#git #github
Published
Author
user-image
Nived Hari
System Analyst
If a port (say 3000) is already in use, you can check what’s running on it with:

Code

lsof -i :3000


Here, lsof stands for “List Open Files” — and in Unix/Linux, everything is a file, including network sockets.

So this command lists all processes that have files (or ports) open.
Example output:

Code

COMMAND   PID  USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
node     1234  nived  22u  IPv6  0x...      0t0  TCP *:3000 (LISTEN)


Now you can see the PID (Process ID) of the program using the port.

To stop it, run:

Code

kill 1234


The kill command sends a signal to a process — by default, it’s SIGTERM (Signal Terminate), which politely asks the process to shut down.
If the process refuses to die, you can forcefully stop it with:

Code

kill -9 1234


Here, -9 represents the SIGKILL (Signal Kill) — which immediately ends the process without cleanup.

#unix
Published
Author
user-image
Mohammad hussain
System Analyst
The JavaScript console isn’t just console.log. It provides specialized methods for different scenarios:
console.error() → logs errors in red.
console.warn() → highlights warnings.
console.table() → formats arrays or objects as tables.
console.group() / console.groupEnd() → groups related logs for better organization.
💡 Using these methods makes debugging clearer and more structured than relying only on console.log.
#Javascript
Published
Author
user-image
Syed Sibtain
System Analyst
How to deploy to fly.

1. Initial Setup

Code

# Initialize the app

fly launch

# This creates:
# - fly.toml (basic configuration)
# - .dockerignore
# - Dockerfile


2. App Creation

Code

# Create app in specific organization

fly apps create ui-delta-c9s --org c9s-staging


3. Configuration Setup

Code

# Set required secrets
# Example

fly secrets set RAILS_MASTER_KEY=$(cat config/master.key) --app ui-delta-c9s
fly secrets set SECRET_KEY_BASE=$(openssl rand -hex 64) --app ui-delta-c9s
fly secrets set RAILS_ENV=production --app ui-delta-c9s


4. Database Setup

Code

# Option 1: Create new database
fly postgres create --name ui-delta-db --region sin

# Option 2: Attach to shared cluster
fly postgres attach postgres-fire-9606 -a ui-delta-c9s


5. Customize fly.toml as required for the project

6. Deploy

Code

fly deploy --app ui-delta-c9s


#fly #deploy
Published
Author
user-image
Syed Sibtain
System Analyst
The Problem:
https://Fly.io|Fly.io databases use internal networks (.flycast domains) that aren't publicly accessible, so we can't connect directly from external tools like DBeaver.

Solution:
Use https://Fly.io|Fly.io's proxy to create a secure tunnel:

Code

fly proxy 5433:5432 --app


How It Works:
• Local port 5433 → Remote database port 5432
• Creates a secure tunnel through https://Fly.io|Fly.io's network
• Keep the proxy running while using external tools
• Allows external tools like DBeaver to connect via localhost:5433
#database #fly
Published
Author
user-image
Syed Sibtain
System Analyst
The Problem: When comparing images for UI testing, we needed to implement a fuzz factor to ignore small colour differences (like anti-aliasing, compression artifacts, or minor rendering variations). This is crucial for UI screenshots where a 1-2 pixel difference shouldn't count as a "failure."

Command Line approach

Ruby

# This works but is fragile
magick compare -metric AE -fuzz 10% image1.png image2.png NULL: 2>&1

# Problems:
# - Shell command parsing issues
# - Error handling is difficult
# - Output parsing is brittle
# - Cross-platform compatibility issues
# - Hard to debug when things go wrong


The Mini Magick Solution

shell

# Step 1: Create difference image
difference_image = first_image.composite(second_image) do |c|
  c.compose "difference"
end

# Step 2: Apply fuzz factor using threshold
thresholded_diff = difference_image.dup
thresholded_diff.combine_options do |c|
  c.normalize
  c.threshold "10%"
# This acts as our fuzz factor!
end

# Step 3: Get statistics
mean_value = thresholded_diff.identify do |c|
  c.format "%[fx:mean]"
end

# Step 4: Convert to percentage
percentage = mean_value.to_f * 100


Key Insight: Fuzz Factor = Threshold
- In ImageMagick: fuzz 10% tells it to ignore differences below 10%
- In MiniMagick: threshold10% does the same thing by setting pixels below 10% to black

#ruby #image
Published
Author
user-image
Syed Sibtain
System Analyst
* The Problem:* I had an existing Elixir app with a users table that used password_digest field, but Devise expects encrypted_password by default.

Devise's Default Password Field:

elixir

# Devise expects this by default:
class User < ApplicationRecord
  devise :database_authenticatable
  # Uses 'encrypted_password' column automatically
end


Our Existing Schema:

Code

# Uses password_digest
create_table :users do |t|
  t.string :password_digest, null: false  # ← Different field name!
  # ... other fields
end


The Override Solution:

Code

# Devise calls: user.encrypted_password
# Our override returns: user.password_digest

class User < ApplicationRecord
  devise :database_authenticatable, :registerable, :validatable

  # Tell Devise to use our existing password_digest field
  def self.encrypted_password_column
    :password_digest
  end

  # Override the getter method
  def encrypted_password
    read_attribute(:password_digest)
  end

  # Override the setter method  
  def encrypted_password=(value)
    self.password_digest = value
  end
end


So we can simply override Devise's password field by:
1. Telling Devise which column to use (encrypted_password_column)
2. Creating getter/setter bridges (encrypted_password methods)
3. Using read_attribute to avoid method conflicts
#devise #auth
Published
Author
user-image
Syed Sibtain
System Analyst
What does model: resource actually do in form_with?

model: resource is the bridge between our form and the data object. It makes forms smart - they remember values, show errors, and handle the complex Rails form lifecycle automatically.

Example:

Code

<%= form_with model: resource, as: resource_name, url: session_path(resource_name), local: true, class: "space-y-6" do |f| %>


model: resource tells Rails:
• Which object to bind the form to
• Where to get field values from
• Where to send validation errors to
• What HTTP method to use (POST for new, PATCH for existing)
In Devise Context:
resource is a Devise helper that returns:
• New User object (for signup) - User.new
• New User object (for signin) - User.new (usually empty, not pre-populated)
Without model: resource:
• Form fields are always empty
• No automatic error handling
• Manual parameter naming required
• No automatic HTTP method detection
#CU6U0R822 #devise
Published
Author
user-image
Satya
To understand network sockets locally, you can try this simple demo with two terminal tabs:
1. In the first tab run ns -l 1234 : This starts a small server process that listens for TCP connections on your computer’s address (localhost / 127.0.0.1) at port 1234.
2. In the second tab run ns localhost 1234 : This connects a client to the server on 127.0.0.1:1234 , creating a TCP connection between the two processes.
Now type text in one terminal and press Enter you’ll see the same text appear in the other terminal and vice-versa. 🚀

#sockets

Showing page 2 of 83

Ready to Build Something Amazing?

Codemancers can bring your vision to life and help you achieve your goals