2025年2月27日木曜日

2人目の育休をはじめて3ヶ月が経ちました

第二子が生まれて12月頃から育休に入っていました。

いくつかの観点で記録を残しておきたいので筆をとっています。

1. お役立ちアイテム
2. 育休前からの過ごし方
3. 第一子と第二子との関わり方
4. リスキリング

このポスト以降で連投したいと思います。

それでは。

2023年12月18日月曜日

ReactのWebComponentsでslotされたものを使い回す

この記事は Uzabase Advent Calendar 2023の18日目 の記事です。


はじめに

UzabaseのProduct Divisionではプロダクトのフロントエンドコンポーネントを他のプロダクトでも再利用できるようWebComponentsを利用しています。WebComponentsにはスロットという機能があり、slotタグによって外部から要素を渡すことができます。

たとえば、ローディングスピナーを表示するspinner-slotという自作要素をlitで作ってみます。2つ上下にローディングスピナーは出ますが、下の方はslotによって外部から差し込まれたスピナーに置き換わっています。

次のように表示されます。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>spinner slot</title>
<script type="module" src="/index.js"></script>
<style>
.another-spinner {
width: 32px;
height: 32px;
margin: 10px auto;
border: 4px #ddd solid;
border-top: 4px red solid;
border-radius: 50%;
animation: another-spinner-anime .45s infinite linear;
}
@keyframes another-spinner-anime {
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body style="display: flex; justify-content: center;">
<div>
<spinner-slot><!-- <div class="another-spinner"></div> --></spinner-slot>
<spinner-slot><div class="another-spinner"></div></spinner-slot>
</div>
</body>
</html>
view raw index.html hosted with ❤ by GitHub
import {LitElement, css, html} from 'lit-element';
class MyElement extends LitElement {
static styles = css`
.spinner {
width: 32px;
height: 32px;
margin: 10px auto;
border: 4px #ddd solid;
border-top: 4px blue solid;
border-radius: 50%;
animation: spinner-anime 1.0s infinite linear;
}
@keyframes spinner-anime {
100% {
transform: rotate(360deg);
}
}
`;
render() {
return html`
<div>
<slot>
<div class="spinner"></div>
</slot>
</div>
`;
}
}
customElements.define('spinner-slot', MyElement);
view raw index.js hosted with ❤ by GitHub


業務の中で、このスロット機能を利用して複数の場所で差し込まれた要素を使おうとしました。今回は名前付きslotを利用して、spinner-slotの中で2つの名前付きslot(another-icon)を表示するようにしてみます。

次のように表示されます。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>spinner slot</title>
<script type="module" src="/index.js"></script>
<style>
.another-spinner {
width: 32px;
height: 32px;
margin: 10px auto;
border: 4px #ddd solid;
border-top: 4px red solid;
border-radius: 50%;
animation: another-spinner-anime .45s infinite linear;
}
@keyframes another-spinner-anime {
100% {
transform: rotate(360deg);
}
}
</style>
</head>
<body style="display: flex; justify-content: center;">
<div>
<spinner-slot><!-- <div class="another-spinner"></div> --></spinner-slot>
<spinner-slot><div slot="another-icon" class="another-spinner"></div></spinner-slot>
</div>
</body>
</html>
view raw index.html hosted with ❤ by GitHub
import {LitElement, css, html} from 'lit-element';
class MyElement extends LitElement {
static styles = css`
.spinner {
width: 32px;
height: 32px;
margin: 10px auto;
border: 4px #ddd solid;
border-top: 4px blue solid;
border-radius: 50%;
animation: spinner-anime 1.0s infinite linear;
}
@keyframes spinner-anime {
100% {
transform: rotate(360deg);
}
}
`;
render() {
return html`
<div>
<slot name="another-icon">
<div class="spinner"></div>
</slot>
<slot name="another-icon">
<div class="spinner"></div>
<slot>
</div>
`;
}
}
customElements.define('spinner-slot', MyElement);
view raw index.js hosted with ❤ by GitHub

あれれ、これはうまくいきません。どうやら子要素は1つのslotにしかアサインされないようです。ということは、another-icon-1のように数字をつけたりしてslot nameを変えて欲しいだけの要素を差し込むしかないみたいです。同じものを出したいだけなのにスッキリしないですよね。なので、どうにかして1つの要素を差し込むだけでOKにしてみます。


これが完成形だ!?

業務ではReactを使ってWebComponentを作っていたので、今回はReactで表現してみます。

サンプルコード(github: react-slot)

isEvenという名前の要素を1つ差し込むだけで、slotにアサインされている要素をuseRefで参照しています。

Templateコンポーネントの中で、参照した要素をcloneNodeでコピーして表示するようにしました。

ただ、この方法でやりたいことはできましたが、描画の最初のほうでアサインされた元のslotが一瞬見えてしまう課題がでてきました。


おわりに

今回は1つの要素を差し込むだけで複数のslotに表示させてみました。ただし、課題も残っています。スクリプトをロードするまで描画しないようにしたら解消できるかもしれません。解決した方はコメントをお願いします。

ちなみに、atomicoというフレームワークで用意されているuseSlotを参考に作りました。そちらでは自前で実装する必要はなさそうです。atomicoもぜひご覧ください。



2023年10月13日金曜日

psqlとmysqlで接続を楽にしたいよね?しよっか

※記憶ベースで書いているところがほとんどなので、うまく行かない場合は参考情報をみていただけると大変助かります。

はじめに

運用・開発でデータベースに接続する機会は結構あるもので、いろんなところに接続しなきゃならないときがあります。でも、接続先とかユーザーとかパスワードとか覚えてられないですよね?接続を楽にしたいですよね?しましょう。

今回は僕がよく使っているMySQLとPostgreSQLで接続を楽してみます。


mysql

mysql_config_editorというものがあり、そこに接続プロファイルを書いてもらいます。プロファイルはホームディレクトリ下の~/.mylogin.confに難読化されて保存されます。

接続プロファイルを記録する

mysql_config_editor set -G ${profile-name} -h ${host} -P ${port} -u ${user} -p

mysql_config_editor set -G mydatabase-profile -h localhost -P 3306 -u akio -p

でパスワードを聞かれるので答えてください。これで記録されます。

使うときは

mysql --login-path=mydatabase-profile

で接続できるはずです。


mysql参考

より詳細なQiita記事はこちらにあります。

MySQLへの接続を楽にする - Qiita

mysql_config_editorに使えるオプションはこちら。print -allでプロファイル一覧を出せます。

MySQL :: MySQL 8.0 リファレンスマニュアル :: 4.6.7 mysql_config_editor — MySQL 構成ユーティリティー


psql

パスワードと接続プロファイルをホームディレクトリ下の2つのファイルに分けて管理します。

接続プロファイルは ~/.pg_service.conf に次のように書きます。

[mydatabase-profile]
host=localhost
port=5432
user=akio
dbname=mydb

パスワードは ~/.pgpass に次のように書きます。

localhost:5432:mydb:akio:mypassword

~/.pgpassは chmod 600 しておきます。これよりゆるくするとpsqlに読み取ってもらえなくなります。

接続するときは次のように書きます。

psql  "service=mydatabase-profile" -w

-wでパスワードを聞かれなくなりますが、その代わり.pgpassを探しに行ってくれます。

ちなみに、.pgpassの中身をパスワード以外の部分で一致させて探すので少しでもserviceの内容と違うと取ってこれないかも...と思っています。ワイルドカードは使えそうなので適宜使うと良いのかもしれません。

psql参考

.pg_service.confにかける他パラメータはこちら。

データベース接続制御関数

.pgpassについて詳細なQiita記事はこちら。

psqlでパスワード入力を省略する - Qiita

pgpassについての公式はこちら。

パスワードファイル

psqlのオプションはこちら。

psql


おわりに

mysqlとpsqlで接続プロファイルの保存方法に違いがあることが少々気になりました。mysqlは難読化している一方、psqlはファイル権限制御で読み取られにくくしています。目的は同じでも実装方法が異なる点が、どういう経緯でそうなったのか興味をひきました。誰か教えてください。(´・ω・`) <-(そこまで知りたいとは思っていない顔)

2023年8月28日月曜日

「くもんのうた200えほん」をカメレオンリーダーのような音声タッチペンで便利にする

こんにちは。

先日、妻が「カメレオンリーダー」というものを紹介してくれました。

今回の成果物の図

カメレオンリーダーとは

カメレオンリーダーと「くもんのうた200えほん」を組み合わせて、音声タッチペンで童謡がいつでも聴けるというのです。

それは便利だ、と思い「いいじゃん、買っちゃえば?」と言ったら

「でも、高い」と。


え、そうなの?と商品サイトを見てみると、シールセット + タッチペンで 18,700円

確かに高い...。


でも、この仕組みはどこかで見たことあるなーと思い、類似品を検索すると「G-Talk」という製品があるらしいです。くもんやZ会にも同じような仕組みのペンがあるらしいのですが、だいたいこのG-Talkの系列とのこと。しかし、G-TalkもAmazonで12,100円と高い...。

もう少し調べると、Z会のエブリスピークを英語の絵本用に改造した人がいました。


エブリスピークは中古で流通しているようで、メルカリで1400円で買えました。また、シール自体はとても安く、Amazonで1500円(送料込み)で買えます。合計3000円弱で、カメレオンリーダーと同じことができるのです。

MaiYaPenが欲しかったけど高いのでZ会のエブリスピークで代用してみた – BeeLabo

音声タッチペンの作り方

まず、「くもんのうた200えほん」の楽曲データをダウンロードしてきます。Amazonで妻が買ったのですが、妻曰く、「Webで楽曲データを落とすのはバグがあって大変だからAmazon Musicのアプリで落とした方がいい」とのこと。Web版はどうもチェックボックスにバグがあって一括ダウンロードができないらしいです。


ダウンロードしてきたら、次はエブリスピークのmicroSDに楽曲データを入れます。これは所定のフォルダ名とファイル名にしないといけません。200曲全部を処理するのは大変なのでプログラムを組みました。こちらは自由にお使いください。Macを持っていたらPython3が入っているはずなので動かせると思います。ディレクトリはこのように配置すると良いです。

プログラムを動かすとこんな感じで作られます。

1シート目の127番目が「およげ、たいやきくん」になっていたら成功だと思います。

import glob
import re
import os
import math
import shutil
import sys
# 最大ファイルサイズ
MAX_FILE_SIZE = 128
SHEET_PREFIX = "D231300"
class TargetDirExistException(Exception):
pass
class InvalidIdException(Exception):
pass
def atoi(text):
return int(text) if text.isdigit() else text
def natural_keys(text):
return [ atoi(c) for c in re.split(r'(\d+)', text) ]
def find_files():
return sorted(glob.glob("./*/*.mp3"), key=natural_keys)
def create_dir(dir_path):
if not os.path.isdir(dir_path):
os.mkdir(dir_path)
return dir_path
else:
raise TargetDirExistException(f"想定外のフォルダが存在します。該当フォルダを移動または削除してください。: {dir_path}")
def create_seq_dirs(dir_id, files):
dir_count = math.ceil(len(files) / MAX_FILE_SIZE)
prefix = dir_id[:1]
first_id = int(dir_id[1:])
dir_paths = []
for i in range(dir_count):
dir_paths.append(create_dir(f"{prefix}{first_id + i}"))
return dir_paths
def place_files(files, seq_dirs):
dir_index = 0
target_dir = seq_dirs[dir_index]
i = 0
for file in files:
if i >= MAX_FILE_SIZE:
i = 0
dir_index += 1
target_dir = seq_dirs[dir_index]
continue
shutil.copy2(file, f"{target_dir}/DS{str(i).zfill(3)}.mp3")
i += 1
def main():
try:
print("楽曲フォルダを作成するプログラムです。いつでも Ctrl + C でプログラムは止められます。")
input_string = input(f"{SHEET_PREFIX}より下の桁のシートのIDを入力してください(例: D231300123450 -> 123450): ")
if len(input_string) != 6:
raise InvalidIdException("シートIDは12桁です。")
y_n = input(f"シート: {SHEET_PREFIX + input_string} から楽曲フォルダを作成しますか? (y/N): ")
if y_n == "y":
files = find_files()
seq_dirs = create_seq_dirs(SHEET_PREFIX + input_string, files)
place_files(files, seq_dirs)
print("作成完了")
sys.exit(0)
except TargetDirExistException as tdee:
print(tdee)
sys.exit(1)
except InvalidIdException as iie:
print(iie)
sys.exit(1)
if __name__ == "__main__":
main()
view raw run.py hosted with ❤ by GitHub


最後に、シールを貼ったら完成です。妻が頑張りました。

細かいところは参考に上げたリンクをご覧ください。

MaiYaPenが欲しかったけど高いのでZ会のエブリスピークで代用してみた – BeeLabo


カメレオンリーダー vs エブリスピーク

一応、カメレオンリーダーと比較しておくと

1. かわいさはカメレオンリーダーの方がいい。

2. SDカードのキャップはネジで閉じられているエブリスピークの方がいい。

3. 音質は気にならない。(youtubeなどの紹介では録音のためか音が割れている気がする)

4. 乾電池(エネループも可)のエブリスピークの方が外出先で比較的楽だと思う。(ちなみに、カメレオンリーダーは充電式だけど、USB type-Cじゃないので使いにくそう)


というわけで、1歳になったばかりの娘とこれで遊びたいと思います。


2023年8月17日木曜日

子供が1才を迎えて変化したこと

こんにちは。前回は5月に投稿していたので3ヶ月ぶりの投稿です。

1年前の写真と一緒に撮ると変化がわかりやすいらしい

娘がついに1才を迎えました。去年の今頃、台風の夜中に生まれたことが懐かしく思い出されます。
生まれた時はわりとこれ

伝い歩きするし、「あうあう、バブー」言ってるので運動・知能共に成長しています。
今回は1年経ってどんな変化があったか書きます。

哺乳瓶がいらなくなった


おそらく9ヶ月頃からミルクを飲まなくなりました。もともと離乳食で栄養が賄えているはずなので積極的にあげることはしていませんでしたが、お風呂の後には飲み物を欲することがあり、少し余っている粉ミルクをあげていました。しかし、ある時からミルクを拒否して麦茶を飲みたがるようになりました。たぶん麦茶のボトルがストローなので、哺乳瓶と比べてすぐにたくさん飲めるからなのだと思います。でもおっぱいは飲むんですけどね、不思議です。

ベッドを我が物にする


娘はお風呂に入ってすぐに眠くなります。だいたい8時過ぎにはベッドで寝ています。
ところで、我が家のベッドはソイネールというベビーベッドが隣接(写真参照)していて、ソイネール上で寝かせています。

我が家のベッド環境

そういった環境の中で、娘は非常に寝相が悪く、ソイネールから飛び出して私たちのベッドの上でコロコロ寝返りをうっています。なので、私たちが寝るころには私たちのベッドの中央で寝ていたりします。

娘の状態によってしばしばこうなる

ちなみに、柵をつけていない代わりにベッドの高さは最低にし、下にはクッションマットを敷き詰めて転落してもなんとかなるようにしています。

お風呂が平気になる


髪を洗ったり洗顔したりすると嫌がって泣いていましたが、今では平気になりました。おそらく、保育園で水遊びをしているため、水に慣れてきたことで顔に水がついても平気だと気づいたのだと思います。サンキュー保育園。
伝い歩きもできるので、今ではバスチェアにつかまりながら洗えるようになって楽になりました。

大人でも食べられそうなご飯を食べる


ツナのクリームマカロニパスタという離乳食レシピがあり、よく作っているのですが、大人でも食べられるレベルで美味しいです。離乳食はわりと素朴味が多いのですが、最近は味がついているご飯を食べられるようになっています。
娘は食べる時に自分でちゃんとスプーンを使えたり、手づかみができるようになってきました。もし親が一方的にスプーンで与えようとすると少し嫌そうにします。
ただし、食べ方はまだ赤ちゃんなので辺りに大量に撒き散らしています。手にヨーグルトつけたまま目をゴシゴシしようとすると少しヒヤッとします。

大 惨 事

というところで変化を書いてみました。
もう1年たったのか、と同時に、これからどう成長するのか楽しみです。

2023年6月11日日曜日

離乳食のおやきを作りたくない妻の話

娘に食べられるために生まれてきたおやき群

9ヶ月頃の離乳食には手づかみ食べをするためにおやきが候補にあがってきます。おやきはジャガイモの皮を向き水にしばらくさらしアクを取った後に茹でてマッシュし、さらにここに他の材料を加えて手ごねで形成しフライパンやらで焼いていくのだが、もうたくさんである。やりたくない!そう妻が申しておりました。

しかし、そんなおやき作りに技術革新、またはイノベーション、あるいはブレークスルーが訪れました。

和光堂のおやきミックス

指定分量の粉と水をまぜ、必要な材料を加えていくだけで粘り気のあるおやき生地が完成します。ジャガイモをあれこれしなくてよい。最強である。

100均で買ったミニフライ返しも使って焼く。あんなに「もうおやきは作りたくない!」と申していた妻がウッキウキで踊りながらおやきを量産している。

妻に踊られているフライパン


ちなみに、ホットケーキミックスも同様に最強でした。

ただし、分量が少ないのでお得サイズのミックスを出してほしいー。
あと、株主優待に入れてほしいー。



2023年5月27日土曜日

スプレッドシートでWebサイトをスクレイピングしてセルの中できれいに整形する (IMPORTXML, TEXTJOIN)

はじめに

Googleのスプレッドシートは表計算するだけでなく、あるセルの言語を翻訳したり、データに対してクエリを発行したりできます。
面白い使い方として、IMPORTXMLのような関数を使うと簡単にWebスクレイピングができるので書いておきたいと思います。

スプレッドシートでWebスクレイピング


今回はYahoo! ニュースのトップページにある主要記事のリストを取得しようと思います。
ちなみに重要なことなのですが、スクレイピングを許可していないサイトもありますし、たくさんスクレイピングすると相手に迷惑なので、ほどほどにしましょう。

まず新規でスプレッドシートを作成します。意外に知られてないのですが、ブラウザのURLにsheet.new と書くと自分のGoogle Driveにスプレッドシートが新規作成されます。

シートのセルに対象となるURLを書きます。

 初手B2



スクレイピングしたい対象のXPathを取得します。ブラウザの検証ツール(開発者ツールともいう?)を出し、対象の位置で右クリックをします。するとコピーが出てくるので、そのツリーの中にあるXPathのコピーを選びます。(フルXPathじゃなくていいです)

取得したい箇所を選ぶ

Copy XPathを選ぶ


任意のセルにIMPORTXMLを書くと、少々のローディングのあとに対象である主要記事リストが取れます。



ただ、このままでは読みにくいのでTEXTJOINを使って整形していきます。理想形としては、1つのセルに縦にニュースが並んでいてほしいです。なので、次のようにTEXTJOINを書きます。



これで縦に並んで読みやすくなりました。

おわりに


WebスクレイピングだとBeautiful Soapの印象が強くて「コード書くのかー」という気分になるのですが、それはそれで楽しいのですが、サクッとやりたいことだけやりたいときにスプレッドシートを見ると面白い関数があって良いです。