<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Weseek-Inc</title>
    <description>The latest articles on Forem by Weseek-Inc (@weseek-inc).</description>
    <link>https://forem.com/weseek-inc</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1323580%2F78a6f4da-6582-40cf-820c-6ce93c4ba725.jpg</url>
      <title>Forem: Weseek-Inc</title>
      <link>https://forem.com/weseek-inc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/weseek-inc"/>
    <language>en</language>
    <item>
      <title>VScode: How to Chain Multiple Devcontainer for Development</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Tue, 04 Jun 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/vscode-how-to-chain-multiple-devcontainer-for-development-2aep</link>
      <guid>https://forem.com/weseek-inc/vscode-how-to-chain-multiple-devcontainer-for-development-2aep</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, I am Ise, an engineer at WESEEK who is in charge of the development and operation of &lt;a href="https://growi.cloud/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=VScode_How_to_Chain_Multiple_Devcontainer_for_Development"&gt;GROWI.cloud&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this issue, I would like to share a story about a time when I encountered a troubling problem in the development of GROWI.cloud and solved it.&lt;/p&gt;




&lt;h2&gt;
  
  
  Background
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;GROWI.cloud develops mainly in node.js, and its projects are divided into “Project A”, “Project B” and so on, according to their roles.&lt;/li&gt;
&lt;li&gt;GROWI.cloud's services are made possible by these “Project A” and “Project B” communicating with each other.&lt;/li&gt;
&lt;li&gt;Recently, we have decided to use VSCode's devcontainer(, docker-compose) for our development environment.&lt;/li&gt;
&lt;li&gt;The devcontainer change had no impact on the development of individual projects, as they were all linked with other projects using the internal test environment.&lt;/li&gt;
&lt;li&gt;However, when “Project A” and “Project B” were developed, the devcontainers of both projects could not communicate with each other and hindered the development.&lt;/li&gt;
&lt;li&gt;Therefore, I reviewed the settings around the network of devcontainer, and decided to improve the development environment to enable communication between multiple devcontainers.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What I did
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Add a setting that allows the network to be specified when the docker-compose of devcontainer is started&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, when devcontainer is built, if there is no Docker network, it will be created automatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmq7kqh8m1iuzycrgk8rv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmq7kqh8m1iuzycrgk8rv.png" alt="Setting" width="800" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;*By adding the same configuration to Project B, it is possible to connect to the same namespace network regardless of whether devcontainer of Project A or B is started first.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;On the same Docker network, you can resolve names by service name&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Fix service names in devcontainer/docker-compose.yml so that they are not covered by Projects A and B&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;*Service names in the same Docker network cannot be resolved correctly if they are the same, so even if they are different projects, it is necessary to make sure that the service names do not overlap.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m1g5wrvm5xcxzaefdty.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0m1g5wrvm5xcxzaefdty.png" alt="Fix service names" width="800" height="72"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can name resolve node.js apps in Project A as node, node.js apps in Project B as node-project-b, and so on!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Set network in .devcontainer/docker-compose.yml to connect to the same network&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F17asogjdy74ylmlm5lyk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F17asogjdy74ylmlm5lyk.png" alt="Set network1" width="800" height="231"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhquwyqh1llhkyub9xvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbhquwyqh1llhkyub9xvu.png" alt="Set network2" width="800" height="230"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Review correspondence destination&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;*Before devcontainerization, the communication destination was sorted by “port number” of localhost, but now it is possible to communicate by specifying the service name, so it has been modified.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;example: When sending a POST request from Project A to Project B&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpznt82ktk9iete9qzogx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpznt82ktk9iete9qzogx.png" alt="Review" width="800" height="92"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Rebuild container&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfkx9fid1hsd0xp6fvni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvfkx9fid1hsd0xp6fvni.png" alt="Rebuild Container" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's all I did!&lt;br&gt;
Hope everyone has a good devcontainer LIFE!&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, we want to introduce a little more about GROWI, an open software developed by &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=VScode_How_to_Chain_Multiple_Devcontainer_for_Development"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=VScode_How_to_Chain_Multiple_Devcontainer_for_Development"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt1jaui0iudzecbfst0w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpt1jaui0iudzecbfst0w.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>vscode</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>Use Self-Made Type Guard with TypeScript "is" Operator</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Thu, 30 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/use-self-made-type-guard-with-typescript-is-operator-13e6</link>
      <guid>https://forem.com/weseek-inc/use-self-made-type-guard-with-typescript-is-operator-13e6</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, I'm haruhikonyan and I've been working on WESEEK for a while now.&lt;br&gt;
Do you use TypeScript?&lt;br&gt;
You can write not only front-end code, but also server-side code with Node, and it's also type-safe!&lt;br&gt;
In this article, I want to introduce a self-made type guard using the "is" operator, one of the user-defined type guards, to make TypeScript more robust and useful.&lt;/p&gt;




&lt;h2&gt;
  
  
  What is a Type Guard?
&lt;/h2&gt;

&lt;p&gt;First of all, what is a type guard?&lt;br&gt;
You can read the &lt;a href="https://basarat.gitbook.io/typescript/type-system/typeguard" rel="noopener noreferrer"&gt;reference&lt;/a&gt; for an overview, but the one you will probably use the most is as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3lw5xt0t2zf3zpr8u8f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft3lw5xt0t2zf3zpr8u8f.png" alt="Type Guard"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We often use null and undefined checks as you can see. Of course, it is often necessary to determine not only primitive types such as null, but also original types defined by the user.&lt;/p&gt;

&lt;p&gt;This is where the "is" operator comes in.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is "is"?
&lt;/h2&gt;

&lt;p&gt;It is probably faster to look at than explain it so I will show you an example first.&lt;br&gt;
&lt;a href="https://github.com/axios/axios#" rel="noopener noreferrer"&gt;Axios&lt;/a&gt;, one of the most widely used libraries, has a simple implementation called &lt;code&gt;isAxiosError&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;As you can see in the &lt;a href="https://github.com/axios/axios#typescript" rel="noopener noreferrer"&gt;example&lt;/a&gt;, it determines whether a variable is an AxiosError or not, and type guarding is used to narrow down the variable type.&lt;/p&gt;

&lt;p&gt;I was going to introduce it as it is, but the original code was in JavaScript, so I rewrote it here in TypeScript to make it relatively easy to read.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fab4467alfnknlv59r2iv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fab4467alfnknlv59r2iv.png" alt="is"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  isObject
&lt;/h3&gt;

&lt;p&gt;This is also like a real type guard. Since the "is" operator is not used, it does not narrow down the type of the type guard in a transpiler sense, but it guarantees that the type is not null and is of type object with the &lt;code&gt;typeof&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  isAxiosError
&lt;/h3&gt;

&lt;p&gt;Here is the main issue. First, let's look at what's inside.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3v7eht5jw9oef53pl3b6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3v7eht5jw9oef53pl3b6.png" alt="isAxiosError1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and the first thing is that &lt;code&gt;payload&lt;/code&gt; is an object. This is good.&lt;br&gt;
Then we see that the property of that &lt;code&gt;payload&lt;/code&gt; has the value &lt;code&gt;isAxiosError&lt;/code&gt; &lt;code&gt;true&lt;/code&gt;.&lt;br&gt;
That is all.&lt;br&gt;
It seems that the error object issued by Axios always contains the value &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymyirwmpgn411l05yeta.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fymyirwmpgn411l05yeta.png" alt="isAxiosError2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This means that if the function &lt;code&gt;isAxiosError&lt;/code&gt; returns &lt;code&gt;true&lt;/code&gt;, it will tell the TypeScript transpiler that the &lt;code&gt;payload&lt;/code&gt; given as an argument is (is) type &lt;code&gt;AxiosError&amp;lt;T, D&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Explanation
&lt;/h2&gt;

&lt;p&gt;The above is almost all that has been explained, but the following URL contains more detailed and complete specifications, so if you are in doubt or want to know more, check it out.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://basarat.gitbook.io/typescript/type-system/typeguard" rel="noopener noreferrer"&gt;https://basarat.gitbook.io/typescript/type-system/typeguard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates" rel="noopener noreferrer"&gt;https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Made a Function to Determine the String Array
&lt;/h2&gt;

&lt;p&gt;I hope everyone now understands the “is” operator.&lt;br&gt;
Here, I would like to introduce a function I created when I was using TypeScript and wanted to know exactly whether a certain variable was a string array or not.&lt;/p&gt;

&lt;h3&gt;
  
  
  Function created
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ttxnutyhzt5y5gj450s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ttxnutyhzt5y5gj450s.png" alt="Function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you have read the above explanation, you may understand it. The explanation is that what we receive as &lt;code&gt;value&lt;/code&gt; is an array with &lt;code&gt;isArray&lt;/code&gt;, and if the &lt;code&gt;value&lt;/code&gt; is determined to be an array, the &lt;code&gt;every&lt;/code&gt; function tells the transpiler that it is of type &lt;code&gt;string[]&lt;/code&gt; if all of its elements are of type &lt;code&gt;string&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In practice, when a query is received from a Request in &lt;code&gt;express&lt;/code&gt;, the type of query is &lt;code&gt;string | string[] | QueryString.ParsedQs | QueryString.ParsedQs[] | undefined&lt;/code&gt;, a type that considers all possibilities. &lt;/p&gt;

&lt;p&gt;If you want just a &lt;code&gt;string&lt;/code&gt;, you can use &lt;code&gt;typeof&lt;/code&gt;, but if you want to determine &lt;code&gt;string[]&lt;/code&gt;, &lt;code&gt;isArray&lt;/code&gt; is not enough, so I created my type guard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Be Careful not Falsify the Mold
&lt;/h2&gt;

&lt;p&gt;I'm sure that you have been tempted to try your hand at type determination using the "is" operator. However, if you write &lt;code&gt;is Hoge&lt;/code&gt; in the definition and the function returns even true, the transpiler already knows that it is a Hoge type, so if you write a proper judgment, it will be a false type.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;isAxiosError&lt;/code&gt; is not always appropriate, but if an appropriate object has a property called &lt;code&gt;isAxiosError&lt;/code&gt; and true is set there, it is assumed to be of type &lt;code&gt;AxiosError&lt;/code&gt;. Both function definition and use of the function should be aware of this danger.&lt;/p&gt;

&lt;p&gt;Let's create a more type-safe and robust system, without escaping to “as” or “any”!&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, I want to introduce a little more about GROWI, an open software developed by us &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Use_Self-Made_Type_Guard_with_TypeScript_is_Operator" rel="noopener noreferrer"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Use_Self-Made_Type_Guard_with_TypeScript_is_Operator" rel="noopener noreferrer"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>programming</category>
      <category>node</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Rails: Switches Serializer according to STI Type</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Tue, 28 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/rails-switches-serializer-according-to-sti-type-4pc7</link>
      <guid>https://forem.com/weseek-inc/rails-switches-serializer-according-to-sti-type-4pc7</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, here is Tamura.&lt;/p&gt;

&lt;p&gt;Suppose you have model data of multiple types using STI and want to mix and return them in a single API endpoint. In this case, you would like to switch the serializer according to the STI type.&lt;/p&gt;

&lt;p&gt;In this article, I will show you how to do this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Issue
&lt;/h2&gt;

&lt;p&gt;Suppose the following class hierarchy is realized in STI&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1atef26vj3kexvvww3m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd1atef26vj3kexvvww3m.png" alt="class hierarchy" width="800" height="470"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;SimplePosts has a &lt;code&gt;title&lt;/code&gt; and &lt;code&gt;body&lt;/code&gt; field, and QAPosts has a &lt;code&gt;question&lt;/code&gt; and &lt;code&gt;answer&lt;/code&gt; field. They all have a common &lt;code&gt;posted_at&lt;/code&gt; field.&lt;/p&gt;

&lt;p&gt;Suppose you define an API endpoint called &lt;code&gt;/api/v1/posts&lt;/code&gt; and want to return JSON as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i6d5im346krq9eo0qzc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6i6d5im346krq9eo0qzc.png" alt="return JSON" width="800" height="769"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Depending on whether the Posts type is &lt;code&gt;SimplePost&lt;/code&gt; or &lt;code&gt;QAPost&lt;/code&gt;, the JSON keys will differ.&lt;/p&gt;

&lt;p&gt;If you are using ActiveModel::Serializers to output JSON, you will need to switch the Serializer depending on the type of Posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;The code is shown below.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app/serializers/post_serializer.rb&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg14q3vc88pbozdvdlz0o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg14q3vc88pbozdvdlz0o.png" alt="post_serializer" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app/serializers/simple_post_serializer.rb&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuciktzassr8hrblna11.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuciktzassr8hrblna11.png" alt="simple_post_serializer" width="800" height="82"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app/serializers/qa_post_serializer.rb&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fno6vef0wvzvpxa2tn9ag.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fno6vef0wvzvpxa2tn9ag.png" alt="qa_post_serializer" width="800" height="83"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;app/controllers/api/v1/posts_controller.rb&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lrlol2bqtumqrsu4156.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2lrlol2bqtumqrsu4156.png" alt="posts_controller" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Override the &lt;code&gt;attributes&lt;/code&gt; method in PostSerializer. Since each data is taken as an &lt;code&gt;object&lt;/code&gt;, the class is determined in case, and &lt;code&gt;SimplePostSerializer.new(object).attributes(nil, reload)&lt;/code&gt; and &lt;code&gt;QAPostSerializer.new(object).attributes( nil, reload)&lt;/code&gt; generates attributes and merges them into &lt;code&gt;@attributes&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reference&lt;/strong&gt;: &lt;a href="https://github.com/rails-api/active_model_serializers/blob/0fbe0fad0dec9368e9335b6280a46ca13442727e/lib/active_model/serializer.rb#L334-L343"&gt;https://github.com/rails-api/active_model_serializers/blob/0fbe0fad0dec9368e9335b6280a46ca13442727e/lib/active_model/serializer.rb#L334-L343&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The reason for overriding the &lt;code&gt;json_key&lt;/code&gt; method is to display &lt;code&gt;posts&lt;/code&gt; in the json toplevel object. If this is not defined, &lt;code&gt;qa_posts&lt;/code&gt; and the type first processed by the Serializer will be set as the key, as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4yw8nofhixm5gf7ec8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn4yw8nofhixm5gf7ec8l.png" alt="set as the key" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that if &lt;code&gt;jsonapi_include_toplevel_object&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;, there is no need to override the &lt;code&gt;json_key&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reference&lt;/strong&gt;: &lt;a href="https://github.com/rails-api/active_model_serializers/blob/0fbe0fad0dec9368e9335b6280a46ca13442727e/lib/active_model/serializer.rb#L384-L392"&gt;https://github.com/rails-api/active_model_serializers/blob/0fbe0fad0dec9368e9335b6280a46ca13442727e/lib/active_model/serializer.rb#L384-L392&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, I want to introduce a little more about GROWI, an open software developed by us &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Rails_Switches_Serializer_according_to_STI_Type"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Rails_Switches_Serializer_according_to_STI_Type"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to Target XHR Errors in Cypress</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Thu, 23 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/how-to-target-xhr-errors-in-cypress-59cl</link>
      <guid>https://forem.com/weseek-inc/how-to-target-xhr-errors-in-cypress-59cl</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, I am &lt;a href="https://github.com/miya" rel="noopener noreferrer"&gt;Miyazawa&lt;/a&gt;, an engineer at WESEEK, Inc. I usually develop &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=How_to_Target_XHR_Errors_in_Cypress" rel="noopener noreferrer"&gt;GROWI&lt;/a&gt;, an &lt;strong&gt;open-source wiki&lt;/strong&gt;. Today, I will explain how to deal with XHR errors that occur in &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt;, which is used for visual regression testing of GROWI.&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Details
&lt;/h2&gt;

&lt;p&gt;The error content introduced here is circled in red below. The screenshot shows the actual GROWI login screen.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc2bx84u4ve0ul4j6n1s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkc2bx84u4ve0ul4j6n1s.png" alt="Error"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The actual Cypress code in which the error occurred is shown below. Specifically, it is a Cypress &lt;a href="https://docs.cypress.io/api/cypress-api/custom-commands" rel="noopener noreferrer"&gt;custom command&lt;/a&gt; to log in by going to &lt;code&gt;/login&lt;/code&gt;, entering the user name and password registered in advance, and pressing the login button. You can code as &lt;code&gt;cy.login(username, password)&lt;/code&gt; to use it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3m9eh57mh4gctvm2rgn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3m9eh57mh4gctvm2rgn4.png" alt="Error2"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Error Cause
&lt;/h2&gt;

&lt;p&gt;I believe that the cause is that the user's session data was not saved properly in the browser by trying to move to a page that requires login without waiting for the &lt;code&gt;/api/v3/login&lt;/code&gt; response that runs when the login button is pressed.&lt;/p&gt;

&lt;p&gt;As a test, after pressing the login button (&lt;code&gt;cy.get('.btnSubmitForLogin').click()&lt;/code&gt;), I added &lt;code&gt;cy.wait(10000)&lt;/code&gt;, and the login process was successfully performed without any XHR errors.&lt;/p&gt;

&lt;p&gt;From the above, I realized that waiting for the response from &lt;code&gt;/api/v3/login&lt;/code&gt; seems to be a good idea, so I will modify the code accordingly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Cypress has an API called &lt;a href="https://docs.cypress.io/api/commands/intercept" rel="noopener noreferrer"&gt;intercept&lt;/a&gt;. This API allows spying and stubbing on HTTP requests made within an application.&lt;/p&gt;

&lt;p&gt;Since I only need to spy in this case, the code refers to the documentation. The first argument is the method name and the second argument is the URL. You can create an alias using &lt;code&gt;as&lt;/code&gt;.If you put the alias you created into &lt;code&gt;cy.wait&lt;/code&gt;, it will wait for &lt;code&gt;/api/v3/login&lt;/code&gt; to complete.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8yn7s2fn9zlt5ilbhjas.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8yn7s2fn9zlt5ilbhjas.png" alt="Solution1"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I put the above code into the custom command causing the error and it worked correctly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7lefm0yt8st0cwbkvnm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu7lefm0yt8st0cwbkvnm.png" alt="Solution2"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, I want to introduce a little more about GROWI, an open software developed by us &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=How_to_Target_XHR_Errors_in_Cypress" rel="noopener noreferrer"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=How_to_Target_XHR_Errors_in_Cypress" rel="noopener noreferrer"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cypress</category>
      <category>xhr</category>
      <category>programming</category>
    </item>
    <item>
      <title>Tips on Handling Hash Keys in Rails</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Tue, 21 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/tips-on-handling-hash-keys-in-rails-3k64</link>
      <guid>https://forem.com/weseek-inc/tips-on-handling-hash-keys-in-rails-3k64</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello everyone, this is Kota.&lt;br&gt;
I use Rails in my daily work, and I would like to briefly share something I learned about hash keys that I handled the other day!&lt;/p&gt;




&lt;h2&gt;
  
  
  Trouble
&lt;/h2&gt;

&lt;p&gt;What I did was obtain the data from the model, put the variable into it, and hashed the variable using the attributes method.&lt;br&gt;
However, when accessing the hashed variable with &lt;code&gt;user[:name]&lt;/code&gt; to obtain the value of &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;nil&lt;/code&gt; was outputed and the value could not be obtained.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9ejm2cb90cebl621fob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx9ejm2cb90cebl621fob.png" alt="Trouble" width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Investigation
&lt;/h2&gt;

&lt;p&gt;As mentioned earlier, the return value when using the attributes method on the data obtained from the model was as follows. That's the time I noticed that &lt;strong&gt;the key is a string&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8iky3p3tc1glzbs13qlk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8iky3p3tc1glzbs13qlk.png" alt="Investigation1" width="800" height="131"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is something obvious, but I realized again that the value can only be obtained by accessing it in the same format in which it is defined.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fim5u1jzrg2xbyhb4fyso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fim5u1jzrg2xbyhb4fyso.png" alt="Investigation2" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was a little bit stuck from there because I often used symbols instead of strings to get the value of params, etc.&lt;/p&gt;




&lt;h2&gt;
  
  
  Further Research &amp;amp; Methodology
&lt;/h2&gt;

&lt;p&gt;I took the opportunity to do a little more research on hash and compiled a list of methods that could be used when you are facing similar issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Convert key from string to symbol
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;symbolize_keys&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Methods provided by Rails. Internally, it uses ruby's &lt;strong&gt;transform_keys(&amp;amp;:to_sym)&lt;/strong&gt; method.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Reference: &lt;a href="https://api.rubyonrails.org/classes/Hash.html#method-i-symbolize_keys"&gt;&lt;/a&gt;&lt;a href="https://api.rubyonrails.org/classes/Hash.html#method-i-symbolize_keys"&gt;https://api.rubyonrails.org/classes/Hash.html#method-i-symbolize_keys&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiy7rxnwt060irj11s29.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmiy7rxnwt060irj11s29.png" alt="symbolize_keys" width="800" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Convert key from symbol to string
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;stringify_keys&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Methods provided by Rails. Internally, it uses ruby's &lt;strong&gt;transform_keys(&amp;amp;:to_s)&lt;/strong&gt; method.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Reference: &lt;a href="https://api.rubyonrails.org/classes/Hash.html#method-i-stringify_keys"&gt;&lt;/a&gt;&lt;a href="https://api.rubyonrails.org/classes/Hash.html#method-i-stringify_keys"&gt;https://api.rubyonrails.org/classes/Hash.html#method-i-stringify_keys&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszszxyanq0x92duxmdub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fszszxyanq0x92duxmdub.png" alt="stringify_keys" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. If you also want to convert hash-nesting
&lt;/h3&gt;

&lt;p&gt;One caveat to the above two methods is that if there are nests within the hash, they will not be converted.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F441bt1akfy4xveinjlb0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F441bt1akfy4xveinjlb0.png" alt="convert hash nesting1" width="800" height="318"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to convert nests as well, you can use &lt;strong&gt;&lt;code&gt;deep_symbolize_keys&lt;/code&gt;&lt;/strong&gt; (&lt;code&gt;deep_stringify_keys&lt;/code&gt;) to do so.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0nprq9dx8m4piomxfbv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa0nprq9dx8m4piomxfbv.png" alt="convert hash nesting2" width="800" height="151"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;PS:The method &lt;code&gt;transform_keys&lt;/code&gt; of ruby is also &lt;code&gt;deep_transform_keys&lt;/code&gt;, which can transform nests.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. If you want to get both symbol &amp;amp; string
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;with_indifferent_access&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check the class of the variable &lt;code&gt;user&lt;/code&gt; that was used earlier.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdso70the5ehx2x73uqm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftdso70the5ehx2x73uqm.png" alt="with_indifferent_access1" width="800" height="61"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let's change the class to &lt;code&gt;ActiveSupport::HashWithIndifferentAccess&lt;/code&gt; using the method &lt;code&gt;with_indifferent_access&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reference:
&lt;a href="https://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html"&gt;https://api.rubyonrails.org/classes/ActiveSupport/HashWithIndifferentAccess.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6svglcp38o5edpkh14ni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6svglcp38o5edpkh14ni.png" alt="with_indifferent_access2" width="800" height="152"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Try to get values in both strings and symbols.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcow74khxw9zt8fuxhnl2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcow74khxw9zt8fuxhnl2.png" alt="with_indifferent_access3" width="800" height="111"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you can retrieve the value as both a string and a symbol.&lt;br&gt;
Params also extend this &lt;code&gt;ActiveSupport::HashWithIndifferentAccess&lt;/code&gt; class and can retrieve values as both strings and symbols.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this article, I briefly summarized the handling of hash keys and related methods used in Rails.&lt;br&gt;
There are many useful methods related to hash, so please check them out yourself.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, I want to introduce a little more about GROWI, an open software developed by us &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Tips_on_Handling_Hash_Keys_in_Rails"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Tips_on_Handling_Hash_Keys_in_Rails"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rails</category>
      <category>programming</category>
      <category>ruby</category>
    </item>
    <item>
      <title>Let's Use the Brower Developer Tools!</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Thu, 16 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/lets-use-the-brower-developer-tools-1844</link>
      <guid>https://forem.com/weseek-inc/lets-use-the-brower-developer-tools-1844</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Browser developer tools are essential tools in web development.&lt;/p&gt;

&lt;p&gt;Good use of developer tools can help you debug your website, optimize performance, improve accessibility, and more.&lt;/p&gt;

&lt;p&gt;This article describes the basic usage of browser developer tools and various techniques.&lt;/p&gt;




&lt;h2&gt;
  
  
  What are Developer Tools?
&lt;/h2&gt;

&lt;p&gt;Developer tools are tools that provide useful functions such as debugging websites, optimizing performance, and improving accessibility.&lt;/p&gt;

&lt;p&gt;Major browsers (Google Chrome, Mozilla Firefox, Microsoft Edge, etc.) come standard with developer tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to Open Major Browsers
&lt;/h3&gt;

&lt;p&gt;In common with all major browsers, you can open the developer tools by pressing the &lt;strong&gt;“F12” key&lt;/strong&gt; or &lt;strong&gt;Ctrl + Shift + I&lt;/strong&gt; (&lt;strong&gt;Command + Option + I&lt;/strong&gt; for MacOS).&lt;/p&gt;

&lt;p&gt;Here is a Google Chrome Example with MacOS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczicmksi65te6vi2bvdd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczicmksi65te6vi2bvdd.png" alt="GOOGLE CHROME" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Element Tab
&lt;/h2&gt;

&lt;h3&gt;
  
  
  View &amp;amp; Edit Elements
&lt;/h3&gt;

&lt;p&gt;The elements tab can view and edit the HTML and CSS of a website.&lt;/p&gt;

&lt;p&gt;This tab allows you to see the structure and style of your web pages.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwouky6iyucqkbfnn156h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwouky6iyucqkbfnn156h.png" alt="the structure and style" width="800" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By double-clicking on an HTML element displayed in the upper right corner, you can freely edit the element itself, its contents, classes, attributes, etc.&lt;/p&gt;

&lt;p&gt;The styles section below allows you to edit CSS styles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyv2cpxrs9hx1u0a28bj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyv2cpxrs9hx1u0a28bj.png" alt="CSS styles" width="800" height="245"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The computed tab within the elements tab allows you to see the actual CSS property values applied to the selected element.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbll4i71dk66cjd9w25in.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbll4i71dk66cjd9w25in.png" alt="CSS property values" width="800" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Inspect Mode
&lt;/h3&gt;

&lt;p&gt;You can activate inspect mode by pressing the button in the top left corner of the developer tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5lmviz4qfaiqvi27tcz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5lmviz4qfaiqvi27tcz.png" alt="Inspect Mode" width="734" height="172"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After activating inspect mode, move the mouse cursor and click on the element you want to select on the web page, and the selected element will appear on the elements tab, where you can see how the element is marked up in HTML.&lt;/p&gt;




&lt;h2&gt;
  
  
  Console Tab
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JS Code Execution
&lt;/h3&gt;

&lt;p&gt;Entering JavaScript code on the console tab and pressing the Enter key executes the JavaScript code and allows you to view the results of the execution.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9znm1jnrmqbdmgusrxi9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9znm1jnrmqbdmgusrxi9.png" alt="JS Code" width="800" height="241"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Message Display
&lt;/h3&gt;

&lt;p&gt;The console tab displays errors, warnings, and other messages on the web page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F716pjff3rntrjdvsk6lt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F716pjff3rntrjdvsk6lt.png" alt="error" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If an error occurs, the number of lines and file names of the script in which the error occurred are also displayed along with the error message, which is useful for debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  Sources Tab
&lt;/h2&gt;

&lt;h3&gt;
  
  
  View and Edit Source Code
&lt;/h3&gt;

&lt;p&gt;The Source tab allows you to view the HTML, CSS, JavaScript, and other source code of a web page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnz5hma3jcyviivnmrbby.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnz5hma3jcyviivnmrbby.png" alt="View and Edit Source Code" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The source code is displayed as a folder hierarchy, and each file can be expanded to see its contents.&lt;/p&gt;

&lt;p&gt;You can also search the code using the search window.&lt;/p&gt;

&lt;p&gt;Or you can directly edit the source code, including HTML, CSS, and JavaScript.Use the editor to edit and save the code so that changes are immediately reflected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Breakpoint Setting
&lt;/h3&gt;

&lt;p&gt;In the source tab, you can set breakpoints.&lt;/p&gt;

&lt;p&gt;Breakpoints are used to pause JavaScript execution for debugging.&lt;/p&gt;

&lt;p&gt;By clicking on any number of lines in the source code, you can set a breakpoint at that point.&lt;/p&gt;

&lt;p&gt;After setting a breakpoint, reload the screen and execute the file, JavaScript execution will stop at the location where the breakpoint was set, and you can check the contents of variables and the screen status at that time.&lt;/p&gt;

&lt;p&gt;You can check the contents of variables in the scope panel on the right or by hovering the mouse over a variable in the source code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0af8w82g2ha8f1prkij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw0af8w82g2ha8f1prkij.png" alt="Breakpoint Setting" width="800" height="451"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Network Tab
&lt;/h2&gt;

&lt;p&gt;The network tab displays detailed information about all network requests issued by the web page.&lt;/p&gt;

&lt;p&gt;You can see basic information such as the request URL, method, and HTTP status code, as well as detailed information such as the request header and response body.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4n8nfupi3ipjsmzy7t1j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4n8nfupi3ipjsmzy7t1j.png" alt="Network Tab" width="800" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use the Timeline
&lt;/h3&gt;

&lt;p&gt;The network tab displays a timeline of network requests and their responses.&lt;/p&gt;

&lt;p&gt;The timeline visually displays information such as web page loads, request processing times, resource downloads, etc.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnzmun61sviwby5x362i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnzmun61sviwby5x362i.png" alt="Timeline" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each request is represented as a horizontal bar.&lt;/p&gt;

&lt;p&gt;The position and length of the bar represent the time from issuing the request to receiving the response or processing time, and its color and shape vary depending on the type and status of the request.&lt;/p&gt;




&lt;h2&gt;
  
  
  Application Tab
&lt;/h2&gt;

&lt;p&gt;The application tab allows you to manage and manipulate various resources and storage information provided by the browser, such as local storage for web applications, session storage, cookies, and service workers.&lt;/p&gt;

&lt;p&gt;By clicking on an item in Storage, you can see the key, value, etc. of the data stored in that storage.&lt;/p&gt;

&lt;p&gt;You can also add, delete, and edit data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsu9gy7mtji1mjnfgwj2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsu9gy7mtji1mjnfgwj2h.png" alt="Application Tab" width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Other Functions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Change Display Device
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlb0pbaa2lv6gcvbmkcs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjlb0pbaa2lv6gcvbmkcs.png" alt="Display Device" width="791" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By clicking on the device icon in the upper left corner of the developer tools, you can switch to a different device view of the web page and preview it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpqsl2gckjhd4l59o0rk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnpqsl2gckjhd4l59o0rk.png" alt="switch view" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The device toolbar contains presets for various devices. Clicking on the drop-down menu on the left side will display a list of available devices.&lt;/p&gt;

&lt;p&gt;Selecting a device from the list will change the display of the web page to match the size and resolution of the selected device.&lt;/p&gt;

&lt;p&gt;Instead of selecting a device, you can also preview the page by specifying the horizontal and vertical sizes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Full-Size Screenshot
&lt;/h3&gt;

&lt;p&gt;In the Developer Tools, you can take a full-size screenshot of the screen.&lt;/p&gt;

&lt;p&gt;To do this, as before, click on the device icon in the upper left corner of the developer tools to display the device toolbar.&lt;/p&gt;

&lt;p&gt;Then select “Capture Full-Size Screenshot” from the three dots to take a full-size screenshot.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxis6pzi4y7qu0jnnh390.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxis6pzi4y7qu0jnnh390.png" alt="Full-Size Screenshot" width="800" height="348"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Useful Extensions for Development
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://chrome.google.com/webstore/detail/rester/eejfoncpjfgmeleakejdcanedmefagga"&gt;RESTer&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;RESTer is a Google Chrome extension that allows you to perform HTTP requests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth4zmmul18lghbjyeat9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fth4zmmul18lghbjyeat9.png" alt="RESTer" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;HTTP requests can be sent in the browser by specifying parameters such as URL, method (GET, POST, PUT, DELETE, etc.), header, and body.&lt;/p&gt;

&lt;p&gt;The RESTer stores a history of previous requests, which can be reviewed at a later time or partially modified and sent again.&lt;/p&gt;

&lt;p&gt;Furthermore, by defining endpoint URLs and other parameters as environment variables, URLs can be easily switched between different environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzzhka9lmdyygk3m0bz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxzzhka9lmdyygk3m0bz1.png" alt="URLs change environments " width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We have found that using developer tools can help in many ways, such as reviewing and editing page elements, executing JavaScript code, and monitoring the network.&lt;/p&gt;

&lt;p&gt;Developer tools are essential for efficient development and debugging for web developers.&lt;/p&gt;

&lt;p&gt;We encourage you to learn these features and become proficient in using the developer tools.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, we want to introduce a little more about GROWI, an open software developed by &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Let%27s_Use_the_Brower_Developer_Tools"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Let%27s_Use_the_Brower_Developer_Tools"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>tutorial</category>
      <category>webdev</category>
      <category>programming</category>
    </item>
    <item>
      <title>Quickly Trace and Understand The Key Concepts of VictoriaMetrics</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Tue, 14 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/quickly-trace-and-understand-the-key-concepts-of-victoriametrics-4ldd</link>
      <guid>https://forem.com/weseek-inc/quickly-trace-and-understand-the-key-concepts-of-victoriametrics-4ldd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi, I am Kouki, a system engineer from &lt;strong&gt;WESEEK, Inc.&lt;/strong&gt; in Japan.&lt;/p&gt;

&lt;p&gt;This article is a hands-on summary of the “Key Concepts — VictoriaMetrics” from the VictoriaMetrics documentation. My motivation for writing the article is as follows.&lt;/p&gt;

&lt;p&gt;First, I couldn’t find any tutorials on the web where I could register my data and query by myself. Also, “Key Concepts — VictoriaMetrics” is easy to understand, with explanations and images, but it took some trials and errors to try on my own.&lt;/p&gt;

&lt;p&gt;*Key Concepts explains the behavior of VictoriaMetrics with images like the one below, so I think it is a beneficial document for understanding.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxqraen4ke16e9yfjep4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyxqraen4ke16e9yfjep4.png" alt="Overall" width="800" height="775"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Try to Touch Key Concepts
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Preparation
&lt;/h3&gt;

&lt;p&gt;For this tutorial, I will assume that you have already established the following environment.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You should be able to type docker commands (docker run … etc.)&lt;/li&gt;
&lt;li&gt;You should have curl commands installed.&lt;/li&gt;
&lt;li&gt;(optional*) jq command is installed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Launch VictoriaMetrics with docker command
&lt;/h3&gt;

&lt;p&gt;Use &lt;a href="https://docs.victoriametrics.com/quick-start/#starting-vm-single-via-docker"&gt;Quick start — VictoriaMetrics&lt;/a&gt; as reference &amp;amp; add &lt;code&gt;-retentionPeriod=100y&lt;/code&gt; option to start up VictoriaMetrics.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffge4ymbjfhge6euyk5jg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffge4ymbjfhge6euyk5jg.png" alt="Start up VictoriaMetrics" width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The docker image tag is v1.85.3. in this case (Because there is a possibility of discrepancy with the article if it is &lt;code&gt;latest&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;The command option &lt;code&gt;-retentionPeriod&lt;/code&gt; specifies the retention period of the data, as described in the &lt;a href="https://docs.victoriametrics.com/?highlight=retentionPeriod#operation"&gt;VictoriaMetrics documentation&lt;/a&gt;. The default is 1 month (after which the data will be deleted), but in this tutorial, we plan to register data older than 1 month, so we specify &lt;code&gt;100y&lt;/code&gt; as a higher value.&lt;/p&gt;

&lt;p&gt;The VictoriaMetrics README also states that the retention period cannot be set to “infinite” and should be set to &lt;code&gt;100y&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqrv0hsfxklxrk3zoy6v1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqrv0hsfxklxrk3zoy6v1.png" alt="VictoriaMetrics README" width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6xecd3r6jj7pfvdj598.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6xecd3r6jj7pfvdj598.png" alt="Single-note VictoriaMetrics" width="800" height="476"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Register your data with VictoriaMetrics
&lt;/h3&gt;

&lt;p&gt;Register the data in the “Query data” section of &lt;a href="https://docs.victoriametrics.com/keyconcepts/#query-data"&gt;Key Concepts — VictoriaMetrics&lt;/a&gt; with VictoriaMetrics.&lt;/p&gt;

&lt;p&gt;The document describes the following data. From left to right, “Metrics Name”, “Data Value”, and “Time Stamp (Unix Time Stamp (milliseconds)”.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;2022-05–10 10:00:00&lt;/code&gt; is listed as a comment, but when checked in UTC, it is &lt;code&gt;2022-05–10 08:00:00&lt;/code&gt; (minus 2 hours). Commands from here on will be based on the time minus 2 hours from the time listed in the official document.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhr7e7hc0l3gruvep1ls.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjhr7e7hc0l3gruvep1ls.png" alt="Register data against the /api/v1/importendpoint with the curl command." width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Register data against the &lt;code&gt;/api/v1/import&lt;/code&gt; endpoint with the curl command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo03ceifzbv6b96jlrnyb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo03ceifzbv6b96jlrnyb.png" alt="curl command" width="800" height="37"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I have prepared and implemented a simple ruby script that outputs a string of curl commands from space-delimited text. Since this script only outputs the above curl command, it is not very important and can be skipped.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fftus4e7kjbu946qehv9o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fftus4e7kjbu946qehv9o.png" alt="simple ruby" width="800" height="876"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Confirm whether the data has been registered
&lt;/h3&gt;

&lt;p&gt;Let’s check if the data has been registered by the curl command described above. The time of the first data is set to &lt;code&gt;2022–05-10T08:00:00.000Z&lt;/code&gt; because the time is minus two hours, as described in “Notes”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06c0h1l1d966gx5f82vx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F06c0h1l1d966gx5f82vx.png" alt="Check" width="800" height="456"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Trace Query data in Key concepts
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Instant query&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s start with the &lt;a href="https://docs.victoriametrics.com/keyconcepts/#query-data"&gt;Query data in Key concepts&lt;/a&gt;. It is recommended to open the Query data page of Key concepts in advance for smooth reading.&lt;/p&gt;

&lt;p&gt;First, let’s try Instant query. Let’s try to throw a query at the time minus 2 hours.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgtq1d3m870jygjnwkxx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgtq1d3m870jygjnwkxx.png" alt="Instant query" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The key point here is that “the value &lt;code&gt;3&lt;/code&gt; was responded to even though there is no data for &lt;code&gt;2022-05–10T08:03:00.00&lt;/code&gt; in the registered data”. (In the original data, between &lt;code&gt;#2022–05–10 10:02:00&lt;/code&gt; and &lt;code&gt;#2022–05–10 10:04:00&lt;/code&gt;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5po6tcenjxk9winnh7s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr5po6tcenjxk9winnh7s.png" alt="Instant query1" width="800" height="683"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please read the &lt;a href="https://docs.victoriametrics.com/keyconcepts/#instant-query"&gt;official description&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Range query&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Next, Let’s try the Range query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin0ro745ra9afs4568xd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fin0ro745ra9afs4568xd.png" alt="Range query" width="800" height="719"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see that the intended value is returned.&lt;/p&gt;

&lt;p&gt;Again, a point to note is that the JSON response listed in the &lt;a href="https://docs.victoriametrics.com/keyconcepts/#range-query"&gt;Range query&lt;/a&gt; includes the number &lt;code&gt;7&lt;/code&gt;, but &lt;code&gt;5&lt;/code&gt; is probably the correct value here.&lt;/p&gt;

&lt;p&gt;The explanatory text also includes a figure as shown below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felaokq0xk6knpaoxxk7j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Felaokq0xk6knpaoxxk7j.png" alt="Range query1" width="800" height="790"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxnsmbmqzlgio5xlyplj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxnsmbmqzlgio5xlyplj.png" alt="explanation" width="800" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Check the shape of the graph in VM UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;VictoriaMetrics has a WebUI called VM UI that allows you to throw queries and see the results. &lt;/p&gt;

&lt;p&gt;Let’s check if the graph looks like the one shown in the image above.&lt;/p&gt;

&lt;p&gt;When the screen appears, check the “Trace query” checkbox, change the “Step value” to &lt;code&gt;60&lt;/code&gt; seconds (1 minute) to align the condition with the document image, and press the “EXECUTE QUERY” button to execute the query.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvdzar8rj7mrimdz7jh0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgvdzar8rj7mrimdz7jh0.png" alt="Check the shape" width="800" height="636"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can confirm that the “Range query” is as shown in the image.&lt;/p&gt;

&lt;p&gt;If you would like to touch the VM UI yourself, you can do the same by clicking the button in the upper right corner of the screen that says “LAST 30 MINUTES” by default, specifying the time, and following the above procedure (setting Step Value and Trace Query).&lt;/p&gt;

&lt;p&gt;Note that the query is based on the time zone of the browser you are using, so if your time zone is JST, set the query to plus 9 hours.&lt;/p&gt;

&lt;p&gt;In the Range Query specified in curl above, it is &lt;code&gt;2022-05–10T07:59:00.000Z&lt;/code&gt;~ &lt;code&gt;2022-05–10T08:17:00.000Z&lt;/code&gt;, so in JST it is &lt;code&gt;2022-05–10 16:59:00&lt;/code&gt; ~ &lt;code&gt;2022-05–10 17:17:00&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Although I have cut out much of the explanations for each chapter of the document, we hope that through this article we have created an environment in which you can practically try VictoriaMetrics.&lt;/p&gt;

&lt;p&gt;I would like to close with a list of interesting things that you can try.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Change “step=1m” to “step=1s” in “Range query” and count the number of data returned by jq (officially stated to be about 1000, but it is about 800).&lt;/li&gt;
&lt;li&gt;Change the command line options passed to VictoriaMetrics, looking at the documentation.&lt;/li&gt;
&lt;li&gt;Set retention period back to default and try to register the data in this article (You probably can’t register the data, but you may want to look at the docker logs to see if it works).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope this article helps you to better understand VictoriaMetrics.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, we want to introduce a little more about GROWI, an open software developed by &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Quickly_Trace_and_Understand_The_Key_Concepts_of_VictoriaMetrics"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Quickly_Trace_and_Understand_The_Key_Concepts_of_VictoriaMetrics"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>victoriametrics</category>
      <category>programming</category>
      <category>infastructure</category>
    </item>
    <item>
      <title>A Quick Guide for GraphQL</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Thu, 09 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/a-quick-guide-for-graphql-1569</link>
      <guid>https://forem.com/weseek-inc/a-quick-guide-for-graphql-1569</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi, I am Kota, a system engineer from WESEEK, Inc. in Japan.&lt;/p&gt;

&lt;p&gt;This time, I have decided to write a blog about my introduction to GraphQL, which I had not yet touched.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is GraphQL?
&lt;/h2&gt;

&lt;p&gt;GraphQL is a query language for APIs and a runtime for building data-driven applications, developed by Facebook and released as open-source in 2015.&lt;/p&gt;

&lt;p&gt;It allows clients to specify the data they need, unlike REST APIs that query endpoints, thus optimizing network usage and improving performance. It also eliminates API versioning issues and allows for API and front-end development decoupling.&lt;/p&gt;




&lt;h2&gt;
  
  
  Technology Before GraphQL Appeared
&lt;/h2&gt;

&lt;p&gt;Before the advent of GraphQL, the predominant way of exchanging data in web applications was through RESTful APIs, which strictly followed the HTTP protocol and used endpoints to access resources.&lt;/p&gt;

&lt;p&gt;However, this RESTful approach had &lt;strong&gt;several problems&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first is the problem of “overfetching” and “underfetching”&lt;/strong&gt;. “Overfetching” means that the client gets more data than it needs, which consumes unnecessary network and computational resources, while “underfetching” means that the client gets more data than it needs, which consumes unnecessary network and computational resources. On the other hand, “underfetching” refers to the fact that the client cannot get all the data it needs at once and must make multiple requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The second is endpoint complexity&lt;/strong&gt;, which requires independent endpoints for each resource, so as the API grows, the number of endpoints increases and becomes more difficult to manage. In addition, multiple requests are required to retrieve data from multiple endpoints.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third is the versioning problem&lt;/strong&gt;, which makes API versioning difficult because a new version of the endpoint must be created each time the format or structure of the data changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The fourth implies a strong coupling between the client and server&lt;/strong&gt; since the endpoint design is highly dependent on the data structure needed by the client. This problem makes it difficult to have front-end and back-end development going at the same time.&lt;/p&gt;

&lt;p&gt;These problems were greatly improved with the advent of GraphQL. Specifically, GraphQL allows a single endpoint to retrieve multiple resources, eliminating the need for versioning and allowing for client and server decoupling.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Has Changed With GraphQL?
&lt;/h2&gt;

&lt;p&gt;With the advent of GraphQL, the above problems were greatly alleviated. This is because GraphQL provides the client with precision in identifying and retrieving data.&lt;/p&gt;

&lt;p&gt;Specifically, GraphQL gives clients the ability to specify which fields to retrieve, thereby ensuring that only the required data is retrieved accurately. This improves network utilization and avoids wasting resources by fetching unnecessary data.&lt;/p&gt;

&lt;p&gt;In addition, because GraphQL functions as a query language, it is now possible to retrieve complex data and refine the data. These elements are critical to the flexibility and performance of the API.&lt;/p&gt;




&lt;h2&gt;
  
  
  GraphQL vs REST
&lt;/h2&gt;

&lt;p&gt;REST and GraphQL are both technologies for building APIs but with the following differences.&lt;/p&gt;

&lt;p&gt;First, REST returns a fixed data structure for each endpoint. While this is simple and easy to understand, it is prone to the aforementioned “overfetching” and “underfetching” problems.&lt;/p&gt;

&lt;p&gt;In contrast, GraphQL allows clients to freely specify the data they need, thus avoiding unnecessary data fetching. This leads to efficient network utilization and high performance.&lt;/p&gt;

&lt;p&gt;Furthermore, with REST, if data needs to be retrieved across multiple endpoints, multiple requests must be made. GraphQL, on the other hand, allows multiple resources to be retrieved with a single request. This greatly reduces the number of requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Code Comparison
&lt;/h3&gt;

&lt;p&gt;To understand the difference between GraphQL and REST APIs, let’s compare their respective requests and responses using a simple example.&lt;/p&gt;

&lt;p&gt;For example, let’s say we want to retrieve information about a user and the title of a blog post by that user. Let’s see how each API style does this.&lt;/p&gt;

&lt;h4&gt;
  
  
  REST API
&lt;/h4&gt;

&lt;p&gt;In a REST API, there is usually a separate endpoint for each resource. You would first retrieve the user’s information, and then make separate requests to retrieve the user’s postings.&lt;/p&gt;

&lt;p&gt;The first request (to retrieve user information):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96gpgmfttxkhvusa6jb6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F96gpgmfttxkhvusa6jb6.png" alt="The first request" width="800" height="36"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6wcwumbliiyoiywl4tr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft6wcwumbliiyoiywl4tr.png" alt="Response1" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second request (to retrieve user posts):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nam22hx9s1zad7vah74.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3nam22hx9s1zad7vah74.png" alt="The second request" width="800" height="41"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp45idc9c75o0racwdd19.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp45idc9c75o0racwdd19.png" alt="Response2" width="800" height="299"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  GraphQL
&lt;/h4&gt;

&lt;p&gt;GraphQL, on the other hand, allows the client to retrieve all necessary information in a single request. The client can also specify the exact shape and amount of data needed. An example is shown below.&lt;/p&gt;

&lt;p&gt;Request:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sfnm94ro55qb399s6eb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6sfnm94ro55qb399s6eb.png" alt="Request3" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Response:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgosx2rxexnmt3psdxnhm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgosx2rxexnmt3psdxnhm.png" alt="Response3" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thus, GraphQL has the advantage that a single request can retrieve multiple related resources and the client can specify the exact data needed. In contrast, the REST API may require multiple requests and return data in a form and quantity defined on the server side.&lt;/p&gt;




&lt;h2&gt;
  
  
  GraphQL 3 Key Features
&lt;/h2&gt;

&lt;p&gt;The primary functions of GraphQL are queries, mutations, and subscriptions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Query
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;A query reads data.&lt;/strong&gt; The following is an example of a GraphQL query:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0eeepkgeid6vj9w6z4jp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0eeepkgeid6vj9w6z4jp.png" alt="Query" width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The query retrieves the name and email fields for a user whose id is 1. The query keyword is optional, but it is easy to read and understand if it is stated. user is the field name, and the id in this case represents an argument. By using arguments, you can retrieve specific users, posts, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutation
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mutation is the modification of data.&lt;/strong&gt; This includes creating, updating, and deleting data. The following is an example of a mutation:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4eqj28543zgao1o2ifr3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4eqj28543zgao1o2ifr3.png" alt="Mutation" width="800" height="180"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mutation creates a new user by calling the createUser function and providing the user’s name and email using the input argument. The function returns the id, name, and email of the newly created user. Mutations are used for operations that modify data, such as creating, updating, or deleting data, and always begin with the mutation keyword.&lt;/p&gt;

&lt;h3&gt;
  
  
  Subscription
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Subscriptions are real-time data updates.&lt;/strong&gt; The client is notified when a server-side event is triggered. The following is an example of a subscription:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famkusyxmzcwr8cfkm4gb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Famkusyxmzcwr8cfkm4gb.png" alt="Subscription" width="800" height="178"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Subscriptions are used to notify clients in real-time when a new user is created with its id, name, and email. Subscriptions are used to notify clients when a specific event occurs on the server, in this case the creation of a new user. Subscriptions begin with the subscription keyword.&lt;/p&gt;




&lt;h2&gt;
  
  
  About GraphQL Schema and Type System
&lt;/h2&gt;

&lt;p&gt;GraphQL provides a powerful type system to clearly define the shape and interaction of the data available through the API. This is known as a “schema”. A schema defines what data a client can retrieve from a server and how that data interacts with it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Type system
&lt;/h3&gt;

&lt;p&gt;The schema consists of “types” that represent objects with specific shapes and characteristics. Types range from simple scalar types (String, Int, Boolean, Float, ID) to more complex object, enumeration, interface, and union types. These are combined to form the overall picture of the data that the API represents.&lt;/p&gt;

&lt;p&gt;For example, imagine an API for a blogging system. In this system, the schema would probably have object types such as “user,” “post,” “comment,” and so on. Each type would have different fields, such as name and age (user), title and content (article), body (comment), etc. Here is the specific code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczt1u0h6owgxjw8pbm8z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fczt1u0h6owgxjw8pbm8z.png" alt="Type system" width="800" height="505"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These types can have scalar or other object types. In this example, the &lt;code&gt;posts&lt;/code&gt; field of type &lt;code&gt;User&lt;/code&gt; indicates that it has a list of type &lt;code&gt;Post&lt;/code&gt;, and vice versa, the author field of type &lt;code&gt;Post&lt;/code&gt; indicates that it has a type &lt;code&gt;User&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In particular, we will discuss notations such as &lt;code&gt;[Post!]&lt;/code&gt; notation. This notation indicates an array of type &lt;code&gt;Post&lt;/code&gt;, but there are two &lt;code&gt;!&lt;/code&gt; has two different meanings.&lt;/p&gt;

&lt;p&gt;The first &lt;code&gt;!&lt;/code&gt; indicates that &lt;code&gt;Post&lt;/code&gt; objects are required (non-nullable). This means that if an array exists, all elements contained within it must be objects of type &lt;code&gt;Post&lt;/code&gt;, and null elements are not acceptable.&lt;/p&gt;

&lt;p&gt;The second &lt;code&gt;!&lt;/code&gt; indicates that the array itself is required (non-nullable). That is, the &lt;code&gt;posts&lt;/code&gt; field should always return an array of type &lt;code&gt;Post&lt;/code&gt;, and the array itself is not allowed to be null.&lt;/p&gt;

&lt;p&gt;Thus, &lt;code&gt;[Post!]&lt;/code&gt; means that the array itself must exist and that the contents of the array must consist of one or more objects of type &lt;code&gt;Post&lt;/code&gt;, which may never contain null. This allows the detailed definition of the type of each field and its null tolerance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Relationships
&lt;/h3&gt;

&lt;p&gt;In this way, the GraphQL schema also represents relationships between data. For example, a “user” can have multiple “articles” and each “article” can have multiple “comments”. These relationships are represented through fields of type Object. This relationship allows the client to select and retrieve only the data they need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema Definition Language (SDL)
&lt;/h3&gt;

&lt;p&gt;GraphQL schemas are written using a special syntax called Schema Definition Language (SDL). This SDL is a language for defining GraphQL data structures and can define various data types, such as the &lt;code&gt;User&lt;/code&gt;and &lt;code&gt;Post&lt;/code&gt; types described above.&lt;/p&gt;

&lt;p&gt;In a type definition, fields are defined in parentheses following the type name, and the type of the field is specified after each field. After the field name, a &lt;code&gt;!&lt;/code&gt; after the field name indicates that the field is required (not nullable). A &lt;code&gt;[]&lt;/code&gt; before the type name indicates an array of that type.&lt;/p&gt;

&lt;p&gt;In addition, the following special types exist in the schema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Query type&lt;/strong&gt;: This is the entry point for the query. Used by the client to read data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutation type&lt;/strong&gt;: handles data modification (creation, update, deletion). Used when the client modifies data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscription type&lt;/strong&gt;: monitors real-time updates. Used when the client tracks real-time changes to data.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These special types allow clients to request various operations from the server, such as data reading, modification, and real-time monitoring.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr670t2aicmmqfvffrqqw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr670t2aicmmqfvffrqqw.png" alt="3type" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above example, a &lt;code&gt;Query&lt;/code&gt; type is defined, with fields such as &lt;code&gt;users&lt;/code&gt;, &lt;code&gt;users&lt;/code&gt;, and &lt;code&gt;posts&lt;/code&gt;. Each of these fields returns a list of all users, users with a given ID, and all posts, respectively.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Mutation&lt;/code&gt; type, on the other hand, defines fields for creating new users and posts, named &lt;code&gt;createUser&lt;/code&gt; and &lt;code&gt;createPost&lt;/code&gt;, respectively, along with the necessary parameters. These operations allow the client to create new users and posts.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;Subscription&lt;/code&gt; type defines a field &lt;code&gt;postCreated&lt;/code&gt;to provide information in real-time when a new post is created. This allows clients to monitor the creation of new posts in real-time.&lt;/p&gt;

&lt;p&gt;These types and relationships allow the client to query exactly the data it needs and the server to validate the query and return accurate data. This demonstrates the power of GraphQL’s schema and type system.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, we want to introduce a little more about GROWI, an open software developed by &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=A_Quick_Guide_for_GraphQL"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=A_Quick_Guide_for_GraphQL"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Speech Recognition with Python &amp; CMU Sphinx</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Tue, 07 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/speech-recognition-with-python-cmu-sphinx-3djg</link>
      <guid>https://forem.com/weseek-inc/speech-recognition-with-python-cmu-sphinx-3djg</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hi, I am Masuyama, a software engineer from WESEEK, Inc. in Japan.&lt;/p&gt;

&lt;p&gt;In this blog, I will explain the simple way to build up speech recognition using Python and CMU Sphinx.&lt;/p&gt;




&lt;h2&gt;
  
  
  Source code
&lt;/h2&gt;

&lt;p&gt;The working code can be found at &lt;a href="https://github.com/hakumizuki/python_sphinx_sample"&gt;https://github.com/hakumizuki/python_sphinx_sample&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The explanation is based on this repository, so please git clone &lt;a href="https://github.com/hakumizuki/python_sphinx_sample"&gt;https://github.com/hakumizuki/python_sphinx_sample&lt;/a&gt; if you want actually to run the code on your hand.&lt;/p&gt;

&lt;p&gt;In the explanation, we will use devcontainer, but if you want to use external devices such as microphones, it may be easier to use an actual device rather than a container.&lt;/p&gt;




&lt;h2&gt;
  
  
  SpeechRecognition Library
&lt;/h2&gt;

&lt;p&gt;To work with CMU Sphinx in Python, we use the &lt;a href="https://pypi.org/project/SpeechRecognition/"&gt;SpeechRecognition library&lt;/a&gt;, which is responsible for the various speech recognition APIs.&lt;/p&gt;

&lt;p&gt;CMU Sphinx is an OSS speech recognition tool that, unlike the Google Cloud Speech API, works completely offline and does not require internet access. It can recognize speech in any language by providing a language model. For more information, click &lt;a href="https://cmusphinx.github.io/"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to try other methods, please refer to &lt;a href="https://pypi.org/project/SpeechRecognition/"&gt;this page&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Development Environment Building
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Install Docker&lt;/li&gt;
&lt;li&gt;Install VSCode&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ git clone https://github.com/hakumizuki/python_sphinx_sample&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cd ./python_sphinx_sample&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ code .&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Press [Ctrl+P or Command+P], type “Reopen in container” and click on the suggestion that comes up&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now the devcontainer has been started and the environment has been built. Let’s look at the program.&lt;/p&gt;




&lt;h2&gt;
  
  
  Program Description
&lt;/h2&gt;

&lt;p&gt;The main library used is &lt;a href="https://pypi.org/project/SpeechRecognition/"&gt;SpeechRecognition&lt;/a&gt;, a Python library for speech recognition.&lt;/p&gt;

&lt;p&gt;Constants such as file paths are written in &lt;strong&gt;constants.py&lt;/strong&gt;, and the speech recognition program is written in &lt;strong&gt;recognize.py&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/hakumizuki/python_sphinx_sample/blob/main/src/constants.py"&gt;constants.py&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61gu0sjgr0q1od84bl0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F61gu0sjgr0q1od84bl0c.png" alt="constants.py" width="800" height="157"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://github.com/hakumizuki/python_sphinx_sample/blob/main/src/recognize.py"&gt;recognize.py&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feidrtbq2kvpns1qb4mdu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feidrtbq2kvpns1qb4mdu.png" alt="recognize.py" width="800" height="834"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  *1
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;python recognize.py&amp;lt;mode&amp;gt;&lt;/code&gt; is assumed to be used, passing &lt;code&gt;mic&lt;/code&gt; as mode will use the audio coming in from the microphone as the audio source, and not passing anything will use the audio file in &lt;code&gt;WAV_OUT&lt;/code&gt; in &lt;strong&gt;constants.py&lt;/strong&gt; as the audio source.&lt;/p&gt;

&lt;p&gt;About microphones, please refer here.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running scripts outside of containers&lt;/li&gt;
&lt;li&gt;Set up the microphone for use on the container, referring to &lt;a href="https://stackoverflow.com/questions/45700653/can-my-docker-container-app-access-the-hosts-microphone-and-speaker-mac-wind"&gt;this article&lt;/a&gt; and others.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  *2
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Create Recognizer instance&lt;/li&gt;
&lt;li&gt;Generate a speech recognition object from the audio file in the record method&lt;/li&gt;
&lt;li&gt;Execute the recognize_sphinx method with the object for speech recognition to perform speech recognition&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Run Program
&lt;/h2&gt;

&lt;p&gt;This time, I would like to create an audio file with &lt;strong&gt;speech.p&lt;/strong&gt;y in the repository and have it recognized. &lt;strong&gt;speech.py&lt;/strong&gt; takes an English string and converts it into an audio file.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;$ mkdir ./audios&lt;/code&gt; → Same hierarchy as src&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;$ python speech.py “apple banana”&lt;/code&gt; → You can change to any English you like.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$ python recognize.py&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the following codes are displayed, your programming is successful.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feysiazn6akgf0haabl8c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feysiazn6akgf0haabl8c.png" alt="success" width="800" height="70"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, we want to introduce a little more about GROWI, an open software developed by &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Speech_Recognition_with_Python_%26_CMU_Sphinx"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Speech_Recognition_with_Python_%26_CMU_Sphinx"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>python</category>
      <category>tutorial</category>
      <category>programming</category>
    </item>
    <item>
      <title>VSCode X Docker: Make a Comfortable Development Environment</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Thu, 02 May 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/vscode-x-docker-make-a-comfortable-development-environment-10pd</link>
      <guid>https://forem.com/weseek-inc/vscode-x-docker-make-a-comfortable-development-environment-10pd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, my name is Ryo, and I am an engineer from WESEEK, Inc. in Japan. In this article, I would like to introduce how to build a dev container environment in a project using Docker and Visual Studio Code (VSCode) extensions.&lt;/p&gt;

&lt;p&gt;Have you ever felt that installing specific programming languages or libraries when building a development environment is a hassle? Especially when installing directly on the host PC, it is very time-consuming because you have to proceed while checking whether there are any conflicts with the existing ones.&lt;/p&gt;

&lt;p&gt;Once the dev container environment introduced in this article is built, it is no longer necessary to install individual programming languages and libraries when building a similar development environment. Thus, you can expect to save a great deal of time. This is very effective when developing with multiple developers.&lt;/p&gt;

&lt;p&gt;We are sure that there are many people who are developing with VSCode, so please take time to read this article and learn how to make a comfortable development environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Environment Used In This Project
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;macOS Catalina: v10.15.7&lt;/li&gt;
&lt;li&gt;VSCode: v1.65.0&lt;/li&gt;
&lt;li&gt;Remote — Containers: v0.224.2&lt;/li&gt;
&lt;li&gt;Docker Desktop: v20.10.12&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;See below for detailed system requirements:&lt;br&gt;
&lt;a href="https://code.visualstudio.com/docs/remote/containers#_system-requirements"&gt;https://code.visualstudio.com/docs/remote/containers#_system-requirements&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is a Dev Container Environment?
&lt;/h2&gt;

&lt;p&gt;The dev container environment can be built using the VSCode extension “Remote — Containers”, and can be built on any OS as long as Docker and VSCode are available.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F252knh2rgoo1tajl9u1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F252knh2rgoo1tajl9u1i.png" alt="remote-containers_1" width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As shown in the figure above, when the dev container environment is launched, VSCode can access the Docker container and edit files on the VSCode container.&lt;/p&gt;

&lt;p&gt;In addition, VSCode configuration, extensions, and installation of necessary languages and libraries can be stored in devcontainer.json and Dockerfile.&lt;/p&gt;

&lt;p&gt;Thus, developers only need to install Docker and VSCode and open the project repository directory on VSCode to use the development environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quickly Build an Environment In 3 Easy Steps
&lt;/h2&gt;

&lt;p&gt;Now, let’s build the dev container environment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Install Docker&lt;/strong&gt;&lt;br&gt;
Please click on the following link to install the software:&lt;br&gt;
&lt;a href="https://www.docker.com/products/docker-desktop"&gt;https://www.docker.com/products/docker-desktop&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Install the extension “Remote — Containers” in VSCode&lt;/strong&gt;&lt;br&gt;
We will add an extension to VSCode. In this case, we will install “Remote — Containers” since it is for accessing containers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fep0q4zpfd2spxqf0vvmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fep0q4zpfd2spxqf0vvmn.png" alt="remote-containers_2" width="800" height="114"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Select “Reopen in Container” and setup&lt;/strong&gt;&lt;br&gt;
Once the extensions are in place, you are almost ready to go.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Firstly, click on the icon with the green background in the lower left corner of the VSCode screen&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezchay5u3tttcgv6x0fy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fezchay5u3tttcgv6x0fy.png" alt="Find the icon" width="100" height="58"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then a menu will appear in the upper center of the screen, click on “Reopen in Container” and wait a moment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvon5wv4rsc5sm2meco3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffvon5wv4rsc5sm2meco3.png" alt="Reopen in Container" width="800" height="390"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select the environment you want to create&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjphw6rmsodys3eqxp0oj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjphw6rmsodys3eqxp0oj.png" alt="Select environment" width="800" height="443"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The construction of the dev container environment is completed&lt;/p&gt;




&lt;h2&gt;
  
  
  About &lt;code&gt;.devcontainer&lt;/code&gt; Directory
&lt;/h2&gt;

&lt;p&gt;When the environment is created by the above procedure, a directory named &lt;code&gt;.devcontainer&lt;/code&gt; is created as shown below, and two files are automatically created under the directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnufr641pwzupd5x9r9up.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnufr641pwzupd5x9r9up.png" alt=".devcontainer" width="800" height="80"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will give a brief description of these two files&lt;/p&gt;

&lt;h3&gt;
  
  
  devcontainer.json
&lt;/h3&gt;

&lt;p&gt;This file is mainly used to describe VSCode settings. It can be used to describe VSCode extensions and settings that you want to standardize in your project.&lt;/p&gt;

&lt;p&gt;Check here for more reference:&lt;br&gt;
&lt;a href="https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_vs-code-specific-properties"&gt;https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_vs-code-specific-properties&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Dockerfile
&lt;/h3&gt;

&lt;p&gt;This file describes the configuration of the container itself. We have posted blogs on Dockerfile in the past. For more details, please refer here.&lt;/p&gt;

&lt;p&gt;You can also put docker-compose.yml instead of Dockerfile and make it readable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker-compose
&lt;/h3&gt;

&lt;p&gt;In that case, the following definitions are required in the devcontainer.json file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dockerComposeFile&lt;/li&gt;
&lt;li&gt;service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Also, we have posted blogs on Docker-compose in the past. For more details, please refer &lt;a href="https://dev.to/weseek-inc/building-a-docker-development-environment-part-1-1lhe?preview=66c3d0de4257b518b013e65729031f9e4b7b0a27d03b0d5a7dc19ccff06758a9915755525f4349806eefa5af2003e6db9ac2441ee4d578bbc6dc50d6"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check here for more reference: &lt;a href="https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_docker-compose-specific-properties"&gt;https://code.visualstudio.com/docs/remote/devcontainerjson-reference#_docker-compose-specific-properties&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Tips
&lt;/h2&gt;

&lt;p&gt;Since the goal of this article is to build a dev container environment, it is necessary to proceed with the expansion of dockerfile/docker-compose in addition to building the dev container environment, depending on the project.&lt;/p&gt;

&lt;p&gt;You can use common extensions in the dev container environment by entering the IDs of the VSCode extensions used in the dev container environment in the extensions of the devcontainer.json file.&lt;/p&gt;

&lt;p&gt;You can enter the ID of the extension directly in the file, but as shown in the image below, search for the extension you want to add and select “Add to devcontainer.json” to automatically enter it in the extensions of devcontainer.json.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo12mxr15x9u7wmje5ej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzo12mxr15x9u7wmje5ej.png" alt="add to devcontainer" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading and learning with me to create a dev container environment in 3 simple steps.&lt;/p&gt;

&lt;p&gt;Why don’t you start now and try to build a dev container environment in the project you are participating in?&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, we want to introduce a little more about GROWI, an open software developed by &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=VSCode_Docker_Make_a_Comfortable_Development_Environment"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=VSCode_Docker_Make_a_Comfortable_Development_Environment"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>docker</category>
      <category>devops</category>
      <category>programming</category>
    </item>
    <item>
      <title>Building a Docker Development Environment (Part 1)</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Tue, 30 Apr 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/building-a-docker-development-environment-part-1-1lhe</link>
      <guid>https://forem.com/weseek-inc/building-a-docker-development-environment-part-1-1lhe</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, I work as a system engineer in Tokyo and am now mainly developing web applications using Ruby and JavaScript.&lt;/p&gt;

&lt;p&gt;I have been using Docker at my workplace for around 2 years now and almost all of my projects are developed using Docker these days. Docker technology has become so helpful that I believe it will be used for a long time.&lt;/p&gt;

&lt;p&gt;So, I will explain Docker Compose, Dockerfile, and how to build a Rails development environment with Docker and put them into two different sections. &lt;strong&gt;In the first section, I will explain what exactly Docker is and the various components of DockerCompose.yml.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Docker?
&lt;/h2&gt;

&lt;p&gt;Docker is a lightweight platform for building containerized virtual environments. This allows you to quickly build, test, and deploy applications.&lt;/p&gt;

&lt;p&gt;Containers created by Docker are independent of the execution environment and are not affected by external influences, so everyone can build the exact same environment by simply sharing docker-compose.yml and Dockerfile.&lt;/p&gt;

&lt;p&gt;Unlike conventional virtualization technologies, a guest OS is not launched, making it extremely lightweight compared to conventional virtualization technologies.&lt;/p&gt;




&lt;h2&gt;
  
  
  Docker Compose
&lt;/h2&gt;

&lt;p&gt;Docker Compose is a tool for Docker applications that define and run multiple containers. By setting up the complex configuration required to launch containers in YAML format in docker-compose.yml, you can create and launch application services based on the configuration with a single command.&lt;/p&gt;

&lt;p&gt;Today, we will create two containers, one for Rails and one for Postgres, a database, in order to build a Rails development environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bvjpsziwlf9bmtnmslg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0bvjpsziwlf9bmtnmslg.png" alt="docker-compose.yml" width="800" height="893"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Components of Docker Compose
&lt;/h2&gt;

&lt;h3&gt;
  
  
  version
&lt;/h3&gt;

&lt;p&gt;It represents the version of the format. Therefore, if the version is changed, the file will be written differently.&lt;/p&gt;

&lt;h3&gt;
  
  
  build
&lt;/h3&gt;

&lt;p&gt;Specify options to be applied at build time. You can specify the path of the build context and the path of the Dockerfile to be used.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;context&lt;/strong&gt; &lt;br&gt;
Specify the Dockerfile to be used in the build. In Docker Compose, any file name other than “Dockerfile” can be specified here. You can also specify the path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;dockerfile&lt;/strong&gt; &lt;br&gt;
Specify the Dockerfile to be used in the build. In Docker Compose, any file name other than “Dockerfile” can be specified here. You can also specify the path.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  image
&lt;/h3&gt;

&lt;p&gt;If no Dockerfile is specified, an image is used. Find the specified image from docker images. If you do not have the image, pull the image from DockerHub to build it.&lt;/p&gt;

&lt;h3&gt;
  
  
  container_name
&lt;/h3&gt;

&lt;p&gt;You can name the container as you like.&lt;/p&gt;

&lt;h3&gt;
  
  
  depends_on
&lt;/h3&gt;

&lt;p&gt;It represents the dependencies (order of creation) of the containers. In this case, the Rails container is created after the Postgres container is created.&lt;/p&gt;

&lt;p&gt;Also, by specifying a condition for depends_on, you can change the condition of depends_on, such as executing after the container is created and finished.&lt;/p&gt;

&lt;p&gt;For more information, please check &lt;a href="https://github.com/compose-spec/compose-spec/blob/master/spec.md"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  ports
&lt;/h3&gt;

&lt;p&gt;You can specify both host-side and container-side ports.&lt;br&gt;
(host side: container side)&lt;/p&gt;

&lt;p&gt;If only one port is specified, a random port number will be assigned to the host side.&lt;/p&gt;

&lt;h3&gt;
  
  
  volumes
&lt;/h3&gt;

&lt;p&gt;There are two types of volumes in DockerCompose. The first is the volumes in rails and postgres in docker-compose.yml. This is what is called a bind mount, which mounts files and directories on the host side to the container side.&lt;/p&gt;

&lt;p&gt;The second one is defined at the bottom of the file and is used to configure data persistence. Therefore, the data can remain even if the container is deleted.&lt;/p&gt;

&lt;h3&gt;
  
  
  tty
&lt;/h3&gt;

&lt;p&gt;This corresponds to the -t option of the docker run command. By setting it to true, you can keep containers running. This prevents the container from being terminated immediately after it is launched.&lt;/p&gt;

&lt;h3&gt;
  
  
  stdin_open
&lt;/h3&gt;

&lt;p&gt;This corresponds to the -i option of the docker run command. By setting it to true, you can tie stdin and error output to the container.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;You have now finished creating docker-compose.yml.&lt;br&gt;
However, we can’t just run this file, we need to prepare a Dockerfile, which is specified in the Rails build.&lt;br&gt;
We will discuss the Dockerfile in the &lt;a href="https://dev.to/weseek-inc/building-a-docker-development-environment-part-2-43i?preview=c1491c120ef9c33b075c08c52fc8a1128b352ddca5a885bab6a661f115ae73129d0ccda1b086ddd6762ba4fd48eed6495aaa74f8563cc933e0e21b5a"&gt;second article&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article is based on the Compose file reference in the official documentation: &lt;a href="https://docs.docker.jp/compose/compose-file/index.html"&gt;https://docs.docker.jp/compose/compose-file/index.html&lt;/a&gt; (Japanese)&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, we want to introduce a little more about GROWI, an open software developed by &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Building_a_Docker_Development_Environment_Part_1"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Building_a_Docker_Development_Environment_Part_1"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Building a Docker Development Environment (Part 2)</title>
      <dc:creator>Weseek-Inc</dc:creator>
      <pubDate>Tue, 30 Apr 2024 14:00:00 +0000</pubDate>
      <link>https://forem.com/weseek-inc/building-a-docker-development-environment-part-2-43i</link>
      <guid>https://forem.com/weseek-inc/building-a-docker-development-environment-part-2-43i</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Hello, I work as a system engineer in Tokyo and am now mainly developing web applications using Ruby and JavaScript.&lt;/p&gt;

&lt;p&gt;I have been using Docker at my workplace for around 2 years now and almost all of my projects are developed using Docker these days. Docker technology has become so helpful that I believe it will be used for a long time.&lt;/p&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/weseek-inc/building-a-docker-development-environment-part-1-3i2e-temp-slug-2870976?preview=66c3d0de4257b518b013e65729031f9e4b7b0a27d03b0d5a7dc19ccff06758a9915755525f4349806eefa5af2003e6db9ac2441ee4d578bbc6dc50d6"&gt;previous article&lt;/a&gt;, I explained Docker Compose. &lt;strong&gt;For this article, I would like to continue the discussion and explain more about Dockerfile.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What is Dockerfile?
&lt;/h2&gt;

&lt;p&gt;A Dockerfile is a text file into which you can write the commands you want to run when creating an image.&lt;/p&gt;

&lt;p&gt;Generally, you could pull the original image from the Docker Hub and then create a new image based on that image, customized to fit your project and development style.&lt;/p&gt;




&lt;h2&gt;
  
  
  Merits of Dockerfile
&lt;/h2&gt;

&lt;p&gt;First, let’s talk about creating a container without a Dockerfile.&lt;/p&gt;

&lt;p&gt;Find and pull the source image of the container from the &lt;a href="https://hub.docker.com/"&gt;Docker Hub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86tf6rcpkaq94y16mwgx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F86tf6rcpkaq94y16mwgx.png" alt="docker_1" width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A container is then created from the pulled image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiq0z0m673f2lsvjnw4vv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiq0z0m673f2lsvjnw4vv.png" alt="docker_2" width="800" height="56"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The docker run command combines Docker Create and Docker Start into one command to create and run containers. Note that the -d option runs in the background (detached mode), and the -i and -t options leave it ready to accept commands.&lt;/p&gt;

&lt;p&gt;Now you have successfully launched a Ruby container named my-container. If you are not particular about it, using the container you created is enough.&lt;/p&gt;

&lt;p&gt;On the other hand, the advantage of using a Dockerfile is that you can write ALL the commands you want to execute in the file when you build the image. This allows you to pull images from DockerHub and customize them to fit your project and development style.&lt;/p&gt;

&lt;p&gt;For example, when launching a Ruby container, you can use COPY or CMD in the Dockerfile to copy the Gemfile and Gemfile. lock into the container and run Bundle Install.&lt;/p&gt;

&lt;p&gt;If you organize the Dockerfile well, you can also start the application by doing all the initial startup processes when the container is launched.&lt;/p&gt;




&lt;h2&gt;
  
  
  Dockerfile Commands
&lt;/h2&gt;

&lt;p&gt;In this case, I prepared the following Dockerfile:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7a4ssrpl98xkdlgrgy30.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7a4ssrpl98xkdlgrgy30.png" alt="dockerfile" width="800" height="412"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  FROM
&lt;/h3&gt;

&lt;p&gt;In the Dockerfile, we usually use FROM first. FROM sets up the base image to be used in subsequent instructions. When the Dockerfile is executed, it first looks for the image in the environment where it was executed. If the image is not found, it will look for the image in the Docker Hub and download it.&lt;/p&gt;

&lt;p&gt;Subsequent instructions are executed sequentially for the image specified in FROM. The build stage can be named by adding “AS name” after FROM. You can use any name other than “name” here. By adding a name, the name can be referenced in subsequent like FROM and COPY, and multiple FROMs can be defined and managed in the Dockerfile.&lt;/p&gt;

&lt;h3&gt;
  
  
  COPY
&lt;/h3&gt;

&lt;p&gt;Copy files and folders. Note that only files and directories in the directory where the Dockerfile is placed can be copied.&lt;/p&gt;

&lt;h3&gt;
  
  
  ADD
&lt;/h3&gt;

&lt;p&gt;Adds files and folders. Unlike COPY, if the file is a compressed file, it would be automatically decompressed. In addition, by specifying a URL instead of a file name, a remote file can be downloaded and added.&lt;/p&gt;

&lt;h3&gt;
  
  
  WORKDIR
&lt;/h3&gt;

&lt;p&gt;Specifies the directory where RUN, CMD, ENTRYPOINT, COPY, and ADD are executed. If the directory specified in WORKDIR does not exist, a new directory will be created.&lt;/p&gt;

&lt;h3&gt;
  
  
  RUN
&lt;/h3&gt;

&lt;p&gt;The commands you specify will be executed at the time the image is built.&lt;br&gt;
This is where you write the commands you want to run at the time of the image, such as installing packages, copying files, etc.&lt;/p&gt;

&lt;h3&gt;
  
  
  CMD
&lt;/h3&gt;

&lt;p&gt;This differs from RUN, with CMD specified command executed when the container is started. The main purpose of a CMD is to specify the initial configuration when the container is run, and it can only be used once in a Dockerfile. If multiple CMDs exist, the last CMD will take effect.&lt;/p&gt;

&lt;h3&gt;
  
  
  ENTRYPOINT
&lt;/h3&gt;

&lt;p&gt;Like CMD, this command is executed when the container is started. However, in the case of CMD, if a command is specified after the docker run, CMD will be overwritten and executed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58a6mcc9eljjycm7dh5a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58a6mcc9eljjycm7dh5a.png" alt="entrypoint_1" width="800" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Like the example, if the above command is used to launch a container, the CMD in the Dockerfile will be overwritten and the ls command will be executed.&lt;/p&gt;

&lt;p&gt;If ENTRYPOINT is used instead of CMD, the command specified in ENTRYPOINT will be executed without overwriting. In other words, the command specified by ENTRYPOINT is always executed.&lt;/p&gt;

&lt;p&gt;If ENTRYPOINT and CMD are used together, a command that is a combination of both will be executed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1tc7xz6wyb93byeqfuop.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1tc7xz6wyb93byeqfuop.png" alt="entrypoint_2" width="800" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For example, if you put such a description in the Dockerfile, “ls -a” will be executed when the container is started. The CMD part can be overwritten, so you can change -a to another option and have it run, but you will probably never use it.&lt;/p&gt;

&lt;h3&gt;
  
  
  USER
&lt;/h3&gt;

&lt;p&gt;Specifies the user who executes commands such as RUN and CMD. The command is automatically executed as the root user if USER is not specified.&lt;/p&gt;

&lt;h3&gt;
  
  
  LABEL
&lt;/h3&gt;

&lt;p&gt;Add metadata to the image. Specifically, you can describe the name, version, and producer information.&lt;/p&gt;

&lt;h3&gt;
  
  
  ENV
&lt;/h3&gt;

&lt;p&gt;Set environment variables. The set environment variables can be overwritten later.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Use the docker-compose.yml we prepared last time and the Dockerfile this time and run the following code:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjokesfuoa2ob5z6tz97p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjokesfuoa2ob5z6tz97p.png" alt="docker-compose" width="800" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we successfully built a Rails development environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  About Us💡
&lt;/h2&gt;

&lt;p&gt;In addition, we want to introduce a little more about GROWI, an open software developed by &lt;strong&gt;WESEEK, Inc&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; is a wiki service with features-rich support for efficient information storage within the company. It also boasts high security and various authentication methods are available to simplify authentication management, including &lt;strong&gt;LDAP/OAuth/SAML&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GROWI&lt;/strong&gt; originated in Japan and GROWI OSS is &lt;strong&gt;FREE&lt;/strong&gt; for anyone to &lt;a href="https://docs.growi.org/en/admin-guide/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Building_a_Docker_Development_Environment_Part_2"&gt;download&lt;/a&gt; and use &lt;strong&gt;in English&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For more information, go to &lt;a href="https://growi.org/en/?utm_source=dev+community&amp;amp;utm_medium=referral&amp;amp;utm_campaign=Building_a_Docker_Development_Environment_Part_2"&gt;GROWI.org&lt;/a&gt; to learn more about us. You can also follow our &lt;a href="https://www.facebook.com/people/GROWIcloud/100089272547238/"&gt;Facebook&lt;/a&gt; to see updates about our service.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1rhpa0qcdukeall2vfsj.png" alt="GROWI.org" width="800" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
