ゆるおたノート

Tomorrow is another day.

【React】JestとReact Testing Libraryを使いたいのに…

今回は、間違いの例です。

最近、下記を参考にReactを使ったWebアプリの作り方を勉強をしています。

【2025年最新版】0からReactを勉強するならこのロードマップに従え! #TypeScript - Qiita

現在テストを書こうとしていますが、思ったように動きませんでした。
どこが悪いか分からないので、理解が進んだ時のために今回試したことを残しておきます。

node_moduleをインストールする

# Jestのインストール
$ npm install --save-dev jest

# React Testing Libraryのインストール
$ npm install --save-dev @testing-library/react @testing-library/dom

jestの設定

コマンドを追加する

package.jsonscriptsに下記を追加

"scripts": {
  "test": "jest"
}

jestとReact Testing Libraryを連携

ルートディレクトリにjest.config.cjsというファイルを追加し、下記を記入する

module.exports = {
  setupFilesAfterEnv: ["@testing-library/jest-dom"],
  testEnvironment: "jest-environment-jsdom",
};

テストを書いてみる

テストケースの作成

srcディレクトリにtestディレクトリを追加し、その中にtruthy.test.jsを作成する

describe('true is truthy and false is falsy', () => {
  test('true is truthy', () => {
    expect(true).toBe(true);
  });

  test('false is falsy', () => {
    expect(false).toBe(false);
  });
});

テストしてみる

ターミナルで下記を実行

# 実行
$ npm test

# 結果
> my-study-log@0.0.0 test
> jest

 PASS  src/test/truthy.test.js
  true is truthy and false is falsy
    √ true is truthy (1 ms)false is falsy

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        0.52 s
Ran all test suites.

通った。

レンダリングもテストしてみる

1回目

テストケース

testディレクトリにApp.test.jsを追加し、npm testしてみる

import React from 'react';
import { render } from '@testing-library/react';

import App from './App';

describe('App', () => {
  test('renders App component', () => {
    render(<App />);
  });
});
実行
# 実行
$ npm test

# 結果
> my-study-log@0.0.0 test
> jest

 FAIL  src/test/App.test.js
  ● Test suite failed to run

    Jest encountered an unexpected token

    Jest failed to parse a file. This happens e.g. when your code or its dependencies use non-standard JavaScript syntax, or when Jest is not configured to support such syntax.

    Out of the box Jest supports Babel, which will be used to transform your files into valid JS based on your Babel configuration.

    By default "node_modules" folder is ignored by transformers.

    Here's what you can do:
     • If you are trying to use ECMAScript Modules, see https://jestjs.io/docs/ecmascript-modules for how to enable it.
     • If you are trying to use TypeScript, see https://jestjs.io/docs/getting-started#using-typescript
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation, specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/configuration
    For information about custom transformations, see:
    https://jestjs.io/docs/code-transformation

    Details:

    SyntaxError: C:\React\my-study-log\src\test\App.test.js: Support for the experimental syntax 'jsx' isn't currently enabled (8:12):

       6 | describe('App', () => {
       7 |   test('renders App component', () => {
    >  8 |     render(<App />);
         |            ^
       9 |   });
      10 | });

    Add @babel/preset-react (https://github.com/babel/babel/tree/main/packages/babel-preset-react) to the 'presets' section of your Babel config to enable transformation.
    If you want to leave it as-is, add @babel/plugin-syntax-jsx (https://github.com/babel/babel/tree/main/packages/babel-plugin-syntax-jsx) to the 'plugins' section to enable parsing.

    If you already added the plugin for this syntax to your config, it's possible that your config isn't being loaded.
    You can re-run Babel with the BABEL_SHOW_CONFIG_FOR environment variable to show the loaded configuration:
        npx cross-env BABEL_SHOW_CONFIG_FOR=C:\React\my-study-log\src\test\App.test.js <your build command>
    See https://babeljs.io/docs/configuration#print-effective-configs for more info.

めっちゃ怒られた…

2回目

テストケース

<という文字が認識できないらしいので、&lt;に変えて実行してみた

import React from 'react';
import { render } from '@testing-library/react';

import App from './App';

describe('App', () => {
  test('renders App component', () => {
    render(&lt;App />);
  });
});
実行
# 実行
$ npm test

# 結果
> my-study-log@0.0.0 test
> jest

 FAIL  src/test/App.test.js
  ● Test suite failed to run

    Jest encountered an unexpected token
~以下略~

…変わらない。

3回目

ちょっと変える

エラー文を読むと下記のように言っているので、@babel/preset-reactも追加してみる。

Add @babel/preset-react (https://github.com/babel/babel/tree/main/packages/babel-preset-react) to the 'presets' section of your Babel config to enable transformation.

(変換を有効にするために、Babelの設定ファイルのpresetsセクションに@babel/preset-reactを追加してください)

# `@babel/preset-react`を追加してみる
$ npm i -D @babel/preset-react

ルートディレクトリにbabel.config.jsonを作成する

{
  "presets": ["@babel/preset-react"]
}
テストケース

2回目と同じなので省略。

実行
# 実行
$ npm test

# 結果
> my-study-log@0.0.0 test
> jest

 FAIL  src/test/App.test.js
  ● Test suite failed to run

    Jest encountered an unexpected token
~以下略~

…変わらない(2度目)。

どうして???

試しに、こちら↓を参考に新しくプロジェクトを作成してみたら、レンダリングのテストも出来た。

Reactコンポーネントのテストを書こう | TypeScript入門『サバイバルTypeScript』

違いが分からないので、とりあえずプロジェクトを作り直そうかな…

もう1度だけ試す

4回目

テストケース

成功したケースを参考に、書き方を変えてみる
(よく分かってないから間違いはあるかもだけど…)

import React from 'react';
import { render } from '@testing-library/react';

import App from './App';

test("タイトルが取得できる", async () => {
  render(<App />);
  const title = screen.getByText("学習記録アプリ");
  expect(title).toHaveTextContent("学習記録アプリ");
});
実行
# 実行
$ npm test

# 結果
> my-study-log@0.0.0 test
> jest

 FAIL  src/test/App.test.js
  ● Test suite failed to run

    Jest encountered an unexpected token
~以下略~

…変わr(3度目)。だめだこりゃ。

参照

ちなみに

現在作っている課題のアプリはこちらです。

アプリ

my-study-log-v2

GitHub

GitHub - yuricks7/my-study-log-v2: Reactの練習用リポジトリv2です。 · GitHub

【Git勉強中】プルリクエストの作り方

最近、下記を参考にReactを使ったWebアプリの作り方を勉強をしています。

【2025年最新版】0からReactを勉強するならこのロードマップに従え! #TypeScript - Qiita

今日は、GitHub Actionsでfirebaseのプロジェクトを更新(デプロイ)する方法を学習しました。
今日の内容では、こちらの記事が大変参考になりました。

ReactプロジェクトをGitHubActionsを使ってFirebaseへ自動デプロイする手順 #cd - Qiita

ところが、プルリクエスト(以下、PR)するところで詰まってしまいました。 今までは、1人でGitHubを触っていてPRする理由が無かったので、PR自体初体験でした。

そういうわけで、普通の人は遭遇しないのか、自力で調べたら解決に半日かかってしまったので、忘れないうちに対策をここに残しておきます。

状況

今回はテストしたかっただけなので、mainブランチで作業してリモートリポジトリにプッシュしました。

ところが、プッシュは出来ましたが、プルリクエストするボタンが出ません。

New Pull Requestというボタンはありますが、そこを押しても、PRのタイトルや本文を書く欄が一向に現れませんでした。

原因

慣れている人ならもうお分かりかもしれませんが、今回はmainブランチで作業していたのが原因でした。

HEADブランチにマージしたい内容を提出する場面なので、当然かもしれませんが、これに気付くまでに時間が掛かりました。

対策

作業を始める段階から、ブランチを切る必要がありました。

$ git switch -c <ブランチ名>

そして、コーディングが出来たらステージング→コミットと進みます。

$ git add .
$ git status
$ git commit -m "<コミットメッセージ>"

コミットが出来たら、その作業ブランチからリモートにプッシュすれば良いようです。

$ git push origin <ブランチ名>

すると、GitHubのリポジトリを見に行くとCompare & pull requestというボタンが出現するので、そこでPRができるようになります。

疑問

ただ、「このときmainブランチはどうするんだろう」という疑問がまだ解決していません…

この記事のことを考えると、リモートにプッシュしてからローカルでマージすることになりますが、これは二度手間な気がしています。
どなたか詳しい人教えていただけませんか…><

参照

ちなみに

現在作っている課題のアプリはこちらです。

アプリ

my-study-log-v2

GitHub

GitHub - yuricks7/my-study-log-v2: Reactの練習用リポジトリv2です。 · GitHub

【Git勉強中】ブランチを削除しようとしたら少し手間取った話。

こちらの記事は、下記URLに移転しました。
約3秒後に自動的にリダイレクトします。

ジャンプしない場合は、下記をクリックしてください。

新記事はこちら

【Git勉強中】ブランチを削除しようとしたら少し手間取った話。 - ゆるおたノート

【Git勉強中】ブランチを削除しようとしたら少し手間取った話。

こちら↓の勉強で、久しぶりにGitを触りました。

【2025年最新版】0からReactを勉強するならこのロードマップに従え! #TypeScript - Qiita

使い終わったブランチを削除しようとしたらすんなりできなくて少し困ったので、忘れないうちに備忘録として残しておきます。

状況

コーディングしてコミット→プッシュが終わったので、用済みになったブランチを削除しようとしたら、こんなエラーメッセージが出て削除を拒否されました。

error: cannot delete branch '{ブランチ名}' used by worktree at '{プロジェクトのディレクトリ}'

「このブランチは削除できない」と言われています。
エラー文って、なぜそうなるのかは書いてくれないんですよね…多種多様だから仕方ないのだけど。

原因

少し調べてみると、このエラーの原因は下記の通りのようです。

具体的には次のどちらかです:

  • 自分がそのブランチにいる(チェックアウトしている)
  • 別の作業ディレクトリ(worktree)でそのブランチが開かれている Gitでは、

👉 使用中のブランチは削除できない というルールになっています。

Gitで「cannot delete branch」エラーが出たときの原因と対処法 #error - Qiita

つまり、他のブランチに移動しないとブランチの操作は受け付けてくれないんですね。

ブランチを削除する手順

そんなわけで、ブランチの削除方法を簡単にまとめます。

[1] 作業ブランチから抜けて、mainブランチに移動する

いったん作業ブランチとは別のブランチ(今回はmain)に移動します。

$ git switch main

ブランチの移動について、詳しくは下記もご参照ください。

【Git勉強中】ブランチの移動を使い分けたい - ゆるおたノート

[2] ここまでの変更を、mainブランチにまとめる

mainに更新が反映されていない場合は、統合しておきます。

$ git merge --ff {削除するブランチ}

これをしないと、このような↓エラー文が出ます。

error: The branch '{ブランチ名}' is not fully merged. If you are sure you want to delete it, run 'git branch -D {ブランチ名}'.

強制削除でもいいのかもしれませんが、それまでの更新を無くさないようにする必要があるかも?

また、マージについて、詳しくは下記もご参照ください。

【Git勉強中】自分のコミット履歴を提出する - ゆるおたノート

[3] 改めて削除する

これで通常なら削除できるはずです。

$ git branch -d {削除するブランチ}

これで削除出来なかったら、下記の参照記事がエラーの原因も含めてそれぞれ詳しく書かれているので参考になるかと思います。

参照

ちなみに

現在作っている課題のアプリはこちらです。

アプリ

my-study-log-v2

GitHub

GitHub - yuricks7/my-study-log-v2: Reactの練習用リポジトリv2です。 · GitHub

【GitHub Pages】ブランチ名を変えたら、Pagesも設定が必要らしい

このブログでは、カスタマイズに使うスクリプトやCSSをGitHub Pagesで管理しています。

しかし、先日少しスクリプトを変更したのですが、何度プッシュしてもPagesは新しくなりませんでした。

少しGoogle先生で調べてみると、反映には数時間~数日かかるとの情報も。
試しに待ってみましたが、変わりませんでした。
ただ、いつもは長くても1分ほどで変わっていたので、これは違うのではないかと思っていました。

そういえば

…と、ふと数ヶ月前にリモートのブランチ名をmasterからmainに変えたことを思い出しました。

【Git】ブランチ名を変えたらPushできなくなった - ゆるおたノート

ここで、Pagesではなくリポジトリの中を見てみると、URLが2つ存在することに気づきました。

https://github.com/{ユーザ名}/{リポジトリ名}/blob/master/{ファイルのパス}
https://github.com/{ユーザ名}/{リポジトリ名}/blob/main/{ファイルのパス}

Pagesもブランチごとにデータが管理されているようなのです…

つまり、いつまで経っても更新されなかったのは、masterブランチのデータで出力されていたからでした。

設定の変更方法

ということで、GitHub Pagesでもブランチを変更する方法を記録しておきます。
とは言っても、難しいことは無いのですぐ終わります。

  1. 画面上部のタブから、Settingsを選択

  2. 画面左のPages→画面中ほどのBranch→作成したブランチ(ここではmain)の順に選択

  3. Saveをクリックして、完了

これで1分程度待てば、Pagesは新しいブランチのデータで表示されます。

まとめ

「GitHub関係のデータが更新されない時は、ブランチの違いを疑え」が今日の学びでした。

きっとまたどこかで異常がありそうですが、これを思い出せますように…

参照

Git初心者がGitHub PagesによるWebページ公開方法をまとめてみた #初心者エンジニア - Qiita

【Ruby】VSCodeでSolargraphのインテリセンスを使えないのは、ワークスペースの設定を間違えていたからだった

去年末ごろからRubyを勉強していますが、環境構築で苦労しています。

rbenvは何とか入れられたのですが、拡張機能でエラーばかり。
特にインテリセンスの味方、Solargraphは、どんなに調べてその通りに設定してもエラーは消えませんでした。
正直堪えました。独学の限界かとしばらく諦めていました。

でも、ふと今日Copilotさん(別名ChatGPTさん)のことを思い出しまして。
今回の問題について聞いてみたところ、なんとすんなり解決しました。
悔し半分うれし半分ですが、忘れないうちにその記録を残します。

現在の状況

Windows11に下記2つのRubyが入っています。

OS Rubyの環境 バージョン
Windows11 Ruby Installer+devkit ruby 3.4.8
WSL2 rbenv ruby 4.0.1

パスが正しくない?

エラー文①

当初はWindows側にRubyとSolargraphをインストールしていたのですが、バージョン管理も兼ねてrbenvに移行しました。
すると、VSCodeを開く度に下記のエラーが出るようになりました。

Failed to start Solargraph: ******* No Such File or Directory

(スクショを撮り忘れてしまったので記憶を頼りに書いていますが、表現が違ったらごめんなさい。)

対処

ファイルの場所が分からないとのことだったので、VSCodeのsettings.jsonで参照するパスをWSL側のGemに変更しました。

"solargraph.commandPath": "\\wsl.localhost\\Ubuntu\\home\\{ユーザー名}\\.rbenv\\shims\\solargraph",

RubyのプロジェクトはWSLの管理下にない?

エラー文②

今度は下記のようなエラーでした。

Failed to start Solargraph: '\wsl.localhost\Ubuntu\home\{ユーザー名}\dev\Ruby'   L ̌  ݂̃f B   N g     CMD.EXE    J n   ܂    B UNC  p X ̓T   g    ܂   BWindows  f B   N g        Ŏg p   ܂  B Could not locate Gemfile or .bundle/ director

文字化けが発生しているので、たぶんOS関係が良くないのだと思っていたのですが…

対処

Copilotさんに聞いてみたところ、

結論:原因は「VSCodeがWSLモードで開かれていない」

からとのこと。

ここで私も結論から言うと、この手続きで無事Solargraphは起動できて、インテリセンスも効くようになりました。
チャッピーありがとう!

どうやって戻ったか。

以下、少し長いですが、Copilotさんの指示と私の環境を構成し直してここに書き残します。
※Copilotさんと私で色を変えようかと考えましたが、ただでさえガチャガチャな画面なので今回は省略します。

【1】VSCodeをWSLモードで開き直す

ターミナルで次を実行。

$ cd ~/dev/Ruby
$ code .

これで VSCode が WSL 内で起動する。
(今は Windows 側で開いてしまっているため UNC パス扱いになっている)

【2】VSCodeの左下が「WSL: Ubuntu」になっているか確認

左下のステータスバーが「WSL: Ubuntu」になっていればOK。

ここが 普通の「Windows」表示になっていると、SolargraphはWindows側でRubyを探してしまう。
左下がWSL: Ubuntuになっているか確認してみて。

もしこうなっていなければ、次のようにWSLに切り替える。

WSLに切り替えてVSCodeを使う
  1. 画面左下の><のようなボタンをクリック

  2. 画面上部のディストリビューションを使用してWSLに接続…を選択

  3. Ubuntu 既定のディストリビューションを選択

  4. 左下が>< WSL: UbuntuになっていればOK。

ターミナルなら、これをまとめて下記でOK。

$ cd ~/dev/Ruby
$ code .
【3】Solargraph を WSL 内にインストール
Bundlerを使う場合

ターミナルで下記を実行

$ gem install solargraph

# プロジェクトに`Gemfile`があるならこれ↓も
$ bundle add solargraph # gemを追加
$ bundle install        # 再インストール

Gemfilesolargraphがあるか確認して、無ければ追加しておく。

gem 'solargraph'

Solargraph は Bundler を使う設定だと、Gemfile が無いと起動しない。

さらにVSCodeのsettings.jsonも変更する

"solargraph.useBundler": true,
Bundlerを使わない場合
$ gem install solargraph

VSCodeのsettings.jsonを変更する

"solargraph.useBundler": false,
【4】それでも動かない場合の追加チェック

原因切り分けのため、改めて確認。

RubyがWSL側で動いているか
ruby -v
gem -v
SolargraphがWSL側に入っているか
solargraph -v

インストールは出来ているらしい

私の環境では、バージョンはすべて表示されました。

$ cd ~/dev/Ruby

$ ruby -v
ruby 4.0.1 (2026-01-13 revision e04267a14b) +PRISM [x86_64-linux]

$ gem -v
4.0.3

$ solargraph -v
0.58.3

そのことをCopilotさんに報告すると、

Ruby / Gem / Solargraphが全部バージョン表示される=WSL側のRuby環境は正常に動いているということ。
つまり、問題はRubyではなくVSCodeがWSLのRubyを使えていないことにほぼ確定する。
ここからは、原因をさらに絞り込んでいくよ。

とのこと。

「まんまAI構文だな…」というのは置いといて、私の中で、原因がRubyではないというのは大きな発見でした。
何か月もずっとRubyかGemのインストールの問題だと思って、エラーコードと闘っていたからです。

Copilotさん、次の指示は…?

【5】改めて、「VSCode左下が『WSL: Ubuntu』になってる?」

いま1度【2】を確認。

【6】VSCodeの拡張機能「Ruby Solargraph」はWSL側にインストールされてる?

VSCodeの拡張機能はWindows側とWSL側で別管理されている。
確認方法:
- VSCode左下が「WSL: Ubuntu」になっている状態で
- 拡張機能タブ(Ctrl+Shift+X)を開く
- Solargraphの横に「WSL: Ubuntu」と表示されているか確認
もしWindows側にしか入っていなければ、WSL側にもインストールしてね。

これは知りませんでした。
早速WSL側にもSolargraph(とShopify版のRuby LSP)を導入しました。

【7】ここまでやってもダメなら、ログを見よう

VSCode のコマンドパレット(Ctrl+Shift+P)でDeveloper: Toggle Developer Toolsを探す

→ Console に Solargraph のエラーが出ているはず。

結果

「WSL: Ubuntu」で開き直してログを見ると、2つのエラー文が出力されていました。

Failed to start Solargraph: Could not locate Gemfile
Couldn't start client Ruby Language Server

これを報告すると、

了解、ここまで来ると原因はかなり絞れてきたよ。
「WSLで開くとSolargraphがGemfileを見つけられない」
「Ruby Language Serverも起動しない」
この2つが同時に出るときは、ほぼ確実にVSCodeがプロジェクトのRuby環境を正しく認識できていない。
ここからは、原因を順番に潰していくね。

でした。

インストールは出来ているのに認識できないなら、どこかに初歩的なミスがあるのか…?

Solargraphはどこ?ていうかディレクトリは合ってるの?

【8】Solargraphが出しているエラー:
Could not locate Gemfile

これはSolargraphが見ているフォルダにGemfileが無いという意味。

(1) 今VSCodeで開いているフォルダにGemfileは存在する?

WSLのターミナルで下記を実行。

$ ls -l

私の環境では、下記の通りでした。

total 24
-rw-r--r-- 1 {ユーザー名} {ユーザー名}   92 Jan 21 09:25 Gemfile
-rw-r--r-- 1 {ユーザー名} {ユーザー名} 2210 Mar 28 11:37 Gemfile.lock
drwxr-xr-x 2 {ユーザー名} {ユーザー名} 4096 Mar 20 16:57 config
drwxr-xr-x 4 {ユーザー名} {ユーザー名} 4096 Mar 20 16:58 docs
drwxr-xr-x 3 {ユーザー名} {ユーザー名} 4096 Mar 20 16:58 projects
drwxr-xr-x 2 {ユーザー名} {ユーザー名} 4096 Mar 20 16:57 vscode
(2) 出力にGemfileがある?
  • ある → 次のステップへ
  • ない → Solargraphは BundlerモードなのでGemfileが無いと動かない
    • VSCodeの設定でsolargraph.useBundlerをOFFにする必要がある

私の場合は、Gemfileがあるので次へ。

【9】VSCodeは本当に「プロジェクトのルート」を開いてる?

よくある落とし穴:

  • VSCodeが~/dev/Rubyではなく~/dev~/dev/Ruby/some_subfolderを開いている

これだとSolargraphGemfileを見つけられない。

VSCodeの左側の一番上のフォルダ名は?

例:Rubyになっている?

もし違うなら、WSL で:

$ cd ~/dev/Ruby
$ code .

で開き直してみて。

私の場合は、RUBY [WSL: UBUNTU]でした。

なるほど、左上がRUBY [WSL: UBUNTU]になっているなら、「VSCodeがWSLモードで開けていない」という問題はクリアしているね。
ここまで来ると、次に疑うべきはSolargraphが見ているフォルダと、実際のGemfileの場所がズレていること。

結論に近づいてきたようです。

【10】今開いているフォルダの直下に Gemfile は本当に存在する?

WSL のターミナルで

$ cd ~/dev/Ruby
$ ls -l

この出力にGemfileがある?

Gemfileが無い場合

SolargraphBundlerモードだとGemfileが無いと絶対に起動しない。
その場合は【3】に戻って再確認。

私の場合はGemfileを使っているので、これは該当しません。

Gemfileがあるのに「Could not locate Gemfile」が出る場合

これはSolargraphが別のフォルダを見ている可能性が高い。

  • よくあるパターン
    • VSCodeが~/dev/Rubyを開いているつもりが、実は~/dev/Ruby/RUBYみたいな二重フォルダになっている
    • Windows側のパスが混ざっている
    • Solargraph のワークスペース設定がズレている

私の場合、これが問題でした。

RubyやGemがインストールされているプロジェクトのルートディレクトリ(以下、ルート)の中に、勉強用と開発用でそれぞれディレクトリがありました。

[Ruby] ─ [勉強]
       │  └Gemfile
       └ [開発]

Gemfileはよく使う勉強用ディレクトリの中に置いていました。
ターミナルでも、ルートではなく勉強用で作業していました。

でも、これはルートディレクトリではないわけで、結果、WSL(と私)の中で混乱を招いていました。

結局、修正すべきはここ。

Gemfileの場所

Gemfile(とGemfile.lock)をルートに移動して、作業フォルダもルートに変更。

[Ruby] ─ <Gemfile>
       ├ <Gemfile.lock>
       ├ [勉強]
       └ [開発]

作業ディレクトリ

$ cd {プロジェクトのルートディレクトリ}
$ code .

これでルートで開き直して、{プロジェクト名}.code-workspaceで保存。

WSLモードで開き直す

VSCodeで開いたら、画面右下のポップアップ↓からReopen Folder in WSLをクリックしてWSLモードで開き直す。

問題解決!

ここまでで、やっとインテリセンス問題解決!

ここ数か月間の問題が、やっと解消しました…

ただ… → これも解決!

このままだと、Rubyのワークスペースを開く度、ポップアップが消える前にReopen Folder in WSLをクリックする必要があります。
めんどくさいのでこれを不要にしたいのですが、少し調べてみた感じだと適切な設定項目まではまだ分かりませんでした。

しばらくはちょっとめんどくさい操作になりそうです…

<2026/03/31追記>
操作してたら見つけました。

  1. ポップアップのReopen Folder in WSLをクリック

  2. タスクバーに[WSL: Ubuntu]と付いているワークスペースをピン止め

以降タスクバーから2.のワークスペースを開くようにすることで、Ubuntu経由でRubyを使えるようになりました。

参考

今回は直接解決に繋がりませんでしたが、とても勉強になりました。

Solargraphのインストール

gemのインストール全般

Gemfileの書き方

Solargraphのエラー対策

Ruby LSPの導入

VSCodeでWSLを使う環境構築

【Google Apps Script】APIへのリクエストを少しでも楽にしたい人のためのライブラリを作ってみた

RESTfulなWeb APIへのリクエストが、ちょっとだけ書きやすくかつ読みやすくなるライブラリです。

個人的にAPIの利用は苦手だったのですが、これで少しラクになりました。

プロジェクト

ライブラリ名 識別子 プロジェクトID
20200604_RestApiHelper RestApiHelper 1_TDv0sV9l82h85UPEQ5JQZNSUyRGGyBX3J5LWQl7PL7pSfvkfdIPgDHa

ソースコード

GitHub - yuricks7/GAS_Library_RestApiHelper: (後日、一般公開予定)GASでREST APIを扱いやすくするためのライブラリです。 · GitHub

サンプル

function myFunction() {
    // リクエストメソッド用のクラス
  const headers     = { "Accept": "application/json", };
  const apiOperator = RestApiHelper.load(headers);
  const url  = 'https://weather.tsukumijima.net/api/forecast/city/080020';
  const json = apiOperator.GET(url);

  console.log(json);
}

ご意見募集中

念のため自分でも確認していますが、特性上、どこかに間違いがあるかもしれません。
お気づきの点がありましたら、コメントやフォームでご連絡いただけると嬉しいです!

【Google Apps Script】Slackの記号をまとめました。

ライブラリ作成練習↓の続編です。

【Google Apps Script】Slackに投稿するだけのライブラリを作ってみた - ゆるおたノート

基本はMarkdown記法のようですが、ところどころ違ったりして覚えるのが面倒なので、ライブラリにまとめてみました。

プロジェクト

ライブラリ名 識別子 プロジェクトID
20250922_SlackSymbols SlackSymbols 1o_MvHyK4ZrAJdbNWbwuYODBAmGW9bv9SMENco7uN2jbNiM5y1rhfEcUi

ソースコード

GitHub - yuricks7/GAS_Library_SlackSymbols: Slack記法で使用する記号を集めたライブラリです。 · GitHub

サンプル

let m = '';
const symbols = SlackSymbols.load();
const bold = symbols.bold;
const lf   = symbols.linefeed;

m += `${bold}【本日の天気】${bold}${lf}`;
m += `本日は、おおむね晴れでしょう。${lf}`;

m += `${bold}【現在の天気】${bold}${lf}`;
m += `薄い雲が広がっていますが、次第に晴れ間が出ます。${lf}`;

console.log(m);

ご意見募集中

念のため自分でも確認していますが、特性上、どこかに間違いがあるかもしれません。
お気づきの点がありましたら、コメントやフォームでご連絡いただけると嬉しいです!

2025年買ってよかったもの、そうでもないもの

新年あけましておめでとうございます。
ふと思い立って、年は明けてしまいましたが、いつか書いてみたかったいわゆる「ベストバイ」記事を書いてみることにしました。

誰かの参考になりますように。

買ってよかった!

静音マウス

会社で買ってもらったマウスの使用感がとても良くて、同じものを買った。
それまで使っていた1代目静音マウスは、サブとして使うことにした。

静かなのはもちろん、ある程度大きさと重さがあるので、手にフィットして疲れにくい。

ただ、ポインターの移動がちょいちょい遅くなるのが玉に瑕。
裏面の電源をon/offすると直るけど、地味に不便なところ。

Apple Watch

長らくfitbitを使っていた。
運動記録はそれで充分だったが、そのほかの体調の記録はiOSのヘルスケアアプリを使用していた。
そのせいで記録がバラバラになってしまって、どうせならiOSで統一したかった。

結果、純正アプリのおかげで、記録も見返すのも楽になった。
見返すのはほかのアプリ(元々これを使いたかったのもある)も併用しているけど。

また、iPhoneの通知が飛んでくるのも、iPhoneが手元にないときに内容を確認出来てとても便利。
目覚ましやタイマーを手元で操作できて快適。

Fire HD 8 タブレット

厳密に言うと買ったのは2024年の夏だけど、2025年になってから活躍。

これまで本は好きだけど読むのが遅くて、読書がなかなか習慣にならなかった。
ところが、これを買ってみたら不思議なことに苦痛が減った。
行間や文字サイズを調整出来たりして、読み易さを調整できたおかげだと思う。
「目が滑って読めない」タイプの方は、この辺をいじるのをオススメする。
ただ、私の場合、ルーラーは効果が無かったのでオフにしている。

ページを飛ばしたりするのは少し不便だけど、それを補って余りある文明の利器だと思う。

エアタグ

※カエレバで商品が見つからなかったので、こちらだけAmazonへのリンクです。

最近失くしものが多い母へ、丸いキーホルダー型タイプと財布に入るカード型タイプをプレゼント。

先日さっそく家の鍵を紛失してしまい、Androidの対応アプリで探してみた。
結果、タグの音が鳴ったのは母のジーパンのポケットから。
笑って済んだからよかったけど、ちょっと気が抜けた。
ともかく見つかって良かった…

初期設定はアプリがタグをなかなか認識してくれなくて苦労したけど、それ以外は便利に使っている。

体組成計

fitbitやiOSの純正アプリは表示項目が少ないので、体重の記録はスプレッドシートにして、自分でグラフを作っていた。
でも、やっぱり手入力はめんどくさい。

その両方(表示項目や手入力の手間)を解決してくれたのが、コレ。

アプリを開いて体重計に乗るだけで、計測開始→記録までしてくれる。
体重計のボタン操作が無いのが地味に便利。

ただ、時々アプリを認識できないのか記録が残らないこともあるので、この辺は後継機種に期待かな?

失敗した…

Apple Watchの画面フィルム

レビューがやたら良かったので買ってみた。

貼ってすぐは画面がキレイに見えてとても満足だったが、2,3日で外周が剝がれてホコリらしきもので白くなってしまった。

商品についていた「レビューで★5にすると割引」商法は信用しちゃいけないと学んだ。

キッズサイズTシャツ

※これは商品が悪いのではなく、私が選択を間違えたものです…

良さげな色とサイズ(160cm)があったのでギャンブル的に買ってみたのだけど、やっぱり子供向けらしく腕がピチピチだった。

レディースと大きめキッズサイズは互換性無いのか…

そんなわけで

振り返ってみると、ガジェット関係が多いですね。お金ないのに。
真新しいものも少ないですが、日々の生活に直結するお買い物が多かった気がします。

無駄遣いには気をつけて、今後もいいものを探していこうと思います。
本年もよろしくお願いいたします。

【Google Apps Script】自分用コーディングガイドライン

最近、ちまちまとGASのスクリプトを練習しています。
書き方が固まってきたので、頭を整理する意味でGAS用のコーディングガイドラインも残すことにしました。

大半はVBAの記事から引用したものも多いので、読んだことのある方は遠慮なく飛ばし読みを!

【VBA】自分用コーディングガイドライン - ゆるおたノート

このページについて

想定読者

  • 作成者自身で使用する場合や、熟練者同士のコーディングなどにはそぐわない部分もあるかもしれません。
    あらかじめご了承ください。

  • 他の誰かが作ったものを改修する場合は、当ページの内容より作業中のルールを優先することとします。

優先度

各項目の【】の部分は、下記の順に優先としています。

優先度 意味
MUST 必ず守る
BETTER 迷ったらこっち。絶対ではない。
WISH 検討中・勉強中。

VBAの記事と同様、クックパッド社のコーディング規約を参考にさせて頂きました()。

ただし、コーディングに自信があるわけではないので、2つ目はSHOULD(~すべき)ではなくBETTER(~した方が良い)としています。

全体

【MUST】コードの長さの制限

特別な理由がない限り、1つの関数は「1行100字程度×35行程度」までにする。

文字列の連結等で1行が長くなる場合は、再代入を積極的に使用する。
(並行して、コードの縦のラインが揃うように必ずレイアウトに気を使うこと。)

処理の分岐等でこれを超える場合は、関数の切り出しを検討する。

【MUST】省略せずに明記する

省略形は極力使わず、単語を明記する。
ただし、プログラミング用語として普及していて、運用担当者が一瞥で誤読なく識別できるものであれば、使用しても良い。

ビジネス用語などの所謂「横文字」の言葉も、可能な限り別の表現に言い換える。

これは、可読性が運用担当者のバックグラウンドに左右されやすいため。
間違いなく共通認識があるものは、この限りではない。

なお、インテリセンス(入力補完)を積極的に使用することとし、一般に普及している語句であれば~ation系の長い単語も使用可とする。

【BETTER】それ自体に意味を持たない単語を避ける

(日本人が)イディオムとして認識しやすい言葉を除き、その単語自体で意味を判別できない単語は、可能な限り使用しないようにする。

▼例
  • 動詞

    • do
    • make
    • take
    • have
    • set
    • get
  • 形容詞・名詞

    • target

【BETTER】数値の表現

単語 使いどころ
Count 数え上げる時
Number ~の番号、数値の計算

【BETTER】前置詞

識別子1つあたり1つまでとする。
A of Bは、B Aと表現できることも多いので、言い換えが出来ないか検討する。

イディオム等を使用するときは、関数やメソッド名などの末尾に前置詞を置くと英文として読みやすくなる(気がする)。

コメント

全体

【MUST】読めば分かることは書かない

コードは主に英語を使用するが、コメントは日本語で書く。
しかし、コメントが「ただの翻訳」になってしまう時は、そもそも変数名や関数名を変更した方がスマートになることが多いので、検討すること。

数カ月後の自分が「コードを読むだけで処理の内容を把握できるもの」を目指すこと。

【MUST】操作の意図を示す

同じ結果を得るのに複数の選択肢がある場合や、何らかの処理を飛ばすような場合には、「なぜそうしたのか」を残すこと。
(後で考慮漏れを検証しやすくするため)

コメント

【BETTER】要約コメント

複数行に渡る処理には、段落分けの意味で要約コメントを付与してもよい。
(併せて処理の区切りごとに空行も必ず挟むこと。)

【BETTER】エラーの可能性の示唆

分かる範囲で。

「何が起こるとエラーになるのか」を記す。

資料として、ベン図やパターンの列挙があると尚良し。
(後で考慮漏れを検証しやすくするため)

ドキュメンテーション・コメント

【MUST】関数ごとに記載する
  • 再利用しやすくするため、小分けした関数、メソッドごとにコメントを記載していく。
【MUST】書式

下記の書式とする(不要なものは削除しても良い)。

/**
 * ●概要●
 * 
 * - 【note】
 * 
 * - 【参考】
 *   - ●記事名● | ●サイト名●
 *     ●URL●
 * 
 * - 【参考】
 *   - ●著者●(●発行年●)『●タイトル●』●出版社●
 *     ●URL●
 *     第●版第●刷(p.●●●)
 * 
 * @param {●型●} name - ●概要●
 * @param {●型●} name - ●概要●
 * @param {●型●} name - ●概要●
 * 
 * @return {●型●} - ●概要●
 */

(記号が多いのは、個人的に書き忘れ・消し忘れを防ぐためです。)

【BETTER】必要なデータの例示
  • 「何」が「どうなっている」と「どう出るのか」を例として記す。
    (後で考慮漏れを検証しやすくするため)
【BETTER】エラーの可能性の示唆
  • 分かる範囲で。

  • 前項に関連して、「何が起こるとエラーになるのか」を記す。

  • ベン図やパターンの列挙があると尚良し。
    (後で考慮漏れを検証しやすくするため)

【BETTER】5W1Hの明記

曖昧な表現になりそうな時は、省略せずすべて記載する。

5W1H 意味
When いつ
Where どこで
What 何を
Who/Whom 誰が/誰に
Why 何のために
How どのように

プロジェクト

全体

【MUST】命名規則

{作成日}_プロジェクト名とする。
なお、プロジェクト名は、アッパーキャメルケース記法とする。

20251130_YuruwotaNoteMaker

ファイル

【MUST】命名規則

メイン処理をindex.gs、テスト関数をtest.gsで固定、各クラスを{クラス名}.gsとする。
なお、クラス名はアッパーキャメルケース記法とする。

【MUST】フォルダ分け

index.gstest.gsのみMainフォルダ、クラス.gsやHTML関係をSubフォルダに分類して格納する。
これは、ファイルがアルファベット順で自動的にソートされるので、視認性を上げるのが主な目的。

Main/index.gs
Main/test.gs
Sub/HTML/index.html
Sub/HTML/style.html
Sub/Props.gs

また、ライブラリの作成時などで、使い方を説明するときはMainフォルダにsample.gsを追加しても良いが、test.gsと内容が被ることもあるので必要性を検討した上で追加すること。

ライブラリ

【MUST】命名規則

ライブラリ作成側は{作成日}_識別子とする。
なお、識別子はアッパーキャメルケース記法とする。

20251130_YuruwotaNote

ライブラリ使用側は、エラーにならないように{作成日}_を削除し、識別子のみとする。

YuruwotaNote
【BETTER】クラスの使用

まとめられる処理は、積極的にクラスとしてまとめる。

その際、クラス全体を無名関数に隠し、インテリセンスの候補として表示させる準備をする。

(function(global){
  /**
   * YuruwotaNoteクラス
   */
  class YuruwotaNote {
    method() {
      // 処理
    }

  global.YuruwotaNote = YuruwotaNote;
})(this);

さらに、インテリセンスの候補に表示させたいメソッドは、index.gsへ擬似的なグローバル関数として定義しておく。

/**
 * YuruwotaNoteをインスタンス化するためのファクトリメソッド
 * 
 * @return {YuruwotaNote} YuruwotaNoteクラスのインスタンス
 */
// ↑`@return`の{}の中にライブラリのGASプロジェクトと同じ名前を指定する。
function load() {
  return new YuruwotaNote();
}

// 補完させたいメソッドのダミーメソッドをグローバルメソッドとして作る。

/**
 * メッセージをYuruwotaNoteに投稿する
 *
 * @param {string} message - 作成したSlackメッセージ
 *
 * @return {Json} REST API呼び出しの戻り値を格納したJsonオブジェクト
 */
function post(message) {
  throw new Error('loadメソッドを呼び出してから呼び出してください。');
}

関数

全体

【MUST】命名規則

すべて「キャメルケース記法」とし、目的により1文字目(と末尾)を変える。

また、名前は動詞始まりの1~5語程度の語句とする。

  • 文型

    • V(動詞)
    • VO(動詞、目的語)
    • VOO(動詞、目的語1、目的語2)
    • VOC(動詞、目的語、補語)
  • GAS(ないしJavaScript)の組み込み関数の名前も参考とする。
    (英文として平易な表現が多い(気がする)ため。)

▼例
目的 1文字目
メイン処理 大文字 PostToHanetaBLog
サブ処理 小文字 generateBody_

また、サブ処理の中で実行する関数の候補に挙げる必要の無いものは、末尾に_をつける。

【MUST】求める結果 > 処理の内容

実際の処理は関数の中に閉じ込めることにして、関数名は「どんな結果になるか」が読み取れる名前を優先する。

【MUST】インデントはスペースを2つずつ
  • ネスト1階層あたり1段のインデントとする。

  • ネストが深くなる時は、関数化や早期リターン、ガード節を積極的に使用すること。

【MUST】早期リターン/ガード節の推奨

n重ループや処理の分岐などは、If文と組み合わせて改善すること。

▼例(複数条件)
const improveIfNests = () => {
  if (isAbc()) return;
  if (d !== e) return;
  if (f === g) return;

  // すべてfalseのときの処理
}
▼例(ループのスキップ)
const improbeForNestsByContinue = () => {
  const arr = ["a", "b", "c"];
  for (let i = 0; i < arr.length; i++) {
   if (arr[i] === "b") continue;

    // 繰り返し処理
  }
}
▼例(ループの抜け出し)
const improbeForNestsByBreak = () => {
  const arr = ["a", "b", "c"];
  for (let i = 0; i < arr.length; i++) {
   if (arr[i] === "b") break;

    // 繰り返し処理
  }
}
▼例(n重ループの抜け出し)
const improveForDoubleNestsByBreak = () => {
  const arr = [["a", "b", "c"], ["d", "e", "f"]];
  for (let r = 0; r < arr.length; r++) {
    let row = arr[r];
    for (let c = 0; c < row.length; c++) {
      if (row[c] === "b") break;

      // 繰り返し処理
    }
  }
}
【MUST】条件を判定する関数
  • 原則、下記の命名規則とする。

    • is~
    • can~
    • has~
  • If文で呼び出すときに肯定文となるように書く。

if (is確認すること()) {
}
▼例
  • bad
const Example = () => {
  if (!checkPathWheterValid(sourcePath)) return;

  // 処理
}

const checkPathWheterValid = (sourcePath) => {
  // 条件の判定処理
}
  • good
const Example = () => {
  if (!isInvalidPath(sourcePath)) return;

  // 処理
}

const isInvalidPath = (sourcePath) => {
  // 条件の判定処理
}
【BETTER】「~にする」という表現

make ~などの表現は、1語で言い換えられないか検討する。

  • 参考

    接頭辞・接尾辞 意味 使いどき
    ~ize <名詞>化する、<名詞>にする
    ~fy <名詞>化する、<名詞>にする
    en~ より<形容詞>にする
    make~ ~にする 上記どれも一般的な単語がない場合
【BETTER】「~を行う」という表現

do ~take ~などの表現は、1語で言い換えられないか検討する。

【BETTER】補助関数
  • スニペットなどに登録する際は、抽象的な名前も可とする。
  • 実際にコード中でヘルパー関数として使用する時は、「何がどう変わるのか」を(可能な限り)明示した名前に変更する。

変数・定数

基本方針

【MUST】定数優先

基本的にconstを使って定数とし、値の変化が必要な場合のみletで変数とする。

【MUST】スコープは狭く

基本的にローカル、もしくはブロックスコープを使用し、値や名前が衝突しないよう気を使うこと。

命名規則

【MUST】スコープごとに1文字目の大文字/小文字を統一する
▼例
スコープ 1文字目
グローバル 大文字 YuruwotaNote
ローカル 小文字 yuruwotaNote
【MUST】変数名は3語まで
  • 可能であれば2語。
  • 動名詞~ing、動詞の名詞形~ationなどを積極的に使用すること。
【BETTER】似たものを対で扱う時は、名前やフォーマットを寄せる
  • 対になる変数を扱う時や型によって操作を分けるような時は、型名を明示した方が読みやすくなることもある。

  • この場合は、コードのフォルムを整えられるように(可能な限り)文字数を統一すること。
    (一瞥で差異を見つけやすくなるため)

▼例1
  • not worse
const sourcePath = 'xxxxxxxxxxx';
const destinationPath = 'yyyyyyyyyy';
  • better
const srcPath = 'xxxxxxxxxxx';
const dstPath = 'yyyyyyyyyyy';
▼例2
  • not worse
const ssIdABc  = 'xxxxxxxxxxxxx';
const ssAbc    = SpreadsheetApp.openById(ssIdABc);
const sheetNameAbc = 'xxxxxxxxxxxxx';
const sheetAbc = ssAbc.getSheetByName(sheetNameAbc);
  • better
const abcSsIdc = 'xxxxxxxxxxxxx';
const abcSs    = SpreadsheetApp.openById(abcSsId);
const abcSheetName = 'xxxxxxxxxxxxx';
const abcSheet = abcSs.getSheetByName(abcSheetName);
【BETTER】配列やオブジェクトの命名
  • 原則、arrobjか複数形を使用する。

  • 単数形と複数形の区別がない単語や、複数形にするとかえって読みづらい語句の場合は、~Array~Collectionも可とする。

クラス、オブジェクト

全体

【MUST】命名規則

アッパーキャメルケース記法とし、1~3語程度の名詞句とする。

YutuwotaNote

メソッド

【MUST】原則、関数と同じ

特にこだわりが無い限り、原則ルールは関数と同じ。

【MUST】関数との違い

サブ処理は「先頭」に_をつける。

プロパティ

【MUST】命名規則

ロワーキャメルケース記法とし、1~3語程度の名詞句とする。

yutuwotaNote

スクリプトプロパティ

命名規則

【MUST】記法

すべて大文字のアッパースネークケース記法で統一する。

'YURUWOTA_NOTE'
【MUST】命名規則

サービス名がある場合は、先頭に名前を付与して(可能な限り)フォルムを整える。

HATENA_API_KEY
HATENA_API_TOKEN

処理

【BETTER】クラスにまとめる

クラスにまとめ、メインの処理を書くときにインテリセンスが効くようにする。

▼例
class Props {
  constructor() {
    const props = PropertiesService.getScriptProperties();

    this.ssId = props.getProperty('SPREADSHEET_ID');

    this.channelId_test = props.getProperty('CHANNEL_ID_TEST');
    this.channelId      = props.getProperty('CHANNEL_ID');

    this.folderId = props.getProperty('IMAGE_FOLDER');
  }
}

参考

以下を参考にさせて頂きました。

記事・サイト

命名規則についてまとめてみた(キャメルケース,パスカルケース,スネークケース,ケバブケース, etc...) #命名規則 - Qiita

GASのライブラリでクラス化と補完 #GoogleAppsScript - Qiita

Google Apps Scriptライブラリの作り方 #GoogleAppsScript - Qiita

Google Apps Script でクラス型のコードを書いたさいのスクリプトエディタでの補完への対処方法 (Bad Hack) - ChangeLog - noissefnoc

書籍

わたしも『知的生産の技術』がほしい…

先日「100日チャレンジ」に挑戦して、そのコミュニティで『知的生産の技術』という本を教えていただいた。

100日チャレンジ | 先送り0で「今日もできなかった」から抜け出す

※本筋とはズレるのでこちら↑の詳細は割愛しますが、タスク管理に悩んでいる方にはオススメです。

何年か前に読んだ『エンジニアの知的生産術』でも紹介されていて気になっていたので、すぐに読んでみることにした。

感想文

この本では、現代人ならどこかしらは役に立つであろう、「知的生産」の技術(タイトルのままですが)を11に分けて説明されている。
とは言っても、技術そのものより、「時代の変化に技術の開発が追いついていない」という話がメインで、ちょっと批判的。
昭和の本だけど、令和の今も当てはまると思う。

私個人は、今でこそAppSheetとスプレッドシートで記録を取るようになったけど、やはり知的生産の技術は無いに等しい。
データの整理はできても、「知的生産」は苦手。特に文章の執筆は時間がかかる。

ノンプロ研に居たころは毎日ブログを書こうと言われて、私はほとんどできなかった。
文章術の本も読んでみたけど、「ネタを集めろ」としか書かれていなかった。
ネタが足りないのはもちろんだけど、『知的生産の技術』の表現を借りると、私の頭の中はネタを文章に変換できない状態なんだと思う。
(その証明として、この記事の分量も少なめ…)

その対策には、カード型に情報を残していくのが大事らしい。
今なら、京大型カードは(最近気になっている)Obsidianで代用できるかも。

少しずつやってみるか…

書籍

知的生産の技術

エンジニアの知的生産術

超スピード文章術

【Google Apps Script】Slackに投稿するだけのライブラリを作ってみた

ライブラリ作成の練習として、Slackに投稿するためだけのGASライブラリを作成しました。

SlackのAPIトークンとチャンネルIDが分かればメッセージを投稿できます。

プロジェクト

メイン

ライブラリ名 プロジェクトID
20250225_SlackApp 1-_bu4FmmALxQl5YQF0Hk0fkbLG0lkZur7wDUgWJMHfpZMOC7N-rr7jC7

サブ

SlackAppライブラリを使用する場合は、これら↓のライブラリもプロジェクトに追加してください。
ただし、RestApiHelper以外は必要になった時だけでもOKです。
<2026/03/05 追記>
ライブラリの依存関係を整理し、プロジェクトへの追加が必要なのはRestApiHelperのみになりました。

ライブラリ名 識別子 必須 プロジェクトID
20200604_RestApiHelper RestApiHelper 1_TDv0sV9l82h85UPEQ5JQZNSUyRGGyBX3J5LWQl7PL7pSfvkfdIPgDHa
20250922_SlackSymbols SlackSymbols × 1o_MvHyK4ZrAJdbNWbwuYODBAmGW9bv9SMENco7uN2jbNiM5y1rhfEcUi
20251116_GraphBlob GraphBlob × 1EvdwaDdfkm-tly7Y7kctYTHaQQ1_3erGBxBwl_iawxxshBJ32ehfAhiT

ソースコード

GitHub - yuricks7/GAS_Library_SlackApp: Slackに投稿するだけの機能を集めたライブラリです。 · GitHub

サンプル

現時点で、postメソッドとpostImageメソッドのみ実装しています。
これらの使い方は、下記の通りです。

/**
 * Slackにメッセージを投稿する
 */
const PostToSlack = () => {
  const props = PropertiesService.getScriptProperties();
  const apiToken  = props.getProperty('SLACK_API_TOKEN');
  const channelId = props.getProperty('CHANNEL_ID');
  const slack = SlackApp.load(apiToken, channelId);

  // メッセージを投稿する
  slack.post("Hello, world!");

  // グラフを投稿する
  const ssId = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
  const sheetName = 'Data';
  const graphName = 'AccessData';
  const blob = GraphBlob.getAsPngBlob(ssId, sheetName, graphName);
  slack.postImage(blob, props.graphName);

ご意見募集中

念のため自分でも確認していますが、特性上、どこかに間違いがあるかもしれません。
お気づきの点がありましたら、コメントやフォームでご連絡いただけると嬉しいです!

【Git】ブランチ名を変えたらPushできなくなった

こちらの記事は、下記URLに移転しました。
約3秒後に自動的にリダイレクトします。

ジャンプしない場合は、下記をクリックしてください。

新記事はこちら

【Git】ブランチ名を変えたらPushできなくなった - ゆるおたノート

【Git】ブランチ名を変えたらPushできなくなった

数年前にローカルのHEADブランチ名をmasterからmainに変更して、そのままリモートにはpushせずに放置していました。

久しぶりにリポジトリを操作してpushすると、何回リモートにpushしても変更が反映されませんでした。

$ git push origin main
Everything up-to-date

このリポジトリGitHub Pagesで使っていますが、Pages側は変更が反映されずじまいです。

原因

少し調べてみると、リモート側にmastermainの2つのブランチが存在する状態でした。
(なぜ、名前の変更ではなく複製になってしまったのかは気になりますが…)

この状態で、ずっとmasterにpushしようとしていたようです。

整理すると、この時点で下記のような状態です。

場所 変更前 変更後
ローカル(HEAD) master main
ローカル developなど -
リモート(default) master -
リモート - main

試しにブランチを切り替えてみると、これまでの変更はちゃんと追跡・保存されていました。
しかし、このブランチがリモート側の先頭(default)、つまりリモートのHEADになっていないので、GitHub Pagesには反映されない状況です。

解決方法

HEADのブランチ名を変更した時は、リモート側も変更が必要のようです。

(今回は一応解決しましたが、正直よく分かっていないので、ブランチの名前変更のコマンドも調べ直そうと思います。)

手順

  1. 問題のリポジトリのアカウントでGitHubにログイン
  2. Settingsタブに移動
    (アカウントに操作権限が無いと、そもそもタブが出現しません)
  3. Switch to another branchボタンを押す
  4. デフォルトにしたいブランチを選択して、Updateボタンを押す
  5. 警告文を読んで、問題が無ければ赤字のI understand, update the default branchボタンを押して保存する
  6. コードタブに戻り、mainブランチが選択されていることを確認

これで、ここまでの変更も無事にGitHub Pagesに反映され、変更も追跡されます。

なお、不要になったら、古い方のブランチは削除しても良いそうです。ご参考まで…

【Google Apps Script】グラフを画像として取得できないエラーの原因と解決策

最近、Slackで体調の記録を毎朝チェックしています。
しかも、文字情報だけでなくグラフも送信できるとさらに最近になって知りました。

早速チャレンジしたところ、エラーが出て送信できませんでした。
解決まで数日かかったので、忘れないうちに記録しておきます。

エラーの詳細

グラフをBlob形式でSlackに送付するスクリプトを書いていた際に、こんなエラーが出ました。

Exception: Service Spreadsheets failed while accessing document with id {xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx}

例外:スプレッドシート・サービスがドキュメント(ID:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx)のアクセス中に失敗しました。

要は、スプシへのアクセスに失敗したらしいです。
とは言っても、スプシには特に問題は無さそうなんですが、なぜ…?

やりたいこと

スプシで使っているグラフをSlackに送付する予定です。
実行しようとしたスクリプトは、下記の通りです。
※コードの詳細については、本題とズレるので今回は触れません。あしからず。

function Test() {
  const props = new Props();
  const slack = SlackApp.load(props.channelId);
  slack.postImage(getGraphBlob_('体重', props.ssIdOfHealthCare, 'HealthGraph')); // エラーで送信できない
}

/**
 * グラフ画像のデータをBlobオブジェクトとして取得する
 *
 * @return {Blob} グラフ画像のBlobデータ
 */
function getGraphBlob_(sheetName, ssId, graphName) {
  // グラフの取得
  const dataSheet = DataSheet.load(sheetName, ssId);
  const graphs = dataSheet.sheet.getCharts();
  const graphBlob = graphs[0].getBlob(); // シート内のグラフは1個なので添え字は0でOK

  // グラフ画像のファイル名を設定
  const date = Utilities.formatDate(new Date(), 'JST', 'yyyy-MM-dd');
  graphBlob.setName(`${date}_${graphName}`);

  return graphBlob;
}

警告文によると、エラーが発生している箇所はこちら↓。

const graphBlob = graphs[0].getBlob();

今回は、Blobがうまく取得できないようです。

原因は?

Google先生に聞いてみると、原因としては

  • IDが正しくない
  • 権限のスコープが適切に設定されていない
  • ファイル形式がxlsxなどのスプレッドシート以外のものになっている
  • グラフの縦軸が左右に分かれている
  • スプレッドシートが重い

などが挙げられていますが、今回はどれも問題はありませんでした。
特に5つ目については、確かにシートをたくさん使っていますが、同じスプシで新しいグラフを追加したらそれは送付できたので、これも問題無いはずです。

では、何が問題か?

ヒントは、4つ目でした。

  • グラフの縦軸が左右に分かれている

これは推測ですが、グラフの設定が細かいと、うまく画像データに変換できないことがあるようです。
私の場合、縦軸は2つ使っても問題ありませんでしたが、今回は「複合グラフ」を使っていたことが原因と分かりました。

ちなみに、複合グラフとはこんなグラフ↓のことです。
縦棒グラフと折れ線を混ぜて使っていました。

試しに折れ線グラフに統一すると、問題なく送信できました。
※念のため、縦軸の数値はぼかしておきます。

読みづらくなるので少し困るのですが、今回はこれで我慢することにしました。

まとめ

スプシかグラフのどちらかに問題があると、グラフをBlobとして取得できないことがあるようです。

今回は、グラフを簡素にすることで、エラーを回避できました。

本当は複合グラフも使えるようになってほしいので、Google様へのお願いも込めて記事としました。
(目に留めてもらえるかどうかは、また別のお話…)

それでは、皆さんも日々の改善を頑張ってまいりましょう。それでは。

参考

Google App Scriptで発生するよくわからないエラーへの対処 #GoogleAppsScript - Qiita

【Google App Script】Google Drive内に保管された全てのファイルのシート名を出力する方法

Google Apps Scriptで「Exception: Service Spreadsheets failed while accessing document with id」というエラーが発生 #GoogleAppsScript - Qiita