Yuki's Tech Blog

仕事で得た知見や勉強した技術を書きます。

【TS】【Ruby】日付をyyyy-mm-ddに変換する方法をざっくりまとめてみた

目次

背景

仕事で日付をyyyy-mm-ddに変換するのをやったときにパッとできなかったので、忘れないように記事にしようと思います。

日付をyyyy-mm-ddに変換する方法

Ruby

まずRubyで日付を生成するには、Dateクラスを使用します。Date.todayで今日の日付を持つDateクラスのインスタンスを生成できます。

require 'date'
today = Date.today

p today # => #<Date: 2022-12-04 ((2459918j,0s,0n),+0s,2299161j)>

この日付をyyyy-mm-ddに変換したい場合、Date#strftimeを使用します。 strftimeには文字列でフォーマットを指定します。フォーマットについて知りたい場合、Date#strftimeには詳しい説明が書いていなかったので、Time#strftimeを見た方が良いです。

require 'date'
today = Date.today.strftime("%Y-%m-%d")

p today # => "2022-12-04"

TS

まずTSで日付を生成するには、Dateオブジェクトを使ってインスタンスを生成します。Dateをnewするときにコンストラクタ引数を何も渡さない場合、作成されるインスタンスは現在の時刻を表すものになります。

const today = new Date();

console.log(today); // => Date: "2022-12-04T23:33:34.966Z" 

getMonth()メソッドは、月を0から11の整数で取得します。そのため、+ 1しています。

// YYYY/MM/DD形式の文字列に変換する関数
const formatDate = (date: Date) => {
  const yyyy = String(date.getFullYear());
   
  // Stringの`padStart`メソッド(ES2017)で2桁になるように0埋めする
  // 既に長さを満たしている場合、0埋めされない
  const mm = String(date.getMonth() + 1).padStart(2, "0");
  const dd = String(date.getDate()).padStart(2, "0");

  return `${yyyy}-${mm}-${dd}`;
}

const today = new Date();
console.log(formatDate(today)); // => "2022-12-05"

参考記事

class Date (Ruby 3.1 リファレンスマニュアル)

Date#strftime (Ruby 3.1 リファレンスマニュアル)

Time#strftime (Ruby 3.1 リファレンスマニュアル)

Date · JavaScript Primer #jsprimer

日付オブジェクト名.getMonth()-JavaScriptリファレンス

【TS】【Ruby】boolean値をランダムに返す方法をざっくりまとめてみた

目次

背景

仕事でboolean値をランダムに返すやり方がパッと出なかったので、ブログにまとめようと思います。

boolean値をランダムに返す方法

Ruby

Array#sampleメソッドを使用します。sampleメソッドは配列の要素を1個ランダムに選んで返します。

isAdmin = [true, false].sample

p isAdmin # => true

TS

Math.randomとMath.floorを使用します。Math.randomは0 以上 1 未満のランダムな浮動小数点数を返します。また、Math.floorで、小数点以下を切り捨てることができます。

// *2して、0以上2未満のランダムな浮動小数点を生成している
// Math.floorで、浮動小数点数の小数点以下を切り捨てている。
const isAdmin = [true, false][Math.floor(Math.random() * 2)]

console.log(isAdmin); // => true

しかし、これは冗長なので、以下のように書いてもOKです。以下のように書くことで、Math.random()の値が0以上0.5未満ではfalse、Math.random()の値が0.5以上1未満ではtrueになります。

const isAdmin = Math.random() >= 0.5

console.log(isAdmin); // => true

参考記事

javascript — JSはランダムなブール値を生成します

JavaScript | 乱数を生成する(Math.random)

Array#sample (Ruby 3.1 リファレンスマニュアル)

【TS】任意の回数ループする方法をざっくりまとめてみた

目次

背景

仕事で任意の回数ループしたいときがあって、手こずったので、忘れないようにまとめようと思います。

任意の回数ループする

5回ループしたいとします。まず、Array(5)で要素数が5個の空の配列を作成します。

const keys = Array(5)

console.log(keys); // => [, , , , ]
console.log(keys[0]) // => undefined
console.log(keys.length) // => 5

この配列は要素数が5個あることを表しているだけで、実際に値が存在しているわけではありません。そのため、スプレッド構文で展開してundefinedを要素とする配列にします。

const keys = Array(5)
const array = [...keys];
console.log(array); // => [undefined, undefined, undefined, undefined, undefined] 

最後にforEachを使えば、完成です。5回ループできます。[...Array(5).keys()]を使う方法もありますが、こちらの方が理解しやすいので、こちらを採用しました。

[...Array(5)].forEach((_, i) => {
    console.log(i);
})

(※) ちなみに空の配列に対してforEachを実行する場合、要素が存在しないので、何も実行されずに終了します。エラーが起きたりはしません。

参考記事

JavaScriptで[ 0, 1, 2, 3, 4 ]のような連番の配列を生成する方法 - Qiita

Array.prototype.keys() - JavaScript | MDN

【Ruby】【TS】オブジェクトやハッシュのキーを取り出して配列を作成してみた

目次

背景

仕事でオブジェクトやハッシュのキーを取り出して配列を作ることがよくあるので、忘れないようにブログにまとめようと思います。

TSの場合

TSの場合、Object.keysを使用します。keysメソッドの引数にキーを取り出して配列にしたいオブジェクトを指定します。

const user = {
  name: "yuki",
  age: 25,
  country: "Japan" 
};

const keys = Object.keys(user);
console.log(keys); // => ["name", "age", "country"]

Rubyの場合

Rubyの場合、keysメソッドを使用します。レシーバにキーを取り出して配列にしたいハッシュを指定します。

user = {
  name: "yuki",
  age: 25,
  country: "Japan" 
}

keys =  user.keys
p keys # => ["name", "age", "country"]

(※) ちなみにRubyではメソッドの仮引数が存在しない場合、メソッド呼び出し時に括弧を省略することができます。TSではこの場合、括弧が必要です。

enumの定数で配列を作る

モデルクラス.enumカラム名の複数形で、定数と整数が紐づいたハッシュが取得できます。そのハッシュに対してkeysメソッドを使用すると、enumの定数のみの配列を作成できます。

irb(main):001:0> Product.storage_temperatures
=> {"normal"=>0, "refrigerated"=>1, "semi_refrigerated"=>2, "frozen"=>3}
irb(main):002:0> Product.storage_temperatures.keys
=> ["normal", "refrigerated", "semi_refrigerated", "frozen"]
irb(main):003:0> Product.storage_temperatures.keys()
=> ["normal", "refrigerated", "semi_refrigerated", "frozen"]
irb(main):004:0>

参考記事

Object.keys() - JavaScript | MDN

class Hash (Ruby 3.1 リファレンスマニュアル)

Railsのenumを使いこなす方法(翻訳)|TechRacho by BPS株式会社

【Rails】 enumチュートリアル | Pikawaka

【Ruby】【TS】関数のデフォルト引数とオプショナルな引数についてざっくりまとめてみた

目次

背景

仕事で「関数のデフォルト引数ってどうやって指定するんだっけ」と悩んだので、忘れないようにするために記事にしようと思います。

関数のデフォルト引数について

RubyでもTSでもデフォルト引数の書き方は同じです。 デフォルト引数を設定しないで実引数なしで関数を呼び出した場合、Rubyではエラーが起こりますが、TSではundefinedが渡されます。

Ruby

Rubyでは、引数にデフォルト値を設定できます。仮引数の右側に =と デフォルト値を書きます。

def getMessage(message = "Hello world")
  puts message
end

getMessage() # => Hello world

Rubyで引数にデフォルト値を指定したい場合、キーワード引数を使ってデフォルト値を設定することが推奨されています。キーワード引数を使ってデフォルト値を設定することで、引数の順番に左右されることがなくなり、必要な引数だけを指定すれば良くなります。また、キーワード引数の方が実引数の意味が分かりやすく、実引数がどのように使われているかを知るために、メソッド定義を見に行く必要がありません。

キーワード引数を使うためには、仮引数の後ろに:をつけます。そうすると、この仮引数がキーワード引数になります。メソッドを呼び出すときは、引数を名前(キーワード)付きで指定します。キーワード引数にデフォルト値を設定したい場合は、キーワード引数の後ろにデフォルト値を書きます。=は書きません。キーワード引数を使わない場合は、デフォルト値を設定するのに =を書きます。

def getMessage(message1:, message2: "World")
  puts message1 + " " + message2
end

getMessage(message1: "Hello") # => Hello world
getMessage(message1: "Hello", message2: "Japan") # => Hello Japan

TS

TSにおけるデフォルト引数とは、 仮引数に渡ってくる値がundefinedのとき、代わりの値を代入できるような引数のことです。 JSのデフォルト引数は、仮引数の右側に = とデフォルト値を書きます。これはRubyも同じです。

const getMessage = (message = "Hello world") => {
  console.log(message);
};

getMessage(); // => Hello world

TSでは、引数の型の右側に=とデフォルト値を書きます。

const getMessage = (message: string = "Hello world") => {
  console.log(message);
};

getMessage(); // => Hello world

TSではデフォルト引数がある場合、引数の型推論ができます。そのため、引数の型は省略することができます。 基本的には省略します。

const getMessage = (message = "Hello world") => {
  console.log(message);
};

getMessage(); // => Hello world

実引数を省略して関数を呼び出すと、仮引数にはundefinedが渡ります。 引数を省略された場合に、undefinedではなく、あらかじめ設定したデフォルト値を代入したいときにデフォルト引数を利用します。

const getMessage = (message: string) => {
  console.log(message);
};

getMessage(); // => undefined
getMessage("x"); // => "x"

ちなみに、当たり前ですが、デフォルト値が設定されている状態で仮引数に値が渡ってきた場合、その値が使われます。

関数のオプショナルな引数について

Ruby

Rubyではデフォルト値を設定した場合、その引数が省略可能なオプショナルな引数になります。 つまり、Rubyでは引数をデフォルト引数にした場合、その引数はオプショナルな引数にもなります。 TSでも同様です。

def getMessage(message2 = "World", message3: "Hello")
  puts message2 + " " ++ message3
end

getMessage() # => World Hello

しかし、TSの場合、デフォルト値を設定せずに、引数そのものをオプショナルな引数にすることができます。 TSはRubyと違ってデフォルト値を設定しないとオプショナルな引数にできないという縛りはないです。 JSでは実引数を省略すると仮引数にundefinedが渡されていたので、TSのオプショナルな引数でも同じです。

TS

TSでオプショナルな引数を設定することで、関数呼び出し時にその引数を省略することができます。引数をオプショナルな引数にしたい場合、 仮引数名の後ろに?をつけます。関数の仮引数なので、型は必ず書きます。

const getMessage = (message?: string) => {
  console.log(message);
}

getMessage(); // => undefined

オプショナルな引数の型は string | undefinedです。そのため、オプショナルな引数にすることで、JSで引数を指定しないで関数を呼び出した場合に引数にundefinedが代入されるという挙動を満たすことができます。

普通の仮引数にstring | undefined型を指定しても関数呼び出し時に実引数を省略できないので気をつけましょう。オプショナルな引数と同じ挙動を実現するためには、undefinedを渡す必要があります。しかし、省略ができないので、実引数を省略したい場合は、オプショナルな引数を使いましょう。

const getMessage = (message: string | undefined) => {
  console.log(message);
}

// Expected 1 arguments, but got 0.(2554)
getMessage(); 

また、オプショナルな引数は一番最後に書きます。オプショナルな引数の後ろに普通の引数を書くと、コンパイルエラーになります。

// A required parameter cannot follow an optional parameter.

実引数の省略を許容しつつ、仮引数にデフォルト値を代入したい場合、普通に仮引数にデフォルト値を指定して、仮引数をデフォルト引数として定義します。以下の場合、messageがデフォルト引数になります。 仮引数にはundefinedが渡ってきますが、その場合は自動的にHello worldが仮引数に代入されるので、messageがstring型を満たすことになります。

const getMessage = (message = "Hello world") => {
  console.log(message);
};

getMessage(); // => Hello world

キーワード引数について

Ruby

キーワード引数を使うためには、仮引数の後ろに:をつけます。そうすると、この仮引数がキーワード引数になります。メソッドを呼び出すときは、引数を名前(キーワード)付きで指定します。キーワード引数にデフォルト値を設定したい場合は、キーワード引数の後ろにデフォルト値を書きます。キーワード引数を使うことで、引数の順番を気にする必要がなくなったり、実引数がどんな引数なのかが明確になってメソッド定義を見に行く必要がなくなります。ただ、引数の省略はできないので、その場合、キーワード引数にデフォルト値を設定します。

def getMessage(message2: "World", message3:)
  puts message2 + " " + message3
end

getMessage(message3: "world") # => World world

TS

TSでキーワード引数と同じことをする場合、仮引数にオブジェクトを渡して分割代入で受け取れるようにします。その際、分割代入でもデフォルト値を設定できます。以下の例では、message2のデフォルト値として、Worldを指定しています。型を書く際にmessage2をstringとして定義すると、message2を省略することができなくてコンパイルエラーになるので、?を書きます。そうすることで、message2の型がstring | undefinedになり、引数を省略できます。

const getMessage = ({ message2 = "World", message3 }: { message2?: string, message3: string}) => {
  console.log(message2 + " " + message3)
};

getMessage({message3: "world"}) // => "World world"

参考記事

デフォルト引数 (default parameter) | TypeScript入門『サバイバルTypeScript』

Rubyのメソッドの引数でデフォルト式を与える場合は、通常の引数ではなく「キーワード引数」を使おう - Qiita

オプション引数 (optional parameter) | TypeScript入門『サバイバルTypeScript』

Rubyメソッドの引数まとめ | Enjoy IT Life

分割代入引数 (destructuring assignment parameter) | TypeScript入門『サバイバルTypeScript』

キーワード引数とOptions Objectパターン | TypeScript入門『サバイバルTypeScript』

【TS】findメソッドとfilterメソッドの使い方をざっくりまとめてみた

目次

背景

仕事でfindメソッドとfilterメソッドをよく使うので、忘れないように記事にしようと思います。

findメソッド

findメソッドは、 指定したテスト関数を満たす最初の配列要素を返します。テスト関数を満たす値がない場合は、undefined が返されます。 また、レシーバが空の配列の場合、満たす値が存在しないので、undefinedが返されます。

const users = [
  {
    firstName: "yuki",
    age: "25",
    country: "japan",
  },
  {
    firstName: "ken",
    age: "27",
    country: "usa",
  },
];

const usaUser = users.find(({ country }) => country === "usa");
console.log(usaUser);
// => {
//      "firstName": "yuki",
//      "age": "25",
//      "country": "usa"
//    } 

↓ undefinedを返す場合

const spainUser = users.find(({country}) => country === "spain");
console.log(spainUser); // => undefined

filterメソッド

findメソッドは、 指定したテスト関数を満たす全ての配列要素を一つの配列として返します。テスト関数を満たす値がない場合、空の配列が返されます。 また、レシーバが空の配列の場合、満たす値が存在しないので、空の配列が返されます。

const users = [
  {
    firstName: "yuki",
    age: "25",
    country: "japan",
  },
  {
    firstName: "ken",
    age: "27",
    country: "usa",
  },
  {
    firstName: "yuki",
    age: "25",
    country: "spain",
  },
];

const newUsers = users.filter(({ age }) => age === "25");
console.log(newUsers); 
// => [
//      {
//        "firstName": "yuki",
//        "age": "25",
//        "country": "japan"
//      }, 
//      {
//        "firstName": "yuki",
//        "age": "25",
//        "country": "spain"
//      }
//    ]

↓ 空の配列を返す場合

const newUsers = users.filter(({ age }) => age === "28");
console.log(newUsers); // => []

参考記事

Array.prototype.find() - JavaScript | MDN

Array.prototype.filter() - JavaScript | MDN

【TS】分割代入の代入先でスプレッド構文を使ってみた

目次

背景

仕事で分割代入の代入先でスプレッド構文を使ってみたので、忘れないように記事にしようと思います。

分割代入とは

分割代入とは、 配列の要素やオブジェクトのプロパティの値を別の変数として定義することができる構文のことです。オブジェクトで分割代入を行う場合、定義する変数の名前はプロパティ名と一致させます。もしプロパティ名と変数名を一致させずに変数を定義したい場合、{ プロパティ名: 変数名 }で変数を定義します。配列の場合は、特に変数名の縛りはないです。

const user = {
  firstName: "yuki",
  age: "25",
};
const { firstName, age: yukisAge } = user;

console.log(firstName); // => "yuki"
console.log(yukisAge);       // => 25

const fruits = ["apple", "orange", "grape"];

// othersには""orange"しか含まれない
const [first, others] = fruits;

console.log(first); // => "apple"
console.log(others); // => "orange"

オブジェクトのプロパティに指定されているオブジェクトのプロパティの値を分割代入で取り出す場合、{ プロパティ名: { ネストされているオブジェクトのプロパティ名 } }と書きます。

const user = {
    children: {
        age: 3,
    }
};

const { children: { age } } = user

console.log(age); // => 3

{ プロパティ名: { ネストされているオブジェクトのプロパティ名: 変数名 } }と書くと、プロパティ名ではなくて独自の変数名で分割代入できます。

const user = {
    children: {
        age: 3,
    }
};

const { children: { age: childAge } } = user

console.log(childAge); // => 3

スプレッド構文とは

スプレッド構文とは、 配列やオブジェクトを展開するための構文です。既存の配列やオブジェクトを利用しつつ、新しい配列やオブジェクトを作成するときに使用します。

const user = {
  firstName: "yuki",
  age: "25",
};
const newUser = {
  ...user,
  age: "26",
}

console.log(newUser.age); // => 26

const fruits = ["apple", "orange", "grape"];
const newFruits = [ ...fruits, "watermelon"];

console.log(newFruits); // => ["apple", "orange", "grape", "watermelon"] 

(注) オブジェクトのプロパティ名が被った場合の優先順位は、後ろにあるオブジェクトのプロパティが優先されます。

分割代入の代入先でスプレッド構文を使ってみる

分割代入の代入先でスプレッド構文を使うことで、分割代入で明治的に宣言していない全ての値をオブジェクトまたは配列として一つの変数に代入することができます。 以下の例ではfirstNameの値以外は、othersにオブジェクトとして代入されています。...othersで残り全てのプロパティを指定したとみなされているため、othersにはオブジェクトが格納されていると考えられます。

↓ 代入元がオブジェクトの場合

const user = {
  firstName: "yuki",
  age: "25",
  country: "japan",
};

const { firstName, ...others } = user;
console.log(others) 
// => {
//      "age": "25",
//      "country": "japan"
//    }

↓ 代入元が配列の場合

const fruits = ["apple", "orange", "grape"];

// 普通にothersと定義した場合、othersには"orange"しか代入されない
const [ firstItem, ...others] = fruits

console.log(firstItem); // => "apple"
console.log(others); // => ["orange", "grape"]

(注) 本当にageを定義しているわけではないので、ageをconsole.logで出力しようとするとエラーが出ます。othersならOKです。

参考記事

オブジェクト · JavaScript Primer #jsprimer

オブジェクト · JavaScript Primer #jsprimer