Skip to content

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.

  1. In JavaScript, you can use localeCompare with { sensitivity: "base" } to compare strings without considering case or accents.
    Example:


    JavaScript

    "Test".localeCompare("test", undefined, { sensitivity: "base" }) === 0; // ✅ True
    "café".localeCompare("cafe", undefined, { sensitivity: "base" }) === 0; // ✅ True
    "Hello".localeCompare("HELLO", undefined, { sensitivity: "base" }) === 0; // ✅ True


    • Case-insensitive
    • Accent-insensitive
    No need for toLowerCase() hacks anymore! 🎉

    second argument is locale . by giving it as "Undefined" it uses default locale of the runtime environment. We can specify as "en", "id" etc. It is used in sorting scenarios ig.

    Sensitivity is the behaviour of the comparison


    JavaScript

    "base" → Ignores case & accents ("café" == "cafe", "Hello" == "hello")
    
    "accent" → Considers accents but ignores case ("café" != "cafe", "Hello" == "hello")
    
    "case" → Considers case but ignores accents ("café" == "cafe", "Hello" != "hello")
    
    "variant" → Considers both case & accents ("café" != "cafe", "Hello" != "he



    #stimulus #JavaScript #StringComparison
  2. By default, Capybara only finds visible and interactable elements. If a button is disabled or outside the viewport, Capybara may fail to locate it.
    To fix this, use:


    Code

    expect(page).to have_button("Add Discrepancy", disabled: true, visible: :all)


    • disabled: true ensures the button is actually disabled
    • visible: :all allows Capybara to find buttons that are hidden, off-screen, or disabled
    This is useful when testing UI behaviors where buttons are conditionally enabled/disabled or require scrolling to be visible.

    #CU6U0R822 #capybara #C041BBLJ57G #specs
  3. local_assigns :
    When using partial views in Rails (like _partial.html.erb), we might pass local variables to customize the rendering. However, if we try to use a local variable that wasn't passed, Rails will raise an error.
    To avoid this, local_assigns is a special hash that helps check if a local variable was provided when rendering the partial. Instead of directly using <%= show_projects %>, which could cause an error if missing, we can safely check local_assigns[:show_projects] first.


    Ruby

    <% if local_assigns[:show_projects] %> 
      <div class="flex">
        <%= (render @user.projects) || (render 'shared/empty_state', message: "No projects found!") %>
      </div> 
    <% end %>


    Here, the partial checks if show_projects was passed before using it. If show_projects was provided, it renders the user's projects or a message if no projects are found. If show_projects wasn't passed, nothing happens, preventing errors.
  4. Mohammad
    The Rails 8.0 release introduces several new features, and among them, params#expect stands out.

    In our daily work with Rails, we often rely on params#require for assignments and queries. However, params#require is more explicit than permit. Here’s an example to illustrate:


    Ruby

    params = ActionController::Parameters.new(posts: [{id: 1}])


    If you expect the posts parameter to contain a list of IDs, such as [{id: 1}, {id: 2}], you can define your expectations like this:


    Ruby

    params.expect(posts: [[:id]])


    The output will be:

    Ruby

    [
      #<ActionController::Parameters {"id"=>1} permitted: true>,
      #<ActionController::Parameters {"id"=>2} permitted: true>
    ]


    Now, consider a different scenario where you expect the posts parameter to have only a single hash with an ID, like this:


    Ruby

    params = ActionController::Parameters.new(posts: {id: 1})


    If you use:


    Ruby

    params.expect(posts: [[:id]])


    It will raise the following error:

    ActionController::ExpectedParameterMissing: param is missing or the value is empty or invalid: posts
    In contrast, using the older params#permit:


    Ruby

    params.permit(posts: [:id])


    Will not enforce your expectation of the nested parameter structure and will accept it without validation.
  5. GiritharanSystem Analyst
    Rails Inflections:
    What is it? Inflections in Rails, powered by the ActiveSupport::Inflector module, allow customization of how words are pluralized, singularized, or treated as uncountable.
    Why use it? Sometimes Rails' default pluralization rules don't fit your app's needs (e.g., irregular words like foot → feet, uncountable words like milk).

    Examples

    • Default Behavior:

    Code

    "person".pluralize  # => "people"
    "person".singularize # => "person"


    • Irregular Inflections:

    Code

    ActiveSupport::Inflector.inflections(:en) do |inflect|
      inflect.irregular "foot", "feet"
    end
    
    // "foot".pluralize  # => "feet"


    • Uncountable Words:

    Code

    ActiveSupport::Inflector.inflections(:en) do |inflect|
      inflect.uncountable "milk"
    end
    
    // "milk".pluralize  # => "milk"


    • Acronym Inflections:

    Code

    ActiveSupport::Inflector.inflections(:en) do |inflect|
      inflect.acronym "HTML5"
    end
    
    // "html5".camelize  # => "HTML5"


    Potential Issues:
    • Default Behavior May Be Inaccurate: Without customizing, words like "tooth" become "tooths" or "milk" becomes "milks."
    • Localization: Inflections are locale-specific, so customizations for one locale won't apply to others.
    Best Practice: Always define rules for edge cases (irregular, uncountable, acronyms) in your config/initializers/inflections.rb ans restart the server after changes

    #rails-inflections #active-support #CU6U0R822
  6. Ashwani Kumar JhaSenior System Analyst
    EXPLAIN ANALYZE Command in PostgreSQL

    1. EXPLAIN: shows the query execution plan that PostgreSQL's query planner generates for the specified query. It tells us how PostgreSQL plans to execute the query, including:
    ◦ What type of scan it will use (sequential scan, index scan)
    ◦ The estimated cost
    ◦ The estimated number of rows
    2. ANALYZE: actually executes the query and shows the real results, including:
    ◦ Actual time taken
    ◦ Actual number of rows processed
    eg:

    Code

    EXPLAIN ANALYZE select * from public.card
    where card_number='120000024223'


    When we will run this command, we'll see output that looks something like this:

    Code

    Seq Scan on public.card  (cost=0.00..11.75 rows=1 width=180) (actual time=0.016..0.018 rows=1 loops=1)
      Filter: ((card_number)::text = '120000024223'::text)
    Rows Removed by Filter: 100
    Planning Time: 0.152 ms
    Execution Time: 0.034 ms


    Here in this output:
    • Seq Scan on public.card:
    ◦ This indicates PostgreSQL is doing a sequential scan (reading the entire table)
    ◦ cost=0.00..11.75: unit-less value that represents PostgreSQL's estimate of how expensive the query will be
    ◦ rows=1: PostgreSQL estimates it will find 1 row
    ◦ width=180: Estimated average width of each row in bytes
    ◦ actual time=0.016..0.018: Actual time taken (in ms)
    ◦ rows=1: Actually found 1 row
    ◦ loops=1: The operation was performed once
    • Filter: ((card_number)::text = '120000024223'::text):
    ◦ Shows the WHERE clause condition being applied
    • Rows Removed by Filter: 100:
    ◦ 100 rows were checked but didn't match the condition
    ◦ This means the table had 101 total rows (100 filtered + 1 matching)
    • Planning Time: 0.152 ms:
    ◦ Time taken to generate the query execution plan
    • Execution Time: 0.034 ms:
    ◦ Actual time taken to execute the query
    This can be used for:
    • Debugging performance issues
    • Finding bottlenecks in query performance
    #PostgreSQL #query
  7. Shared Context in RSpec

    Shared Context: A shared context in RSpec is a way to define common setup code that can be reused across multiple test examples or groups. Instead of duplicating setup code, we define it once in a shared context and include it wherever needed. It helps keep our tests DRY.


    Ruby

    RSpec.shared_context "user and post setup", shared_context: :metadata do
      let(:user) { User.create(name: "Alice") }
      let(:post) { Post.create(title: "First Post", user: user) }
    end
    
    RSpec.describe "Using shared context in tests" do
      include_context "user and post setup"
    
      it "has a user with a name" do
        expect(user.name).to eq("Alice")
      end
    
      it "has a post with a title" do
        expect(post.title).to eq("First Post")
      end
    end


    In the example, the shared context user and post setup defines let variables for a user and a post.
    By including the shared context with include_context, we gain access to those let variables in the test examples.

    #rspec #rubyonrails
  8. Vaibhav YadavSenior System Analyst
    Using DISTINCT ON in PostgreSQL

    When using DISTINCT ON in PostgreSQL, the columns specified in the DISTINCT ON clause must appear first in the ORDER BY clause and in the same order. This is a requirement to ensure PostgreSQL knows how to determine the "first" row for each distinct group.

    For example:

    Code

    SELECT DISTINCT ON (user_id, event_name) id, user_id, event_name, inquiry_id, created_at
    FROM public.persona_inquiry
    ORDER BY user_id, event_name, created_at DESC;


    Key points:
    • DISTINCT ON (user_id, event_name) selects the first row for each unique (user_id, event_name) combination.
    • ORDER BY user_id, event_name ensures that the sorting starts with the same columns as the DISTINCT ON clause.
    • Additional columns in ORDER BY (like created_at DESC) determine which row to pick when there are duplicates.
    Mistakenly not matching the DISTINCT ON columns with the start of the ORDER BY clause will result in an error:
    SELECT DISTINCT ON expressions must match initial ORDER BY expressions.

    #postgres #sql #database
  9. ActiveSupport::CurrentAttributes provides a thread-isolated attributes singleton, perfect for request-specific data like current user, role, or locale.
    create a current.rb in models directory and add the attributes we want to set

    Ruby

    class Current < ActiveSupport::CurrentAttributes
      attribute :role
    end


    then in application controller we can set it like this

    Ruby

    class ApplicationController < ActionController::Base  
      before_action :set_current_attributes
    
      def set_current_attributes
        Current.role = session[:role]
        // ... other attributes
      end
    end


    now in your application we can directly access and use like Current.role

    #CU6U0R822 #rails-current-attributes
  10. Codemancers
    Mise

    Mise is a fast, lightweight (thanks to Rust :happy_pepe:), language agnostic version manager that can be used instead of having separate language based version managers like rbenv for Ruby, npm for Node.js and Pyenv for Python etc.

    Installing a Ruby version globally is as simple as follows:

    Code

    mise use -g ruby@3


    Installing mise is as easy as following in MacOS

    Code

    curl https://mise.run | sh


    Proceed with following to configure the Shell Initialisation

    Code

    echo 'eval "$(~/.local/bin/mise activate)"' >> ~/.zshrc


    Reload the shell configuration changes in current tab

    Code

    source ~/.zshrc


    #mise #ruby-version-manager #version-manager #C04HPTKNZ8R #ruby #python #CCT1JMA0Z
  11. mattr_accessor is a Rails utility method that creates a class-level accessor for a variable.
    When we define mattr_accessor for a variable, it creates
    1. A getter method for the class.
    2. A setter method for the class.
    Eg:

    Ruby

    class MyClass
      mattr_accessor :my_variable
    end


    This is equivalent to:

    Ruby

    class MyClass
      @my_variable = nil
    
      def self.my_variable
        @my_variable
      end
    
      def self.my_variable=(value)
        @my_variable = value
      end
    end


    It also works on module-level classes, which makes it particularly useful for defining global configuration in gems.

    #CU6U0R822
  12. accepts_nested_attributes_for is a Rails method that allows you to easily manage the creation, updating, and destruction of associated models through the parent model's attributes. This is particularly useful when you have nested forms or when you want to handle multiple models in a single operation (e.g., creating or updating a User and its associated Profile in one form submission).


    Ruby

    class User < ApplicationRecord
      has_one :profile
      accepts_nested_attributes_for :profile
    end


    Given the User model has a has_one :profile association, and you want to create or update a User and their Profile at the same time, you can use accepts_nested_attributes_for to pass attributes for both models:

    Ruby

    user_params = {
      name: "John Doe",
      profile_attributes: { bio: "Developer", age: 30 }
    }
    
    user = User.create(user_params)


    In this example, Rails will create both a new User and a new Profile with the attributes provided in profile_attributes.
    #CU6U0R822
  13. When working with paginated data in Ruby on Rails, we might encounter situations where we need to paginate an array rather than an Active Record collection. The pagy gem provides an efficient and flexible way to handle pagination, and it includes an extras/array feature specifically for arrays.

    Require the Pagy Extras Array:

    Ruby

    # config/initializers/pagy.rb
    
    require "pagy/extras/array"


    And then use the pagy_array method to paginate your array in the controller

    Ruby

    def index
     // some code
     @pagy, @purchase_order_attachments = pagy_array(orders_with_attachments, items: params[:limit] || 10)
    end


    #rubyonrails #pagination #pagy
  14. Adithya HebbarSystem Analyst
    In Python, dir() lists the attributes and methods of an object, such as a class or instance.

    Example:

    Python

    class MyClass:
        class_variable = "Class Variable"
    
        def __init__(self):
            self.instance_variable = "Instance Variable"
    
        def my_method(self):
            pass
    
    obj = MyClass()
    print(dir(obj))


    Output:
    dir(obj) shows a list of attributes (class_variable, instance_variable) and methods (my_method), along with special methods (e.g., __init__). It helps explore what’s available in an object.
  15. Test SSH connection detailed logs to debug #ssh #CCTJN6PK4

    Code

    ssh -vT "[email protected]"


    This will output detailed logs
  16. Ashwani Kumar JhaSenior System Analyst
    Definite Assignment Checks in TypeScript 5

    • Before TypeScript 5:

    TypeScript

    let value: string;
    console.log(value); // TS4.x: This was allowed but could lead to runtime undefined


    • After TypeScript 5:

    TypeScript

    let value: string;
    console.log(value); // TS5.x: Error - Variable 'value' is used before being assigned
    
    // To fix, either initialize:
    let value = "initial";
    
    // Or use definite assignment assertion:
    let value!: string;


    • The ! is a promise to TypeScript that we'll assign a value before using it
    • Use of ! should be avoided as it bypasses TypeScript's safety checks
  17. When working with routes in a Rails application that includes an engine, route references need to be scoped appropriately based on where they are being called:
    • Referencing engine routes from outside the engine: Prefix the route with the engine's name. For example, use engine_name.some_route_path (e.g., rapidfire.surveys_path) to access routes within the engine.
    • Referencing routes from another engine: Use the other engine's name as a prefix, similar to referencing routes from outside.
    This naming ensures the correct routing context and prevents conflicts when multiple engines or the main application define similar paths.

    #CU6U0R822 #routes
  18. Form Objects in Rails
    Form objects are a pattern that is used to encapsulate logic for managing and validating form data. They act as an intermediary between the view and the model layer, they simplify the handling of complex forms, particularly when working with complex forms that don't map to a single active record model.
    Why use form objects?
    In typical rails applications, forms are directly tied to active record models. This is ok when the forms are simple, but this can cause problem when complexity increases such as,
    when forms interact with multiple models
    In these kind of scenarios, we can encapsulate the corresponding logic into a single class which acts like an active record model which is easier to maintain.

    Example form object
    app/forms/route_request_form.rb

    Ruby

    class UserProfileForm
      include ActiveModel::Model
    
     # Attributes accessible for the form object.
      attr_accessor :user_name, :email, :profile_bio, :profile_age
    
      validates :user_name, :email, presence: true
      validates :profile_age, numericality: { only_integer: true, greater_than: 0 }
    
      def save
        return false unless valid?
        
        #a single transaction for multiple operations
        ActiveRecord::Base.transaction do
          user = User.create!(name: user_name, email: email)
          user.create_profile!(bio: profile_bio, age: profile_age)
        end
    
        true # Return true if all operations succeed.
      rescue ActiveRecord::RecordInvalid
        false # Return false if the save process fails.
      end
    end


    Using it in controller

    Ruby

    class UsersController < ApplicationController
      def new
        @form = UserProfileForm.new
      end
    
      def create
        @form = UserProfileForm.new(user_profile_form_params)
    
        if @form.save
          redirect_to root_path, notice: "User created successfully!"
        else
          render :new, status: :unprocessable_entity
        end
      end
    
      private
    
      def user_profile_form_params
        params.require(:user_profile_form).permit(:user_name, :email, :profile_bio, :profile_age)
      end
    end




    #ruby_on_rails #form_objects
  19. Codemancers
    *
    *Convert .pem certificate into .pfx

    To convert a .pem certificate to .pfx, follow these steps:
    1. Ensure you have OpenSSL installed.
    2. Prepare the required files:
    ◦ .pem certificate file (certificate.pem)
    ◦ Private key file (privatekey.pem)
    ◦ (Optional) CA chain file (ca-chain.pem)
    3. Run the following command to create the .pfx file:

    Code

    openssl pkcs12 -export -out certificate.pfx -inkey privatekey.pem -in certificate.pem -certfile ca-chain.pem


    4. When prompted, enter a password to secure the .pfx file.
    5. Verify the .pfx file using:

    Code

    openssl pkcs12 -info -in certificate.pfx


    This process combines the certificate, private key, and CA chain (if provided) into a .pfx file, which is commonly used for secure applications like Windows servers or browser-based authentication.
    #Certificates #SSL&TLS
  20. Codemancers
    Convert .pem certificate into .pfx
    To convert a .pem certificate to .pfx, ensure you have OpenSSL installed and have your .pem certificate file, private key file, and optionally a CA chain file ready.
    Use the command:

Showing page 6 of 42

Your competitors are already using AI. The question is how fast you want to unlock the value.

  • Don't know where to start?

    AI is everywhere but it's unclear which investments will actually move your metrics and which are expensive experiments.

  • Your data isn't ready

    Most AI projects fail at the data layer. Pipelines, quality, access all need work before LLMs can deliver value.

  • Internal teams are stretched

    Your engineers are shipping product. They don't have capacity to also become AI specialists with production-grade experience.

  • Legacy systems block everything

    Aging, undocumented codebases make AI integration slow, risky, and expensive. They need to move first.

Don't worry. We've got you covered.

Start with the audit.

Book a free discovery call