OmniAICreator/Qiita-1.07M huggingface dataset:
GitHub Pagesでデプロイしたサイトにカスタムドメインを割り当てると、次のGitHub Actionsでデプロイした際にカスタムドメインが消える

GitHub PagesでNuxt3で作成したサイトを公開していたのですが、カスタムドメインを割り当てたら、Actionsによる自動デプロイ時にカスタムドメインが勝手に削除されてしまいました。

調査していたところ、以下の投稿を見つけました。
https://github.com/facebook/docusaurus/issues/3889


読んでみたところ、CNAMEファイルなるものを追加する必要があるようです。

> If you use a static site generator to build your site locally and push the generated files to GitHub, pull the commit that added the CNAME file to your local repository. For more information, see "Troubleshooting custom domains and GitHub Pages."

引用：https://docs.github.com/en/pages/configuring-a-custom-domain-for-your-github-pages-site/managing-a-custom-domain-for-your-github-pages-site#configuring-a-subdomain


# 対策

### Actions用yml修正

GitHub Actions用のymlファイルにCNAMEファイル作成コマンドを追加します

```cd.yml
・・・
      - name: Generate
        run: yarn generate

      - name: create CNAME
        run: touch dist/CNAME && echo ${{ secrets.CNAME }} >> dist/CNAME

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./dist
```

※yarn generateで作成されるdistディレクトリをデプロイするため、その中にCNAMEファイルを作成します


### 環境変数追加

Settingsで環境変数を追加します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/71ed7701-71ac-c6e4-faa8-4dae53edbfee.png)

### ymlプッシュ

対応したymlファイルをプッシュします。
Actionsでデプロイが実行されたときに、自動でサブドメインが登録されます！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325108/fdf2e848-c3d5-f3af-a1df-25341b3e28d9.png)

# ちなみに

※以前、以下の記事を書いたときに書き忘れてたみたいです。。。
　該当のリポジトリを見たらCNAMEファイルありました:sweat:

https://qiita.com/teracy164/items/ce31608876f6515d242e
MySQL カラムのデータを入れ替える


## やりたいこと
MySQLを使ってテーブルのカラムのデータを入れ替えたい。
下記のarticleテーブルで、titleとcontentのカラムの中身を入れ替えてみる。
![スクリーンショット 2022-07-24 15.24.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/c9db9cd8-251a-3451-aece-bc081791e5e4.png)

## 実行するSQL
```.sql
UPDATE article SET title=CONCAT(title, ':', content),
content=SUBSTRING_INDEX(title, ':', 1),
title=SUBSTRING_INDEX(title, ':',  -1);
```
*contentに`:`が使われていないことを前提とする。


id=1で動きの説明をする。

①`title=CONCAT(title, ':', content),`
titleとcontentの間に':'の文字を挟んで結合。
->titleカラムは`タイトル1:コンテンツ1`のようになる。

②`content=SUBSTRING_INDEX(title, ':', 1),`
contentカラムに①で連結した文字列の`:`より前の文字列を取得させる。
->`タイトル1`となる。

③`title=SUBSTRING_INDEX(title, ':',  -1);`
titleカラムに①で連結した文字列の`:`より後の文字列を取得させる。
->`コンテンツ1`となる。


↓上記を実行するとtitleとcontentの中身が入れ替わった。
![スクリーンショット 2022-07-24 18.37.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969534/aa608932-70b0-d9cd-22a4-646132c77ecf.png)
OpenVSwitchが動かなくなったので直した

OpenStackを再インストールしたりしてる内に、OpenVSwitchが動かなくなった。。。
~~~~~
Setting up openvswitch-switch (2.17.0-0ubuntu1) ...
Could not execute systemctl:  at /usr/bin/deb-systemd-invoke line 142.
A dependency job for openvswitch-switch.service failed. See 'journalctl -xe' for details.
invoke-rc.d: initscript openvswitch-switch, action "start" failed.
○ openvswitch-switch.service - Open vSwitch
     Loaded: loaded (/lib/systemd/system/openvswitch-switch.service; enabled; vendor preset: enabled)
     Active: inactive (dead) since Sun 2022-07-24 02:25:44 UTC; 6h ago
   Main PID: 1237 (code=exited, status=0/SUCCESS)
        CPU: 5ms

Jul 24 08:23:23 master-node systemd[1]: Dependency failed for Open vSwitch.
Jul 24 08:23:23 master-node systemd[1]: openvswitch-switch.service: Job openvswitch-switch.service/start failed with result 'dependency'.
Jul 24 08:25:33 master-node systemd[1]: Dependency failed for Open vSwitch.
Jul 24 08:25:33 master-node systemd[1]: openvswitch-switch.service: Job openvswitch-switch.service/start failed with result 'dependency'.
Jul 24 08:28:00 master-node systemd[1]: Dependency failed for Open vSwitch.
Jul 24 08:28:00 master-node systemd[1]: openvswitch-switch.service: Job openvswitch-switch.service/start failed with result 'dependency'.
Jul 24 09:03:29 master-node systemd[1]: Dependency failed for Open vSwitch.
Jul 24 09:03:29 master-node systemd[1]: openvswitch-switch.service: Job openvswitch-switch.service/start failed with result 'dependency'.
Jul 24 09:04:03 master-node systemd[1]: Dependency failed for Open vSwitch.
Jul 24 09:04:03 master-node systemd[1]: openvswitch-switch.service: Job openvswitch-switch.service/start failed with result 'dependency'.
dpkg: error processing package openvswitch-switch (--configure):
 installed openvswitch-switch package post-installation script subprocess returned error exit status 1
Errors were encountered while processing:
 openvswitch-switch
~~~~~

ので以下の通りに修正した。
~~~~~
$sudo vim  /usr/lib/systemd/system/ovsdb-server.service
[Unit]
Description=Open vSwitch Database Unit
After=syslog.target network-pre.target dpdk.service local-fs.target
Before=network.target networking.service
PartOf=openvswitch-switch.service
DefaultDependencies=no

[Service]
LimitNOFILE=1048576
Type=forking
Restart=on-failure
EnvironmentFile=-/etc/default/openvswitch-switch
ExecStart=/usr/share/openvswitch/scripts/ovs-ctl \
          --no-ovs-vswitchd --no-monitor --system-id=random \
          --no-record-hostname \
          --remote=punix:/var/run/openvswitch/db.sock \
          start $OVS_CTL_OPTS
ExecStop=/usr/share/openvswitch/scripts/ovs-ctl --no-ovs-vswitchd stop
ExecReload=/usr/share/openvswitch/scripts/ovs-ctl --no-ovs-vswitchd \
          --no-record-hostname \
          --no-monitor restart $OVS_CTL_OPTS
RuntimeDirectory=openvswitch
RuntimeDirectoryMode=0755
RuntimeDirectoryPreserve=yes
~~~~~
【rails】任意のバリデーションを設定

単体テストコードでエラーと超格闘してます。そこでバリデーションを任意で設定する方法について、わかったのでアウトプットします。

やり方
```ruby:model
class Room < ApplicationRecord
    validate :deadline_date　#deadline_dateはメソッド名

    private

    def deadline_date
        if deadline.nil?
          errors.add(:deadline, "締切を入力して下さい")
        end
    end
end
```
注意点
・普段バリデーションを追加するときは「validates :カラム名, presence: true」というように記述しますが、今回は「validate　メソッド名」と記述していると点
・メソッドはprivateより下に記述すること。
・今回はメソッド（deadline_date_cannot_be）がtrueの場合、バリデーションが作用し、エラーメッセージに"締切を入力して下さい"が追加されるようになっている

# 参考になったサイト
https://mintaku-blog.net/rails-ownvalidation/

https://railsguides.jp/testing.html#%E3%83%A2%E3%83%87%E3%83%AB%E3%83%86%E3%82%B9%E3%83%88


https://railsguides.jp/active_record_validations.html#presence
Linuxコマンドで、ファイルの差分を表示するdiffコマンド

ファイル同士の差分をLinuxコマンドで表示してみました。
サンプルコードと同じく書いたつもりが、
タイプミスなので、動かない時に使えます。

また、単体テストとかで、
想定結果と、実際に実施した結果が同じかどうか？
そんな時も、使えます。

diff ファイルA ファイルB
今回は、Rubyのファイル同士に差分があるか、比較をしました。
otehon.rbとsample01.rbというファイルの比較です。

◆入力コマンド
```
~/r/20220724 ❯❯❯ diff otehon.rb sample01.rb
◆出力結果
5c5
\<   def initialize(price, color, capacity)
\---
\>   def initilize(price, color, capacity)
```
◆解説
5c5というのは、5行目に差分がありますよってことを表しています。
今回は、initializeのタイプミスがありました。

Windowsであれば、Winマージというソフトでも、
同じようなことができますが、
手順的には、コマンドの方が早く簡単にできます！
webサーバーとアプリケーションサーバーの違いについて

## なぜ記事を書こうと思ったか
  アプリケーションサーバーとWebサーバーについての明確な違いと例えば、どのような種類があるか調べた為、備忘録としてまとめる。

## webサーバーとアプリケションサーバーの説明
- webサーバー(例：Nginx、Apache、WEBrick)
ユーザーから送られてきた自サイトへのリクエストを受け取り、なんらかの処理を加えるプログラムです。そして、場合によってはあなたのRailsアプリケーションにリクエストを投げます。SSLリクエストや静的なファイルやアセット、圧縮されたリクエスト等を処理したり、その他大半のwebサイトが必要としそうな数多くの処理をこなしたりすることができます。もし、Railsアプリケーションがリクエストを処理しなければならない場合は、webサーバーはリクエストをアプリケーションサーバーにパスします。
複数のアプリケーションを一度に処理したり、アセットを素早くレンダリングしたり、リクエストごとに発生する多くの処理をさばいたりしてくれます。

- アプリケーションサーバー(例：Unicorn、Thin、Rainbows、Mongrel)
Railsアプリケーションを動かしているもの。コードを読み込み、アプリケーションをメモリに保持します。webサーバーからリクエストを受け取ると、Railsアプリケーションにそのことを知らせます。アプリケーションがリクエストを処理すると、アプリケーションサーバーはそのレスポンスをwebサーバーに返します。webサーバーを使わずに単体で実行できます。

まとめると、ユーザーからのリクエストをwebサーバーが処理し、Railsにアクセスする必要がある場合は、アプリケーションサーバーにリクエストを送る。その後、アプリケションからレスポンスされた情報をアプリケションサーバーがwebサーバーに送り、ユーザーに届けます。
しかし、必ずしもアプリケーションサーバーが必須なわけではなく、Pumaなどは、webサーバーでありながら、アプリケーションサーバーの仕事もこなすことができる為、Puma一つだけでもアプリケーションを動作させる事は可能である。

## 最後に
　正直、インフラ関連の内容について理解が薄い為、今後も触れて行き深く理解して行きたいと思います。
　間違っている箇所やわからない箇所があれば、ぜひコメントしていただけると嬉しいです。
　読んで頂きありがとうございました。

## 参考資料
- [Rails：Pumaは何者？](https://kichintodaisuke.wordpress.com/2020/04/29/rails%EF%BC%9Apuma%E3%81%AF%E4%BD%95%E8%80%85%EF%BC%9F/)
RockyLinux 9.xでLet's Encrypt(certbot)を動作するようにする

3か月間の証明書を無償で取得できるLet's EncryptをRockyLinux 9.x系で利用する方法をご紹介。
操作方法自体は、RockyLinux 8.xやRHLE互換のAlma Linux等でも利用可能だと思います。

# Snapdをパッケージをインストールする

```
dnf install epel-release
dnf install snapd
systemctl enable --now snapd.socket
ln -s /var/lib/snapd/snap /snap
```

# Snapdを利用してcertbotをインストールする

```
snap install core
snap refresh core
snap install --classic certbot
ln -s /snap/bin/certbot /usr/bin/certbot
certbot --version
```

以上で終了です。証明書の取得は以下の形で取得します。

# DNSレコード反映での証明書取得方法

## ワイルドーカード証明書の取得

```
certbot certonly --manual --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory -m メールアドレス  -d *.example.com
```

RSA形式で取得するにはパラメーターに「--key-type rsa」を追加します
```
certbot certonly --manual --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory -m メールアドレス  -d *.example.com --key-type rsa
```



## CSRをあらかじめ用意して証明書を取得

```
certbot certonly --manual --preferred-challenges dns-01 --server https://acme-v02.api.letsencrypt.org/directory -m メールアドレス  -d *.example.com --csr /path/to/example.com.202202.csr
```
Tips: Rubyでprivate/protectedなattr_*を宣言する方法

## これは何
Rubyには`attr_*`という宣言でインスタンス変数に対するアクセスメソッドを用意することが可能です。
ただ、単純に`attr_*`を使ってしまうと、クラス外部にもパブリックな形で公開されてしまいます。
内部だけで参照したい場合でも、アクセスメソッドを用意して変数へのアクセスを厳密に定義したい場合はあると思います。
今回はどうそれを実現するのかを説明します。

### バージョン3.0より古いバージョンの場合
実はアクセスメソッドのスコープの絞り方は、3.0以降かそうではないかで書き方が変わります。
まずはバージョン3.0より古いバージョンの場合はどう書くかを説明します。
方法は単純で、`private`などの宣言をした後に`attr_*`の指定を行えば問題ありません。

以下のようなイメージです。

```rb
class Hoge
  def initialize
    @fuga = 'fuga'
  end

  private

  attr_reader :fuga
end
```

### バージョン3.0以降の場合
バージョン3.0以降の場合、`attr_*`の挙動が変わり、よりスタイリッシュな宣言の仕方ができるようになりました。
以下のような書き方ができます。

```rb
class Hoge
  private attr_reader :fuga
  
  def initialize
    @fuga = 'fuga'
  end
end
```

なぜこのような書き方ができるようになったか説明します。

### 1. `private/public/protected`などが、配列も指定できるようになった
3.0より前のバージョンのRubyでは、`private`などは配列を取ることができませんでした。

```rb:3.0より前
class Hoge
  private :hoge, :fuga #=> OK
  private [:hoge, :fuga] #=> Error
end
```

しかし、3.0以降のバージョンでは配列も取れるようになっています。

```rb:3.0以降
class Hoge
  private :hoge, :fuga #=> OK
  private [:hoge, :fuga] #=> OK
end
```

### 2. `attr_*`がメソッド名の配列を返すようになった
3.0より前のバージョンのRubyでは、`attr_*`は`nil`を返していました。

```rb:3.0より前
class Hoge
  attr_reader :fuga #=> nil
end
```

しかし、3.0以降のバージョンでは定義されるメソッド名を返すようになっています。

```rb:3.0以降
class Hoge
  attr_accessor :fuga #=> [:fuga, :fuga=]
end
```


### まとめ
1の変化と2の変化によって、3.0以降では以下のような宣言が可能になっています。
```rb
class Hoge
  private attr_reader :fuga
  
  def initialize
    @fuga = 'fuga'
  end
end
```

## おまけ
3.0以降の挙動の変化は↓あたりのコードを追うことでわかります。

`attr_*`の変化

https://github.com/ruby/ruby/blob/ruby_2_7/object.c#L2336

https://github.com/ruby/ruby/blob/ruby_3_0/object.c#L2358

`private/public/protected`の変化

https://github.com/ruby/ruby/blob/ruby_2_7/vm_method.c#L1731

https://github.com/ruby/ruby/blob/ruby_3_0/vm_method.c#L2079

もしよかったら読んでみてください。
Spring Initializrを使って作成したプロジェクト起動時に「Outdated Bundled Kotlin Compiler」と表示されてしまう

# 事象

記事のタイトルの通り、Spring Initializrで作成したプロジェクトを起動したらIntelliJで以下が表示されました。

```
Outdated Bundled Kotlin Compiler
The compiler bundled to Kotlin plugin (1.5.31-release-546) is older than external compiler used for building modules:
	demo (1.6.21)
	This may cause different set of errors and warnings reported in IDE.
```

エラー内容はgradleで指定されているバージョンよりもIDEのKotlinのバージョンが古いよ、というものです。

# 対処法

IntelliJをアップデートすれば解決します。

IntelliJ IDEA > 
Check for Updates... > 
右下の「IntelliJ IDEA XXXX.X.X available」のUpdate...

をクリックして、アップデートと再起動を繰り返して最新版にすれば解消するはずです。
Drupal開発で便利なVS Code拡張

## [Drupal Smart Snippets](https://marketplace.visualstudio.com/items?itemName=andrewdavidblum.drupal-smart-snippets)

フック関数の自動補完を行なってくれる。

![Screen Shot 0004-07-24 at 18.07.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79577/588669e0-0550-0b8a-26c2-ffcae4f5af5d.png)


## [phpcs](https://marketplace.visualstudio.com/items?itemName=shevaua.phpcs)と[phpcbf](https://marketplace.visualstudio.com/items?itemName=persoderlind.vscode-phpcbf)

別記事で解説。

https://qiita.com/hmaruyama/items/6f9a5144ef1744c58483


## [Twig Language 2](https://marketplace.visualstudio.com/items?itemName=mblode.twig-language-2)

Twigファイルのシンタックスハイライトやスニペットを提供する。

![Screen Shot 0004-07-24 at 10.57.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79577/38d3df82-82de-3c03-6ab1-ee5632ae52ef.png)


## [PHP DocBlocker](https://marketplace.visualstudio.com/items?itemName=neilbrayfield.php-docblocker)

PHPドックブロックの自動補完を提供する。

![Screen Shot 0004-07-24 at 10.56.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79577/2ef109f3-19b3-259e-dc9b-d243b459bb9d.png)

使用する際には、intやboolなどの省略形を許可する設定を行っておく。

```json-doc
{
  // PHP DocBlocker. see https://www.drupal.org/docs/develop/development-tools/configuring-visual-studio-code#s-php-docblocks
  "php-docblocker.useShortNames": true
}
```

## [Composer](https://marketplace.visualstudio.com/items?itemName=ikappas.composer)

composerをVS Codeで操作するためのインターフェースとcomposer.jsonのスキーマ検証を提供する。
システムにComposerがインストールされていることが前提（拡張機能の設定でComposerの実行パスを設定する必要がある）。

```json-doc
{
  // Composer. see https://www.drupal.org/docs/develop/development-tools/configuring-visual-studio-code#s-composer-drupal-8
  "composer.executablePath": "/usr/local/bin/composer"
}
```

## [Drupal Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=marcostazi.VS-code-drupal)

\*.themeや*.moduleなどDrupal固有のファイルのシンタックスハイライトを提供する。
この拡張機能を入れれば、VS Codeで次のような設定を省略できる。※が、後述のPHP Intelephense拡張を使用する場合は、結局次の設定を行わなければならないので、PHP Intelephense使用者はこの拡張は不必要かも。

```json-doc
{
  "files.associations": {
    "*.inc": "php",
    "*.module": "php",
    "*.install": "php",
    "*.theme": "php",
    "*.profile": "php",
    "*.tpl.php": "php",
    "*.test": "php",
    "*.php": "php",
    "*.info": "ini"
  }
}
```

## [PHP Intelephense](https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client)

PHPのインテリセンス機能を提供する。
この拡張機能を使用する際には、VS Codeでデフォルトで用意されているPHP Language Features拡張(  `@builtin php` で検索すると出てくる)をオフにする。
\*.themeや*.moduleなどDrupal固有のファイルでもインテリセンス機能を使用するためにはfiles.associations設定項目を用いてPHPファイルと認識してあげる必要がある。

```json-doc
{
  "files.associations": {
    "*.inc": "php",
    "*.module": "php",
    "*.install": "php",
    "*.theme": "php",
    "*.profile": "php",
    "*.tpl.php": "php",
    "*.test": "php",
    "*.php": "php",
    "*.info": "ini"
  }
}
```

## 参考
- https://www.drupal.org/docs/develop/development-tools/configuring-visual-studio-code
【DB設計】非正規化が必要な理由とタイミング

# はじめに
今回の記事は私が去年アルバイトで、EC系サイトのテーブル設計しているときに、非正規化について学んだことを共有します。

基本情報を勉強している私は、`非正規化 =  悪`と考えていました。
理由は基本情報の問題によくRDBの非正規化されたテーブルを正規化しないといけない問題が出題されるからです。
しかし実際は後に紹介する内容のように、必要に応じて非正規化しないといけない場面があります。

# 非正規化が必要な理由とタイミング
## 理由
データの整合性を取るため

## 非正規化が必要なタイミング
以下の商品テーブルと購入明細テーブルがあるとします。

### 商品名テーブル
| 商品ID | 商品名 | 単価 |
|:-----------|------------:|:------------:|
| 1 | 青森県産りんご | 100 | 
| 2 | 和歌山県産みかん | 110 | 

### 購入明細テーブル
| 購入明細ID | 商品ID | 購入数 | 購入日 |
|:-----------|------------:|:------------:|:------------:|
| 1 | 1 | 10 | 5月15日 |
| 2 | 2 | 5 | 6月8日 |

#### このテーブル設計で起きる問題点
商品テーブルのレコード内容が変わると、変わる以前の購入明細が購入した時の内容と合わなくなります。

##### 例
例えば商品テーブルの商品名の`青森県産りんご`を`沖縄県産りんご`にして、単価を`100`から`200`円にします。
| 商品ID | 商品名 | 単価 |
|:-----------|------------:|:------------:|
| 1 | 沖縄県産りんご | 200 | 

こうすると以下の変更前に青森県産りんごを購入した購入明細の内容が次の内容に変わってしまいます。
| 購入明細ID | 商品ID | 購入数 | 購入日 |
|:-----------|------------:|:------------:|:------------:|
| 1 | 1 | 10 | 5月15日 |
- 青森県産りんごではなく、沖縄県産りんごを購入したことになる。
- 購入金額が1000円から2000円になってしまう。

## 非正規化カラムで購入明細の整合性を保つ
商品明細テーブルに以下のカラムを追加することにより、非正規化されて整合性が保たれます。
- 商品名
- 単価

### 非正規化カラム(商品名・単価)を追加したの商品明細テーブル
| 購入明細ID | 商品ID | 購入数 | 購入日 | 商品名 | 単価 |
|:-----------|------------:|:------------:|:------------:|:------------:|:------------:|
| 1 | 1 | 10 | 5月15日 | 青森県産りんご	 | 100 |
| 2 | 2 | 5 | 6月8日 | 和歌山県産みかん | 110 |

# 最後に
以上のことから私は、`非正規化 = 悪`と考えを改め直す事ができました。
基本情報を勉強されたいる方も本記事から、非正規化の意味を学んでほしいです。
react-nativeでreact-native-sqlite-storageをlinkしようとしたときにコマンドが見つからないと言われた時にした対処

# 環境
Windows 10 Pro
react-native 7.0.4
npm 8.1.0
npx 10.2.2
node 16.13.0

# 事象
react-native-sqlite-storageを利用するために下記のコマンドを実行するとエラーが発生した。
~~~
react-native link react-native-sqlite-storage
~~~

エラー
~~~
react-native : 用語 'react-native' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識されません。名前が正しく記述されて 
いることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行してください。
発生場所 行:1 文字:1
+ react-native link react-native-sqlite-storage
+ FullyQualifiedErrorId : CommandNotFoundException
~~~

# 対処
~~~
PS C:\Users\hoge> npx react-native link react-native-sqlite-storage
warn Calling react-native link [packageName] is deprecated in favor of autolinking. It will be removed in the next major release.
Autolinking documentation: https://github.com/react-native-community/cli/blob/master/docs/autolinking.md
~~~

とりあえずコマンドは実行できた。
きっとベストプラクティスではないと思いますので、どなたかご存じであれば、正しい対処法を教えてください。
静的コナーセンスについて　「意味のコナーセンス」から「名前のコナーセンス」に弱めるコード実例

## 本記事の目的
現在、「ソフトウェアアーキテクチャの基礎　エンジニアリングに基づく体系的アプローチ」を読んでいます。
＊読んでいる途中で記事を書いているので、間違った解釈が含まれているかもしれません。

この本で「コナーセンス」という言葉が出てきます。
コナーセンスには、「静的コナーセンス」と「動的コナーセンス」という二種類に分けられますが、今回は、静的コナーセンスの中にある「意味のコナーセンス」と「名前のコナーセンス」について、コードベースでお話したいと思います。

新卒１年目の記事のため、説明が下手だったりすると思いますが、お手柔らかにお願いします。


## 静的コナーセンスとは
この本では、Page-Jonesという方が定義したと書かれていました。
> 静的コード解析によって発見可能な静的コナーセンスと、実行時の振る舞いに関する動的コナーセンスという、２種類のコナーセンスを定義した。

つまり、静的コナーセンスは、コード解析やコード部分でのコナーセンスである。

「意味のコナーセンス」...マジックナンバーとか。意味のある値
「名前のコナーセンス」...定数名、クラス名、メソッド名とか。命名。

## 静的コナーセンスについて少し調べてみた
コナーセンス？なにそれおいしいの状態だったので、少し調べて、コナーセンスについて素人なりに知ろうとしました。

参考にしたのは、下記の記事
https://qiita.com/fujiharuka/items/68fadefa6dad4cf33b4d

すごくわかりやすく勉強になりました。この記事でコナーセンスの理解度が高まりました。


## コードベースで説明し、まとめておきたいなと思い記事書いている
静的コナーセンスは、コードに関するものなので、コードで説明しまとめておきたいな...と思い、書きました。（自分が忘れないようにするためにも）

今回は、参考記事にも説明されている「意味のコナーセンス」から「名前のコナーセンス」に弱めることについてコードベースでどうやれば弱められるのかを説明したいと思います。

## じゃあ、実際にコードで説明する。
マジックナンバーが含まれているソースコード

```php:magicNumber.php
<?php
class magicNumber
{
  private function main(int price)
  {
    price = price * 1.10;
    return price;
  }
}
```

上記はあくまでマジックナンバーの簡単な例だが、priceという入力値から消費税をかけて返却している。
この消費税を加える際にこのメソッドを利用するのだろうけど、「1.10」という数値には、意味が含まれており、本来は定数クラスなどに定義する必要がある。

別の例だと

```php:magicNumber2.php
<?php
class magicNumber2
{
  private function main()
  {
    ...
    if ($serviceType === 1)
    {
      return 'トランプ';
    }
    else if ($serviceType === 2)
    {
      return 'テレビゲーム';
    }
    else if ($serviceType === 3)
    {
      return 'チャンバラ';
    }
  }
}
```
serviceTypeという変数を元に遊びの名前を返している。（例がひどくて申し訳ない...）
このif文の判定に数字を用いているが、1とか2とか実はただの数字ではなく、１はトランプ。２はテレビゲームという`意味`が含まれています。

では、これをどうすればよいか。

定数クラスを定義し、各種クラスのメソッドから意味ある定数であることを明確化します。

```php:gameServiceType.php
<?php
final class gameServiceType
{
  const SERVICE_TYPE_TRUMP = 1;
  const SERVICE_TYPE_TVGAME = 2;
  const SERVICE_TYPE_CHANBARA = 3;
}
```

```php:magicNumber2.php
<?php
class magicNumber2
{
  private function main()
  {
    ...
    if ($serviceType === gameServiceType::SERVICE_TYPE_TRUMP)
    {
      return 'トランプ';
    }
    else if ($serviceType === gameServiceType::SERVICE_TYPE_TVGAME)
    {
      return 'テレビゲーム';
    }
    else if ($serviceType === gameServiceType::SERVICE_TYPE_CHANBARA)
    {
      return 'チャンバラ';
    }
  }
}
```

といった具合に変えれます。
（そもそも１とか２とか数字使うなよ！というのはごもっともですが、例が思いつかなかったのと、長いサービスほどこれってあり得るのでは？と思います。やってはいけないと知りながら...）

## 言いたいことは結局何かというと...
「意味のコナーセンス」は、ここでいうとif文の`１`とか`２`であったり、消費税の`1.10`になります。
「名前のコナーセンス」は、ここでいうと定数名。

「意味のコナーセンス」
から
「名前のコナーセンス」という変更容易なものへと変化しています。

コナーセンスという言葉言っているだけで、中身はリファクタリングや可読性をあげることになります。
（今回のコナーセンスの変化については。）


## 長くなりましたが、
説明は以上になります。
あまり詳細に丁寧に書いていませんが、今回はざっと書きました。

また、何かあればメモ程度に書いていきます。
reqwestでWebAPIにアクセスする際にハマったこと

# 環境

- Ubuntu 22.04 LTS
- rustup 1.25.1
- cargo 1.62.1

# 課題

Rust で WebAPI にアクセスしたい。
reqwest というクレートを使うと HTTP 通信をして返ってきた JSON データを構造体に落とし込むまでをやってくれるのだが、
返ってきた JSON のプロパティ名と自分で定義した構造体のフィールド名は一致していないといけない。つまり、

```json:WebAPI
{
	"userName": "田中一郎",
	"userAge": 30,
	"isPremiumMember": false
}
```

のような会員情報の JSON を返す WebAPI にアクセスするとき、

```rust:Rust
struct Member {
	userName: String,
	userAge: i32,
	isPremiumMember: bool
}
```

のような構造体を定義しておく必要があるのだが、これを実行すると

```text
warning: structure field `userName` should have a snake case name
warning: structure field `userAge` should have a snake case name
warning: structure field `isPremiumMember` should have a snake case name
```

のように怒られる。Rust の構造体のフィールド名はスネークケースで書くべきだからだ。  
このままでも一応コードは動くけれど、大量の warning が出たままなのは気持ちが悪い。
どうすればよいだろうか？

# ソースコード

`Cargo.toml`はこんな感じ。  
reqwest クレートで JSON を構造体に変換するために features に json を指定している。
serde クレートは構造体の直列化に、tokio クレートは非同期処理のために使用している。

```toml
[package]
name = "reqwest-sample"
version = "0.1.0"
edition = "2021"

[dependencies]
reqwest = { version = "0.11.11", features = ["json"] }
serde = { version = "1.0.140", features = ["derive"] }
tokio = { version = "1.20.0", features = ["full"] }
```

`src/main.rs`はこんな感じ。  
まず JSON を受け取るための構造体を定義し、impl Member 以下で reqwest を使って WebAPI にアクセスする関数を定義している。

```rust
use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize, Debug)]
struct Member {
    userName: String,
    userAge: i32,
    isPremiumMember: bool
}

impl Member {
    async fn get(url: &str) -> Result<Self, reqwest::Error> {
        let response = reqwest::get(url).await.unwrap();
        let json = response.json::<Self>().await.unwrap();
        Ok(json)
    }
}

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let url = "https://gist.githubusercontent.com/YUUKIToriyama/1045d7941e4e9dc1c416b120050c8f1b/raw/213f8c713860b4b7ec90ff15f420e1e96826cc84/sample.json";
    let member = Member::get(url).await.unwrap();
    println!("{:#?}", member);
    Ok(())
}
```

# 解決法

serde のアトリビュートを使えば、JSON のプロパティをそれと異なる名前のフィールドに格納できることがわかった( https://serde.rs/field-attrs.html#alias )。

たとえば、次のようにすれば良い。

```rust
struct Member {
    #[serde(alias = "userName")]
    user_name: String,
    #[serde(alias = "userAge")]
    user_age: i32,
    #[serde(alias = "isPremiumNumber")]
    is_premium_member: bool
}
```

# 応用

serde のアトリビュートを使えば、異なる名前のプロパティとフィールドを紐付けられることがわかった。
これを応用すれば、次のようなプロパティ名が日本語の JSON をうまく処理することができる。

```json: WebAPI
{
	"名前": "田中一郎",
	"年齢": 30,
	"有料会員": false
}
```

```rust: Rust
struct Member {
    #[serde(alias = "名前")]
    user_name: String,
    #[serde(alias = "年齢")]
    user_age: i32,
    #[serde(alias = "有料会員")]
    is_premium_member: bool
}
```

どうやら最新の Rust では識別子に Ascii 以外の文字も使えるらしいので、この場合そのままでもいいかもしれませんが。

# 参考リンク

- [How to read response JSON as structs when they contain hyphens in key names? - Stack Overflow](https://stackoverflow.com/questions/71328963/how-to-read-response-json-as-structs-when-they-contain-hyphens-in-key-names)
- [[Rust] 識別子に日本語を使う - Qiita](https://qiita.com/osanshouo/items/aad5e5ebde5470a2f9c2)
PHPの変数、定数について

## 自己紹介

はじめまして、日本システム開発株式会社の藤井といいます。
業務でPHPを触ることが多く、勉強してみようと思ってドキュメントを読み、役立ちそうな内容を記事にまとめています。
記事の内容は大体[php.net](https://www.php.net/manual/ja/)に書いてありますが、ドキュメントを読むのが面倒くさいと思った方は、
ぜひこの記事を役立ててください。

## 変数について

### 概要

変数とは値を格納する箱のことです。ドル記号の後ろに変数名が続く形式で記述し、値を代入して使用します。
基本的に、いつでも値を取り出したり、変更したりすることができます。

変数名のルールは以下の2つです。

- 大文字小文字を区別します。
- 文字またはアンダースコアから始まり、任意の数の文字、数値、アンダースコアが続きます。

変数の利用

```php
$variable = 'variable';
```

### 変数のスコープ

スコープとは範囲のことです。スコープは2種類あり、グローバルスコープとローカルスコープです。
以下のコードを例を用いて説明します。

```php
<?php
// グローバルスコープ
$a = 'a'; //グローバル変数

function abc()
{
    // ローカルスコープ
    $a = 'b'; // ローカル変数
}

abc();
echo $a; // a
?>
```

ローカル変数は、abc()が実行されている間のみ存在します。
そのため、ローカルスコープからグローバル変数へはアクセスできますが、
グルーバルスコープからローカル変数へはアクセスできません。

ローカルスコープからグローバル変数へアクセスするには、globalキーワードを用います。
globalキーワードを用いることで、対象の変数がローカル変数なのか、グローバル変数なのかを区別することができます。

```php
<?php
// グローバルスコープ
$a = 'a';

function abc()
{
    // ローカルスコープ
    global $a; // グローバル変数a
    $a = 'b';
}

abc();
echo $a; // b
?>
```

### 可変変数

一言で説明すると、変数名、プロパティ名を可変にできる機能です。ドル記号を複数続けて記述します。
以下、コード例を用いて説明します。

```php
$a = "hello";
$$a = "world";
```

上のコードで、aとhelloの2つの変数が定義されます。
`$a`は`"hello"`なので、`$$a`は`$hello`と同じ意味になります。

プロパティの場合

```php
$foo = new StdClass();
$foo->bar = "It's bar";
$foo->buzz = "It's buzz";

$b = "bar";
echo $foo->$b; // It's bar
```

## 定数について

### 概要

値に名前つける機能です。定数の値はスクリプト実行中に変更できません。
定数は大文字小文字を区別しますが、慣習的に大文字のみで表記します。

定数の定義には、define関数かconstキーワードを使用します。

```php
define("DEFINE_CONSTANT", "constant");
const CONSTANT = "constant";
```

定数は、スコープに関係なく、あらゆる場所からアクセス可能です。
また、スカラー値と配列のみ格納できます。

### 定義済みの定数とマジック定数

PHPには、スクリプト内で利用可能な多くの定義済み定数が存在します。
よく利用される例として、PHP_EOLがあります。

マジック定数とは、使われる場所によって値が変化する定数です。全部で9つあります。
利用例として、ClassName::classがあります。
Azure無料枠でTodoアプリ【ASP.NET, CosmosDB】

## この記事は

マイクロソフトの公式ドキュメントにあるチュートリアルを試した記録です

https://docs.microsoft.com/ja-jp/azure/cosmos-db/sql/sql-api-dotnet-application

### 経緯

こちら👇の記事を読んで CosmosDB が**25GBストレージ容量と1秒あたり1000RUスループット**まで利用可能と知った

https://www.publickey1.jp/blog/22/free_tier2022.html

:::note warn
これらの無料提供サービスの内容は、提供側の都合によって変更されるので、最新の情報をあたってください
:::

#### 最新の情報をあたってみる

[マイクロソフトのドキュメント](https://docs.microsoft.com/ja-jp/azure/cosmos-db/free-tier#free-tier-with-azure-discount)から引用👇（22' 7/23時点）

> 12 か月の有効期限が切れた後も、Azure Cosmos DB アカウントの有効期間中、Azure Cosmos DB Free レベルから 1000 RU/秒 と 25 GB を引き続き得られます。

#### 蛇足

Azure の無料アカウントで 12 か月間サービスが無料」の期間であればさらに無料枠が使えるらしい

> 最初の 12 か月間は、1400 RU/秒 (Azure Cosmos DB Free レベルから 1000 RU/s、Azure 無料アカウントから 400 RU/秒) と 50 GB のストレージ (Azure Cosmos DB Free レベルから 25 GB、Azure 無料アカウントから 25 GB) の結合割引を受けることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/85c18fca-0041-027e-896a-c3875c51b371.png)

## アプリを作る

チュートリアルは`.NET Core 3.1`をターゲットにしている

せっかくなので、最新の`.NET 6`で試した
98%はドキュメント通りに進めればできる

### チュートリアルから変更すべき箇所

チュートリアル通り書くと、**コントローラーの`CreateAsync`メソッドが想定通り動かない**

引数の`Item.Id`が`null`のままで、`ModelState.IsValid`が`false`になるため
if文の中に入れないことが原因

```cs
    public async Task<ActionResult> CreateAsync([Bind("Id,Name,Description,Completed")] Item item)
    {
        if (ModelState.IsValid) // <<-- ここが false になる
        {
            item.Id = Guid.NewGuid().ToString();
            await _cosmosDbService.AddItemAsync(item);
            return RedirectToAction("Index");
        }

        return View(item);
    }
```

エラーメッセージを捕捉してみると・・・

```cs
var errormsgs = ViewData.ModelState.SelectMany(x => x.Value.Errors.Select(z => z.ErrorMessage)).ToList();
```

「`Id`と`Description`が必要です」とのメッセージ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/a5d378b4-c3d3-a4ca-8082-a2e4bf28c080.png)

#### 解決する

モデルフォルダーに作成した`Item.cs`のプロパティをNull許容型にする

`public string? Id { get; set; }`

## デプロイ

App Service の無料枠`1GB`に対して、使用料は8%です
あと9個くらいはデプロイできます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/bd5866b1-e9ca-eb10-0933-1656e1e1aa5f.png)

## 構成の変更

チュートリアルには書いてないが、GitHubによると、デプロイ後にアプリの構成を必ずしてくださいとのこと。

https://github.com/Azure-Samples/cosmos-dotnet-core-todo-app

`appsettings.json`の Cosmos DB に関する値を適当な値に変えて再デプロイすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/39ed3262-54db-2bb3-583c-cc7f11ae0fb2.png)

`500`エラーになる。

ここでAzureポータルへ移動してアプリの構成を追加する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272511/113153b6-071b-96d4-e21c-20537498ac5b.png)

内容はもともと`appsettings.json`に書いてあったもの

```json
{
  "CosmosDb": {
    "Account": "",
    "Key": "",
    "DatabaseName": "",
    "ContainerName": ""
  }
}
```

こうすることで、DB側のURIやアクセスキーが変わった場合でも、デプロイせずポータル側で構成を変えられる

## おわりに

使わないときは App Service を停止しておきましょう

## 参考

https://pie001.hatenablog.com/entry/2017/06/20/175934

https://ufcpp.net/study/csharp/sp2_nullable.html
PlantUML を VSCode で利用したいけど、プレビューが表示されずエラーが出る

INDEX
[1. やりたいこと](#1-やりたいこと)
[2. エラー内容](#2-エラー内容)
[3. 調査](#3-調査)
[4. 原因](#4-原因)
[5. 解決策](#5-解決策)

# 1. やりたいこと

- やりたいことを確認する。

VSCodeの拡張機能としてインストールした PlantUML を利用したい（UMLのプレビューを表示させたい）。

https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml

## 環境

- macOS Big Sur バージョン11.6
- Visual Studio Code バージョン: 1.68.1

# 2. エラー内容

- 課題（エラーの状況、不明点、エラーログ）を確認する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527226/4c307644-42ff-77a9-c933-240faa28fcbe.png)

VScodeの拡張機能「PlantUML」を検索した後、「インストール」ボタンをクリックして、インストール成功！

気軽に始めようとしたところ、プレビューしてもエラーが出て、表示がされない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527226/ebf06904-fa17-154f-ed82-5cb2c96f5e84.png)

赤字のエラー内容は、以下の文面。

```
ダイアグラム"oop_two_poker"にエラーが見つかりました
The operation couldn’t be completed. Unable to locate a Java Runtime.
Please visit http://www.java.com for information on installing Java.
```

（操作を完了できませんでした。Javaランタイムを見つけることができません。

Java のインストールについては、 http://www.java.com を参照してください。）

# 3. 調査

- 調査する（ググる、ドキュメントを読む）。

大人しくドキュメントを読もう。

https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml

> **ローカルレンダリングの要件**
> 
> 
> 以下をインストールする必要があります。
> 
> - [Java](http://java.com/en/download/)：PlantUMLを実行するためのプラットフォーム。
> - [Graphviz](http://www.graphviz.org/download/)：PlantUMLでは、ダイアグラム内の位置を計算する必要があります。
> 
> ### Mac用のクイックインストール
> 
> ```bash
> brew install --cask temurin
> brew install graphviz
> ```
> 
（Google翻訳）

# 4. 原因

- 調査結果から、原因の考察をする。

エラー文でもJavaがないよと書かれているので、追加のインストールで良さげ。

# 5. 解決策

- 解決策を実行する。

```bash
brew install --cask temurin
brew install graphviz
```

無事、図のプレビューができた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527226/3ca9b835-0da8-8e5d-1121-83c063396a80.png)
githubで作成したリポジトリをsourcereeでクローンするときの注意点(m1pro mac)

# githubで作成したリポジトリをsourcereeでクローンするときの注意点

今までの単純なベーシック認証では、2021年8月13日からクローンするとこは出来てもプッシュとプルができなくなったので、変わりのやり方をメモ


- githubでアカウントを作る（ここは今まで通り）
- sourcetreeをインストールする（ここは今まで通り）
- sourcetreeからクローンする前にgithubで作成したアカウントをsourcetreeに登録する.その時下記添付画像の設定で必要な情報を入力するがパスワードに入力する情報は、githubアカウントのパスワードでは無く、アクセストークンという代わりのパスワードが必要になる
![スクリーンショット 2022-07-24 17.24.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745145/4e249625-16b1-a65d-935a-c984768d1929.png)
- アクセストークンの作成方法は下記URLを参照
https://zenn.dev/koushikagawa/articles/3c35e503c8553a
- 作成したアクセストークンを入力して保存をクリックし下記添付画像通りの内容が表示されたらアカウントの連携は完了![スクリーンショット 2022-07-24 17.29.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2745145/b63da1f8-a7c9-791e-866c-e461ea09bd62.png)
- アカウントの連携が完了したら下記添付画像を参考にクローンしたいリポジトリを選択してクローンを作成する。クローンの作成が完了した概ね作業は完了だが、念の為適当なファイルを作成してプッシュとプルができるかを確認してみることをおすすめする。
Chakra-ui  V2.2.4  ~  React18に対応！

UIライブラリのchakra-uiがReact18に対応してました。
v18が出たばかりの頃はエラーが出ていたのでv17にダウングレードしてたので使ってみます。

[chakra-ui](https://chakra-ui.com/getting-started)

環境
{
Mac
vscode
Next.js(12.2.3) (React v18.20)
typescirpt (4.7.4)
}

備忘録

## chakra-uiのインストール
公式の通り下記を実行
```terminal
//terminal

npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion

yarn add @chakra-ui/react @emotion/react @emotion/styled framer-motion
```

## chakra-ui/iconsもインストール
```terminal
npm i @chakra-ui/icons

yarn add @chakra-ui/icons
```

## react/iconsもインストール
純粋にchakra-uiのアイコンだけではの足りない
というかreact/iconsを使うことが前提な気がします。
```terminal
//こっちをインストール
npm install react-icons --save

//大きな開発の時は下記
npm install @react-icons/all-files --save
```

## 使ってみる
　
`index.tsx`を下記のように変更して下さい。
```js
 //  src/pages/indes.tsx

import { Flex, Heading, Icon } from "@chakra-ui/react";
import { SiChakraui } from "react-icons/si";
import { ChatIcon } from "@chakra-ui/icons";

import type { NextPage } from "next";

const Home: NextPage = () => {
  return (
    <>
      <Flex
        color="blue.600"
        fontSize="50px"
        justify="center"
        align="center"
        mt="100px"
      >
        <Heading>React/iconsのアイコンだよ！</Heading>
        <Icon as={SiChakraui} />
      </Flex>
      <Flex
        color="green.600"
        fontSize="50px"
        justify="center"
        align="center"
        mt="100px"
      >
        <Heading>Chakra-ui/iconsのアイコンだよ！</Heading>
        <ChatIcon />
      </Flex>
    </>
  );
};

export default Home;
```

`npm run dev`で画面を表示するとこうなると思います。エラーも吐かれてません！
![スクリーンショット 2022-07-24 17.26.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2280802/83066409-af3a-f0e4-b642-0a136eb33e81.png)


[React/icons](https://react-icons.github.io/react-icons)　には豊富なアイコンんが揃っています。chakra-uiのアイコン、Twitter、Instagramなどのアイコンもあります。
[chakra-ui/icons](https://chakra-ui.com/docs/components/icon/usage)　は必要最低限といった感じです。

そのためchakra-uiには`<icon>`タグがありこれを使ってreact/iconsを表示させます。

```js
//react/iconsを使う場合
<icons as={対象のアイコン名} />

//chakra-ui/iconsを使う場合
<対象のアイコン名>

```

## react/iconsをインポートするとき
react/iconsのアイコンはファイル別に分かれています。
```js
//頭文字が "si" なのでインポートする際は　"/si"とします。
//その他にも、"ImTwitter" であれば　 "im" となります。
import { SiChakraui } from "react-icons/si";
```
最初は既に他のアイコンをインポートして使っているのにエラーが出る！となりがちですが、ここが適当か見てみましょう。

## 後書き　　
ありがとうございます。
chakra-uiが使いやすく、よく使ってます。コンポーネント化されているので、スタイルも当てられて動きもつけられるので使っていて面白いです。

chakra-uiはv2.2.4にアップデートされましたが、Reactv18としか使えません。
Reactv17との下位互換性はないとのことですので、Reactv17の人は注意して下さい。

ちょくちょくchakra-ui関連の投稿をしたいと思います。

## 雑談
chakra-uiのchakraって「チャクラ」って読むんです。
ナルトが技を出す際にチャクラを使いますがそのチャクラです。
![スクリーンショット 2022-07-24 17.20.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2280802/926c2eae-0a12-cc93-8375-8c5e971c40e5.png)
終わり
計算結果の標準出力をエラーメッセージ込みで記録用ファイルに格納する

計算をすると、エラーやどこまで計算を進めたかとかが標準出力される（とする）。
それを記録用ファイル（Log.txtとする）に格納して残しておきたいというのが今回の目標である。

イメージとしては、
./test.sh　> Log.txt
っていう感じ。でもこれだとエラーメッセージは入らない（以下で三つ目の● ）。

# 結論
- ./test.shを走らせて標準出力される全て（結果＋エラーメッセージ）をファイルに入れる。
```
./test.sh >& Log.txt
```

- ./test.shを走らせて出るエラーメッセージだけファイルに入れる。
ファイルに上書き（>）か追記（>>）かは目的によるが、とりあえず2を付け足せばいい。
```
./test.sh >2 Log.txt
```

-  ./test.shを走らせて出る結果だけファイルに入れる。
ファイルに上書き（>）か追記（>>）かは目的に応じて変える。
要は、sortとかのコマンドでこれはよく使われてそう。
```
./test.sh > Log.txt
```

- sshで、sshが切れても計算を続けたいとき（nohup コマンド &）なら
```
nohup ./test.sh >& Log.txt &
```
としとけばいい。
LNCS Formatに関するTips


## 概要

論文の投稿先によってはSpringerのLNCS（Lecture Notes in Computer Science）のフォーマットに従って執筆する必要があります．基本的には以下のサイトからサンプルのtexソースをダウンロードして加筆していけば良いのですが，いくつか困ったことがあったので解決策を共有します．
※本記事では理屈はおいといて，こうしたら動いた！という話をしていきます．あしからず．

https://www.overleaf.com/latex/templates/springer-lecture-notes-in-computer-science/kzwwpvhwnvfj#.WtR5Hy5ua71

## 埋め込む図の形式について

samplepaper.texには以下のように注意書きがあります．

> Used for displaying a sample figure. If possible, figure files should be included in EPS format.

この”If possible,”をどれくらい真面目に捉えればいいのかは悩ましいところですが，とりあえず埋め込む図はEPS画像を使うことが無難そうです．

...が, EPS画像を埋め込んでPDF化すると真っ白になっちゃって表示されない...という現象がわりとよく起こります(涙)．この時の対象法を以下の記事で書いているので，ご参考下さい♪

https://qiita.com/housewifeCat/items/dc74a9e625e63fe43bd2

## 参考文献にウェブサイトのURLを載せる

samplepaper.texでは以下のように指示されています．

> % If you use the hyperref package, please uncomment the following line
> % to display URLs in blue roman font according to Springer's eBook style:
> % \renewcommand\UrlFont{\color{blue}\rmfamily}

ここで3行目をコメントアウトしてコンパイルすると上手くいかないことがあります（つか，上手くいきませんでした）．

urlパッケージを使いましょうというサイトも多いのですが私はパッケージにい`\usepackage[dvipdfmx]{hyperref,xcolor}`を追加することで解決しました．

### ひとこと

それにしてもLNCS Formatは格式高いですよね．ちなみに私が投稿した論文はRejectでした（涙）．再投稿，頑張るぞ:triumph:

## 参考文献

- Springer Lecture Notes in Computer Science - Overleaf, Online LaTeX Editor
    - https://www.overleaf.com/latex/templates/springer-lecture-notes-in-computer-science/kzwwpvhwnvfj#.WtR5Hy5ua71
    - LNCS Formatのサンプルはこちらからダウンロードできます．

- formatting - How to style text in hyperref \url? - TeX - LaTeX Stack Exchange
    - https://tex.stackexchange.com/questions/79051/how-to-style-text-in-hyperref-url
Go クロージャー(closure) の理解

A Tour of Go でクロージャーが出てきたのでまとめてみた。


```go:sample.go
package main

import "fmt"

//クロージャー
func adder() func() int {
	sum := 0
	return func() int {
		sum += 1
		return sum
	}
}

func main() {
	a := adder()
	for i := 0; i < 10; i++ {
		fmt.Println(a())
	}
}
```
出力結果は以下の通り
```
0
1
2
3
4
5
6
7
8
9
10
```
当時の自分: a()を10回実行しているのは理解できる。あれ...a()に代入しているadder()は
```go:closure.go
//クロージャー
func adder() func() int {
	sum := 0
	return func() int {
		sum += 1
		return sum
	}
}
```
これだから、毎回　`sum := 0`　で初期化されるのでは？？？

いや違う！　
`a := adder()` 
では、関数adderを実行し、その戻り値がaに代入されている。
つまりaの中身は以下である。
```go: a.go
func() int {
	sum += 1
	return sum
}
```

なるほど！　最初の代入の段階で`sum := 0`が実行されていて、その後は戻り値の関数のみが実行されているということか。

終わり
AWS「ポリシーの評価論理フローチャート」（日本語版）

AWSの「[アカウント内でのリクエストの許可または拒否の決定 - ポリシーの評価論理](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow)」のフローチャートを日本語版を作成してみた。S3のようにリソースベースのポリシーがあったり、権限の境界が出てきたりすると、このフローチャートがないと勝てない。

![2022.07.12 AWS「ポリシーの評価論理フローチャート」（日本語版）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55718/298b473a-23b2-be1d-d9d7-461cad1d363b.png)

編集可能なPowerPointファイルは以下。

https://www.dropbox.com/scl/fi/z0ijlbjvn9zjfdntsjfm2/2022.07.12-AWS.pptx?dl=0&rlkey=lofmbi1ou333l3r9v0gq9umb7

どこかほかで和訳されていたらぜひ教えてください。図をメンテし続けられる自信はないので、あれば自作分は破棄したい。あと内容については保証しませんし、実際、自信もありません。誤りのご指摘や改善の提案など、あればぜひお寄せください。

# 参考

* [アカウント内でのリクエストの許可または拒否の決定 - ポリシーの評価論理](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_evaluation-logic.html#policy-eval-denyallow)
Power Automateのフローの構成をMermaidで書く

# 記事概要
MarkdownのMermaidでどのような表現ができるか確認するため、Power Automateのフローの構成をMermaidで可能な限り再現する。

# オリジナルのフロー
毎週月曜日10時にSharePointリストのアイテム数をカウントし、4000件以上なら警告メールを送信する。 
　※「警告終了」はフローの趣旨に沿って「終了」アクションを設定したものだが、「終了」アクションの状態に設定できる値は「失敗」「取り消し済み」「成功」であり、「警告」は設定できない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/8d8f86c5-d439-e424-6720-9958637fdeee.png)


# ソース
```
::: mermaid
graph TB;
 classDef Time fill:#DAEAFE, stroke:#C3C1C0;
 classDef SPO fill:#D4E6E6, stroke:#C3C1C0;
 classDef JSON fill:#EBE5FE, stroke:#C3C1C0;
 classDef Var fill:#E2D0F0, stroke:#C3C1C0;
 classDef Ctrl fill:#D9DADB, stroke:#C3C1C0;
 classDef OWA fill:#D5E8F7, stroke:#C3C1C0;
 classDef Exit fill:#FBD7D4, stroke:#C3C1C0;
 style はい fill:#E9F5EA, stroke:#C3C1C0;
 style いいえ fill:#FDEAE9, stroke:#C3C1C0;

 A[毎週月曜日10時に実行]:::Time --> B[リストアイテムのカウント]:::SPO;
 B --> C[JSONの解析]:::JSON;
 C --> D[変数ItemCount]:::Var;
 D --> E{アイテム数が4000件以上}:::Ctrl;
 E --> |はい|F[警告メールの送信]:::OWA;
 subgraph はい;
  F --> G[警告終了]:::Exit;
 end;
 E --> |いいえ|H[正常終了]:::Exit;
 subgraph いいえ;
  H;
 end;
:::
```

# プレビュー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/971567b6-9aa9-43a8-bbbd-0911552fe353.png)


# ポイント
## クラスを定義してスタイルを適用する
MermaidはSVGの属性を利用してスタイルを適用する。本記事で利用した属性は以下の通り。

・fill
ノードの内部の色。
アクション名部分の色をスポイドツールで抽出して設定している。

・stroke
CSSで言うところのborder=枠線の色。
全アクション共通。こちらもスポイドツールで抽出する。

### 例
SharePoint Onlineのアクションに相当するノードに設定したクラス「SPO」。その他のアクションもクラス名を3~4文字に設定。

```
classDef SPO fill:#D4E6E6, stroke:#C3C1C0;
```
## サブグラフを利用する
サブグラフを利用することで、ブロックを分けることができる。本記事では、はい/いいえの分岐で利用した。
### 例1
サブグラフ「はい」。サブグラフの範囲はendで区切る。

```
subgraph はい;
 F --> G[警告終了]:::Exit;
end;
```

### 例2
サブグラフ「いいえ」。リンクに接続されたノード単体にサブグラフを適用したい場合、定義済みのノードを指定する。

```
subgraph いいえ;
 H;
end;
```

サブグラフにもスタイルを設定できる。
```
style はい fill:#E9F5EA, stroke:#C3C1C0;
```

# 改善点
## サブグラフ名とリンクがダブる

サブグラフ名を左寄せにする、またはリンクの長さを変更することで解決可能。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/28570fd3-cbd6-9c05-b1fc-9019ac41d7ee.png)


## 分岐の位置が意図したものにならない
はい:左、いいえ:右に表示されるはずが、プレビュー上では逆に表示される
サブグラフを利用しない場合は以下のように表示され、サブグラフを適用したことが原因と考えられる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/338126/67525609-78fb-b576-641c-b03ef68f4a59.png)

# 参考文献
[Mermaid のテーマ・スタイルの変更方法](https://zenn.dev/junkawa/articles/zenn-mermaidjs-theme-config)
[SVG属性リファレンス](https://developer.mozilla.org/ja/docs/Web/SVG/Attribute)
crypt zombies lesson3

```solidity
pragma solidity ^0.4.19;

import "./zombiefeeding.sol";

contract ZombieHelper is ZombieFeeding {

  uint levelUpFee = 0.001 ether;

  modifier aboveLevel(uint _level, uint _zombieId) {
    require(zombies[_zombieId].level >= _level);
    _;
  }

  // 1. ここにwithdraw関数を作成するのだ

  // 2. ここにsetLevelUpFee関数を作成せよ

  //payable修復詞で関数呼び出し者のイーサが0.01イーサであるか確認し、レベルを上げている
  function levelUp(uint _zombieId) external payable {
    require(msg.value == levelUpFee);
    zombies[_zombieId].level++;
  }

  function changeName(uint _zombieId, string _newName) external aboveLevel(2, _zombieId) {
    require(msg.sender == zombieToOwner[_zombieId]);
    zombies[_zombieId].name = _newName;
  }

  function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) {
    require(msg.sender == zombieToOwner[_zombieId]);
    zombies[_zombieId].dna = _newDna;
  }

  function getZombiesByOwner(address _owner) external view returns(uint[]) {
    uint[] memory result = new uint[](ownerZombieCount[_owner]);
    uint counter = 0;
    for (uint i = 0; i < zombies.length; i++) {
      if (zombieToOwner[i] == _owner) {
        result[counter] = i;
        counter++;
      }
    }
    return result;
  }

}
Quarkusで引数付きバッチを作成・コンテナ化する方法

# はじめに
マイクロサービス向けのJavaフレームワークである[Quarkus](https://ja.quarkus.io/)は、コマンドラインで起動するバッチアプリケーションを開発することも可能です。

バッチアプリケーションは起動時に引数を与えて実行することが多いですが、Quarkusで引数を与えたバッチを作成することが意外に手間取ったので備忘録として残します。

なお、手間取ったのは、`mvn` や `quarkus`コマンドでの実行ではなく、Quarkusアプリケーションをコンテナ化したときの引数付き実行になります。


# 前提
Quarkus　：　2.10.1


# サンプルのバッチアプリケーション
バッチのサンプルとして、以下のようなMainクラスを用意します。ここでは、引数の数、および、各引数の値を1行ずつ表示する処理を実行しています。

```java
@QuarkusMain
public class BatchSampleMain implements QuarkusApplication {

    @Override
    public int run(String... args) throws Exception {
        System.out.println(args.length);
        Arrays.stream(args).forEach(System.out::println);
        return 0;
    }
}
```

# quarkusコマンドでの引数付き実行
Quarkusには専用のCLIとして`quarkus`コマンドが用意されています（`quarkus`コマンドのインストールは、「[QUARKUS コマンドラインインターフェイス (CLI) を使用した QUARKUS アプリの構築](https://ja.quarkus.io/guides/cli-tooling)」を参照）。

`quarkus`コマンドで、「x y」という2つの引数を与えて実行する場合、以下のように実行します。`quarkus.args` システムプロパティを指定することで引数を与えることができます。

```bash
quarkus dev -Dquarkus.args='x y'
```

# コンテナ化した場合の引数付き実行
Dockerを用いてコンテナ化する場合、まず`container-image-docker`エクステンションを追加します。

```bash
quarkus extension add 'container-image-docker'  
```

コンテナ化する（コンテナイメージをビルドする）には以下のコマンドを実行します。

```bash
 ./mvnw clean package -Dquarkus.container-image.build=true -DskipTests=true 
```

これにより、前述のバッチアプリケーションがDockerイメージ化され、`docker`コマンドでの実行が可能となります。`docker container run`でバッチを起動することができますが、このままだと引数を与えてもそれがQuarkusのアプリケーションまで伝わりません。

Quarkusの過去のバージョンでは、Quarkusでプロジェクトを作成した際にデフォルトで作成されるDockerfile（`src/main/docker/Dockerfile.jvm`）において`ENTRYPOINT`が設定されていました。そのため、`docker container run`での実行で引数を与えると、コンテナ内のQuarkusアプリケーションまで引き渡されていましたが、前述のバージョンのQuarkusでは`ENTRYPOINT`が無くなっており、引数を渡せなくなっています。

これを解決するには、`src/main/docker/Dockerfile.jvm`の末尾に以下を追加します。過去のQuarkusで使用されていた [run-java.sh](https://github.com/fabric8io-images/run-java-sh) をcurlで取得し、適切なパーミッションを与えたうえで、`ENTRYPOINT`に指定します（パーミッションのユーザID・グループIDは、`Dockerfile.jvm`内、および、`FROM`で指定されたベースイメージを確認してください）。

```docker
ARG RUN_JAVA_VERSION=1.3.8
RUN curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
    && chown 185 /deployments/run-java.sh \
    && chmod 540 /deployments/run-java.sh

ENTRYPOINT ["/deployments/run-java.sh"]
```

あるいは、もっと簡単な方法として、`src/main/docker/Dockerfile.jvm`の末尾に以下を追加する方法もあります。

```docker
ENTRYPOINT ["java", "-jar", "/deployments/quarkus-run.jar"]
```

この設定を加えたうえでコンテナイメージをビルドすると、以下のように引数を与えて実行することで、Quarkusアプリケーションまで引数が渡されます（`x y`の部分が引数）。

```bash
docker container run --rm --name batch-sample <コンテナイメージ> x y
```

以上です。
【Rails】present?を少し理解してみる（クイズあり）

# 僕はpresent?について「完全に理解」していた
Railsにはpresent?という便利なメソッドがあり、使う機会も見る機会もなかなかに多いです。

present?はblankではないオブジェクトに対してtrueを返してくれて、だいたいの場合において直感通りの挙動を示します。（`present? = !blank?`）

しかし先日少し直感とは反する挙動に遭遇し、せっかく検証したのでメモを残しておきます


# blank?ってなんだっけ？

blank?メソッドの仕様はこちら

https://api.rubyonrails.org/classes/Object.html#method-i-blank-3F

> An object is blank if it’s false, empty, or a whitespace string. For example, false, ”, ‘ ’, nil, [], and {} are all blank.

falsyなオブジェクト or emptyなオブジェクト or 空白文字がblankなオブジェクトになります。

まあそうだよねーという感じでしょうか

`empty?`がどんな判定か、空文字が何かを理解できていれば`blank?`あるいは`present?`について「なにもわからない」状態になれるのではないでしょうか

※ 「なにもわからない」状態についてはこちら参照ください
https://togetter.com/li/1268851


# ということでクイズ

ほとんど環境による差はないと思いますが、一応検証環境です。
* Ruby: v3.1.0
* Rails: v7.0.2.2

以下はどんな結果になるでしょう？

```ruby
# Q1
:''.present?

# Q2
:' '.present?

# Q3 (全角スペース)
'　'.present?

# Q4
"\n\r\s\t".present?

# Q5
{ nil => nil }.present?

# Q6
[nil].present?

# Q7 (NaN)
(0.0/0.0).present?
```

（blank?で問題出せよという声も聞こえてきそうですが、present?のほうが使う機会多いと思うのでこのような出題にしています。）


# 気になる解答


<details><summary>こちら</summary><div>

```ruby
# Q1
:''.present?
#=> false

# Q2
:' '.present?
#=> true

# Q3 (全角スペース)
'　'.present?
#=> false

# Q4
"\n\r\s\t".present?
#=> false

# Q5
{ nil => nil }.present?
#=> true

# Q6
[nil].present?
#=> true

# Q7
(0.0/0.0).present?
#=> true
```


全問正解できたでしょうか？

ちなみに僕は`[nil].present?`は当然falseを返すだろうと思い込んでいました。（trueが返ってきたのでこの記事を書くことにしたという次第です。）

</div></details>

# おまけ


ドキュメントには以下のように書かれており、最初blank?の中身は`!address || address.empty?`かと誤読しておりました・・(⌒-⌒; )

> This simplifies
`!address || address.empty?`
to
`address.blank?`

これは`!address || address.empty?`  => `address.blank?`のように簡略化できますよという意味で、両者は同義ではないです。


# まとめ

覚える必要はないですが、たまに騙されるので注意

他にも面白い挙動のオブジェクトがあればコメントくださいませ^-^

全問正解できなかった人はLGTMしてね
Lambda関数をローカル環境からワンタッチでデプロイする

ローカルPythonコードからboto3を経由してLambda関数を更新します。  
作成済のLambda関数のロジック修正が簡単に実施できるので便利だと思います。

## コード説明

- デプロイ対象のLambda関数はPythonを前提とします。
- デプロイ対象のLambda関数は作成済であることを前提とします。
- このPythonファイルを置き換えたいLambda関数と同一フォルダへ配置します。
- Pythonファイルが置かれたフォルダ名がLambda関数名と一致することを前提とします。
- Lambda関数の中身を更新します。

`upload_lambda.py`

```python
import io
import os
from zipfile import ZipFile
import boto3
import pathlib

def main(funcName):
    print("main start")
    file_name = "lambda_function.py"
    buf = io.BytesIO()
    with ZipFile(buf, 'w') as z:
        z.write(pathlib.Path(__file__).parent.joinpath(file_name), file_name)
    client = boto3.client('lambda', region_name="ap-northeast-1")
    response = client.update_function_code(
        FunctionName=funcName,
        ZipFile=buf.getvalue()
    )
    print("main end")

if __name__ == "__main__":
    print("start")
    funcName = pathlib.Path(__file__).parent.name
    main(funcName)
    print("end")
```
eclipse2022にjava EEがない

## eclipse2022にjava EEがない
### JavaEEとは
企業向けのWebアプリケーション開発ができる機能がセットになったプラットフォームのこと

調査してみると

https://mergedoc.osdn.jp/

eclipseのダウンロードサイトにこんな表記が
`・変更: Java EE パースペクティブ廃止 (サーバー・ビューは Java パースペクティブ初期表示、DTP 廃止のため)`
らしい,ぐぬぬぬぬ

### そもそもパースペクティブとは
eclipseの作業内容に応じて切り替わる画面レイアウトで、表示するビューやエディタ、メニューをコントロールする設定のこと

#### DTP廃止
`DTP`とはeclipse上からGUIでDB操作を行うためのプラグインだがこれが廃止されたとのことだ
ちなみにこれは`Eclipse IDE for Java EE Developers`に標準で入っていたらしく、その`DTP`が廃止されたこととサーバー・ランタイム環境の操作をする`サーバー・ビュー`がJavaパースペクティブで初期表示になったことにより、Java EEパースペクティブがいらなくなったということか、ならいらないのか。。。。
じゃあそのままJavaパースペクティブでWebアプリケーション開発に取り組むとしよう:punch:

※補足、間違い等ありましたらご指摘いただけると幸いです
【Flutter】WebViewをPageViewやTabBarViewで状態を保持しながら切り替える

# ソースコード
https://github.com/popy1017/flutter_multi_webview

※ WebView には flutter_inappwebview パッケージを使用。

https://pub.dev/packages/flutter_inappwebview/example

# 課題
PageViewやTabBarViewでWebViewを表示している際、WebViewのページ（またはタブ）を表示するたびにロードが走ってしまう。  
→ Webページの状態（スクロール位置や表示内容）が保持できない。

# 解決策
こちらのQAを参考にした。

https://stackoverflow.com/questions/56985081/how-to-make-webview-not-reload-when-i-switch-appbar-in-my-flutter-app

WebViewを`AutomaticKeepAliveClientMixin`をmixinしたWidgetとすることで、ページやタブ切り替え時にも状態が保持できるようになる。

```dart:AutomaticKeepAliveClientMixinをmixinしたWebView
class KeepAliveWebPage extends StatefulWidget {
  const KeepAliveWebPage(this.url, {Key? key}) : super(key: key);

  final String url;

  @override
  State<KeepAliveWebPage> createState() => _KeepAliveWebPageState();
}_

class _KeepAliveWebPageState extends State<KeepAliveWebPage>
    with AutomaticKeepAliveClientMixin {
  @override
  Widget build(BuildContext context) {
    super.build(context);
    return InAppWebView(
      initialUrlRequest: URLRequest(url: Uri.parse(widget.url)),
    );
  }

  @override
  bool get wantKeepAlive => true;
}
```

```dart:PageViewの書き方は通常の使い方通り
class PageWebView extends StatefulWidget {
  const PageWebView({Key? key}) : super(key: key);

  @override
  State<PageWebView> createState() => _PageWebViewState();
}

class _PageWebViewState extends State<PageWebView> {
  final _controller = PageController();

  int _currentPageIndex = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Page: $_currentPageIndex'),
      ),
      body: PageView(
        controller: _controller,
        children: const [
          KeepAliveWebPage("https://flutter.dev/"),
          KeepAliveWebPage("https://www.nintendo.co.jp/"),
          KeepAliveWebPage("https://www.playstation.com/ja-jp/"),
        ],
        onPageChanged: (int pageIndex) {
          setState(() {
            _currentPageIndex = pageIndex;
          });
        },
      ),
    );
  }
}
```