OmniAICreator/Qiita-1.07M huggingface dataset:
複数のハッシュからストロングパラメーターを設定したい

# 複数のハッシュからのストロングパラメーターの設定に関して

**色々参考にさせていただきながらネストしたパラメーターの取り出し方などは確認させてもらいましたが、なぜかうまく取り出すことができず、試行錯誤した結果を備忘録として残します。きっともっと簡単（正式）なやり方があるかと思うのですが、ご容赦ください。**


今回は下記のパラメーターから「item」でハッシュされたものと「image」でハッシュされたものをmergeしてコントローラーへ渡し保存します。

このパラメーター（中身は微修正しています）を

```ruby
 pry(#<ItemsController>)> params
=> <ActionController::Parameters {"authenticity_token"=>”hoge==", "image"=><ActionController::Parameters {"images"=>(中略)Type: image/jpeg\r\n">]} permitted: false>, "item"=><ActionController::Parameters {"name"=>”hoge”, "info"=>”hoge”, "category_id"=>”1”, "sales_status_id"=>"2", "shipping_fee_status_id"=>"3", "prefecture_id"=>"3", "scheduled_delivery_id"=>"2", "price"=>"4000"} permitted: false>, "commit"=>"出品する", "controller"=>"items", "action"=>"create"} permitted: false>
```

下記コントローラーへ送って保存したい。

```ruby
  def create
    @item = Item.new(item_params)
  end
```

結果


```ruby
def create
    @item = Item.new(item_params)
  end

private

 def item_params
    image_params = params.require(:image).permit(images: [])
    params.require(:item).permit(:name, :info, :category_id, :sales_status_id, :shipping_fee_status_id, :prefecture_id,
                                 :scheduled_delivery_id, :price).merge(user_id: current_user.id, images: image_params[:images])               
end
```


## 試行錯誤の内容

まず、今までの知識で考えて、上記はベースとしつつもmargeの中でimagesを取り出しスマートに送るはずが、、うまくいかず。。

一度、reqireを外してpermit で全てを指定いくため、ネストなどの関係も記述するもうまくいかず。

慣れないことをするよりも今の知識でできる方法がないかと模索し、一度imagesだけを取り出して、それをmergeする方法にたどり着き、

```ruby
def item_params
    image_params = params.require(:image).permit(images: [])
    params.require(:item).permit(:name, :info, :category_id, :sales_status_id, :shipping_fee_status_id, :prefecture_id,
                                 :scheduled_delivery_id, :price).merge(user_id: current_user.id, images: image_params)               
end
```

とするも、**Could not find or build blob: expected attachable**というエラーで、何やら見つからなかったとのこと。

再度パラメーターを確認すると、ハッシュに組み込まれているものの、**image_paramsに"images"=><ActionController::Parameters**が代入したimage_params余計に含まれている模様。

上記をそのままmergeしたのでエラーとなったようですね。ここから先ほど少し学習したネストを思い出し、この中からimeges以降を取り出せないかとやった結果が上記となります。

絶対にもっとスマートなやり方がある！とささやくもう一人の自分を押し殺し数時間に及ぶ戦いに終止符が打たれました。
【Python】Worksheet.merge_cellsメソッドを使って、セルを結合する。

pythonを使用してExcelファイルの操作を勉強しています。
本日の気づき(復習)は、セルの結合に関してです。
pythonでExcelを操作するため、openpyxlというパッケージを使用しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927441/7c56de5d-8ce5-fd5d-c731-a98450ab7f64.png)

上記のようなブック「表」を

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927441/4e220f91-8c7d-5705-63ac-d5bb4bcff52b.png)

の様な年のセルを結合したいです。

# Worksheet.merge_cellsメソッド

```python
ws.merge_cells(start_row=開始の行番号, start_column=開始の列番号,
               end_row=終了の行番号, end_column=終了の列番号)
```

セルの結合は上記のようにWorksheet.merge_cellsメソッドを使うのですが
ここで気を付けるのは列番号で、
A,B,C・・・ではなく、1,2,3・・・のように数値を設定します。

# 最終的なコード

```python
from openpyxl import load_workbook
from openpyxl.styles import Alignment, Border, PatternFill, Side

wb = load_workbook('表.xlsx')
ws = wb.active

green_fill = PatternFill(fgColor='C6E0B4', fill_type='solid')
center_alignment = Alignment(horizontal='center')
black_thin = Side(color='000000', border_style='thin')
border = Border(left=black_thin, right=black_thin,
                top=black_thin, bottom=black_thin)

row_no = 2
start = 5
end = 16

# セルを結合
ws.merge_cells(start_row=row_no, start_column=start,
               end_row=row_no, end_column=end)

# 結合したセルの塗りつぶし
ws.cell(row_no, start).fill = green_fill

# 結合したセルの文字配置
ws.cell(row_no, start).alignment = center_alignment

# 結合したセルの罫線
for column_no in range(start, end+1):
    ws.cell(row_no, column_no).border = border

wb.save('表_結合.xlsx')
```

ここでも、注意点があります。

罫線の設定は結合したセルすべてに対して設定する必要があるということです。

何気に見落としがちなので注意した方が良いです。
(私は？？？ってなってました。)
MPU6050とArduinoの使い方に関するメモ　内部プルアップ抵抗の話

今回の記事は、加速度センサとジャイロセンサを使いたくてMPU9250とArduino MEGAをI2C通信でつなげようとした時につまづいたポイントのメモです。


https://invensense.tdk.com/products/motion-tracking/6-axis/mpu-6050/

#症状：
センサの値をシリアルモニタで読み取ろうとしてたら、値が途中で止まった。(数十秒程度は取得できた)センサ単体で使う分にはこの問題は生じなかったが、出力強めのDCモータと併せて使おうとした際に電磁ノイズの影響か、この症状が発生した。

#原因：
AruduinoのI2C通信のデフォルトプルアップ抵抗の値が適切じゃなかったっぽい。

以下の記事参照




https://ohguma.hatenablog.com/entry/20161219/p1







#対策：
内部プルアップ抵抗を無効にし、2-3kΩくらいの抵抗をSDAとSCL線に挟んでやると、止まることなく動いた。




#まとめ：

抵抗などの電子回路部品は適切な値のものを使用しましょう、ArduinoのI2Cのデフォルトの内部プルアップ抵抗はそのまま使うと困ることあるよ、と言う話でした。(MPU6050でも同じ対策が必要)
matplotlibで画像は保存できるけどplt.show()が動かなくなるケアレスミス

#1. 結論
`fig = plt.figure()`のところが`fig = plt.Figure()`と、大文字で打ち間違えているせいかも。

#2. 目次
[1. 結論](#1-結論)
[2. 使用環境](#2-使用環境)
[3. 実例](#3-実例)
[4. おわりに](#4-おわりに)

#2. 使用環境
- [python](https://www.python.org/) 3.7 ([conda](https://www.anaconda.com/) 4.9.2)
- [Matplotlib](https://matplotlib.org/)  3.3.4 

#3. 実例
以下は普通に動くはず。※本ページのスクリプトの利用は自己責任でお願いします。

```
>>> import matplotlib.pyplot as plt
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> fig = plt.figure()
>>> ax = fig.add_subplot(111, facecolor="white")
>>> ax.plot(a,b)
[<matplotlib.lines.Line2D object at 0x7fb5b8888390>]
>>> plt.show()  # ウィンドーが出てくる
>>> fig.savefig("a.png")
```
ここで`fig`の型を確認しておくと、

```
>>> type(fig)
<class 'matplotlib.figure.Figure'>
```
である。上のプログラムの`plt.figure()`を`plt.Figure()`に置き換えると、

```
>>> import matplotlib.pyplot as plt
>>> a = [1,2,3]
>>> b = [4,5,6]
>>> fig = plt.Figure()
>>> ax = fig.add_subplot(111, facecolor="white")
>>> ax.plot(a,b)
[<matplotlib.lines.Line2D object at 0x7facccd9ed50>]
>>> plt.show()  # ウィンドーが出てこない!!
>>> fig.savefig("b.png")
```
こうなる．特にエラーは出ないが、`plt.show()`で出てくるべきウィンドーが出ない。ディレクトリを見ると画像はちゃんと保存されていた。型を調べると、

```
>>> type(fig)
<class 'matplotlib.figure.Figure'>
```
先程と同じもの。では何が違うのかというと、attributeが違う。とくに後者では`show()`がない。

```
>>> fig = plt.figure()
>>> fig.show()  # ウィンドーが出てくる
>>> fig = plt.Figure()
>>> fig.show()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/python3.7/site-packages/matplotlib/figure.py", line 408, in show
    "Figure.show works only for figures managed by pyplot, "
AttributeError: Figure.show works only for figures managed by pyplot, normally created by pyplot.figure()
```
`matplotlib.pyplot.figure()`によって作られた`Figure`でないと`Figure.show()`は動きませんよ、と言ってくる。けしからん。

#4. おわりに
conda で作成したpython 3.8の仮想環境でも同様であった。
【実験】Dockerを使用してGitLabを構築してみる part3

前回に引き続き、Dockerを使ったGitLabについて触れていきます。
今回からは複数のGitLabサーバーでデータ共有を試してみたいと思います。今回はその事前準備としてGitLabサーバーのバージョンを合わせる作業を実施します。
なぜこの作業が必要になるかと言いますと、GitLabのデータは異なるバージョン同士のデータで互換性が無い為です。
異なるバージョン同士のGitLabサーバーでデータ共有しようとするとどうなるかはいずれ試してみたいとは思います。
現行のバージョンは13.10.x以上ですが、今回は例として13.8.1をインストールします。

#バージョンを指定してGitLabインストールを実施する(yum install版)
まずは事前準備としてGitLabに必要なパッケージを一括でインストールします。
インストール後、sshdとpostfixを有効化します。
※以降のコマンドは全てsudoを省略しています

```
yum install -y policycoreutils-python curl openssh-server openssh-clients postfix
systemctl enable sshd postfix
systemctl status sshd postfix #sshdとpostfixが「active (running)」になっていればOK
```

インストール完了後、firewallのhttp通信を許可設定します。

```
firewall-cmd --permanent --add-service=http
systemctl reload firewalld
```

firewallの設定が完了したら、GitLabのリポジトリを登録します。

```
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
```

ここまでは通常のGitLabインストール手順と同様です。
次はGitLabのインストールとなりますが、その前にyum installでバージョン指定してインストールする場合、以下のコマンドからインストールしたいバージョンのパッケージ名を調べます。

```
yum --showduplicates search gitlab-ce | grep <バージョン>
例：
yum --showduplicates search gitlab-ce | grep 13.8.1 #GitLab バージョン13.8.1の場合
gitlab-ce-13.8.1-ce.0.el7.x86_64 : GitLab Community Edition (including NGINX,
```

上記出力結果を```yum install```コマンドの後ろに記述すればバージョン指定のインストールが可能となります。

```
例：
yum install -y gitlab-ce-13.8.1-ce.0.el7.x86_64 #GitLab バージョン13.8.1の場合
```

インストールが完了しましたら、初回のreconfigureを実行します。

```
gitlab-ctl reconfigure
```

しばらく待つと```gitlab Reconfigured!```と表示されます。
```gitlab-ctl status```コマンドで全てのサービスが「run」となっていれば完了です。

#バージョンを指定してGitLabインストールを実施する(docker install版)
Dockerからインストールする場合で、バージョン(tag)を指定してインストールする場合の書式は以下の通りとなっているようです。
単にタグをバージョンのナンバーにすれば良い訳ではなく、バージョンのナンバーの後ろに```-ce.0```を含めています。
インストールしたいバージョンのGitLabが存在しているか、存在している場合のtag名を確認したい場合は[Docker HubのGitLab公式](https://hub.docker.com/r/gitlab/gitlab-ce/tags?page=1&ordering=last_updated)から確認してみてください。

```
docker pull gitlab/gitlab-ce:<バージョン>-ce.0
例：
docker pull gitlab/gitlab-ce:13.8.1-ce.0 #GitLab バージョン13.8.1の場合
```

バージョン指定して取得したGitLabのイメージをインストールするには[こちら](https://qiita.com/fy406/items/c875d5c979664651f941)で実施したインストール方法と同じコマンドで実施します。
注意点としては最後に指定するタグ名はlatestではなく今回取得した対象タグ名に書き換えする必要があります。

```
docker run --detach \
  --hostname gitlab.example.com \
  --publish 443:443 --publish 80:80 --publish 2002:22 \
  --name gitlab \
  --restart always \
  --volume $GITLAB_HOME/config:/etc/gitlab \
  --volume $GITLAB_HOME/logs:/var/log/gitlab \
  --volume $GITLAB_HOME/data:/var/opt/gitlab \
  gitlab/gitlab-ce:<タグ名(例：13.8.1-ce.0)> #GitLab バージョン13.8.1の場合
```

上記コマンドでインストールを実行し、```docker logs -f gitlab```コマンドでインストールの進行状況を確認すると、ループが発生するので、何度も繰り返しているなと思ったらctrl + cでキャンセルし、```docker exec -it gitlab gitlab-ctl reconfigure```コマンドを実行します。

少し待つと```gitlab Reconfigured!```と表示されます。
```docker exec -it gitlab gitlab-ctl status```コマンドで全てのサービスが「run」となっていれば完了です。

#インストール後の確認(共通)
インストール完了後、```http://<ホストのIPアドレス>```へアクセスし、rootでログインします。
無事ログインが出来たら```http://<ホストのIPアドレス>/help```へアクセスします。
アクセスした先で想定通りのバージョンが表示されていれば完了です。

今回は以上です。
次回はバージョンを合わせたGitLabサーバー同士でデータの共有を試そうと思います。
テスト環境にnoindexを設定してGoogle検索で表示させないようにした。

## noindexとは
htmlのメタタグのことです。
これをページに設定することで、Googleの検索エンジンにインデックスされなくなります。

## noindexを設定した目的
テスト環境に構築したアプリケーションを、Google検索で表示させないようにするためにnoindexを設定しました。
今回作成したアプリは、AWS上にテスト環境を構築し、特にアクセス制限などもかけていません。
そのため、テスト環境を誰でも利用、閲覧できる状態です。
本番環境と間違えてテスト環境を使ってしまうことを防ぐため、テスト環境にnoindexを設定する必要がありました。

## 実際にやったこと
今回作成したアプリケーションはRailsを用いています。
Railsでは"application.html.haml"の内容が全てのビューファイルに反映されるため、このファイルにnoindexを設定することにしました。
具体的には以下のような感じです。

```haml
!!!
%html
  %head
    - if ENV['NOINDEX'] == 'YES'
      %meta{:name => "robots",:content => "noindex"}
~以下略~
```

テスト環境に環境変数"NOINDEX"を設定することで、環境変数のによって条件分岐するようにしました。
ページのソースを見てみると、ちゃんとnoindexが設定されているようです。
![スクリーンショット 2021-04-04 19.08.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429077/7bd4085b-cdb5-eb0c-b42e-225219dc9a36.png)

## これでいいのか？
環境毎にnoindexの設定を分けるには、今回用いた方法が一番楽で簡単だと思いました。
しかし、同様の方法を用いている記事や実例が調べても出てこなかったので、セキュリティや保守性などに不味い点でもあるのか？と疑っております。
今回紹介した方法が、世界中のエンジニアの盲点をついた大発見であることを祈ります。
Railsでattr_accsessor使ってますか？

### はじめに
Rubyを勉強し始めたときに必ず出てくる `attr_accsessor`
しかしRailsを勉強し始めて、ポートフォリオ等を作る過程では、中々触れる機会が減ると思います。


### この記事で触れない部分
- `attr_accsessor`の細かい説明
- rubyの基礎基礎的な部分
- railsの基礎的な部分

### `attr_accsessor`が有効活用できる場面

- Userモデル

| id |  name  |
| ---- | ---- | 
|  1 |  ユーザーA  |
|  2  |  ユーザーB |

以下のような要件を想定

Userモデルの中に、ユーザーの名前情報を格納する`name`という属性が定義されている
しかしユーザー情報の登録・編集フォームでは、名字と名前を別々のテキストフィールドから入力させたい。


上記のユースケースの場合、`attr_accsessor`が活躍する場面です。
`name`カラム塗とは別に、今回は `fisrt_name`と `last_name`という擬似的なフィールドを定義してあげましょう。

## 実装
#### モデル
以下を定義したことで、Userモデルのインスタンスを作成すると、`fisrt_name`と`last_name`のゲッターとセッターが使えるようになりました。

```ruby:app/models/user.rb

class User < ApplicationRecord
  attr_accsessor :fisrt_name, :last_name
end

```
ビューとコントローラ側でも `fisrt_name`と`last_name`が使えるようにしましょう。

#### コントローラ

```ruby:app/controllers/users_controller
class UsersController < ApplicationController
  
  def new
    @user = User.new
  end
  
  def create
    user = User.new(user_params)
    user.save
  end

  private

    def user_params
      params.require(:user).permit(:first_name, :last_name)
    end
end

```
コントローラ側ではstrong parameterに設定してあげます。

#### ビュー

```ruby:app/views/users/new.html.erb
  <%= form_with model: @user, local: true, url: url, method: method do |f| %>
    <!-- 姓 -->
    <%= f.label :last_name %>
    <%= f.text_field :last_name %>

    <!-- 名 -->
    <%= f.label :first_name %>
    <%= f.text_field :first_name %>
    
    <%= f.submit "送信" %>
  <% end %>
```
ビューではそのまま`text_feild`のname属性に`last_name `と `first_name `を指定します

ここまでで下準備は出来ました。
ただ現状では、`last_name`と `first_name`のパラメータをフォームから送信する事は出来ても、受け取り側が不十分です。
具体的には、実際にDBに登録されるのは `name`という属性です。
`last_name`と `first_name`はDBとモデルには定義されていないので登録時にはそのまま使う事が出来ません。

そこでモデル側に、コントローラ側で受け取った`last_name`と `first_name`を`name`に結合してあげる処理を実装します。

```ruby:app/models/user.rb
class User < ApplicationRecord
  attr_accsessor :fisrt_name, :last_name

  # 以下追加分 

  # 登録処理の前に呼び出す
  before_save :create_fullname
  
  
  # last_name と first_nameの結合処理
  def create_fullname
    self.name = self.last_name.concat(" ",self.first_name)
  end
end
```

コールバックで、`user.save`の直前に `create_fullname`を呼び出します。

ちなみに `concat(" ",self.first_name)`で半角スペースを入れているのは、編集時のデリミタを指定できるようにするためです。
そのまま結合をしてしまうと、`name`編集時にどこで文字列を分割するかが分からなくなるからです。


### まとめ
`attr_accsessor`を使うユースケースよりの記事になってしまいましたが、やhりRubyの基礎を理解しておくことでアプリケーションの要件が複雑化した際の対応力が圧倒的に変わります。
Railsは便利なフレームワーク故に、ついRubyの基礎を忘れてしまいがちです。
自分も今一度基礎を見直して日々精進します
【Docker】Dockerfileを書く際に気を付けること

# 概要
 Dockerfileの書き方は、人それぞれあると思います。しかし、キャッシュや可読性を考えてDockerfileを記述すると、より効率的に扱うことができます。今回は、どのように書くと、良いのだろうかを自分なりに調べてまとめてみました。始めに、キャッシュについての知識も述べております。ひとまずよく使うコマンドのみ述べております。今後もなにか良い書き方があれば追記予定です。

# キャッシュについて
- `COPY`, `ADD`コマンドは、**ファイルに変更があればキャッシュは使用せず、新規にコピー行う**
- `RUN apt-get update`などは、コマンドだけを見るため、**中身のファイルに変更があったとしても、キャッシュを使用し、以前の状態のままとなる**
- キャッシュを使用したくない場合は、`--no-cache=true`をつければOK


# RUNコマンド

### 1. インストールコマンドは例に示すようにインストールすること

理由

- `$ apt-get update`を別に分けると、キャッシュを使用するため最新のパッケージがインストールできない可能性がある
- レイヤー数は限られているため、なるべく少なくすることが大事
- 最後2行でaptキャッシュをクリーンにし、 /var/lib/apt/lists を削除することでイメージのサイズを減らす
- パッケージはアルファベット順に書く


```dockerfile:Dockerfile
RUN apt-get update && apt-get install -y \
    aufs-tools \
    automake \
    build-essential \
    curl \
    dpkg-sig \
    libcap-dev \
    libsqlite3-dev \
    lxc=1.0* \
    mercurial \
    reprepro \
    ruby1.9.1 \
    ruby1.9.1-dev \
    s3cmd=1.1.* \
 && apt-get clean \
 && rm -rf /var/lib/apt/lists/*
```

```dockerfile:Dockerfile
# ダメな例
RUN apt-get update                  # 以前のキャッシュを使用して以後のinstallが古いバージョンとなる可能性あり
RUN apt-get install -y aufs-tools
```

# COPYとADD
### 1. できるだけCOPYを使うこと
理由

- ADD は複数の機能（ローカル上での tar アーカイブ展開や、リモート URL のサポート）を持ち、一見では処理内容が分からないため
- COPYは、ホスト側のディレクトリをコンテナ側にコピーするだけというシンプルな機能なのでわかりやすい。

### 2. tarアーカイブを展開したい場合、curl,wgetを使用すること

理由
- ADDで行うと不要なファイルが残るが、curl,wgetだと不要なファイルを削除してくれる


```dockerfile:Dockerfile
# ダメな例
ADD http://example.com/big.tar.xz /usr/src/things/
RUN tar -xJf /usr/src/things/big.tar.xz -C /usr/src/things
RUN make -C /usr/src/things all

# 良い例
RUN mkdir -p /usr/src/things \
    && curl -SL http://example.com/big.tar.xz \
    | tar -xJC /usr/src/things \
    && make -C /usr/src/things all
```

### 3. パッケージリストファイルだけを先にコピーしインストールを行い、のちにその他のファイルをコピーする

理由

- あまり変更がないパッケージリストファイルを先にコピーしインストールすることで、キャッシュを使用し早くビルドができる

```dockerfile:Dockerfile
COPY requirements.txt /tmp/
RUN pip install /tmp/requirements.txt
COPY . /tmp/
```


# 参考
https://docs.docker.jp/engine/userguide/eng-image/dockerfile_best-practice.html
Chatworkへデプロイ完了を通知するBitbucket Pipeline Pipe


## 概要
chatwork投稿用のpipeです
slackはあったけどchatworkはなかったので作成

api keyとroom idをRepository variablesに登録してください
room idは数値です(ridはトル）

投稿例
![スクリーンショット 2021-04-04 19.17.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124609/7e3d6028-9509-ff3b-567c-6b80ff0ea8f0.png)

## Variables

| Variable                   | Usage                                                |
| ----------------------------- | ---------------------------------------------------- |
| CHATWORK_ROOM (*)         |  chatwork room id. |
| CHATWORK_API_KEY (*)     |  chatwork api key. |
| MESSAGE_TITLE     |  default="Deployment complete." |
| MESSAGE_BODY     |  default="" |

_(*) = required variable._

## Examples

### Basic example:

```yaml
script:
  - pipe: docker://kdhagino/chatwork-post
    variables:
      CHATWORK_ROOM: $CHATWORK_ROOM
      CHATWORK_API_KEY: $CHATWORK_API_KEY
```

## links
* [Bitbucket Pipes](https://bitbucket.org/product/features/pipelines/integrations)
* [公式Pipesリポジトリ](https://bitbucket.org/atlassian/workspace/projects/BPP)
* [Bitbucket Pipelines 用パイプの作成方法](https://ja.confluence.atlassian.com/bitbucket/how-to-write-a-pipe-for-bitbucket-pipelines-966051288.html)
PMがPTA広報の部長になった訳だが(1)

# 初めに
これは2021年の事です。
SIer企業に長年勤めアプリケーション開発、インフラ構築を一通り経験し最近はPM職のおじさんがPTAの広報部部長を引き受けました。
この1年興味深い事が沢山起きそうなのでPTA活動をPJ運営に見立ててその記録(と私が感じるだろうやるせなさの解消)の為記事を投稿しようと思います。
一年間続けるつもりですのでよろしくお願いします。

##状況

* 広報部員は約30名、男性は私1名、他は全て女性
* 昨年2020年はコロナの影響で一切のPTA活動が停止、活動実績がないのでメンバーの経験不足
* 3年生保護者退部に伴い、運営ノウハウ保持者の不足
* 過去のアウトプットはバインダーに閉じられているので成果物イメージは読み取れる
* 電子資料はPCとUSBメモリにコピーが散逸し整理されていない。お知らせのお手紙のフォーマットを探すのも困難
* LINEグループが存在する、これは活用できる

##リスク
これは私自身も含めた全体にあてはまるリスクです。
* 非協力的メンバー。PTA活動は苦痛でしかないという雰囲気を部員から感じる
* 要員の稼働確保が困難。元々ボランティアなので仕方ないが活動の協力が取りずらい
* 曖昧な作業内容。広報誌発行という目的は分かるがその為に何をするか分からない
* 思い込みを事実と誤認。本部がやってくれるだろうという思い込みの事実確認をしないまま前提条件にして会議をすすめる傾向が強い
* 担当者の報告無し。担当した作業の進捗、結果、変更報告が一切なくやりっぱなし。確認しないと報告が得られない
* 意思表示が無い。 副部長、書記、会計にアイデアの提案をすると賛成も反対もなくスルーされます。もしくは違う話題で空中戦を始めます。
* コミュニケーションの拒絶。「パソコンの事分からないので話についていけない」という伝家の宝刀がすぐ出てきます。私は丁寧に解説しながら話してるつもりなんですけどね…しかもICTとかクラウドサービスとかパソコンの話じゃなくて今日では一般用語になってる名称の筈なんですけどね…何らかの理由により会話が中断される事が多いです。

だんだん愚痴になりそうなのでこれくらいにします。
PMとしてアサインされたら泣きそうになる状況ですね（よくこういうPJをアサインされてます…)


##勝利条件

私の勝利条件をブログ投稿の最初に書いておきます。一年後達成出来たか反省会します。

### 必達
* 来年及び未来の部員が躓かないよう今年切り開いたノウハウを活動マニュアルとして文書化し残す

### 第二勝利条件
* ICTツール/サービスを用いた広報部活動の定着、来年も同じように作業出来たら勝ち
* ケレンミのある広報誌の作成。せっかくPTA会費出して、それを運用してよいのだからキャッチーな広報誌を出して人目を引いて特別賞とか健闘賞などの所謂すごいけど評価不能のアウトプットを出したい
dockerとkubernetesについて（基礎的な自分メモ用）

何も理解しないままkubernetesのコマンドを叩き込んでサーバーにアップロードしている中で、自分はkubernetesについてほぼ無知のことを今さら（使い始めて2か月後）気づきました。ググってみた今でも”結局何、、？”と迷ってはいますが、とりあえずわかった内容だけ記録として残そうとします。

1. dockerは何だろう
---------------------------------------

要するに仮想化環境構築のためのもの。ローカル環境とサーバーの環境は会わないほうが多く、開発済みの結果物をまたサーバー環境に合わせて更新（＝残業）が必要になります。
そこでdockerの登場。
dockerはローカルで使っていたライブラリ、設定ファイルなどなど今までローカル環境からの運用で使われていたものをcontainerに納めます。このcontainerを通じて環境を同一させて、追加作業なしでデポロイができるようになります。
また、一つのサーバーに必要に応じて幾つのcontainerを作って使い分けができるようになります。


2. dockerを補完するkubernetes
---------------------------------------
しかし、dockerにも弱点は存在していて、それは複数のcontainerをコントロールが難しいこと。
いきなりアクセスが爆発することが起きて、それを迎えるcontainerの数が一つや二つ（極端の話で）しかないのであれば、サーバーは耐えられないと思います。また、その一つや二つしかないcontainerが死んでしまえば大変なことになりかねないでしょう。

そこらをkubernetesは対応します！

アクセスが多くなるほどkubernetesは対応のためcontainerを増やしてきます。逆の場合はcontainerの数を減らすことで柔軟に問題を解けてくれます。簡単に言うといつもサーバーを見張っていて上記のようにサーバーがいきなり止まるのなら再起動してくれます。

---------------------------------------
書いてからみればkubernetesがほぼ万能のように書いてしまいましたが、kubernetesにも弱点は存在すると思います。ただ今回は両方を全く知らなかった時点からメモ書きしているので、今後修行を重ねてもっと詳しい紹介を書けるようになろうと思います。
Ubuntu (18.04)で多機能（多ボタン）マウスの設定をする

1. `sudo apt-get install easystroke`
1. 「設定」->「外観」でEasystrokeを自動起動だけチェック->「ジェスチャ・ボタン」->使用したいボタンを灰色の枠内で押す
1. 「アクション」-> 「アクションを追加」->「名前」を適当に設定->「種類」で「キー」を選ぶ->「詳細」を選択し、設定したいキーを入力->「ストローク」で上で設定したボタンを押す
Atomのterminal-plusパッケージを動くようにする

# 事象
 Atomの[terminal-plusパッケージ](https://atom.io/packages/terminal-plus)をインストール後、terminalを起動しようとしても、真っ暗なままでうんともすんとも言わない。
 これをどうにかしたい。

(結論から言うと、たぶん [terminusパッケージ](https://atom.io/packages/terminus)とか使ったほうが早いと思いますが、備忘として残しておきます)

# 環境
```
$ sw_vers                                                                                                      
ProductName:	macOS
ProductVersion:	11.2.3
BuildVersion:	20D91
$ node -v
v14.16.0
$ npm -v
6.14.11

% atom --version
Atom    : 1.55.0
Electron: 6.1.12
Chrome  : 76.0.3809.146
Node    : 12.4.0

% apm show terminal-plus
 terminal-plus
├── 0.14.5
├── https://github.com/jeremyramin/terminal-plus
├── A terminal package for Atom, complete with themes and more.
├── 999044 downloads
└── 709 stars
```

# やったこと

`~/.atom/packages/terminal-plus`での作業
 
- package.json書き換え

```jsonc:package.json
  "dependencies": {
    "atom-space-pen-views": "^2.1.0",
 // "pty.js": "git+https://github.com/jeremyramin/pty.js.git#28f2667", // この行はを削除
    "node-pty": ">= 0.1.0",                                           // この行を追加
    "term.js": "git+https://github.com/jeremyramin/term.js.git",
    "underscore": "^1.8.3"
  },
```

- requireするパッケージを変更

```coffee:lib/process.coffee
 # pty = require 'pty.js' # こっちはコメントアウトor削除
 pty = require 'node-pty' #読み込むパッケージ名を変更したものを追加
 path = require 'path'
 fs = require 'fs'
 _ = require 'underscore'
 child = require 'child_process'
# (略)
```

`$ npm install` `$ apm rebuild` で事象が解消する。

# 何をしたか
- pty.jsはterminal-plusで参照されるパッケージ。その名の通り擬似端末をforkしてくれるもの。
- こちらはあまりメンテされておらず、最近のnode.jsではビルド[^1]が(少なくとも手元の環境では)上手くいかない。 
    - pty.jsが更に参照しているnanのバージョンが古いままで、node10系以降では対応できていなかったり、pty.js自体のコードも古かったり。
- これを、pty.jsのフォークである [node-pty](https://github.com/microsoft/node-pty) に置き換えてしまう。
    - node-ptyは割とアクティブにメンテされているようにみえるので、こちらを使うのがよさそう。

[^1]: `npm rebuild`のこと。 そもそも、`apm install terminal-plus`の時点でエラーにならずインストール成功したり、terminal-plus起動時に明示的にエラーが出てこないのは何故かは理解できていない。。

# 参考
- https://github.com/jeremyramin/terminal-plus
- https://github.com/jeremyramin/pty.js
    - terminal-plusが参照しているpty.js。
- https://github.com/chjj/pty.js
    - 上記のfork元。時折、[package.jsonのdependencies部分更新のpull request](https://github.com/chjj/pty.js/pull/199) 等が上がっているが、取り込みなどはされていない模様。
- https://github.com/nodejs/nan/issues/763
    - node v10以上だとbuildに失敗する件のissue。
- https://github.com/microsoft/node-pty
    - 今回差し替えたパッケージ。こちらも https://github.com/chjj/pty.js のフォーク
- https://atom.io/packages/terminus 
    - node-ptyを使っているパッケージ。これだと一発で動く。
Property 'accessToken' does not exist on type 'AuthCredential'の解決方法

FirebaseでgetRedirectResultのレスポンスを扱う際に型のエラーが発生しました。


```
firebase
  .auth()
  .getRedirectResult()
  .then((result) => {
    const credential = result.credential
    console.log(credential.accessToken)　// ここでエラーが発生する
  })
```

この状態だと以下のエラーが発生する

`Property 'accessToken' does not exist on type 'AuthCredential'.Vetur(2339)`

accessTokenプロパティがAuthCredentialオブジェクトに存在していないようです。


### 対策

AuthCredentialにOAuthCredential持つaccessTokenプロパティをキャストする必要があります。
https://github.com/firebase/firebase-js-sdk/blob/master/packages/auth-types/index.d.ts#L244



```
firebase
  .auth()
  .getRedirectResult()
  .then((result) => {
    const credential = result.credential as firebase.auth.OAuthCredential
    console.log(credential.accessToken) //  エラーは発生しない
  })
```


`const credential = result.credential`
この部分を
`const credential = result.credential as firebase.auth.OAuthCredential`
こんな感じにする




### 参考記事
https://stackoverflow.com/questions/53458622/property-accesstoken-does-not-exist-on-type-authcredential
curlでGitHub APIを使ってコマンドラインからリポジトリを自動作成する

複数のリモートリポジトリを作成するとき、
GitHubにログインしてリポジトリ作成のボタンを押すのが面倒なのでコマンドで済ませます。

#環境
 - OS : MacOS 14.15
 - zsh

#GitHub アクセストークン取得

[GitHub](https://github.com/login)にログインして
右上のユーザーアイコンから `Settings` に移動
サイドカラムの下の方の `Developer Settings` に移動して
`Personal Accesss Token` を開く

![スクリーンショット 2021-04-04 18.33.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677894/d9bf837e-2da8-b936-efdd-d96db77c6783.png)

このような画面になるので `Generate new token` する。

![スクリーンショット 2021-04-04 18.37.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677894/20ede0d9-323b-ab01-b86a-88fa10297335.png)

名前を適当に決めて `repo` のところにチェックを入れてトークン発行
(トークンを紛失すると再発行が必要)

ここで発行したトークンをコピーしておく


#Shellの設定

ここではマシンがMacOS 14.15(Catalina)なのでzshですが、bashの場合は適宜読み替えてください。

`.zshrc` に以下を追記

```shell-session:.zshrc
export GITHUB_USER=yourname
export GITHUB_URL_BASE=git@github.com:$GITHUB_USER
export GITHUB_TOKEN=your_access_token

create_repo() {
  rm -rf .git/
  git init
  curl -H "Authorization: token $GITHUB_TOKEN" \
  --data "{ \
  \"name\": \"$1\", \
  \"auto_init\": true, \
  \"private\": true }" \
  https://api.github.com/user/repos
  git remote add origin $GITHUB_URL_BASE/$1.git
}
```

`""`がネストされているので適宜エスケープ
json形式のところは適宜変更してください。


```shell-session
% source ~/.bashrc
```
保存して反映


#使い方

```shell-session:
% create_repo 作成するリポジトリの名前
```

で任意のリポジトリが作成できる。



#参考

- https://docs.github.com/en/rest/guides/getting-started-with-the-rest-api
- https://stackoverflow.com/questions/28385884/how-to-create-repository-in-github-through-github-api
【図で見る】ノンブロッキングI/O通信とJava


#概要
どうもです。

ノンブロッキングI/Oの概念やjavaでの実装を調べてる中で、
javaのクラス間の関係を図とかで一気に登場人物が欲しかったので作りました。

また、
「同期I/Oや非同期I/Oに対するメリット」
「一番の(構造上の)違い」
という感じの図も欲しくなり作りました。
というわけで行ってみましょう。

#内容
##ノンブロッキングI/Oとは
###~背景~ C10K問題

主にWebシステムにおいて、

「サーバに対するクライアントの数が増えるとやばいよね」

という問題がことの発端です。
>C10K問題（英語: C10K problem）とは、Apache HTTP ServerなどのWebサーバソフトウェアとクライアントの通信において、クライアントが約1万台に達すると、Webサーバーのハードウェア性能に余裕があるにも関わらず、レスポンス性能が大きく下がる問題である。

from [wiki...](https://ja.wikipedia.org/wiki/C10K%E5%95%8F%E9%A1%8C)

###ノンブロッキングI/Oでやること
通信方式の一つです。
非同期I/O同様サーバプロセスが複数の接続を保持することができる方式ですが、
若干やることが違います。

正確性を犠牲にして噛み砕いた表現をすると、
______________
非同期I/O
-> 接続ごとにスレッドを用意する

ノンブロッキングI/O
-> 複数の接続を一つのスレッドで相手取る
_________________

といったところです。

「接続を管理台帳みたいなところに登録しておいて、
定期的にそれらの接続に何か届いていないか、とかを確認して届いていれば処理を行う」

というものです。
###ノンブロッキングI/Oの考え方と従来方式の違い
同期I／Oや非同期I/Oの違いを調べた感じは以下のような感じです。
![ノンブロ考え.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494883/99ec5c63-9ea7-a04c-1e9d-ca8a19265e75.png)

表の中身をイラストで表すとこういう感じです↓
![ノンブロ図解.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494883/f3d18440-b611-3fab-fb65-1c22eff6a9b1.png)

##JavaでのノンブロッキングI/O通信の実装に関わるクラス
###登場人物と事前準備

JavaでノンブロッキングI/O通信を実装する場合、java.nioパッケージの中身をいくつか使うと思います。
割とよく見る使い方はこんな感じです↓。こういう感じで事前準備をします。
![4_ノンブロ事前準備.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494883/bc0c1ab2-b5ee-5939-fe38-ae18905838ac.png)

###そのあと「セレクタ」でやること
ノンブロッキングでは「セレクタ」の処理が特色というか、大事なところです。
SocketChannelを登録するところですが、関連する処理は↓のような感じです。
![5_セレクターとかでやること.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494883/5b4209c8-42dc-4d47-3a22-add1a7f0d303.png)

- 1.新しい接続が来ると、先に登録したサーバーソケットチャネルがacceptメソッドで取り出します。

- 2.その接続(SocketChannel)をキーとして「セレクタ」の「キーセット」に登録します。
その時に、「その接続に対してやりたいこと(リクエストの中身を読み出すとか)」を設定します。
(interestOpsとか、registerといったメソッドです)

- 3.その後、select()というメソッドを読ぶと
「やりたいことができる状態になっているか？」
がOSに問い合わせられ、できる状態であれば、「選択されたキーセット」に入ります。

- 4.選択されたキーセットに入ってしまえば、あとはそこから接続をイテレータで取り出して処理するだけです。

##SelectorとSelectionKey
Selectorとその中で使われるSelectionKeyはいくつかのフィールドを持ちます。

重要なのが以下です。
![7_セレクタ関連登場人物.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494883/63e1be36-38f6-ac7e-e784-098a17852143.png)
Selectorには、

- 最初に登録される「キーセット」
- 読み出しや書き込みなどの操作ができる状態でselect()を使うとキーセットからこちらに登録される「選択されたキーセット」
- 接続が切断された時等に追加される「取り消されたキーセット」

という３つのセットがあります。選択されたキーセットには、
直接キーを登録するようなAPIはありません。

また、実際に登録されるキーであるオブジェクトのSelectionKeyには、

- 操作種別を指定できる「対象セット」
- 実際に対象セットに指定した操作が可能かという情報が登録される「実行可能操作セット」

があります。実行可能操作セットには、直接値を設定するようなAPIはありません

これらが前述の処理の中でどう動くかというと、↓のような感じになります。
![8_セレクタ内部動作.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494883/f805715b-90a0-0b14-c148-f974b0669d76.png)


#おわりに

調べてみて、
Selectorのselect()や
SelectionKeyの振る舞い、関連性が分かりにくいな、
と思っていたので整理してある程度頭がスッキリした感じはします。

あと、正直ServerSocketとSocketの具体的な役割の違いも怪しかったので
いい勉強になりました。
間違い、ご指摘等あればいただけるとありがたいです。

以上になります。

ご一読ありがとうございました。
UbuntuからTP-Link Archer T3U AC1300を使って接続する

# ドライバーインストール

```
git clone https://github.com/cilynx/rtl88x2bu
cd rtl88x2bu/
git rev-parse HEAD # 48e7c19c92a77554403e1347447f8e2cfd780228
VER=$(sed -n 's/\PACKAGE_VERSION="\(.*\)"/\1/p' dkms.conf)
sudo rsync -rvhP ./ /usr/src/rtl88x2bu-${VER}
# /usr/src/<module_name>_<module_version> に移動させて dkms で管理する

# sudo 
sudo apt-get install dkms
sudo dkms add -m rtl88x2bu -v ${VER}
sudo dkms build -m rtl88x2bu -v ${VER}
sudo dkms install -m rtl88x2bu -v ${VER}
sudo dkms status
sudo modprobe 88x2bu
```

# WiFiに接続

```
# 接続可能なWiFiをリスト表示
nmcli d wifi list

# ネットワークインターフェース名を取得
nmcli device status

sudo nmcli device wifi connect 'SSID' password 'wifi のパスワード' ifname wlan0

# 確認
nmcli device status
```

connectedになれば成功
WSLでのnode管理をnからnodebrewに切り替え

# はじめに

Windows10 ProにWSLを入れて開発をしています。
以前は[n](https://github.com/tj/n)を使ってnodeのバージョン管理をしていたのですが、
ある問題にぶつかりnodebrewに切り替えました。
そのときのメモです。

問題とは、Windows側にインストールした[RunJS](https://runjs.app/)で、
npm packageのインストールができないことでした。
nodebrewに切り替えたら問題なくインストールできるようになりました。

# 環境

- Windows 10 Pro
- WSL
    - version 2
    - Ubuntu 20.04 LTS

# 方法

## n のアンインストール

こちらの[記事](https://qiita.com/kouki_tsuji/items/bf4951a76d221e874fdd)を参考にしました。

```bash
$ sudo n uninstall
$ sudo rm -rf /usr/local/n
```

## nodebrewのインストール

```bash
$ curl -L git.io/nodebrew | perl - setup
```

.bash_profileに以下を環境変数の設定を記述

```bash
export PATH="$HOME/.nodebrew/current/bin:$PATH"
```

環境変数を適用

```bash
source .bash_profile
```
## nodeのインストール

nodebrewでnodeをインストールします。
今回は最新の安定板をインストールしました。

```bash
$ nodebrew install-binary stable
$ nodebrew use stable
use v14.16.0

# [補足]インストール可能なバージョンの確認
$ nodebrew ls-all
```

インストールされたnodeの確認

```bash
$ which node
/home/mypath/.nodebrew/current/bin/node
$ which npm
/home/mypath/.nodebrew/current/bin/npm
$ node -v
v14.16.0
$ npm -v
-bash: /mnt/c/Program Files/nodejs/npm: /bin/sh^M: bad interpreter: No such file or directory
```

npmのパスを誤って認識しているらしい。

## トラブルシューティング

.bash_profileのパスの設定を以下のように変更して解決

```bash
export PATH="$HOME/bin:$HOME/.local/bin:$HOME/.nodebrew/current/bin:$PATH"
```

これでWindows側でインストールしたRunJSでもnpm packageをインストールできるようになりました。
マインクラフトサーバーで SessionLock$ExceptionWorldConflict エラーが発生したときの対処法

## 環境について
この記事で利用している端末は RaspberryPi 4B 8GB Model でOSは RaspberryPi OS を利用しています。
マインクラフトサーバーソフトウェアは SpigotMCベースの PaperMCを利用しており、SpigotMCと互換性があります。

## エラー内容
```
[23:21:24] [Server thread/ERROR]: Encountered an unexpected exception
java.lang.RuntimeException: net.minecraft.server.v1_16_R3.SessionLock$ExceptionWorldConflict: /home/pi/sv4/./utility_nether/session.lock: already locked (possibly by other Minecraft instance?)
        at net.minecraft.server.v1_16_R3.MinecraftServer.loadWorld(MinecraftServer.java:361) ~[patched_1.16.5.jar:git-Paper-471]
        at net.minecraft.server.v1_16_R3.DedicatedServer.init(DedicatedServer.java:239) ~[patched_1.16.5.jar:git-Paper-471]
        at net.minecraft.server.v1_16_R3.MinecraftServer.w(MinecraftServer.java:936) ~[patched_1.16.5.jar:git-Paper-471]
        at net.minecraft.server.v1_16_R3.MinecraftServer.lambda$a$0(MinecraftServer.java:174) ~[patched_1.16.5.jar:git-Paper-471]
        at java.lang.Thread.run(Thread.java:834) [?:?]
Caused by: net.minecraft.server.v1_16_R3.SessionLock$ExceptionWorldConflict: /home/pi/sv4/./utility_nether/session.lock: already locked (possibly by other Minecraft instance?)
        at net.minecraft.server.v1_16_R3.SessionLock$ExceptionWorldConflict.a(SourceFile:98) ~[patched_1.16.5.jar:git-Paper-471]
        at net.minecraft.server.v1_16_R3.SessionLock.a(SourceFile:44) ~[patched_1.16.5.jar:git-Paper-471]
        at net.minecraft.server.v1_16_R3.Convertable$ConversionSession.<init>(Convertable.java:218) ~[patched_1.16.5.jar:git-Paper-471]
        at net.minecraft.server.v1_16_R3.Convertable.c(Convertable.java:200) ~[patched_1.16.5.jar:git-Paper-471]
        at net.minecraft.server.v1_16_R3.MinecraftServer.loadWorld(MinecraftServer.java:359) ~[patched_1.16.5.jar:git-Paper-471]
```
どうやら utility_nether の session.lock が原因らしい。（2023年2月21日追記：session.lockとはマインクラフトサーバーを起動させる際の誤動作を防止するためのファイルらしいです。よう分からん。）

## 解決法
session.lock を削除してもう一度作り直してあげればいい。

```
rm -r "マインクラフトサーバーのファイル"/"問題の起きているワールド"/session.lock
```

この場合は sv4 がマインクラフトサーバーのファイルで utility_nether が問題の起きているワールドなので

```
rm -r sv4/utility_nether/session.lock
```
となります。

## できた！！と思ったら....
```
net.minecraft.server.v1_16_R3.SessionLock$ExceptionWorldConflict: /home/pi/sv4/./utility_the_end/session.lock: already locked (possibly by other Minecraft instance?)
```
今度は utility_nether でも同一のエラーが...
先ほどと同じようにすることで解決しました。

```
rm -r sv4/utility_the_end/session.lock
```

質問などございましたら、コメントをしていただければ幸いです。
NextjsのCLIのコマンドについて

## はじめに
Nextjsのコマンドについてよくわかっていなかったので調べたメモ

※ NextjsCLIコマンドについては

```
npx next -h
```
で詳細を確認できます。

## next dev

```
npx next dev
```
このコマンドでは、ホットリロードやエラーレポートなどの開発モードでアプリケーションを起動できます。
デフォルトでは、
http://localhost:3000
で起動しますが、-pオプションをつけると起動するポート番号を指定できます。

```
npx next dev -p 8888
```
開発時には基本的にnext devでサーバを立ち上げます。

## next build

```
npx next build
```
このコマンドでは、本番用に最適化されたビルドを行い、各ルートの情報がコンソールに出力されます。

出力例
![スクリーンショット 2021-04-04 18.19.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/732594/25e485b4-c8a2-cd83-abbc-cc1abce4813d.png)


Sizeの項目には、各ページにクライアントサイドで遷移した際にダウンロードされるassetsのサイズが表示されています。

First Load JSの項目には、各ページにサーバから遷移した際にダウンロードされるassetsのサイズが表示されています。

First Loadは緑か黄か赤色で表示され、パフォーマンスを求められるアプリケーションなら緑色に収まるようにすれば良いみたいです。

## next start

```
npx next start
```
このコマンドは、```npx next build```でビルドした後に実行し、本番用としてサーバが立ち上がります。

このコマンドもデフォルトでは、
http://localhost:3000
で起動しますが、-pオプションをつけると起動するポート番号を指定できます。

```
npx next start -p 8888
```

## 終わりに
buildした際に色でパフォーマンスが判断できるのは良いと思いました。

## 参考
https://nextjs.org/docs/api-reference/cli
VScodeでTSを使うと出るCannot use JSX unless the '--jsx' flag is provided. ts(17004)を解決する。

#はじめに
create-react-appを実行し、いざ開発を始めようとしたらこんなエラーが
```Cannot use JSX unless the '--jsx' flag is provided. ts(17004)```
なんぞこれ。

#解決方法

どうやらVScodeでのTypeScriptのバージョンが違うらしい。
ということでTypeScriptのバージョンを変えてみる。

``Ctrl+Shift+p``で開き、**TypeScript select**でバージョンを選択
![スクリーンショット 2021-04-04 18.32.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/b94bdc2d-0cd0-06b4-40f6-a6ee28fd02b0.png)

ここでバージョンを4.2.3に変更

![スクリーンショット 2021-04-04 18.33.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/39cf7953-0e9d-4886-213b-d6ee181ab4b7.png)

これでエラーが出なくなりました！
![スクリーンショット 2021-04-04 18.34.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/29aa175a-11d0-84e5-8095-92940e5760d8.png)
Command Line【学習記録】

■touch ファイル名
ファイルを作成する

■cat ファイル名
ファイルの中身を表示する

■mkdir ディレクトリ名
ディレクトリを作成する

■ls
ファイル・ディレクトリを一覧で表示する

■cd ディレクトリ名
指定したディレクトリに移動する

■cd ../
一つ上のディレクトリに移動する

■cd
ホームディレクトリに移動する
ホームディレクトリは、ユーザーが作業をするときに起点にするディレクトリのこと

■pwd
カレントディレクトリを確認する
ルートディレクトリからカレントディレクトリまでの階層が表示される

■mv 移動させたいファイル名 移動先のディレクトリ名
ファイルを移動させる、ディレクトリも移動できる

■mv 現在のファイル名 新しいファイル名
ファイル名を変更する、ディレクトリ名も変更できる

■cp ｺﾋﾟｰするファイル名 新しいファイル名
ファイルをコピーする

■cp -r ｺﾋﾟｰするディレクトリ名 新しいディレクトリ名
ディレクトリごとコピーする

■rm ファイル名
ファイルを削除する

■cp -r ディレクトリ名
ディレクトリごと削除する
Ruby の gem の中の .bundle ファイルを確認した話

# Ruby の `*.bundle` ファイルを確認した話

gem が拡張ライブラリの場合，例えば MacOS であれば `bundle`という拡張子のファイルができる．

```shell-session
$ file vendor/bundle/ruby/2.6.0/gems/greenmat-3.5.1.1/lib/greenmat.bundle
vendor/bundle/ruby/2.6.0/gems/greenmat-3.5.1.1/lib/greenmat.bundle: Mach-O 64-bit bundle x86_64
```

見ての通り，`Mach-O 64-bit bundle x86_64` というファイルフォーマットになっている．

- Mach-O
    - https://ja.wikipedia.org/wiki/Mach-O
    - Mac の実行ファイル，オブジェクトファイルのフォーマット

## ダイナミックリンクライブラリ

bundle ファイルには，ダイナミックリンクライブラリがリンクされている場合がある．

```shell-session
$ otool -L vendor/bundle/ruby/2.6.0/gems/greenmat-3.5.1.1/lib/greenmat.bundle
vendor/bundle/ruby/2.6.0/gems/greenmat-3.5.1.1/lib/greenmat.bundle:
        /usr/local/opt/rbenv/versions/2.6.3/lib/libruby.2.6.dylib (compatibility version 2.6.0, current version 2.6.3)
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
```

今回は，Ruby のライブラリだったけど，他の依存ライブラリ(libmysql，libssh とか) の場合もありえる．

見ての通りファイル名にバージョン番号が含まれている場合があるので，バージョンが変わる(=ファイル名が変わる) と面倒になる可能性がある．

## Case

例えば，ライブラリとしては互換性があるけど，ファイル名が変わってしまった場合は，同名ファイルを作る(シンボリックリンクとか) ことで解決できるかもしれないし，
互換性が無い場合は，`.bundle`ファイルを再作成した方がいいかもしれない．

## Linux だと

ちなむと

```shell-session
$ file /usr/local/bundle/gems/greenmat-3.5.1.1/lib/greenmat.so
/usr/local/bundle/gems/greenmat-3.5.1.1/lib/greenmat.so: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=43f2c67f9b7512be3bc1554841f662413140d434, with debug_info, not stripped
```

```shell-session
$ ldd /usr/local/bundle/gems/greenmat-3.5.1.1/lib/greenmat.so
        linux-vdso.so.1 (0x00007ffc0b58e000)
        libruby.so.2.6 => /usr/local/lib/libruby.so.2.6 (0x00007f73e54a6000)
        libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f73e531a000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f73e5159000)
        libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f73e4f3b000)
        libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f73e4f1a000)
        librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f73e4f10000)
        libgmp.so.10 => /usr/lib/x86_64-linux-gnu/libgmp.so.10 (0x00007f73e4e8b000)
        libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f73e4e86000)
        libcrypt.so.1 => /lib/x86_64-linux-gnu/libcrypt.so.1 (0x00007f73e4e4c000)
        /lib64/ld-linux-x86-64.so.2 (0x00007f73e581e000)
```

## 付録

もうちょっと色々出る

```
$ otool -l /usr/bin/diff3 | awk '/LC_LOAD_DY/,/name/{print}'
          cmd LC_LOAD_DYLINKER
      cmdsize 32
         name /usr/lib/dyld (offset 12)
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
```

# Refs

https://guides.rubygems.org/gems-with-extensions/

https://mteramoto.hatenablog.com/entry/20070114/p2

https://web.archive.org/web/20090901205800/http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html
float('inf')を使うと型ヒントで怒られる問題

## 例：最大値を求める関数

Pythonで整数のリストの最大値を求める関数を自作する場合を考えてみる。

これまでの最大値とリストの各整数を比較し、最大値より大きい場合は最大値を更新する関数を作成すればよいわけだが、型ヒントを使う場合、最大値の初期値が問題になってくる。

## 最大値を`0`と置く方法

```python:my_max.py
def my_max(nums: List[int]) -> int:
    mx: int = 0
    for num in nums:
        if num > mx:
            mx = num
    return mx
```

リストがすべて負の数からなっていた場合、`0`が返ってきてしまうという問題がある。

## `sys.maxsize`を使う方法

```python:my_max2.py
def my_max2(nums: List[int]) -> Optional[int]:
    mx: int = -sys.maxsize - 1
    for num in nums:
        if num > mx:
            mx = num
    return mx
```

`sys.maxsize`はPy_ssize_t型の変数が取りうる最大値を示す整数[^1]であって無限大ではないため、メモリの許す限りより大きな数が存在してしまうという問題がある。

[^1]: https://docs.python.org/ja/3/library/sys.html#sys.maxsize

## 最大値を`float('inf')`や`math.inf`と置く方法

```python:my_max3.py
def my_max3(nums: List[int]) -> int:
    mx: int = float('-inf')  # mx: int = -math.inf でも同じ
    for num in nums:
        if num > mx:
            mx = num
    return mx
```

整数int型に浮動小数点float型を代入することができないため、Pylanceやmypyの型チェックでエラーになる。

## Union型を使う方法

```python:my_max4.py
def my_max4(nums: List[int]) -> Union[int, float]:
    mx: Union[int, float] = float('-inf')
    for num in nums:
        if num > mx:
            mx = num
    return mx
```

浮動小数点float型を許容してしまうという問題がある。

## Optional型を使う方法

```python:my_max5.py
def my_max5(nums: List[int]) -> Optional[int]:
    mx: Optional[int] = None
    for num in nums:
        if not mx or num > mx:
            mx = num
    return mx
```

None型を許容してしまうという問題と条件式がやや長くなるという問題がある。
heroku H10エラー解決方法(Railsチュートリアル13章）

#エラー内容
Railsチュートリアル13章を終えて、herokuにデプロイしたところ、こんな画面が表示されました。
![heroku eroor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110285/c723f075-f2af-d73b-29d2-4dae6fe7ee89.png)

`$ heroku logs --tail`コマンドを打てとのことだったので、試したところ

```
at=error code=H10 desc="App crashed" method=GET
```

とのこと。
エラーコードの中身から、code=H10,desc="App crashed"らしい。

#解決方法
詳細を確かめるべく、`$ heroku run rails c` を見てみる。
おそらく、AWSのS3の設定でミスが起きているはず。

```
Cannot load `Rails.config.active_storage.service`: (Aws::Errors::InvalidRegionError)
Invalid `:region` option was provided.
```

何やら、regionの設定が間違っているよう...
もう一度、regionの設定をし直すことで、無事解決しました。
（config/storage.ymlで間違えていました）

#まとめ
エラーが起きた時は、コンソールで確認するのが大事！
【Ruby】配列の先頭に要素を挿入するunshiftメソッドの使い方

#プログラミング勉強日記
2021年4月4日

#unshiftメソッドとは
　配列の先頭に引数で指定した要素を挿入するメソッド。(pushメソッドは配列の最後に要素を追加する。)
　引数を指定しなければ何も起こらない。

```ruby:使い方
配列.unshift(引数, ...)
```

#サンプルプログラム

```ruby
# 配列を定義
num = [1, 2, 3, 4, 5]

puts "挿入前：#{num}"

# 配列の先頭に要素を挿入する
num.unshift(0)

puts "挿入後#{num}"
```

```:実行結果
挿入前：[1, 2, 3, 4, 5]
挿入後：[0, 1, 2, 3, 4, 5]
```

#参考文献
[instance method Array#prepend](https://docs.ruby-lang.org/ja/latest/method/Array/i/prepend.html)
【heroku】デプロイ時のbundler (LoadError)エラー

herokuへのデプロイを試みた際にbundlerに関連したエラーを経験したので、解決策を載せておきます。
## bundler (LoadError)
このエラーはherokuが対応しているbundlerと、アプリ内のbundlerのバージョンが違うことに起因するものでした。
現時点で、herokuは2.1.4までのバージョンのみ対応しているらしく、それ以降のバージョンはエラーになってしまいます。
ということで、アプリディレクトリに移動しGemfile.lockを確認。アプリには以下の記述のバージョンのbundlerが適用されています。

```Gemfile.lock
BUNDLED WITH
   2.*.*
```

Gemfile.lockはgemの関係性を保つためのファイルで、bundle install時に自動で作成されます。よって、このファイルを削除してから、バージョン2.1.4のbundlerをインストールし、bundle installを実行します。

```ターミナル
$ rm Gemfile.lock 
$ gem install bundler -v 2.1.4
$ bundle _2.1.4_ install without production
```

この方法で、デプロイに成功しました。

# 参考
[cannot load such file -- rake (LoadError)やcannot load such file -- bootsnap/setup (LoadError)と出てherokuへのデプロイに失敗する](https://qiita.com/i05tream/items/8b64d6061a3589e5d242)
Djangoのrest_frameworkのviewsの使い方をさらっとまとめてみた

普段、インターンでDjangoのrest_frameworkを用いてAPIを作ったりしているので、アウトプットとして自分なりにまとめてみた。

### APIView

APIViewはrest_frameworkの全ての**Viewクラスの継承元となるクラス**である。**リクエストのメソッド名と同じインスタンメソッドが呼ばれる**。これらのメソッドは、DRFではハンドラメソッドと呼ばれる。この仕組みは**dispatch**メソッドによって実現されている。

参考記事
[DjangoのView呼び出しの仕組み ~getメソッドはどう呼ばれるのか \- りんごとバナナとエンジニア](https://udomomo.hatenablog.com/entry/2018/08/17/010011)

getやpostメソッドは自前で用意する必要がある。

```py
class ArticleAPI(views.APIView):
    # 一覧を返す
    def get(self, request, *args, **kwargs):
        articles = Article.objects.all()
        # リスト形式のJsonを出力する場合は、 「many=true」を指定する必要がある。
        serializer = ArticleSerializer(instance=articles, many=true)
        return Response(serializer.data, status.HTTP_200_OK)

    # 記事を作成する
    def post(self, request, *args, **kwargs):
        serializer = ArticleSerializer(data=request.data)  
        serializer.is_valid()
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)
        
```
この他にも、putメソッドやdeleteメソッドを作成して更新や削除などの処理を作ることができる。


### 汎用APIView

汎用APIViewでは、CreateAPIViewやListAPIViewなどのビュークラスのことを言う。get()やpost()などのハンドルメソッドの代わりに**list()やcreate()**などのアクションメソッドが用意されてある。

下記がアクションメソッドの一覧である。
[Viewsets \- Django REST framework](https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions)

**単一モデルを対象とするREST APIを作るのであれば、対応するアクションに応じてCreateAPIViewなどを継承すればいいだろう。**

https://github.com/encode/django-rest-framework

listアクションやcreateアクションが呼ばれる仕組みは下記の通りだ。

1. GenericAPIViewは**APIViewを継承している**ためGetリクエストなどが送られたらget()メソッドが呼ばれる
2. **汎用APIViewのgetメソッド内でlist()メソッドが呼ばれる。**

**実際のコード例**

```py
class ListAPIView(mixins.ListModelMixin,
                  GenericAPIView):
    """
    Concrete view for listing a queryset.
    """
    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)
```
api/users/の時はCreateListAPIViewを継承して、api/users/pk/の時はRetrieveUpdateDestroyAPIViewを継承したりなど、REST APIを容易に作ることができてかなり便利である。


### ModelViewSet

ModelViewSetは、**単一モデルのCRUD処理を用意に実現することができる**。ModelViewSetも**GenericAPIViewを継承している**ため、汎用APIViewのようにリクエストとアクションを結びつけつることができる。

```py
class ModelViewSet(mixins.CreateModelMixin,
                   mixins.RetrieveModelMixin,
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet):
    """
    A viewset that provides default `create()`, `retrieve()`, `update()`,
    `partial_update()`, `destroy()` and `list()` actions.
    """
    pass
```
GitHubにも提供されるアクションメソッドの一覧が表記されている。

https://github.com/encode/django-rest-framework/blob/master/rest_framework/viewsets.py

なお、CRUD処理以外の処理を実装したい時は、actionデコレーターを使うこともできる。
参考記事
[Viewsets \- Django REST framework](https://www.django-rest-framework.org/api-guide/viewsets/#marking-extra-actions-for-routing)

### まとめ
参考記事

- [\[Django REST Framework\] View の使い方をまとめてみた \- くろのて](https://note.crohaco.net/2018/django-rest-framework-view/)
- [Viewsets \- Django REST framework](https://www.django-rest-framework.org/api-guide/viewsets/)

参考書籍

- 「現場で使えるDjango REST Frameworkの教科書」
stash ファイル指定

## ファイル指定 退避 復元

ファイル指定して退避

```
git stash push -m "メモ" -- <ファイルパス１> <ファイルパス２>
```

退避指定して復元

```
git stash pop stash@{0}
```

## Ref

- [[Git] ファイル単位でstashする - Qiita](https://qiita.com/yukitaka13-1110/items/935bfa233c6e024f82dc)
【Next.js】Dynamic Import を使ってSSR回避する方法

## 概要
Next.jsでコードを書いている時にこのようなエラーをみたことがあるのではないでしょうか
**`Warning XXX did not match. Server: XXX Client XXX`**
**このエラーはサーバーとクライアントでレンダリング結果が異なる場合に起こります**。Next.jsはビルド時(SSGの本番環境)またはリクエスト時（SSGの開発環境、SSR）にサーバー側で事前にレンダリング(Pre-rendering)が行われサーバ側でコードが走ります、その後、クライアントで処理が走ります。その時の処理のレンダリング結果が異なる場合には上記のエラーになります
この場合、サーバーとクライアントのレンダリング結果を同じにすればいいのですが、どうしようもない場合があります。その時は、**Dynamic Import を使ってSSRを回避してCSRにする方法があります**
それでは、**現在時刻を取得するプログラムを作成し、このエラーをわざと発生させ説明していきます**

## 本題
#### 現在時刻を取得するプログラム

```index.jsx
import { useState } from 'react';

const index = () => {
  const now = new Date();
  const [hour, setHour] = useState(now.getHours());
  const [min, setMin] = useState(now.getMinutes());
  const [sec, setSec] = useState(now.getSeconds());
  setInterval(() => {
    const now = new Date();
    setHour(now.getHours());
    setMin(now.getMinutes());
    setSec(now.getSeconds());
  }, 1000);

  return (
    <div>
      {hour}時{min}分{sec}秒
    </div>
  );
};

export default index;

```

#### エラー画面
![ezgif.com-gif-maker (13).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927983/fabb15f6-25ec-0755-4311-b8ea7750e5b7.gif)
このように毎回エラーが走るわけではありません。サーバーとクライアントのレンダリングが同じ場合も考えられます(秒数が同じ)
最初に起きたエラーのログは
`Warning Text content did not match. Server: 30 Client 31`
**これは、30秒の時にサーバー側でレンダリングされ31秒の時にクライアント側でレンダリングされたため起こったエラーです**。実際に30秒の時にリロードしていることがわかると思います

**このプログラムを今から書き換えていきます**

### エラーを修正したプログラム
#### Dynamic Import
Dynamic Importを使ってSSR回避しCSRにするプログラムです

```index.jsx
import dynamic from 'next/dynamic';

const index = () => {
  const DynamicComponentWithNoSSR = dynamic(() => import('../components/Timer'), {
    ssr: false,
  });

  return <DynamicComponentWithNoSSR />;
};

export default index;

```

```components/Timer.jsx
import { useState } from 'react';

const Timer = () => {
  const now = new Date();
  const [hour, setHour] = useState(now.getHours());
  const [min, setMin] = useState(now.getMinutes());
  const [sec, setSec] = useState(now.getSeconds());
  setInterval(() => {
    const now = new Date();
    setHour(now.getHours());
    setMin(now.getMinutes());
    setSec(now.getSeconds());
  }, 1000);
  return (
    <div>
      {hour}時{min}分{sec}秒
    </div>
  );
};

export default Timer;
```
**これで、何度リロードを押してもエラーが走らないのが確認できると思います**
これで`Timer.jsx`内の処理はクライアントだけの処理になっています

#### 修正後デモ画面
![ezgif.com-gif-maker (14).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927983/bd2f53f7-36c8-e9cf-7e7d-270664927c8c.gif)

## おわりに
何か他の良いやり方知ってる方がいればコメントで教えていただけるとうれしいです


## 参考
[Dynamic Import](https://nextjs.org/docs/advanced-features/dynamic-import)
ローカルディレクトリをGitHubのリモートリポジトリへ新規Push

# はじめに

手元の Linux 環境で作成したディレクトリを使って、GitHub の新規 Repository へ Push する手順を備忘録としてメモしています。



# ローカル環境

こんな感じで、ローカルにある Python のソースコードを GitHub へ Push したい状態です。

```
> ls -la
total 4
drwxr-xr-x  3 ec2-user docker   44 Apr  4 17:24 .
drwx------ 13 ec2-user docker  294 Apr  4 12:28 ..
-rw-r--r--  1 ec2-user docker 1509 Apr  4 17:26 selectAurora.py
drwxr-xr-x  3 ec2-user docker   47 Apr  3 18:06 .vscode
```



まず、git init で初期化します。

```
git init
```



VS code を使っているので、`.gitignore` を作成して、`.vscode` を無視します。

```
.vscode/
```



git status で確認します

```
> git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        .gitignore
        selectAurora.py

nothing added to commit but untracked files present (use "git add" to track)
```



全ファイルを追加

```
git add -A
```



git commit を実施

```
git commit -m "first commit"
```



# GitHub で新規 Repository 作成

画面右上から、Your repository へ移動

![image-20210404174216462.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/5ba07eba-df66-83d9-72ff-657279597279.png)



New を押す

![image-20210404174237720.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/1bec6dc2-c75a-c6d6-6e8d-14105d20de5d.png)



Create Repository

![image-20210404174419944.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/94652bd8-cb63-a4fe-59b8-1de9791adb6c.png)



作成完了。HTTPS の URL をメモっておきます

![image-20210404174440448.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/54361640-2b02-bb7e-4860-9e1ee2a5a577.png)



# ローカル環境

remote origin として設定

```
git remote add origin https://github.com/Sugi275/mysql-connection-python-sample.git
```



Push

```
git push origin master
```



Push される

![image-20210404174635811.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/03902a16-e671-aa79-7259-c40528801dff.png)



# 参考URL

https://qiita.com/sodaihirai/items/caf8d39d314fa53db4db