Hono Tutorial Pt. 3

August 07, 2024

Before we go further and learn more about the Hono framework, the one thing that is bothering me is database credentials written in code. We should adjust the existing code by removing the credentials from the code and put it within the .env file. We should never hard-code the secret(s) as per 12factor app.

Go ahead and create a .env file in the root of the project.

touch .env

Let’s define the following environment variables within this created .env file.

DB_NAME="hono"
DB_HOST="localhost"
DB_PORT=5432
DB_USER="postgres"
DB_PASS="password"

We should not commit this file in the Git. The file should be added within .gitignore file. But, to give and idea about the existence of the .env file, we should have the .env.example file in the repo with same content as we have in .env file but with dummy environment variables or env vars.

cp .env .env.example

Hono has an adapter to read the env vars from the .env file. But, unfortunately it is not working for the Node and outside of c or context. For now, we are going to use the dotenv package. Let’s first install the dotenv package.

npm i -E dotenv

Import dotenv/config in app.js and we are good to go.

import { serve } from "@hono/node-server";
import { Hono } from "hono";
import postgres from "postgres";
import "dotenv/config";

const sql = postgres({
  host: "localhost",
  port: 5432,
  username: "postgres",
  password: "password",
  database: "hono",
});

const app = new Hono();

app.get("/", async (c) => {
  const result = await sql`SELECT 1 + 1`;
  console.log(result);
  return c.text("Hello!");
});

serve(app, (info) => {
  console.log(`Listening on http://localhost:${info.port}`);
});

Now, replace the hard-coded database connection options within app.js with the env vars using process.env as follows.

import { serve } from "@hono/node-server";
import { Hono } from "hono";
import postgres from "postgres";
import "dotenv/config";

const sql = postgres({
  host: process.env.DB_HOST,
  port: process.env.DB_PORT,
  username: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
});

const app = new Hono();

app.get("/", async (c) => {
  const result = await sql`SELECT 1 + 1`;
  console.log(result);
  return c.text("Hello!");
});

serve(app, (info) => {
  console.log(`Listening on http://localhost:${info.port}`);
});

With these changes, we have removed the hard-coded secrets from our code. These changes should not effect the output. Run the application to confirm the same!

npm run dev
Listening on http://localhost:3000

Visit the http://localhost:3000 in the web browser and you should see the following output in terminal while displaying Hello! in the browser.

Result(1) [ { '?column?': 2 } ]
Note
The code is available at GitHub. Checkout chapter03 branch for the code of this chapter.

Hono Tutorial Pt. 2

August 06, 2024

In this article, we are going to connect the database in Hono application. For the purpose of demonstration, we are going to use PostgreSQL database and postgres as npm package. You are free to use any other package and database as steps will be similar except you need to consult the respected documentation for initial setup.

Let’s install a postgres package.

npm i -E postgres

As per postgres package documentation, we first need to import the postgres function. This function accepts the connection options, and we can save the connection within sql variable as follows.

import { serve } from "@hono/node-server";
import { Hono } from "hono";
import postgres from "postgres";

const sql = postgres({
  host: "localhost",
  port: 5432,
  username: "postgres",
  password: "password",
  database: "hono",
});

const app = new Hono();

app.get("/", async (c) => {
  return c.text("Hello!");
});

serve(app, (info) => {
  console.log(`Listening on http://localhost:${info.port}`);
});

You need to adjust the connection options to the postgres() function based on your PostgreSQL setup. Once done, you now have the active connection within sql variable.

Let’s execute the simple SELECT 1 + 1 query within root route and print the result of it. The query returns the promise, and due to this we need to update the signature of the callback function to async/await.

import { serve } from "@hono/node-server";
import { Hono } from "hono";
import postgres from "postgres";

const sql = postgres({
  host: "localhost",
  port: 5432,
  username: "postgres",
  password: "password",
  database: "hono",
});

const app = new Hono();

app.get("/", async (c) => {
  const result = await sql`SELECT 1 + 1`;
  console.log(result);
  return c.text("Hello!");
});

serve(app, (info) => {
  console.log(`Listening on http://localhost:${info.port}`);
});

That’s it! Run the application using the following command.

npm run dev

Visit http://localhost:3000 in the browser and check the terminal. You should see the following console message.

Result(1) [ { '?column?': 2 } ]

We got the result 2 as 1+1 and when you don’t define the column name in SELECT clause in PostgreSQL, PostgreSQL by default gives ?column? as column name.

With these changes, our Hono application is connected with database. You might say that this is boring and nothing specific to Hono. That is right! As Hono doesn’t re-invent wheel in every aspect of the web development and database connection is one such a case!

Note: The code is available at GitHub. Checkout chapter02 branch for the code of this chapter.

Phoenix Framework Pt. 3

August 05, 2024

The routes of the application are defined within the lib/hello_web/router.ex file. In this file, look for the following code snippet.

scope "/", HelloWeb do
  pipe_through :browser

  get "/", PageController, :home
end

In a future article, we will cover what other code does in this file. But, for now we can focus on this code block and specifically, this line - get "/", PageController, :home. It means when a GET / or root route is requested, execute the home action (function) of PageController.

You can find this PageController or page_controller.ex file within the lib/hello_web/controllers folder. Open this file, and you should see the following code.

defmodule HelloWeb.PageController do
  use HelloWeb, :controller

  def home(conn, _params) do
    # The home page is often custom made,
    # so skip the default app layout.
    render(conn, :home, layout: false)
  end
end

There we have the home function! This function renders home template or home.html.heex file without layout and located at lib/hello_web/controllers/page_html folder.

Don’t worry about the location of these files! Don’t memorize the locations. With some practice, you know all these eventually.

So, we have the router.ex file that defines the routes of the application that point to the controller’s action and the controller’s action to render a view. There is one more file page_html.ex located at the lib/hello_web/controllers folder. But, we haven’t talked about it yet and we’ll talk about it in future articles. But, it is required to have to complete this request-response cycle.

---

Let’s add a new route GET /about. Open router.ex file, and write the following.

scope "/", HelloWeb do
  pipe_through :browser

  get "/", PageController, :home
  get "/about", PageController, :about
end

When the GET /about is requested, we are going to call about the action of the PageController file. Let’s add this about function in the page_controller.ex file. Open the page_controller.ex file and write the following.

defmodule HelloWeb.PageController do
  use HelloWeb, :controller

  def home(conn, _params) do
    # The home page is often custom made,
    # so skip the default app layout.
    render(conn, :home, layout: false)
  end

  def about(conn, _params) do
    # The home page is often custom made,
    # so skip the default app layout.
    render(conn, :about)
  end
end

I almost copied the home function with two notable changes - we are going to render about.html.heex file and remove the layout argument to use default layout. We do not have this about.html.heex file in the lib/hello_web/controllers/page_html file. So, let’s create one.

touch lib/hello_web/controllers/page_html/about.html.heex

Open this about.html.heex file and write the following code.

<h1>About<h1>

Visit http://localhost:4000/about file and you should see this header text with navigation. This navigation is coming from the default layout.

With these changes, now we have the Phoenix application with a new route!


Phoenix Framework Pt. 2

August 04, 2024

In this article, I am going to briefly explain to you the purpose of a few files and folders present in this hello Phoenix project. This will be brief. Because, as you start to become familiar with Phoenix projects, it will become second nature to you.

We have a _build folder. When you run the application, Elixir compiles the project and saves the artifacts within this folder. You can ignore what is within this folder because Git also ignored this folder in the .gitignore file!

We have an assets folder. You can put static assets such as JavaScript or CSS within this folder that further require compilation such as TailwindCSS. But, if you want to save the static assets that don’t require the compilation such as plain CSS files or images, you can put it within the priv/static folder.

We have a config folder. This folder contains the configurations of the project. config.exs is the starting point and then we have files after each of the environments. We already know the config/dev.exs file as modified for the database configuration for the dev or development environment.

We have a deps folder. This folder contains the dependencies of this project. Again, we do not have to worry about this file as this file is ignored in .gitignore.

We have a lib folder. This folder contains the application code. We are going to spend most of the time in this folder.

We have a priv folder. This folder contains files which are directly not needed in production but the application depends on. For example, migration scripts. We need migration scripts for database modification but production does not directly include the code of it.

Finally, all the test cases are written within the test folder. And mix.exs and mix.lock file contains the dependencies of the project.

I think this brief overview is enough to get started and I will cover in details where it requires.

---

Let’s do a quick modification in scaffold code to print the hello, world text instead of the default landing page. What you are seeing at http://localhost:4000 is coming from lib/hello_web/controllers/page_html/home.html.heex. Open this file and replace the whole HTML with the following.

<h1>hello, world</h1>

You do not have to reload the page in the browser thanks to the Phoenix framework as it will auto reload for you! There you have the hello, world application in the Phoenix framework.


Migration

August 02, 2024

I'm migrating this blog to chauhankiran.pages.dev. This chauhankiran.blogspot.com blog is created in a first-generation blog theme that I highly customized. I want to customize more. But, I'm not getting any help on it. Also, I'm unable to find the documentation on first-generation themes. Current theme is too complicated for me! I remember copying one widget of 12-15 lines of code and expanding it into a couple of hundred lines of code is complicated for me.

Although, chauhankiran.pages.dev looks the same as this one, it is created in Jekyll and the theme is customized to retain the curren look-and-feel. The repo. is hosted on GitHub and deployed on CloudFlare pages.

I'm slowly migrating these articles. I do not plan to delete this current blogspot. But, the new content will be posted there!

Hono Tutorial Pt. 1

August 02, 2024

This is the first article in a series where we are going to build a simple back-end application in Hono in Node.js environment.

Create a new folder with the name hono-app.

mkdir hono-app

Go inside the created hono-app folder.

cd hono-app

Create a package.json file using npm with default values (-y).

npm init -y

Let’s install the hono package.

npm i -E hono

In order to use Hono in the Node.js environment, we also need to the @hono/node-server package.

npm i -E @hono/node-server

Finally, let’s install nodemon to ease the development. We should install this as a development dependency (-D).

npm i -E -D nodemon

For now, we are done with setup. Let’s move on to the coding side. Create a new file with name app.js.

touch app.js

Open this file (or hono-app folder) in your favorite text-editor/IDE and write the following code.

import { Hono } from 'hono';

const app = new Hono();

We are using the latest import...from syntax in our Node.js application! We have imported the Hono and then created an instance of the Hono() using a new keyword and saved it as an app.

Let’s now define a root route(/) and return a simple Hello! text as a response (don’t forget to return the response).

import { Hono } from 'hono';

const app = new Hono();

app.get('/', (c) => {
    return c.text('Hello!');
});

Here, c is a context and it contains both request and response in it with many useful methods such as .text(). The .text() method return response in plain text with string passed to it e.g. Hello!.

Now, to run the application in Node, we need to use @hono/node-server package. Import serve from @hono/node-server package.

import { Hono } from 'hono';
import { serve } from '@hono/node-server';

const app = new Hono();

app.get('/', (c) => {
    return c.text('Hello!');
});

Use this serve method as follows.

import { Hono } from 'hono';
import { serve } from '@hono/node-server';

const app = new Hono();

app.get('/', (c) => {
    return c.text('Hello!');
});

serve(app, (info) => {
    console.log(`Listening on http://localhost:${info.port}`);
});

serve() function takes Hono instance as the first argument and second argument should be a callback function with info param that gives useful information such as port. If you don’t define the port value as we did, the default is 3000.

Before we go further and run the application, we need to do some adjustment in the package.json file. As we are using the latest import...from syntax, we need to define type as module. Also, update the main entry point to app.js file.

{
    "name": "hono-app",
    "version": "1.0.0",
    "main": "app.js",
    "type": "module",
    "scripts": {
        "test": "echo \"Error: no test specified\" && exit 1"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "description": "",
    "dependencies": {
        "@hono/node-server": "1.14.0",
        "hono": "4.7.5"
    },
    "devDependencies": {
        "nodemon": "3.1.9"
    }
}

Finally, let’s add two scripts dev and start to run the app.js file with nodemon and node respectively.

{
    "name": "hono-app",
    "version": "1.0.0",
    "main": "app.js",
    "type": "module",
    "scripts": {
        "dev": "nodemon app.js",
        "start": "node app.js"
    },
    "keywords": [],
    "author": "",
    "license": "ISC",
    "description": "",
    "dependencies": {
        "@hono/node-server": "1.14.0",
        "hono": "4.7.5"
    },
    "devDependencies": {
        "nodemon": "3.1.9"
    }
}

With these changes, we are now ready to run the application. Run the following command in the terminal.

npm run dev
Listening on http://localhost:3000

Open http://localhost:3000 in the web browser and you should see Hello! as the plan text. If that is the case, congratulations! You have just created first Hono application in Node.js.

Note: The code is available at GitHub. Checkout chapter01 branch for the code of this chapter.

PostgreSQL

July 29, 2024

I suggest PostgreSQL when someone asks for the recommendation on what database one should use. I use PostgreSQL when I am learning or building something in a new web framework or library. I use PostgreSQL when I want to experiment with databases. PostgreSQL is the default choice for me in most of the cases.

Every few months, I change the operating system from one GNU/Linux distro to another mostly staying with the land of Debian (e.g. apt). Most of the time, I just need to run the following command to install PostgreSQL.

apt install postgresql

This command install and activates the PostgreSQL server locally on my computer. I use the psql command tool to work with this database server.

Following are the commands I use to work with PostgreSQL.

sudo -i -u postgres
psql

Although technically it is not correct, I read the first command as sudo imagine user as postgres to provide access. After entering the password, the user changes from the current logged-in user to postgres and then I can directly work with PostgreSQL using the second psql command.

We can combine the above two commands into a single one as follows.

sudo -iu postgres psql

Again, technically it is not correct, but I read it as sudo imagine users as postgres and then launch psql directly.

The first thing I normally do after connecting with PostgreSQL is to change the password. This is trivial as running the following command.

password \postgres

We are changing the password for the postgres user. After running this command, PostgreSQL asks you to enter and re-enter a new password for the postgres user. And then you are ready to go!

---

If somehow, you are facing difficulties installing PostgreSQL on your computer, installing via Docker is yet another option. At some convenient place, save the docker-compose.yml file with following content.

version: '3'

services:
  db:
    image: postgres
    restart: always
    ports:
      - '5432:5432'
    environment:
      POSTGRES_PASSWORD: pq2q4a

You can choose any other password you like instead of pq2q4a!

Once done, run the following command in the terminal where you have this docker-compose.yml file.

docker-compose up -d

This will run the docker-compose.yml file and up the PostgreSQL service in detached mode. Meaning that it'll run the PostgreSQL service in the background once the docker is running. When you start the computer, if Docker is not running, you just need to run the docker and it'll auto run the PostgreSQL service for you.

કરસનદાસ મૂળજીનું પ્રવાસ પુસ્તક

July 25, 2024

 

ઈંગલેન્ડમાં પ્રવાસ પુસ્તકનું પૂઠું

આમ જોવા જઈએ તો "લેખક" આવે પણ અહીં "કરનાર" લખ્યું છે. પણ, એ વધુ બંધ બેસે છે કે, પ્રવાસ કરનાર કરસનદાસ મુલજી.

એક મિત્ર એ કીધું એ પણ ખરું કે પહેલાના લોકો પ્રેક્ટિકલ હતા.

Sails Tutorial — Chapter 3

June 21, 2024

Note: To follow this article, you need to install an API client to test the routes that we are going to create in this article. Try Postman or Insomnia if you haven’t one.

In this article, we are going to create the APIs for the Contact resource. If you are building an MVC web app, then you need to create seven routes whereas if you are creating an API, you need to create five routes.

To start with, let’s add a route that returns all the contacts as GET /contacts. When this route is requested, the server should run the index action of ContactsController in the config/routes.js file.

module.exports.routes = {
  "GET /": "HomeController.index",

  // Contacts
  "GET /contacts": "ContactsController.index",
};

We don’t have this ContactsController.js file yet! Let’s create one in the api/controllers folder.

touch api/controllers/ContactsController.js

Open this ContactsController.js file and write the following code.

module.exports = {
  index: (req, res) => {
    res.json({ message: "All contacts" });
  },
};

Open the http://localhost:1337/contacts in the browser and you should see this JSON response.

Now, we need to add a route for a specific contact as GET /contacts/:id. When this route is requested, the server should run the show action of ContactsController in routes.js file.

module.exports.routes = {
  "GET /": "HomeController.index",

  // Contacts
  "GET /contacts": "ContactsController.index",
  "GET /contacts/:id": "ContactsController.show",
};

Let’s define this show action within ContactsController.js file and also print the passed id value using req.params.id.

module.exports = {
  index: (req, res) => {
    res.json({ message: "All contacts" });
  },

  show: (req, res) => {
    console.log(`contact id is ${req.params.id}`);
    res.json({ message: "Single contact" });
  },
};

Open the http://localhost:1337/contacts/1 in the browser and you should see this JSON response. You should also see the console message as contact id is 1 in the terminal.

Next, we need to add a route that creates a new contact by passing first name and last name as firstName and lastName respectively. We can define this route as POST /contacts and map against the create action of ContactsController.

module.exports.routes = {
  "GET /": "HomeController.index",

  // Contacts
  "GET /contacts": "ContactsController.index",
  "GET /contacts/:id": "ContactsController.show",
  "POST /contacts": "ContactsController.create",
};

Let’s define this create action within ContactsController.js file and also print the passed firstName and lastName values using req.body.firstName and req.body.lastName (you can destructure in single line, if you want).

module.exports = {
  index: (req, res) => {
    res.json({ message: "All contacts" });
  },

  show: (req, res) => {
    console.log(`contact id is ${req.params.id}`);
    res.json({ message: "Single contact" });
  },

  create: (req, res) => {
    console.log(`first name is ${req.body.firstName}`);
    console.log(`last name is ${req.body.lastName}`);
    res.json({ message: "Creating contact" });
  },
};

To test this route, we need to do a POST api call in Insomnia (or any other API client you are using). You should get the above JSON response when calling this route and first name & last name should be consoled in the terminal.

Before we go further and add route for updating a resource, let’s do a status code modification in create route as 201 should be the status code when creating a resource. We know how to do it as we’re going to use Express’s .status() method.

module.exports = {
  index: (req, res) => {
    res.json({ message: "All contacts" });
  },

  show: (req, res) => {
    console.log(`contact id is ${req.params.id}`);
    res.json({ message: "Single contact" });
  },

  create: (req, res) => {
    console.log(`first name is ${req.body.firstName}`);
    console.log(`last name is ${req.body.lastName}`);
    res.status(201);
    res.json({ message: "Creating contact" });
  },
};

Much better! Just confirm in Insomnia that you should get 201 status code in response (You can chain .status() and .json() methods in single line, if you want).

Let’s define a route to update a specific contact as PUT /contacts/:id. When this route is requested, the server should run the update action of ContactsController.

module.exports.routes = {
  "GET /": "HomeController.index",

  // Contacts
  "GET /contacts": "ContactsController.index",
  "GET /contacts/:id": "ContactsController.show",
  "POST /contacts": "ContactsController.create",
  "PUT /contacts/:id": "ContactsController.update",
};

Let’s define this update action within the ContactsController.js file. Let’s also print the id as req.params.id and passed firstName & lastName values as req.body.firstName and req.body.lastName (you can also destructure, if you want).

module.exports = {
  index: (req, res) => {
    res.json({ message: "All contacts" });
  },

  show: (req, res) => {
    console.log(`contact id is ${req.params.id}`);
    res.json({ message: "Single contact" });
  },

  create: (req, res) => {
    console.log(`first name is ${req.body.firstName}`);
    console.log(`last name is ${req.body.lastName}`);
    res.status(201);
    res.json({ message: "Creating contact" });
  },

  update: (req, res) => {
    console.log(`contact id is ${req.params.id}`);
    console.log(`first name is ${req.body.firstName}`);
    console.log(`last name is ${req.body.lastName}`);
    res.json({ message: "Updating contact" });
  },
};

We need to test this route in Insomnia. You should get the above JSON response when calling this route and id, firstName & lastName should be consoled in the terminal.

Finally, we need to add a route that deletes a specific contact as DELETE /contacts/:id and should run the destroy action of ContactsController. delete is a reserved keyword in JavaScript. Due to this, we choose destroy as function name.

module.exports.routes = {
  "GET /": "HomeController.index",

  // Contacts
  "GET /contacts": "ContactsController.index",
  "GET /contacts/:id": "ContactsController.show",
  "POST /contacts": "ContactsController.create",
  "PUT /contacts/:id": "ContactsController.update",
  "DELETE /contacts/:id": "ContactsController.destroy",
};

Let’s define this destroy action within ContactsController.js file and also print the id as req.params.id.

module.exports = {
  index: (req, res) => {
    res.json({ message: "All contacts" });
  },

  show: (req, res) => {
    console.log(`contact id is ${req.params.id}`);
    res.json({ message: "Single contact" });
  },

  create: (req, res) => {
    console.log(`first name is ${req.body.firstName}`);
    console.log(`last name is ${req.body.lastName}`);
    res.status(201);
    res.json({ message: "Creating contact" });
  },

  update: (req, res) => {
    console.log(`contact id is ${req.params.id}`);
    console.log(`first name is ${req.body.firstName}`);
    console.log(`last name is ${req.body.lastName}`);
    res.json({ message: "Updating contact" });
  },

  destroy: (req, res) => {
    console.log(`contact id is ${req.params.id}`);
    res.json({ message: "Deleting contact" });
  },
};

And now we have the stub end-points for the given resource e.g. Contact with best practice to create REST APIs.


Go: Get Started Pt. 1

March 07, 2024

 Create a folder with name of the project e.g. project-name.

$ mkdir project-name

Go inside the created project-name folder.

$ cd project-name

Create a module or mod file using following command.

$ go mod init project-name

This command will create go.mod file. This file is the manifest file of the project that contains info of your project such as project name, Go version, dependencies of the project and so on. Following is the content as of now we’ve in this go.mod file.

module go-example 

go 1.21.5

We don’t have any dependency related information in this file yet. Because, our project yet not consuming any third-party package.

Create a file with name main.go and write following code in it.


package main


import "net/http"

import "github.com/gin-gonic/gin"


func main() {

  r := gin.Default()

  r.GET("/", func (c *gin.Context) {

    c.JSON(http.StatusOK, gin.H{

      "message": "hello, world",

    })

  })

  r.Run()

}


This is the simple hello, world program in Gin framework. Notice that we’re importing Gin framework from github.com/gin-gonic/gin. But, we haven’t installed this package yet. In order to install the package, we need to run following command.

$ go mod tidy

This command will look for the dependencies used in this project and download it for us. After successful completion of the command, if you look over the go.mod file again, it looks like this.

module project-name

go 1.21.5

require github.com/gin-gonic/gin v1.9.1

require (
  github.com/bytedance/sonic v1.9.1 // indirect
  github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
  github.com/gabriel-vasile/mimetype v1.4.2 // indirect
  github.com/gin-contrib/sse v0.1.0 // indirect
  github.com/go-playground/locales v0.14.1 // indirect
  github.com/go-playground/universal-translator v0.18.1 // indirect
  github.com/go-playground/validator/v10 v10.14.0 // indirect
  github.com/goccy/go-json v0.10.2 // indirect
  github.com/json-iterator/go v1.1.12 // indirect
  github.com/klauspost/cpuid/v2 v2.2.4 // indirect
  github.com/leodido/go-urn v1.2.4 // indirect
  github.com/mattn/go-isatty v0.0.19 // indirect
  github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
  github.com/modern-go/reflect2 v1.0.2 // indirect
  github.com/pelletier/go-toml/v2 v2.0.8 // indirect
  github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
  github.com/ugorji/go/codec v1.2.11 // indirect
  golang.org/x/arch v0.3.0 // indirect
  golang.org/x/crypto v0.9.0 // indirect
  golang.org/x/net v0.10.0 // indirect
  golang.org/x/sys v0.8.0 // indirect
  golang.org/x/text v0.9.0 // indirect
  google.golang.org/protobuf v1.30.0 // indirect
  gopkg.in/yaml.v3 v3.0.1 // indirect
)

On line number 5, there we’ve the dependency. Remaining are the indirect dependency as they end with comment // indirect meaning that these dependencies are not directly consume by the project. But, project’s dependency are depends on it.

Finally, you should see a file with name go.sum. This file is auto generated by Go for the dependencies with checksum to figure out whether to download the dependencies again or not. Let’s not worry about this file as it’ll be created, updated, and managed by Go for us.

સારા ભાષાંતરના ગુણ

February 06, 2024

સારા ભાષાંતરમાં નીચેના ગુણ હોવા જોઈએ:

  1. એ જાણે સ્વભાષામાં જ વિચારાયું અને લખાયું છે તેવું સહજ અને સરળ હોવુ જોઈએ. જે ભાષામાંથી ઉતારાયું હોયતે ભાષાના રૂઢીપ્રયોગો અને શબ્દોના વિશેષ અર્થો ન જાણનાર એને સમજી ન શકે એવું તે ન હોવું જોઈએ.
  2. ભાષાંતરકારે જાણે મૂળ પુસ્તકને પી જઈને તથા પચાવીને એને ફરીથી સ્વભાષામાં ઉપજાવ્યું હોય તેવી કૃતિ લાગવી જોઇએ.
  3. આથી સ્વતંત્ર પુસ્તક કરતા ભાષાંતર કરવાનું કામ હંમેશા સહેલુ નથી હોતું. મૂળ લેખક સાથે જે પૂરેપૂરો સમભાવી અને એકરસ થઈ શકે નહીં અને તેના મનોગતને પકડી લે નહીં, તેણે તેનું ભાષાંતર ન કરવું જોઈએ.
  4. ભાષાંતર કરવામાં જુદી જુદી જાતનો વિવેક રાખવો જોઈએ. કેટલાંક પુસ્તકોનું અક્ષરશઃ ભાષાંતર કરવું આવશ્યક ગણાય, કેટલાંકનો માત્ર સાર આપી દેવો બસ ગણાય તો કેટલાંક પુસ્તકોનાં ભાષાંતર સ્વ સમાજને સમજાય એ રીતે વેશાંતર કરીને જ આપવાં જોઈએ. કેટલાંક પુસ્તકો તે ભાષાના ઉત્કૃષ્ટ હોવા છતાં પોતાનો સમાજ અતિશય જુદા પ્રકારનો હોવાથી તેના ભાષાંતરની સ્વભાષામાં જરૂર જ ન હોય; અને કેટલાંક પુસ્તકોના અક્ષરશઃ ભાષાંતર ઉપરાંત સારરૂપ ભાષાંતરની પણ જરૂર ગણાય.

~ મોહનદાસ કરમચંદ ગાંધી 

The Law Of Complexity

February 05, 2024

Complexity never eliminate,
it just move from one place to another.


When you're not writing middleware to log requests, someone else wrote or is writing middleware for you. If you think that you can easily write a single page application in a given framework or library then understand that it depends on 1000+ modules to make it easy and the complexity is divided between these 1000+ modules but not eliminated.
 

Day 2 - Lisp Learning

February 04, 2024

Going forward with learning, defvar is used to define variables. Continue with last program written in hello.lisp. Here is how I've defined the hello, world program again with variable.

(defvar greetings "hello, world")


(format t greetings)

I read many places that variables are defined with star(*) around it to mark as global variable and * is valid character to define a variable.

(defvar *greetings* "hello, world")

(format t *greetings*)


Not just * but hyphen(-) can be used to define multi-words variables and this is recommended instead of camelCase or snake_case.

(defvar hello-world "hello, world")

(format t hello-world)

Frankly speaking I haven't seen a program like above anywhere else (defining a variable and then using it in next line without context). May be in functional programming, most of the variables are bound to the scope and only defined where needed.

But, defvar is used to define the variable in Common Lisp.

Day 1 - Lisp Learning

February 03, 2024

In my free time (which I have very less), I'm learning Lisp programming language. After doing some search, I decided to go with Common Lisp and installed sbcl.

Unless you're using Emacs, do not write multiple lines of code in REPL (in Terminal). Most of the terminals don't support paren auto-closing and highlight. Due to this, you might frustrate.

I'm using GNU/Linux machine. Following command help me to install the sbcl on my computer.

sudo apt install sbcl

After installation, check for the version and you can confirm the installation.

sbcl --version

Write only sbcl and it'll open the true REPL for you. In order quit or exit the REPL you need to write (quit).

You can directly write 10 or "hello, world" (use double quotes) as these are the literal values.

* 10
10
* "hello, world"
"hello, world"


If you try to write 10 as (10) or "hello, world" as ("hello, world") you'll get errors. Because, in simple terms, after open paren, Lisp expect to have something that can execute. For example, (+ 3 4) works as + will execute on 3 and 4 values.

Here is the hello, world in Common Lisp.

* (format t "hello, world")

Here, format print on terminal (actually it is standard output) "hello, world" string. You can write code within file that can have .lisp extension. Then you can run it as,

sbcl --script hello.lisp

or Open sbcl REPL and load the file.

sbcl
* (load "hello.lisp")
 

Sails Tutorial — Chapter 2

January 19, 2024

Application is up and running at http://localhost:1337 but it throws a 404 error. Let’s fix it by adding a root route. To do so, first create a config folder and then routes.js file within config folder.

mkdir config
touch config/routes.js

Open the config/routes.js file and write the following code.

module.exports.routes = {};

It exports the routes object that will have all the routes of the application.

Go ahead define a root route or GET / as follows.

module.exports.routes = {
  'GET /': 'HomeController.index',
};

Meaning that when the root route (/) is requested, server run the index action (or method) from the HomeController. But, we don’t have controller and action.

Go ahead and create a folder with the name api. Within this api folder, create a folder with name controllers. In this folder, we’ll put all the application controllers.

mkdir api
mkdir api/controllers

Finally, within this controllers folder, create a file with the name HelloController.js. The name of the file should be the same as the controller name defined in routes.js file.

touch api/controllers/HomeController.js

Open the api/controllers/HomeController.js file and write the following code.

module.exports = {};

It exports the object that will have all the actions we are interested in calling from this controller.

Sails internally uses Express framework. So, the actions within the controller are essentially the callback function we usually write in Express for a given route with req and res (and next) parameters.

Let’s define an index as a named function that returns a sample JSON response.

module.exports = {
  index: (req, res) => {
    res.json({ message: 'Home page' });
  },
};

That’s it! Reload (or open) the http://localhost:1337 in the browser. You should now see a JSON response with the message { "message": "Home page" } instead of a 404 error page.


Express.js Code Reading

October 24, 2023

Following are the list of the points that I find interesting while reading Express code (I'm still reading the source code).

  • Express 4.x support Node v0.10. Due to this, code is not written in ES6.
  • 'use strict' increase the performance.
  • When you write app.set('view engine', 'something'), Express will check something module in node_modules and load it. EJS use this trick and due to this, you just have write this line only. Even you don't have to import ejs (or something in example).
  • All the repos under Express org on GitHub has either index.js if the package is consist of only one file or the package code is within lib folder.

In progress. I'll add more points as I learn more.

PostgreSQL Tutorial Pt. 1

October 22, 2023

Run the following command in the terminal.

$ sudo -i -u postgres

This command is used to open a shell session as the user "postgres" with an environment set up as if "postgres" had logged in directly. This is often useful when you need to perform administrative tasks or run commands specific to the PostgreSQL database system, which typically runs with a dedicated user account for security reasons.

Now, write psql command in terminal to open the command-line interface to PostgreSQL.

$ psql

We now have the PostgreSQL open in our terminal.

To fetch the all database, following command is used.

$ \l
                                    List of databases
          Name           |  Owner   | Encoding | Collate | Ctype |   Access privileges   
-------------------------+----------+----------+---------+-------+-----------------------
 abc_development         | postgres | UTF8     | en_IN   | en_IN | 
 exp_development         | postgres | UTF8     | en_IN   | en_IN | 
 postgres                | postgres | UTF8     | en_IN   | en_IN | 
 template0               | postgres | UTF8     | en_IN   | en_IN | =c/postgres          +
                         |          |          |         |       | postgres=CTc/postgres
 template1               | postgres | UTF8     | en_IN   | en_IN | =c/postgres          +
                         |          |          |         |       | postgres=CTc/postgres
(7 rows)

To connect with specific database, use \c followed by the database name.

$ \c abc_development
You are now connected to database "abc_development" as user "postgres".

We're now connected with the abc_development database.

To list all the tables within given database, following command is used.

$ \dt
Did not find any relations.

We get the message "Did not find any relations." meaning that no table exists as of now in this database.

We can create the table using following command (do not run this command yet).

create table products (
  id int primary key,
  name varchar(256) not null 
);

We're trying to add id as primary key and name as the another string column. But, this query has one problem - id is not auto increment for us by default. To have it that feature, we need to defined it as serial than int like this (now you can run this command).

create table products (
  id serial primary key,
  name varchar(256) not null 
);

With this the products table is created.

Let's write a simple insert query to confirm the usage of the table.

insert into products (name) values ('Neem plant');

Finally, let's confirm that the product is added successfully in table by writing the select query.

select * from products;
 id |     name     
----+--------------
  1 | Neem plant
(1 row)