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.

Nov 28, 2024
*
*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:


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:


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
sagar.ghorse
sagar.ghorse
Nov 28, 2024
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:
sagar.ghorse
sagar.ghorse
Nov 26, 2024
Optimizing Validations with Caching

When we have a Member model where each user has a specific number of coins. When performing operations like capturing or deducting coins, we want to validate:

1. The user exists or not.
2. The user has enough coins to complete the operation.
The basic validation will look like this (with dry-validation gem)



class CoinsValidator < Dry::Validation::Contract
  params do
    required(:user).filled(:integer)
    required(:coins).filled(:integer, gt?: 0)
  end

  rule(:user) do
    member = Member.find_by(unique_id: value) // querying database for member details
    key.failure("does not exist") if member.nil?
  end

  rule(:coins, :user) do
    member = Member.find_by(unique_id: values[:user]) // querying database for member details
    if member && member.coins < values[:coins]
      key(:coins).failure("are insufficient")
    end
  end
end


But the problem here is, We query the database twice to fetch the same Member object once in the :user rule and again in the :coins rule. This redundant querying increases database load and slows down validation, especially in high-traffic applications.

To avoid redundant queries, we can cache the Member object using the values hash provided by the dry-validation gem. The values hash allows us to store intermediate results, making them accessible to other validation rules.
The optimized code looks like this:



class CoinsValidator < Dry::Validation::Contract
  params do
    required(:user).filled(:integer)
    required(:coins).filled(:integer, gt?: 0)
  end

  rule(:user) do
    values[:member] = Member.find_by(unique_id: value)  // Caching the member object
    key.failure("does not exist") if values[:member].nil?
  end

  rule(:coins) do
    member = values[:member]  // accessing the cached Member from values[:member] rather than querying the database again.
    if member && member.coins < value
      key.failure("are insufficient")
    end
  end
end


#ruby on rails
nitturu.baba
Nitturu Baba
System Analyst
Nov 21, 2024
Mocking Timers for Controlled Testing

If your code uses setTimeout or setInterval, Jest's timer mocking lets you fast-forward time.
Example: Using jest.useFakeTimers()



jest.useFakeTimers();

test("delayed greeting is sent after 3 seconds", () => {
  const callback = jest.fn();

  setTimeout(() => callback("Hello!"), 3000);
  jest.runAllTimers();

  expect(callback).toHaveBeenCalledWith("Hello!");
});


#CCT1JMA0Z # testing #jest
amber.srivastava
amber.srivastava
Nov 19, 2024
In Ruby, attr_reader and attr_accessor are used to create getter and setter methods for class attributes. These are part of a group of methods (attr_* methods) that make it easier to create getter and setter methods for class attributes.

attr_reader: Creates a getter method, allowing read-only access to an instance variable.


class Person
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

person = Person.new("Sibtain")
puts person.name  # Outputs: Sibtain


attr_accessor: Creates both getter and setter methods, allowing read and write access to an instance variable.


class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

person = Person.new("Sibtain")
puts person.name  # Outputs: Sibtain

person.name = "John"
puts person.name  # Outputs: John


Furthermore, using attr_reader and attr_accessor promotes encapsulation by controlling how the attributes of a class are accessed and modified.

#ruby #rubyonrails
syedsibtain
Syed Sibtain
System Analyst
Nov 14, 2024
------------------------- useFieldArray hook in react-hook-form -------------------------
The useFieldArray hook is part of react-hook-form and is used for handling dynamic fields in forms, such as arrays of inputs that can be added or removed dynamically.
For example, if you have a list of items (like questions, tasks, or other fields) that can be added, removed, or reordered during form submission, useFieldArray is the ideal solution to manage that dynamic behaviour without manually managing the state of each individual field.

How useFieldArray works:
fields: An array of objects, where each object represents a field in the array.
append: A function to add new fields to the array.
remove: A function to remove fields from the array.
update: A function to update an individual field in the array.
Example:-


import { useForm, useFieldArray } from "react-hook-form";

function DynamicForm() {
  const { register, control, handleSubmit, formState: { errors } } = useForm({
    defaultValues: {
      questions: [{ question: "" }],
    },
  });

  // UseFieldArray to handle the questions array dynamically
  const { fields, append, remove } = useFieldArray({
    control,
    name: "questions",  // Name of the array in the form's state
  });

  const onSubmit = (data: any) => {
    console.log(data); // Submitting form data with dynamic fields
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      {fields.map((item, index) => (
        <div key={item.id}>
          <input
            {...register(`questions.${index}.question`)}  // Register each question dynamically
            defaultValue={item.question}  // Set default value for each item in the array
          />
          {errors.questions?.[index]?.question && (
            <span>{errors.questions[index]?.question.message}</span>
          )}
          <button type="button" onClick={() => remove(index)}>Remove</button>
        </div>
      ))}
      
      <button type="button" onClick={() => append({ question: "" })}>
        Add Question
      </button>

      <button type="submit">Submit</button>
    </form>
  );
}


Key Points:
1. name: The name prop in useFieldArray points to the field array in your form state (in this case, questions).
2. fields: This array holds the current data of the dynamic fields. Each item corresponds to a field in the form array.
3. append: This method is used to add a new item to the array. You can pass the new data for the item when appending.
4. remove: This method is used to remove an item by its index.
When to use useFieldArray:
Dynamic Forms: When you have a form where the number of fields can change over time, such as adding/removing questions, tasks, team members, etc.
Nested Fields: When you have an array of objects (e.g., an array of questions, where each question has a title and description).
Advantages:
• It reduces the need for manual state management when adding/removing fields.
• It integrates seamlessly with react-hook-form to handle validations and form submission.
• It improves performance by avoiding unnecessary re-renders when fields are added or removed.
#CCT1JMA0Z #useForm #react-hook-form
amber.srivastava
amber.srivastava
Nov 14, 2024
Slack's chat.deleteScheduledMessage API allows you to delete messages that were scheduled using chat.scheduleMessage but have not yet been sent.


const response = await slackClient.chat.deleteScheduledMessage({
  channel: channelId, {// ID of the channel where the message was scheduled }
  scheduled_message_id: scheduledMessageId, {// ID of the scheduled message to delete}
});


#slack #api
ayasha.pandey
Ayasha Pandey
System Analyst
Nov 14, 2024
How to write tests for external APIs?

This can be achieved using the gem "webmock".

Using webmock we will similate the external API call and use mockdata as the response to the APIs.

step1: install the gem "webmock"
step2: add the following lines to rails helper.


require 'webmock/webmock_api.rb'

config.before(:each) do
    stub_request(:any, /domain_name/).to_rack(WebmockApi
end


step3: create mock data responses for the APIs inside fixtures folder in spec.

member_api_success.json


# spec/fixtures/member_api_success.json
[
  {
    "id": 1,
    "name": "John Doe",
    "email": "john.doe@example.com",
    "phone": "123-456-7890",
    "membership_type": "Gold",
    "status": "active"
  },
  {
    "id": 2,
    "name": "Jane Smith",
    "email": "jane.smith@example.com",
    "phone": "987-654-3210",
    "membership_type": "Silver",
    "status": "inactive"
  }
]


step4: inside spec create webmock file. Inside webmock create webmock_api.rb file. In this file we will simulate the responses for the API using mock data we have created.


class WebmockApi
  SPEC_FIXTURES_PATH = 'spec/fixtures'.freeze
  MEMBERS_SUCCESS = File.read("#{SPEC_FIXTURES_PATH}/members_api_success.json").freeze
  POSTS_SUCCESS = File.read("#{SPEC_FIXTURES_PATH}/posts_api_success.json").freeze
  ERROR = File.read("#{SPEC_FIXTURES_PATH}/error.json").freeze

  def self.call(env)
    new.call(env)
  end

  def call(env)
    action = env['REQUEST_METHOD']
    path = env['PATH_INFO']
    params = env['QUERY_STRING']

    case path
    when '/external_members_api_path'
      params.include?('test_user') ? [ 200, {}, [ MEMBERS_SUCCESS ] ] : [ 500, {}, [ ERROR ] ]
    when '/external_post_api_path'
      params.include?('new_post') ? [ 200, {}, [ POSTS_SUCCESS ] ] : [ 500, {}, [ ERROR ] ]
    end
  end
end


step5: write the test cases for the APIs in requests folder.


require 'rails_helper'
require 'webmock/rspec'

RSpec.describe "Members", type: :request do
  describe "GET /members_search_path" do
    context "when the members API call is successful" do
      it "returns member details from the API" do
        get "/external_members_api_path", params: { member: "test_user" }

        expect(response).to have_http_status(:ok)
        user = response.parsed_body["member"]
        expect(["id"]).to eq("123456")
        expect(user["name"]).to eq("abc")
      end
    end
    
    context "when the members API call is successful" do
      it "returns error message from the API" do
        get "/external_members_api_path", params: { member: "unknown_user" }

        expect(response).to have_http_status(:ok)
        expect(response).to have_http_status(:internal_server_error)
        error = response.parsed_body["error"]
        expect(error).to eq("Something went wrong")
      end
    end
  end
end


#ruby on rails
nitturu.baba
Nitturu Baba
System Analyst
Nov 7, 2024
SEND SLACK MESSAGE AS A THREAD

To send a message as a thread in Slack using the Slack API, we can use the chat.postMessage method with the thread_ts parameter. This parameter specifies the timestamp (ts) of the parent message you want to reply to, creating a thread.

Here’s how to send a threaded message:
1. Get the ts (timestamp) of the Parent Message
• If you’re replying to a specific message, you’ll need its ts value. You can retrieve it by fetching messages in the channel, or from the response of a previously sent message.
2. Send a Threaded Message Using thread_ts
• Use thread_ts in the chat.postMessage payload to post your message as a reply in the thread.
Example:-


import { WebClient } from "@slack/web-api";

const client = new WebClient("YOUR_SLACK_BOT_TOKEN");

async function sendThreadedMessage(channel: string, parent_ts: string, message: string) {
  try {
    // Post a new message as a reply in the thread
    const response = await client.chat.postMessage({
      channel,
      text: message,
      thread_ts: parent_ts, // This makes it a threaded message
    });
  } catch (error) {
    console.error("Error sending threaded message:", error);
  }
}

// Usage example
sendThreadedMessage("C123456789", "1688852910.123456", "This is a reply in the thread.");


If we don't have any parent message then,we can first send a message and then use its ts as the thread_ts for replies:


async function sendMessageWithThread(channel: string, message: string, replyMessage: string) {
  try {
    // Send the parent message
    const parentMessage = await client.chat.postMessage({
      channel,
      text: message,
    });

    // Reply to the message in a thread
    await client.chat.postMessage({
      channel,
      text: replyMessage,
      thread_ts: parentMessage.ts,
    });
  } catch (error) {
    console.error("Error sending messages:", error);
  }
}

// Usage example
sendMessageWithThread("C123456789", "This is the main message", "This is a reply in the thread.");


#C04A9DMK81E #slack #slackapi #thread
amber.srivastava
amber.srivastava
Nov 7, 2024
When working with Stimulus, it's common to dynamically update DOM elements. While string interpolation works, using HTML <template> elements is a cleaner and more maintainable approach.
#CU6U0R822 #stimulus #templates

String interpolation


// In your stimulus controller 
updateList() {
  this.listTarget.innerHTML = `
    <div class="flex gap-2">
      <span>${this.name}</span>
      <button>Delete</button>
    </div>
  `
}


HTML Templates


// In your view 
<template data-list-target="template">
  <div class="flex gap-2">
    <span data-placeholder="name"></span>
    <button>Delete</button>
  </div>
</template>

// In your Stimulus controller
updateList() {
  const template = this.templateTarget.content.cloneNode(true)
  template.querySelector('[data-placeholder="name"]').textContent = this.name
  this.listTarget.appendChild(template)
}

satya
satya

Showing 8 to 10 of 79 results

Ready to Build Something Amazing?

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