OmniAICreator/Qiita-1.07M huggingface dataset:
pt-online-schema-changeを理解する

## はじめに
こんにちは、webエンジニアの@an_sonyです。

最近巨大テーブルをalterする機会があり、そのツールとしてpt-online-schema-changeを初めて利用しました。そこで得た知見をまとめてみます。

## pt-online-schema-change（以下pt-osc）とは？

主にMySQL向けに作られた運用ツール群[percona](https://www.percona.com/doc/percona-toolkit/LATEST/pt-online-schema-change.html)の一つです。
テーブルへのread/writeを許容できる状態に保ったままalter操作を実行することを可能にします。

## なぜpt-oscが必要か

なにも考えずに通常のalter操作を実行すると、共有ロックを取得するのでinsert/updateができなくなります。alterしようとしているテーブルのレコード数が多い場合、その間書き込みプロセスは待ち状態となり処理が完了しないため、サービスが停止してしまいます。

なお、MySQL5.6からはオンラインDDLができるようになりましたが、全てのalter操作ができるわけではないです。例えばインデックスの追加・削除なら可能ですが、カラムのデータ型の変更は不可です。

## pt-oscの仕組み

仕組みについては、[分かりやすくまとまっている記事](https://ameblo.jp/principia-ca/entry-12129289966.html)がありますので参照ください。

ざっくり流れを記載すると↓

1. 旧テーブルと同じスキーマ構造をした、新テーブルを作る
2. 新テーブルにalter tableを適用
3. トリガーを3つ作成し、旧テーブルのinsert/update/deleteが新テーブルに反映されるようにする
4. 旧テーブルのレコードを新テーブルにコピー
5. 新旧テーブルを入れ替え(rename)
6. 旧テーブルの削除
7. 3で作ったトリガーを削除

実行した時のログ↓

```
Altering `testdb`.`testtable`...
Creating new table...
Created new table testdb._testtable_new OK.
Altering new table...
Altered `testdb`.`_testtable_new` OK.
2021-2-27T08:00:32 Creating triggers...
2021-2-27T08:00:32 Created triggers OK.
2021-2-27T08:00:32 Copying approximately 10 rows...
2021-2-27T08:00:32 Copied rows OK.
2021-2-27T08:00:32 Analyzing new table...
2021-2-27T08:00:32 Swapping tables...
2021-2-27T08:00:32 Swapped original and new tables OK.
2021-2-27T08:00:32 Dropping old table...
2021-2-27T08:00:33 Dropped old table `testdb`.`_testtable_old` OK.
2021-2-27T08:00:33 Dropping triggers...
2021-2-27T08:00:33 Dropped triggers OK.
Successfully altered `testdb`.`testtable`.
```
## 注意点

### 実行中リソースへの負荷が高い

実行中はデータコピーやトリガー処理が走るので、ディスクI/O、CPUに負荷がかかります。
pt-oscにはリソース状況をチェックしながら動作を制御できる便利なオプションが存在しています。
例えば `--check-slave-lag`で全スレーブのレプリケーション遅延をチェックできたり、`--max-lag`で指定秒数のレプリケーション遅延が発生すると処理を一時停止するといった制御が可能です。

### 十分なディスク容量が必要

一時的なテーブルコピーをするので、相応（具体的な数値は分かりませんでした）のディスク容量が必要です。

### デットロックは発生する

pt-oscは旧テーブルのデータを細切れで新テーブルにコピーするツールなので、コピーした瞬間はロックがかかります。その瞬間でクエリがバッティングしてしまうとデットロックが発生します。

###  テーブルロックを取得するタイミングがある

トリガー作成/削除、またはrename tableのタイミングでテーブルロックを取得します。その間はselectもできなくなるので、同時アクセスが多い場合は処理が詰まりやすいです。

## まとめ

便利なツールではありますが、なんでも解決してくれるわけではないので事前に十分な検証が必要です。
できるだけテーブルにアクセスが少ない時間帯を選んだり、実行中はバッチなどによる大量データ処理（read/write）も避けた方が良いです。また、alterしたいテーブルへのread/write頻度が高かったり、デットロックが発生するとサービスへの影響が大きい場合は、他の方法を検討するしかなさそうです。

### 参考

https://www.percona.com/doc/percona-toolkit/LATEST/pt-online-schema-change.html
https://ameblo.jp/principia-ca/entry-12129289966.html
https://dev.mysql.com/doc/refman/5.6/ja/innodb-create-index-overview.html
https://nisshiee.org/blog/2018/105/
レンタルサーバーでPHPのSESSIONが作動しないとき

<h3>きっかけ</h3>
SESSIONがないとログイン機能を実装できないのに、コアサーバーではSESSIONがなぜか機能していなかった。例えば推移先のページにこのようなコードを打つと、「ログインし直して下さい。」が返されてしまう。

```php:
session_start();
if(!empty($_SESSION["userName"]))
echo $_SESSION["userName"]."がログイン中";
else {echo "ログインし直して下さい";exit;}

```
sessionが使えないときの対処法はすでにいくつか記事があるが、sudoコマンドが使えないレンタルサーバーでは少し異なる部分がある。
これを解決するのにかなりのサイトをめぐり試行錯誤したので結果をまとめておく。


<h3>環境</h3>
レンタルサーバー：コアサーバー
使用言語：php7.4
機能：SESSION

<h3>やりたいこと</h3>
<ul><li>SESSION変数に値が保存される。</li>
<li>SESSIONを自分の任意のディレクトリに保存できるようにする。※初期値の保存先は/tmpだが、これはセキュリティ上よろしくないし、なぜか私の場合は保存できなかったため。</li></ul>

<h3>やったこと</h3>
<h5>１.iniファイルのSESSION設定をいじる</h5>
（私はphp7.4を使いました）。コアサーバーでは各ユーザーに対して.iniファイルが用意されています。.htacessや.user.iniでも多分いけるとは思います。

```shell:
cd ~/public_html/.fast-cgi-bin

session.save_path = /virtual/ユーザー名/session

```
ちなみに検索している最中に下記の設定を加える話があったが、あくまで任意の設定で、触らなくても動く。

 session.hash_function = 1
　（sessionファイル名の名前はハッシュ値で出るらしいが、これのアルゴリズム）
 session.hash_bits_per_character = 4
session.sid_bits_per_character = 6　
（sessionファイル名に使われる文字の種類が増える。4なら0-9とa-fまで、6なら0-9とa-zの大文字小文字が使われる）
 session.sid_length = 64　
（sessionファイル名の長さ。長い方が特定されにくいらしい）
 session.entropy_file = /dev/random 
（sessionファイルの名前を乱数で生成する時、どこから取るかを指定。php7.1ですでに廃止された）

<h5>２セッションを保存するディレクトリを作成する。</h5>
私はホームディレクトリ(~/)にsessionディレクトリを作った

```shell:
$ mkdir session
$ chmod u+rwx session
#実行権限を与えることでsessionにファイルを作れるようになる

```
sessionファイルがうまく作れるとlsでこんなファイルが生成される。今回は所有者グループの欄をapacheやngixに直す必要はなかった。（レンタルにはそもそも権限がない）

```shell:
$ ls-l
-rw-------  1 username hpusers   0  2月 25 19:20 sess_3aQ6CWkJDFln6Fn0vDQVRSrU3gcAhkBIdxlWkTZemiNuqUH55ShVgqqMBabIYA,v
```


<h3>おまけ</h3>
全般的なデバッグについてはこちらの方が徹底的に分類してくださっているので、おすすめします。最終的にcookieの設定は関係なかったけど、sessionを理解する上では役立ちました。
https://note.kiriukun.com/entry/20191125-session-not-working-in-php#file

var_dumpにこんなものを入れると検証に役立つ。
<ul><li>var_dump(session_save_path());
→セッションのセーブ先を出力する。iniファイルで設定したパスと同様になっているかはこれで確認する。ちなみにコアサーバーは<b style="color:red;">かなりの時間を置くことでiniファイルの設定が反映される</b>。一般的にはapacheを再起動するとiniファイルが反映されるようだが、間違ってもレンタルサーバーでしようとしてはいけない（というかできない）。</li>
<li>var_dump(shell_exec('ls '.session_save_path().' -la'));
→セッションのセーブ先のファイル一覧を出力する。ここにSESSIONファイルらしきものが保存されていれば保存には成功している。</li></ul>
fetchを使ってパラメータつきリクエストをキャンセルする

#概要
ページ遷移をした際にレスポンスが返ってきていないものをキャンセルする方法をメモします。
今回はfetchを利用してキャンセルしたいと思います。


#実装
##store
```store/comment.js
const state ={
  controller: new AbortController()
}
const getters = {
  controller: state => state.controller ? state.controller: '',
}
const mutations = {
  setController(state, controller){
    state.controller = controller
  }
}
const actions = {
  async getComment({commit, state}, {id}){
    const { signal } = state.controller
    const params = {
      id: id
    }
    const query_params = new URLSearchParams(params)
    await fetch(`/api/comment?${query_params}`, { signal })
      .then(result=> result.json())
      .then(result=>{
      //処理を記述
      }).catch(error=>{
      //処理を記述
      })
  },
  //キャンセル処理
  cancel({state}){
    state.controller.abort()
    console.log('キャンセル完了')
  },
}
export default {
  namespaced: true,
  state,
  getters,
  mutations,
  actions
}
```

##Vue

```comment.vue
<script>
export default{
  beforeRouteLeave(to, from, next){
    //ページを去った時にcancel()をする
    this.$store.dispatch('comment/cancel')
    //キャンセル処理後にstate.controllerにnew AbortController()を設置
    this.$store.commit('comment/setController', new AbortController())
    next()
  }
}
</script>
```
C++で数字を最初から取り出す方法

メモ代わり

意外と難しいのだと感じました．まー難しいなーという感じ.

```
#include<iostream>
#include<string>

int main() {
	std::string s;
	std::cin >> s;
	int n = s.length(), sur = 0;
	for (int i = 0; i < n;i++) {
		sur += int(s[i]-'0');
		sur %= 9;
	}
	if (sur == 0) std::cout << "Yes" << std::endl;
	else std::cout << "No" << std::endl;
	return 0;
}

```

まだまだ勉強ですな（笑）
一覧表示での進捗率ゲージの作成

# はじめに
オリジナルアプリでクラウドファンディングサイトを作成した際に、
jQueryを使って進捗率ゲージを作成したので紹介します。
前回、詳細画面での作成方法を紹介しましたが
今回は一覧表示画面での作成方法です。

[![Image from Gyazo](https://i.gyazo.com/9d48b4ecd07f0773ae0f8649277a7115.jpg)](https://gyazo.com/9d48b4ecd07f0773ae0f8649277a7115)

詳細画面での作成はこちら→
https://qiita.com/takiguchiharuna1221/items/df517f2a9e4b74299328#comment-bd0d8efa2c7c3dc7651e
※こちらではlinear-gradientを使った別の方法も投稿していただいています。

初学者なのでより良い方法が他にもあるかもしれませんが、どなたかの参考になれば嬉しいです。

# 環境
・Rails 6.0.0
・Ruby 2.6.5
・jQuery

# 作成手順
【view】

```ruby:index.html.haml
.Contents__projects
  - @projects.each do |project| 
  # 一部省略
    .Projects 
      = link_to display_project_path(project.id) , class: "Box3"do
        .Box1
          = image_tag project.image.url.to_s, class: "Box1__image"
        .Box2
          %p.Box2__title= project.title
          %p.Box2__percent__contents 進捗率
          - @percent = number_to_percentage(@total.to_f/project.target_amount*100,precision: 1)
          = @percent
          .contents-pacent__box2__graph1
            .contents-pacent__box2__graph2
              %input{name: "percent", type: "hidden", value:@percent, class: 'percent' }
```
①ゲージを挿入したい部分にクラスを設定します。
　→.contents-pacent_box2_graph2の部分

②inptを用いてDBのインスタンス変数の値を取得します。
　→inputのvalueに変数を設定することでjQueryで変数を使えるようにします。
　　※今回は変数の詳細は割愛します。
　参考記事：https://qiita.com/Kohei_Kishimoto0214/items/d919b00d75dec0699cf0

【CSS】

```ruby:_project.scss
.contents-pacent__box2__graph2{
  background-color: #ea662d;
  height: 15px;
  border-radius: 6px;
  max-width: 100%;
}
```

③CSSは以上の通りです。
　進捗率が100％以上になっても突き抜けてしまわないように
　max-width: 100%;を設定しています。

【jQuery】

```ruby:project.js
$(function() {
  $('.percent').each(function(i){
    $(this).attr('id', `percent_${i}`);
  });
  $('.contents-pacent__box2__graph2').each(function(i){
    $(this).attr('id', `graph_${i}`);
  });
  
  (window.onload = function() {
    var ele = document.getElementsByClassName("Projects");
    for(var i = 0; i < ele.length; i++){
      $("#graph_"+i).css({ 'width' : $( "#percent_"+ i).val() } );
    };
  });
});

```

④.percentと.contents-pacent__box2_graph2のそれぞれにidを振ります。
⑤リロードのタイミングでProjectsの数を数え、その回数だけ
”.contents-pacent__box2_graph2のwidthの値を@percentからとる”
を繰り返すように①で付与したidを使ってfor文で設定します。

# 最後に
idの使い方やfor文の設定が自分では使ったことがなかったので苦労しました。
日々勉強します。
MatlabでデータをCSVに書き出す

#目的
Matlabで計算したデータをCSVに書き出す方法の記載


#実行コード
```matlab
%保存データの作成

Time(:,1) = 0:0.2:0.8;
Data(:,1) = 1:2:10;
Data2(:,1) = (1:2:10)*4;


%csvで保存
CSVFileName = 'test.csv';

Output = [Time,Data,Data2]; %配列形式に編集

csvwrite(CSVFileName,Output); %csvで書き出し

%R2019a 以降ならwritematrixを推奨　下記は実際に動かして試していない。
% Output2.Time = Time;
% Output2.Data = Data;
% Output2.Data2 = Data2;
% 
% writematrix(Output,CSVFileName)
````

#実行結果
test.csvがm-fileと同じフォルダにできる。
[解決] Railsの言語設定エラー　'translation missing: ja.datetime.distance_in_words.x_days ago'　

## 現状確認

ruby 2.6.6
Rails 6.1.0

インスタンス変数は、正しく定義されている。

```ruby
[1] pry(#<#<Class:0x00007ff69c4e9978>>)> @post.created_at
=> Sun, 31 Jan 2021 08:28:26.434149000 UTC +00:00
[2] pry(#<#<Class:0x00007ff69c4e9978>>)> time_ago_in_words(@post.created_at)
=> "translation missing: ja.datetime.distance_in_words.x_days"
```

ファイルを見ると、日本語になっている(自分がen→jaに変えたことに気づいていなかった)

```ruby:application.rb
config.i18n.default_locale = :ja
```

## 解決

今までtime_ago_in_wordsは英語設定だったから、上記の日本語変更でエラーが起きたっぽい

time_ago_in_wordsを日本語化するする

locales/ja.ymlにこれを書く

```ruby

ja:
  datetime:
    distance_in_words:
      half_a_minute: "30秒前後"
      less_than_x_seconds:
        one:   "1秒"
        other: "%{count}秒"
      x_seconds:
        one:   "1秒"
        other: "%{count}秒"
      less_than_x_minutes:
        one:   "1分"
        other: "%{count}分"
      x_minutes:
        one:   "約1分"
        other: "%{count}分"
      about_x_hours:
        one:   "約1時間"
        other: "約%{count}時間"
      x_days:
        one:   "1日"
        other: "%{count}日"
      about_x_months:
        one:   "約1ヶ月"
        other: "約%{count}ヶ月"
      x_months:
        one:   "1ヶ月"
        other: "%{count}ヶ月"
      almost_x_years:
        one:   "１年弱"
        other: "%{count}年弱"
      about_x_years:
        one:   "約1年"
        other: "約%{count}年"
      over_x_years:
        one:   "1年以上"
        other: "%{count}年以上"
```

ブラウザで確認した、エラーは無くなっていた。

参考

[【Rails】time_ago_in_words メソッドで created_atを「〜前」と表示する | RemoNote](https://remonote.jp/rails-time-ago-in-words)
pytesseract 概要と使い方 メモ

* `pytesseract`の概要と使用方法についてメモする。



## pytesseract 概要

* OCRツール`Tesseract`のPythonラッパー。

* `Pillow`や`NumPy`などの形式で解析対象データを受け取ることが可能。

* コマンド呼び出しで実行。

  

## インストール

* `pip`コマンドを使用し、インストールする。

```shell
pip install pytesseract
```

※必要に応じて解析データの読み込み用途で`Pillow`などもインストールする。

※`tesseract`本体も必要。Linux環境などでは`apt-get -y install tesseract-ocr tesseract-ocr-jpn`でインストールしておく。



## 使用方法

* Pythonコード

```python
from pytesseract import pytesseract
from PIL import Image

# 読み込み対象ファイルの指定
img = Image.open("./test.png, "r")
# tesseractコマンドのインストールパス
pytesseract.tesseract_cmd = "/usr/bin/tesseract"
# 文字列として出力できる。
ocr_result = pytesseract.image_to_string(img, lang="eng+jpn")
```



## 参考情報

* [pytesseract](https://pypi.org/project/pytesseract/)
【VBScript】CSVの文字列から、任意(x番目）の項目を取り出す

こんばんは。
今日は自作のプログラムを紹介します。

###１．速くてお手軽なVBScriptが好きです。

会社のデスクに、大量のVBScriptのツールが入っています。
ファイルの内容確認や、項目単位でのマッチングなど。
Excelのマクロで更に高度な処理が可能ですが、VBScriptとテキストファイルの組み合わせは、自分でいろいろ工夫ができるし、処理も高速で処理が止まるストレスもないし（データが多かったり、ループすれば別です！）、ソフトのインストールも必要なくwindowsパソコンがあればすぐ始められるし、個人的には最高のツールです。

無印良品が、テキストファイルをデータベース代わりにbashでシステムを運用（しかも内製）していると聞き、何か近しい事ができないかなあと模索したところ、この手法にたどり着き、ほぼ10年愛用しています。
Shift-Jis対応のため、win10でUTF-8標準になってからはファイル保存にUTF-8をいちいち選択したりと面倒になっていますが、それでも現役です。

さて、今回はCSVファイルの特定の文字列を抽出するプログラムをご紹介します。
・時代に逆行してShift-Jis専用です・・。
・","の中を変更すれば、CSV以外でも使えます（タブに変更すればtabファイルでも可能）。

###２．プログラム

itemget.vbs

```vb

Function item(rec,itemno)
    '取得項目格納先    
    item = ""
    'タブ取得数    
    tabcnt = 0
    ' "0" : 未取得 "1"：取得中 "2"：取得済
    status = "0"
    for i = 1 to 10000 
        lett = Mid(rec,i,1)

        'itemnoが'1'の時（1項目目を取得したいとき）は、最初からstatusを"1"にする。
        if itemno = 1 and tabcnt = 0 then
            status = "1"
        else
        end if

        '取得文字が区切り文字だったとき、ステータスを変更する。
        if lett = "," then
            tabcnt = tabcnt + 1
            if CInt(itemno) = CInt(tabcnt+1) then 
                status = "1"
            else
                if CInt(itemno) > CInt(tabcnt+1) then
                    'itemno > tabcnt +1 の場合 (項目番号よりも取得タブ+1が小さい場合）、statusを"0"とする
                    status = "0"
                else
                    'itemno < tabcnt +1 の場合 (項目番号よりも取得タブ+1が大きい場合）、statusを"2"とする
                    status = "2"
                end if
            end if
        else
        '取得文字が区切り文字でない時、status:1（取得中）の時は文字列を連結する。
            if status = "1" then
                item = item & lett
            else
            end if
        end if

        'status:2の時は処理を終了させる。
        if status = "2" then
            i = 10001
        else
        end if

    next    
end Function
```

###３．使い方

「item(rec,itemno)」の値はそれぞれ以下の意味になります。

item：戻り値
rec：対象レコード
itemno：取得したい項目の番目

下記のように呼び出します（レコード：inputtの5番目の文字列を取得して、MSG出力）。
ここには文字列を直接指定していますが、好きなCSVファイルを読み込んで使ってみてください。

```vb
inputt = "a1,b2,c3,d4,e5,f6,g7,h8,i9,j0"
msgbox(item(inputt,5))
```

これを色々なマクロで活用しています。
・CSVファイル同士のキーマッチング（Aファイルのx項目目と、Bファイルのxx項目目を比較）
・xx項目目の数値項目を集計


###４．さいごに

記事に書くために、適当だった項目名を修正したり、インデントをきれいにしました。
作品を発表する気分です。
用途は限られますが、良かったら使ってみてください！
uWSGI と Nginx 使ってて"No module named 'myproject' "　が出てきたお話

# 概要 #

AWSのEC2にてDjango + Nginx + uWSGIと言う構成でデプロイしようとしていた。

Nginxの設定とかも終えて、

```console
$ uwsgi --socket :8001 --module myproject.wsgi
```
と打ち込んで行けるかなと思っていたところ、下記のエラーが出た。

```console
ModuleNotFoundError: No module named 'myproject'
```

原因を調べていると、少なからず同じ境遇で困っている人がいたので解決法を見ていたのだが、
各自、違う理由で件のエラーが起きており、違う解決法で対処していた。

なので、手探りで解決の糸口を探していた。

# 解決法 #

```console
$ python3 manage.py collectstatic
```

なんと、コレクトスタティックしただけですんなり行けた。

ちゃんとuWSGIが動いていることも確認できたし、何よりURLにアクセスできた。

# 備考 #

もう少し、エラーの内容をわかりやすく吐き出して欲しいなと思った。（ログ吐く場所があるらしいからそこ見なさいって話だが）

[2021/2/28 22:17 追記]
プロジェクトルートがカレントディレクトリじゃないと上手く動かないかもしれないことを発見。
ディレクトリ(フォルダ)のコピーの仕方

# はじめに
この記事は、パソコン初心者がアウトプットをするために書いた記事です。
内容としては、ディレクトリのコピーの仕方について解説していきます📚
ちなみに私は知らなかったのですが、ディレクトリとフォルダは読み方が違うだけで基本的には同じらしいです。
***

#手順１　vscodeでターミナルを開く
vscodeを開いたら、ポインターを画面一番上に移動させます。するとバーが現れますので、ファイル→開く→ディレクトリを開くといった順に操作します。
次にvscode画面の左下に⚠️←このようなマークがあるので、それをクリックします。すると以下のような画面がvscodeの画面下に表示されると思います。画面が表示されたら『ターミナル』ををクリックします。するとターミナルの画面が表示されます。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005678/37757ec8-07d5-0f71-8acc-e4312b97c173.png)
#手順２　ターミナルにコマンドを入力する
それでは、実際にターミナルにコマンドを打ち込んでいきます。
ディレクトリをコピーするためには、以下のターミナルに入力されている、コマンドを入力します。
するとhtml_folderの中に入っているファイルの全てが、html_folder２のディレクトリの中にコピーされます。
~補足~
html_folder２という名前のフォルダーは、このコマンドを実行する前に新規フォルダを作っておきましょう。

```ターミナル:ターミナル
cp -r html_folder html_folder２
```

#最後に
ありがとうございました！
【合格体験記】AZ-900:Microsoft Azure Fundamentals 

#AZ-900とは
Azure の初心者向け基礎資格な資格です。
Azureの試験になりますが、Azureというよりクラウドの概念を理解できているかが問われる内容になっているので、これからクラウドについて勉強したいという方の初めの1歩として受験してみるのにも最適かと思います。

同格の資格としてAWSの認定クラウドプラクティショナーがありますが、

| |AZ-900|AWS 認定クラウドプラクティショナー|
|---|---|---|
|有効期限|無し|3年|
|受験費用|12,500円<br>※無料バウチャーあり|11,000円|
となっています。

AZ-900は資格の有効期限がないため資格維持の手間もなく、無料で受講できる[Microsoft Virtual Training Days](https://www.microsoft.com/ja-jp/events/top/training-days.aspx?activetab=a1%3aprimaryr4)を受講することでAZ-900を無料で受験できるバウチャーが付与される為、受験へのハードルも低いです。

#私の知識レベル
Webアプリ開発にAWSを一通り触ったことがある程度で、なんとなくで把握しているという状態でした。
ここ数年レガシーな技術しか使わない仕事をしていたため、クラウドについて1から勉強しなおすついでに資格を取得しようかなという状況で、上記の通りAZ-900の方が受験のハードルが低かったのでAzureは未経験でのAZ-900受験でした。

#受験対策
### 参考書：2時間
[合格対策Microsoft認定AZ-900:Microsoft Azure Fundamentalsテキスト＆問題集](https://www.amazon.co.jp/dp/B0872LVYD6/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
Azureは経験がなかったため、まずサービス名等を一通り覚えるために参考書を読みました。
現状、AZ-900の対策本としてはこちらしかないようですが、非常によくまとまっていているため
何かしらのクラウドサービス経験者ならこの本を1度読めば、試験でどういった内容が問わるのか把握できるので難なく合格できるかと思います。

### Microsoft Learn：10時間
2020年9月に試験内容が改定されたらしく、上記の参考書は以前の内容に合わせたものだったため
念のため[Microsft learn のAzureの基礎](https://docs.microsoft.com/ja-jp/learn/paths/az-900-describe-cloud-concepts/)を一通り行いました。
架空の会社をモデルにストーリー形式でAzureについて学べます。
正直参考書で学んだ内容とそこまで差異は感じませんでしたが、より詳しく学べるのとサンドボックス環境でAzureに触れることができるため、やっておいて損はないでしょう。

### Udemy：5時間
CBT形式の試験を受験するのが初めてだったため、慣れるために[Udemyのこちらの問題集](https://www.udemy.com/course/microsoft-azure-fundamentals-az-900-practice-tests/)を購入して一通りこなしました。
Udemyは定期的にセールを行っているのでタイミングが良ければ1200円で購入できます。
合格するということだけに焦点をあてるならば、この問題集丸暗記でも良いレベルの内容だったので購入して非常によかったと思います。

# 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/539781/c7984097-7563-de1a-eddd-4626914c75fd.png)
上記の勉強内容で無事940点で合格できました。
問題も悩むようなものもなくサクサク答えられ15分弱で終わったので満点取れたかなと思いましたが、どこかで間違ったようです…(どこを間違ったのか結果表示して欲しいですね…)

Azureは公式の勉強ツールが充実していおり、イベントで無料バウチャーが配布していたり等
非常に受験しやすい資格かと思うので、上位資格の無料バウチャーが手に入ったら上位資格にも挑戦してみようと思います。
【初心者向け】横スクロールバーがでてしまう原因の対策方法

# どうも7noteです。やっとの思いで完成したサイトだけど、なんか横スクロールバーがでてる時の対処法

初*「やっと完成したと思ったサイト。だけどなんだか横スクロールバーが出てる。」*

初*「よくわからんからbodyに`overflow-x: hidden;`いれよっと・・・」*

***「その手抜き工事ちょっとまった！！！」***

***「`overflow-x: hidden;`を使うのは最終手段！その前に直せないかチェックせよ！」***

## 横スクロールバーがでる原因は、なにかの要素がはみ出ているから


「横スクロールバーが出ている」　＝　**「画面からはみ出ている要素がある」**

ということです。

特にはみ出る原因になりやすいのは**画像**や**padding**。
これらがはみ出していないか確認をします。

## はみ出した要素を見つける方法

### ①確認したいサイトをPCのブラウザで開く。(google Chromeがオススメ)

### ②F12キー等を使い、開発者ツールを開く。（右クリック→検証でも可）

![step02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/98b9cbdf-ca28-454a-a507-2ee29b5e70ee.png)

※スマホ表示を検証する場合はこのマークでスマホ表示にできます。

![step2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/8ff5ed2d-fcb1-179f-b15f-f36699cf901c.png)

### ③selectツールを使って原因の箇所を捜査

※selectツールはこれをクリック。青くなってたらOK。

![step03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/fd9b025b-44c6-c618-d729-c26314f568e3.png)

こんなかんじに要素を1つ1つ調べることができます。
ここでは以下のような感じで表示されます。

・ 青・・・要素本体
・ 緑・・・paddin
・ オレンジ・・・margin

![step03-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/e92421ad-5e1f-7d43-0823-bce9df3cf5d8.png)

今回であれば、緑の部分が出ているのでpadding分外にはみ出ていますね。
検証ツールのcssを見てみるとwidthが100%に加えてpaddingも設定しているので、最終的にはみ出てしまっています。

### ④ 改善するたにCSSを調整・編集

今回は`box-sizing:border-box;`を入れて対応することにします！
これを入れることで、width:100%の中にpaddingが含まれるので、もうはみ出ることはないでしょう。

```style.css
.htype-simple {
  /* (省略) */
  width:  100%;
  padding: 0 20px;
  box-sizing: border-box; /* これを追記 */
}
```

![step04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/cb287bea-39f0-c0a2-1105-147ea44ac144.png)

## まとめ

原因が1箇所だけではなく複数ある場合もあるので、「検証→修正」を繰り返して改善していきましょう！

**なかなか原因がみつからない場合にオススメな方法として、HTMLの要素をいくつかに区切って、検証ツール上から消していく方法があります。**
検証ツールで大きめのブロックごとdeleteキーで削除していきます。「削除してもまだ横スクロールが解決しなければ、原因が他の箇所にある」ということになります。
このように**原因の箇所を少しずつ少しずつ絞っていく方法が、確実に原因を突き止める有力な方法の1つ**です。


もちろん`overflow-x: hidden;`でも解決できるのですが、これって問題を完全に解決したわけではなくてあくまでも問題を隠蔽しているような状態だと思っています。
なのでその時はよくてもあとあとそのせいでうまく行かない場面に直面したりもするので**個人的には`overflow-x: hidden;`で済ませてしまうのはあまり好きではありません。**

でも**開発者なら自分で起こした不具合くらい、自分で直したくないですか？**

それでは。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
【Rails】Capistrano main以外のブランチをデプロイする方法

通常、mainブランチをcapistranoでデプロイする時、このように入力すると思います。

```terminal
$ bundle exec cap production deploy
```

ただ、開発中にmain以外のブランチをデプロイして確認したい時もあると思います。
そんな時は、

config/deploy.rbに追記して

```terminal
$ set :branch, ENV['BRANCH'] || "main"
```
デプロイする。

```terminal
bundle exec cap production deploy BRANCH=ブランチ名
```


特に指定しなければmainが、main以外ならブランチ名を指定してやれば、それぞれデプロイできます。
GitHub チーム開発の流れ

#【GitHub チーム開発の流れ】

山浦清透さん いつもありがとうございます。
[Git：もう怖くないGit！チーム開発で必要なGitを完全マスター](https://www.udemy.com/course/unscared_git/)

##Git 推奨される開発流れ

masterブランチをリリース用ブランチにして、開発はトピックブランチを作成して始めることが基本だそうです。

（私が従事する業務プロジェクトも上記のようなチーム開発の体制を取っています。）

masterブランチが最新リリースの状態に保っておくことが出来る。
バグが発生しても、前のバージョンに遡ればバグのない状態に出来る。
　→ masterブランチで開発すると、バージョンの状態がややこしくなる。

##プルリクエスト

<strong>自分の変更したコードをリポジトリに取り込んでもらえるようにする依頼する機能。</strong>

###プルリクエストの手順

1、ローカルリポジトリからリモートリポジトリ（GitHub）にプッシュする。
2、<strong>プルリクエストを送る。</strong>
3、チームメンバーにレビューしてもらう。
4、OKであれば、プルリクエストマージする。
5、不要になったブランチは削除する。

##GitHub Flow

<strong>GitHub社が自社でおこなっているワークフロー</strong>

###GitHub Flowの手順

1、masterブランチからブランチを作成する。
2、ファイルを変更して、コミットする。
3、同名のブランチをGitHubにプッシュする。
4、プルリクエストを送る。
5、レビューをして、masterブランチにマージをする。
6、masterブランチを本番サーバにデプロイする。

<strong>ポイント</strong>

・masterブランチは、常に最新に保つ。
・新しく開発する場合は、masterブランチから新規で作成する。
・定期的なPushを心がける。
・masterブランチにマージするためのプルリクエストを欠かさない。
・必ずレビューを受けてから、masterブランチにマージして、デプロイする。
（テストとデプロイ作業は自動化しよう。）

※シンプルなワークフローにすることで、ミスを減らす！
Numeraiに上位20%以上のスコアがでる予測値を提出する方法 

#はじめに
はじめまして。
[tit_BTCQASH ](https://twitter.com/tit_BTCQASH "tit_BTCQASH ")と申します。

この記事では上位20%以上の性能が出る予測値を[Numerai](https://numer.ai/tournament "Numerai")にサブミットする方法を解説します。

Numeraiにステークしたいけど、毎週プログラミングなんてめんどくさい・プログラミングなんてできない、という人向けです。

Numeraiって何？という方は、私の過去記事( [日本語版](https://qiita.com/tit_BTCQASH/items/366a2d1c273507dd4b8c "日本語版") /[英語版](https://tit-btcqash.medium.com/a-comprehensive-guide-to-competing-at-numerai-70b356edbe07 "英語版"))をご参照ください。



#データのダウンロードから予測の提出まで
本項ではNumeraiに予測値を提出する方法を説明します。
使用する計算モデルは[公式](https://github.com/numerai/example-scripts "公式") がGithubで頒布しているexample_model.pyです。
公式が配布しているサンプルモデルですが、下手な独自モデルよりも性能が良いです。また、Numeraiに提出する予測値を格納したCSVファイルも公式が毎週配布しています。

それでは、提出用ファイルのダウンロードと提出方法について説明いたします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015710/6cc17dfc-3b3e-f27b-324b-09cd69f8b205.png)
公式サイトの左側にあるDownload Dataを押し、Zipファイルを解凍すると、example_predictions.csvというファイルがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015710/d0ec3d3d-4c87-2239-43c8-07229ea7de45.png)

example_predictions.csvを公式サイト左側にあるUpload Predictions（Download Dataの下）からアップロードすれば完了です。
~~（ね？簡単でしょう？）~~
本ファイルは毎週土曜日18:00(UTC)にダウンロードできるようになります。本ファイルを月曜日の14:30(UTC)までに提出すれば、その週から開催されるNumeraiトーナメントに参加できます。



#example_model.pyの性能
[example_model.py](https://numer.ai/integration_test/submissions "example_model.py")から計算した予測値は毎週公式が提出してくれています。本モデルの性能について下図に示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015710/5fc08b79-ef3b-7441-be2b-4df74f7384ed.png)
本モデルの性能で一番見るべきところはCorr Reptationです。Corr Reptationとは20ラウンドのCorr平均値を表しており、Corr*100の値が週当たりの平均リターン[%]を表します。example_model.pyは週当たり2.83%の平均リターンがあり、年利換算で約150%とかなり高いです。
一方mmcはマイナスの値なので、他のモデルに対する優位性はありません。そのため、ステーキングをする場合はCorrのみがよいでしょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015710/2b2a4065-4403-31b4-91d7-e79c563d52d2.png)
また、ランキングを見ると過去20ラウンドでは200-700位の間に位置することが分かります。現在4861モデルがNumeraiに存在するので、example_model.pyは上位4~15%程度の性能を持つことがわかります。
下手に独自モデルを作って予測値を提出するより、example_model.pyを出した方が高いリターンを得られるかもしれません。

#さいごに
NMRのトークン価値は変動しますので、NMRトーナメントで優秀な成績を修め、NMRの枚数を増やしても、JPY建てでは損失が発生する可能性があります。

また、NMRを一度ステークすると、トーナメント期間中は引き出せないことも注意が必要です。

個人的には、下手に年利が高いDefiよりもリスクが低いと感じておりますが、リスク感度は個人個人で異なると思いますので、ご自身の判断でご参加ください。

チップ用
NMR:0x0000000000000000000000000000000000021d96
Hello Minikube をやってみた

Kubernetes公式のチュートリアルの一つである、**Hello Minikube**をやってみました。

https://kubernetes.io/ja/docs/tutorials/hello-minikube/

### 実行環境

- MacBook Air (2019)
- macOS Catalina v10.15.7
- Minikube v1.17.1

### やってみた

#### Minikubeクラスターの作成

HyperKitを用いてMinikubeクラスターを作成します。
VirtualBoxでも作成可能です。

```shell
minikube start --vm-driver=hyperkit
```

ブラウザでダッシュボードを表示します。

```
minikube dashboard
```

#### Deploymentの作成

Pod(コンテナの集合)の状態を管理してくれるDeploymentを作成します。

```
kubectl create deployment hello-node --image=k8s.gcr.io/echoserver:1.4
```

作成したDeploymentを確認します。

```
kubectl get deployments
```

作成したPodを確認します。

```
kubectl get pods
```

クラスターのイベントを確認します。

```
kubectl get events
```

設定を確認します。

```
kubectl config view
```

#### Serviceの作成

Serviceを作成して、Podにクラスター外部からアクセス可能にします。

```
kubectl expose deployment hello-node --type=LoadBalancer --port=8080
```

作成したServiceを確認します。

```
kubectl get services
```

ブラウザにServiceを表示します。

```
minikube service hello-node
```

![スクリーンショット 2021-02-28 21.02.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637012/76aac970-6de7-afc6-f065-07cd2deffaac.png)


#### 作成したクラスターの掃除

Serviceを削除します。

```
kubectl delete service hello-node
```

deploymentを削除します

```
kubectl delete deployment hello-node
```

### 感想

とりあえずkubectlとMinikubeを使ってみたかったので、公式チュートリアルをやってみました。
用語や概念の理解が不十分なのでもうちょっと公式を読み込む必要がありそうです。
LPIC1とLPIC2を取得時のメモ

###LPIC1とLPIC2を取得したのでメモ

1.資格勉強に対する考え方

・資格は勉強した証拠としては使える。
・実力の証明には正直ならないと思った。(勉強した内容は忘れかけている…わからん時はぐぐれ)

なので、**すべてを理解しないで良い。ざっくり理解**

2.勉強方法

 ①小豆本でざっくり理解
 ②ping-tを解きまくる。わからない部分は小豆本で復習して理解する。
 ③模擬試験で安定で80%出せるようになる。もしくは勉強にあきる。
 ④1週間後くらいに試験を申し込む
 ⑤あとはひたすら、問題を解く

**ping-tのコマンド問題について**
特にやらないくて良いと思った。 
・試験のコマンド問題は〇〇するためのコマンドは？コマンドのみ書いて　とかなので…
・コマンドとそのオプションの意味くらい覚えていれば良いと思う。
・設定ファイル系はしっかり覚えた方が良いと思うので、活用はありだと思う。

LPIC101,102,201までは毛色が似ている。（ここまではすんなりいけた！）
LPIC202からはbind,Apacheなどの設定項目の意味とか、覚えることが多すぎる

（以下を参考にして、自宅PCのVitrualBoxで手を動かして作ったりした。）
[Linuxサーバー構築標準教科書](https://linuc.org/textbooks/server/)

3.よかったこと

・Linuxに対する抵抗感が少し減った
・勉強すれば、ある程度は理解できることがわかった。
（仕事だと分からんこと多すぎて、しゅんですが時間しっかり勉強すれば、理解できるかもという自信になった。）
・現場の人に褒められた
Github Actionsで始めるプログラム定期実行

# はじめに

よくプログラムの定期実行の方法として、Windowsではタスクの登録、Linuxではcronでの定期実行が紹介されるが、ローカル環境でこれらを行う場合は、もちろんPCを起動しておく必要がある。しかし、たかが1プログラムのために電気代を消費するのも勿体ないし、サーバーを借りて実行するほどでもない、といった需要に一番マッチするのがGithub Actionsである。
`※この記事はGitに関しての記事ではないため、コミットやプッシュなどは理解しているものとして話を進める。`

# GitHub Actionsとは?

Github Actionsはその名の通りGitHubから提供されているワークフローを自動化するためのツールである。
具体的には、リポジトリの`.github/workflows`の配下にYAML形式の実行制御ファイルを配置することによって利用することができる。Linuxで利用されるcronによる定期実行やレポジトリへのプッシュを検知して、ワークフローを実行することもできる。

公式ドキュメント -> https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions

# 実行するトリガーとなるイベントを検知

### リポジトリの`main`ブランチにプッシュされたときに実行
```yaml
on:
  push:
    branches:
      - main
```

### 時間を設定して定期実行
```yaml
on:
  schedule:
    - cron: '0 3 * * *'
```
`※時間はUTCであることに注意が必要。上記の例では、1日に1回日本時間の12:00に実行。`
cronの時間設定については↓の記事を参照
[クーロン(cron)をさわってみるお](https://qiita.com/katsukii/items/d5f90a6e4592d1414f99)

# 実行する環境の設定

```yaml
jobs:
  build:
    runs-on: ubuntu-latest
```
他にもWindows ServerやMacOSなども使用できる。利用する場合は[公式ドキュメント](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions)を参照されたい。

# ワークフローの実行

ここからは主にLinuxで実行したいコマンドを書いていくことになる。(Linuxのコマンドの内容については解説しない)
今回は例としてPythonの環境を構築して、レポジトリ内の`main.py`を実行し、実行した結果をレポジトリに自動でプッシュするように設定する。

```yaml:.github/workflows/actionstest.yaml
name: ActionsTest # GitHub Actionsにつける名前。任意で良い。

on:
  schedule:
    - cron: '0 3 * * *' # cronで定期実行

jobs:
  build:
    runs-on: ubuntu-latest # 最新のubuntu環境で下記のジョブを実行
    steps:
      - uses: actions/checkout@v2 # おまじない
      
      - name: Setup python # ワークフローのセクションごとに設定する名前。特に設定する必要はないが、どこでエラーが起きているかを把握する為にも設定しておいた方が良い。
        uses: actions/setup-python@v2 # Pythonのセットアップ
        with:
          python-version: "3.x" # Pythonのバージョン指定
      
      - name: Install dependencies # Pythonの依存環境のインストール
        run: | #このような書き方で複数行を一気に実行することができる。
          python -m pip install --upgrade pip
          pip install pandas
          pip install pytz
          pip install matplotlib
          pip install numpy
          
      - name: Run main.py # Pythonファイルの実行
        run: |
          python main.py

      - name: Commit and Push # 実行した結果をプッシュして変更をレポジトリに反映
        run: |
          git config user.name "YOUR NAME"
          git config user.email "YOUR MAIL"
          git add .
          git commit -m "Commit Message"
          git pull
          git push origin master
```
`※最後のGitにコミットする前の名前とEmailは必須だそうだ。(この行を省いた状態でテストしていない...)`

これだけで簡単にスクリプトを実行し、レポジトリに反映するスクリプトが出来る。ただし、月当たりの利用時間の制限があるので、サーバーとして運用するのは厳しいかと思われる。（無料枠では**2000分/月**）

# その他の機能

上記で紹介したもののほかにも、環境変数を利用したり、特定のシェルを利用することもできる。これらの機能の詳細については、下記のドキュメントを参考にされたい。

公式ドキュメント -> https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions
Alpine.jsでライフゲームを作ってみた

突然ですが、[PETALスタック](https://thinkingelixir.com/petal-stack-in-elixir/)というのをご存知でしょうか？
少し前にElxir界隈ですこし話題になっていたのですが、

**P**hoenix
**E**lixir
**T**ailwind
**A**lpine.js
**L**iveView

の略みたいです。

この中でフロントエンド担当のAlpine.jsについては、 State of JavaScriptでも
話題にあがっており、気になっていたので少し触ってみました :sparkles: 

## Alpine.js

https://github.com/alpinejs/alpine

>ベスト5の新顔はAlpine.jsで、これはLaravel LiveWireの作者によって作られたミニマルなリアクティブフレームワークです。
Vue.jsとAngularの両方から、カスタムHTMLディレクティブや双方向バインディングといったアイデアを拝借しています。
HTMLに古き良きscriptタグを追加するだけで簡単に使うことができ、ビルドプロセスも不要で、HTMLマークアップだけで全てを動かすことができます。
本格的なフレームワークを導入することが困難な既存のWebページをさくっと強化する目的については、最も適切なソリューションであるかもしれません。
引用元: [JavaScript ベスト・オブ・ザ・イヤー 2020 by @rana_kualu](https://qiita.com/rana_kualu/items/e8a0f8f5589ff082539d)


とてもミニマルなフレームワークみたいで、基本的には`x-hogehoge`で指定できるHTMLディレクティブが14個と6個のMagic Propertyのみ覚えればいいみたいです。
 
## 作ったもの

![alpine_game.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55219/40055c9d-a92c-2afe-e249-08c719cb8eeb.gif)


https://github.com/tamanugi/alpine_game

https://tamanugi.github.io/alpine_game/index.html

npmいらずでindex.htmlのみで150行ほどで実装することができました。


実装の中身は以下のような感じです。

```html
    <div class="container" x-data="data()" x-init="init()">
        <div class="board">
            <template x-for="(row, index) in board">
                <div class="row">
                    <template x-for="(cell, idx) in row">
                        <div class="cell" x-on:click="toggle(index, idx)"
                        x-bind:class="{ 'live': !!cell, 'dead': !cell }"></div>
                    </template>
                </div>
            </template>
        </div>
        <div class="info">
            <button x-show="state == 'STOP'" x-on:click="start()">スタート</button>
            <button x-show="state == 'START'" x-on:click="stop()">ストップ</button>
            <button x-show="state == 'STOP'" x-on:click="randomBoard()">ランダム</button>
            <div>世代数: <span x-text="generation"></span> </div>
        </div>
    </div>
    <script>
        const data = () => ({
            w: 20, 
            h: 20,
            generation: 0,
            board: [],
            state: 'STOP', // START or STOP
            timerId: null,
            ...
            (ライフゲームの処理とか)
        })
    </script>
```

`x-data="data()"` をつけた`div`で囲った範囲で、 `data`関数が返すオブジェクトの中身(プロパティ、変数)を参照できるようです。

`x-init` は最初に呼び出したい関数を指定できます(Vueでいうmountedみたいなもの)

Vueとかと違って変数を表示する場合は `<span x-text="generation"></span>` のように`x-text`を使ってDOMのinnerTextとして、指定してあげるみたいです。

他にも
`x-on:click` 
`x-bind:class`
`x-show`
など使っていますが、ほぼ直感的に書くことができて、とてもいい感じでした :sparkles: 

ちなみにCSSフレームワークは同じく読み込むだけで使える sakura というCSSフレームワークを使っています

https://github.com/oxalorg/sakura


## 最後に

nodeランタイムなしで実装ができるので、ペライチなどでさらっと使う分にはとても良さそうに感じました！
フロントエンドフレームワークを入れるほどでもないけど、jQueryだけで頑張るにはつらい。。。。っていうときには採用を検討してみても良さそうです。

Tailwindとの組み合わせも非常に気になりますね :sparkles: 
また機会があったら試してみようと思います！
【Android】【初心者向け】RoomのAutoIncrement(PrimaryKeyのautogenerate = true)の値は、０で良い

# 【Android】【初心者向け】 RoomのAutoIncrement(PrimaryKeyのautogenerate = true)の値は、０で良い
## 概要
タイトル通りですが、AndroidのRoomのAutoincrement(PrimaryKeyのautogenerate = true)の値は、0で良いという話です。

今まで、業務でRoomを使う経験がなく、 ドキュメントやサンプルコードを見ていて、
AutoIncrementのときに、何を渡せば良いのかわからず、どこかで見たサンプルと同じように`0`を渡しすようにしていました。
ただふとこれで正しいのかと気になり、調べてみて良かったということに気づいたという話です。

## 参考にしたもの
developers: [Primarykey](https://developer.android.com/reference/androidx/room/PrimaryKey.html)

以下は、引用です。

```
autoGenerate

public boolean autoGenerate ()
Set to true to let SQLite generate the unique id.

When set to true, the SQLite type affinity for the field should be INTEGER.

If the field type is long or int (or its TypeConverter converts it to a long or int), Insert methods treat 0 as not-set while inserting the item.

If the field's type is Integer or Long (or its TypeConverter converts it to an Integer or a Long), Insert methods treat null as not-set while inserting the item.
```

つまり、以下のような内容かと思います。

* autoGenerateをtrueにすると、SQLiteがユニークなIDを生成するよ
* 型が `long`か`int`のときは、insertのメソッドは、0を未設定として扱うよ
* 型が、`Long`か`Integer`のときは、insertのメソッドは、nullを未設定として扱うよ

そして、基本的にはkotlinの`int`を使うかと思いますので、0を設定してあげるのが良いということになるかと思います。

## コード的なイメージ
仮にUserというEntityを使う場合ですが、以下のようになるのかと思います。

``` UserEntity.kt
@Entity(tableName = "users")
data class User(
  // デフォルト引数に0を設定
  @PrimaryKey(autoGenerate = true) val id: Int = 0,
  @ColumnInfo(name ="name") val name: String
)
```
AWSとWordPressを使ってWebサイトを構築しよう①

本記事ではパート毎に分けて最終的にはタイトルの通り「AWSとWordpressを使ってWebサイトを構築」していきます。
初学者の方はゆっくりと確実に１つ１つ記事の通りに進めて頂けたら最終的にはWebサイトを構築することができます。

まずはWebサイト構築を始める前に理解しておくべきサーバーとネットワークについて抑えましょう。

#目次
[1.サーバー構築の考え方](#1-サーバー構築の考え方)
[2.ネットワーク構築の考え方](#2-ネットワーク構築の考え方)


#1. サーバー構築の考え方
そもそもサーバーとは簡単に言うと<b>「何かを相手に提供する」</b>ということです。
例えばコーヒーサーバーでしたらコーヒーを提供するためのサーバー。
それと同じようにコンピュータで言うサーバーとはクライアントにサービスを提供するためのサーバーです。

![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159544/96143b38-ce79-927f-ab9f-2d4c4d260cc0.jpeg)

サーバーを構築する際にまずは”どんなサーバーが必要なのか”を考えます。

もしあなたが”自分のWebサイトを作成して公開したい”という時は、Webサイトを提供するための<b>Webサーバー</b>が必要となります。
またWebサイトに書いた記事や画像を保存しておくためのデータベースも必要ですよね。なので<b>DBサーバー</b>も必要です。

このようにどんなサービスを提供するかで構築するサーバーも変わっていきます。
とはいえWebサーバーだからWebサーバーというものがあるということではなく、正確に言うと「Windows Server」などのOSをインストールしたコンピュータにWeb機能をインストールさせたものをWebサーバーと言います。

![キャプチャ1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159544/521e76b2-83e3-0189-525c-ab837c45d861.jpeg)


#2. ネットワーク構築の考え方
サーバーを構築した後にインターネットへ繋げるにはネットワークを通じて通信できるようにしてあげる必要があります。

インターネットは<b>TCP/IP</b>というプロトコルを使ってネットワーク上で通信を行っており、それぞれのサーバーにIPアドレス(こんな形「10.0.1.1」)という固有の番号を割り振って他の機器と重複しないように識別しています。

さらにインターネットへ接続するのに<b>ルーター</b>という機器を使用しており、サーバーからルーターへ通信するように構成する必要があります。

また通常インターネット上ではWebサイトの住所を表す時に「https://www.google.co.jp」 このようなドメイン名と呼ばれるものを使用します。
実はこれは人間が見やすいように作成されたもので、IPアドレスに関連付けされて設定されています。
このような設定を行うのに<b>DNSサーバー</b>というサーバーの設定も必要です。

![キャプチャ6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159544/0d645199-da4a-c731-5c78-402420d1ad11.jpeg)

それでは次回からAmazonが提供しているクラウドサービスである<b>AWS</b>サービスにWordPressをインストールしてWebサイトを構築していきましょう！

</br>

次の記事はこちらから
<a href="https://qiita.com/uchino_infra/private/2e0d2e2dc7f1d0ffcdf3">AWSとWordPressを使ってWebサイトを構築しよう②
</a>
vue ui コマンドで起動エラー spawn cmd ENOENT 

##環境
- Windows10
- npm 6.14.8
- Node.js v14.15.0
- vue @vue/cli 4.5.11

##問題
vue CLIのプロジェクト管理ツールを起動するために下記のコマンドを実行するとエラーが発生する
` vue ui`

```
Starting GUI...
Ready on http://localhost:8000
events.js:170
throw er; // Unhandled 'error' event
^

Error: spawn cmd ENOENT
at Process.ChildProcess._handle.onexit (internal/child_process.js:247:19)
at onErrorNT (internal/child_process.js:431:16)
at processTicksAndRejections (internal/process/task_queues.js:81:17)
Emitted 'error' event at:
at Process.ChildProcess._handle.onexit (internal/child_process.js:253:12)
at onErrorNT (internal/child_process.js:431:16)
at processTicksAndRejections (internal/process/task_queues.js:81:17)
```

##環境変数にパスを通しPC再起動で解決

1. 環境変数に `C:\Windows\System32\`を追加
2. PCを再起動

再度実行したら無事画面が起動

参考　https://stackoverflow.com/questions/28624686/get-spawn-cmd-enoent-when-try-to-build-cordova-application-event-js85

##環境変数を設定したら再起動が必要
はじめ環境変数を追加しても変わらないので滅入りそうになっていました。
設定が反映されるのは、再起動後なんですね。学びました。。

ちなみにENOENT とは、Error No Entryの略で、ファイル・ディレクトリが存在しないという意味のエラーメッセージらしいです。
【メモ】【自分用】cryptozombiesやってみた。

## はじめに
去年あたりにブロックチェーンに興味を持ち出し勉強していたのですが、
業務状況などもあり、別の勉強を行なっていたが一区切り着いたこともあり
再度、ブロックチェーン熱が入ってきたので、勉強再開がてらメモを記載していく自分用の投稿です。

## CryptoZombies
ブラウザ上で、体系的にSolidityの勉強が出来るとか。
面白そうなので、やってみることにしました。

・[CryptoZombiesリンク](https://cryptozombies.io/jp/course/)

### 実績
####レッスン2
想像してたより、面白くてわかりやすい印象
引き続きやってみようと思いました。

作ってみたゾンビ
　・[gasのゾンビ](https://share.cryptozombies.io/jp/lesson/2/share/gas)

---

####レッスン3
　・[gasのゾンビ](https://share.cryptozombies.io/jp/lesson/3/share/gas)

---
修飾詞

- **private**
  - コントラクト内からのみ呼び出し可能
- **internal**
  - コントラクトを継承したコントラクトからも呼び出し可能。 （子のコントラクトも呼び出し可能）
- **external**
  - コントラクト外からのみ呼び出し可能
- **public**
  - どこからでも呼び出し可能（コントラクト内部・外部どちらからでも）


---

状態修飾詞

- **view**
 - 関数が処理を実行しても、データの保存または変更を行わない場合に使用する
- **pure**
 - 関数が処理を実行しても、データの保存または変更を行わない、かつブロックチェーンからデータを読み込みを行わない場合に使用する

上記の状態修飾詞はコントラクト外部から呼び出された場合は、ガスは必要としない。
※ただし、コントラクト内にある別の関数から呼び出されるとガスが必要になるので注意。

---

####レッスン4
　・[gasのゾンビ](https://share.cryptozombies.io/jp/lesson/4/share/NoName?id=W251bGwsMSwxNF0=)

---

####レッスン5
　・[gasのゾンビ](https://share.cryptozombies.io/en/lesson/5/share/H4XF13LD_MORRIS_%F0%9F%92%AF%F0%9F%92%AF%F0%9F%98%8E%F0%9F%92%AF%F0%9F%92%AF)

---

####レッスン6
　・[gasのゾンビ]
(https://share.cryptozombies.io/jp/lesson/6/share/The_Phantom_of_Web3?id=Y3p8MTE2MTMw)


---

後半は、年上案件に放り込まれたので、
なかなか進捗が悪いまま無理やり終わらせました。。。悲しい
また時間作ってもう一周したいところです。


## おわりに
投稿したい内容とかありますが、
なかなか投稿できず。。頻度をあげたいのが悩み。
if 文なしで じゃんけん J 言語版

[if文なしでじゃんけん](https://qiita.com/tadsan/items/65d91ba6b50535fc8815) というのを見たので J 言語でも書いてみました。

# J の if 文

J 言語というと、`+/>:i.100` [^1] のような記号の羅列でプログラムを書けることで有名 (?) ですが、手続き的な記述も可能です。

```j
if. a do.
   echo'true'
else.
   echo'false'
end. 
```

とはいえ、じゃんけん程度の簡単な場合分けなら if 文よりも配列を使って分岐することが多いように思います [^2]。そこで、if 文に加えて**配列を利用した分岐も禁止**することにしました。

# 下準備

実装に使う部品を用意します。可読性を高めるために、処理を細かく分割しています [^3]。もちろん、ここでも if などの条件分岐は使っていません。

```j
is=: 0 0 $ {{ (x)=: y }}

rps=: (< [ is~);._1' rock paper scissors'

vs=: ,

sign=: {{ {.m }}

beats=: {{
   (x vs x) is 'あいこ'
   (x vs y) is 'あなたの勝ち'
   (y vs x) is 'あなたの負け'
}}

result=: {{
   '[' , (".x sign) , ' vs ' , (".y sign) , '] ' , ".x vs y
}}

every=: {{ u@v&>/~ }}

of=: ]
```

# 実装

上で定義した部品を組み合わせると、簡潔に実装することができます。

```j
rock sign is '✊'
paper sign is '🖐'
scissors sign is '✌'

rock beats scissors
paper beats rock
scissors beats paper

echo every result of rps
```

```:結果
[✊ vs ✊] あいこ
[✊ vs 🖐] あなたの負け
[✊ vs ✌] あなたの勝ち
[🖐 vs ✊] あなたの勝ち
[🖐 vs 🖐] あいこ
[🖐 vs ✌] あなたの負け
[✌ vs ✊] あなたの負け
[✌ vs 🖐] あなたの勝ち
[✌ vs ✌] あいこ
```

**宣言的で、とても可読性が高い**ですね。ソースコードが そのままドキュメントとしても機能しています [^4]。J 言語の構文には柔軟性があるので、このように小さな DSL をアドホックに作って使用することができます。

場合分けは、変数名を動的に生成して eval することによって実現しています (`beats`・`result` 辺り)。詳しい説明を書く気力は残っていないので、知りたい方は最新版の [J をインストール](https://code.jsoftware.com/wiki/System/Installation) して試してみてください (丸投げ [^5]

<details><summary>コード全体</summary><div>

```j
is=: 0 0 $ {{ (x) =: y }}

rps=: (< [ is~);._1' rock paper scissors'

vs=: ,

sign=: {{ {.m }}

beats=: {{
   (x vs x) is 'あいこ'
   (x vs y) is 'あなたの勝ち'
   (y vs x) is 'あなたの負け'
}}

result=: {{
   '[' , (".x sign) , ' vs ' , (".y sign) , '] ' , ".x vs y
}}

every=: {{ u@v&>/~ }}

of=: ]


rock sign is '✊'
paper sign is '🖐'
scissors sign is '✌'

rock beats scissors
paper beats rock
scissors beats paper

echo every result of rps
```

</div></details>

# 余談 (と布教)

ちなみに、上のプログラムでは if 文だけでなく for / while 文も使わずに全てのパターンを列挙しています。これには配列を処理する機能の一つ `/` を使っています。J では九九の表も同様の方法で簡単に作れます。

```j
   */~>:i.9
1  2  3  4  5  6  7  8  9
2  4  6  8 10 12 14 16 18
3  6  9 12 15 18 21 24 27
4  8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
```

この記事を読んで少しでも J に興味を持った方は、是非試してみてください。

+ 公式サイト: https://www.jsoftware.com
+ Wiki: https://code.jsoftware.com/wiki/Main_Page

[^1]: これは 100 以下の自然数の和を求める式です。
[^2]: J は APL の後継なので、配列の操作を得意としています。
[^3]: えっ…… 分割しても まだ読みにくいですか?
[^4]: 英語は得意ではないので、正しい意味になっているかは分かりませんが……
[^5]: あるいは誰か、解説記事を書いてください (やはり丸投げ
Postmanの使い方

# 目次

- ダウンロードとインストール
- アプリケーションの実行
- 実行アプリの保存
- エクスポート
- インポート

# ダウンロードとインストール

- [こちら]([https://www.postman.com/downloads/)からアプリをダウンロードする。
- インストーラファイルをダブルクリックしてインストールする。

# アプリケーションの実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/e317de3c-c39a-6946-5352-7beadb150ba9.png)

# 実行アプリの保存

- この状態で Ctrl + S を押下する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/e364ec72-4641-52a0-6f4b-2fd2b1ddadb4.png)

- 以下のように入力し、保存する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/e175757f-6240-5c61-1713-1af3e888305d.png)

# エクスポート

- フォルダで保存したすべてのアプリをエクスポートする事が出来る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/9a6b7fc8-0454-dc70-6725-5c2dd98c4383.png)

# インポート

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602725/4045636e-46a8-0175-9a14-3ebc2852551e.png)
【チートシート】Vueの単一ファイルコンポーネントの命名規則まとめ

#概要
Vue.jsの学習をしていると、キャメル、ケバブ、パスカル...と書き方のルールが記述場所によってまちまちで混乱してしまうことが多いですよね。自分用の備忘録　兼　同じ初学者の方の参考になればと思い執筆しました！
プロジェクト、人によりこの限りではないと思いますが、チートシートとして自分なりにまとめてみましたので、迷った時の参考にしていただければと思います。

#チートシート
(項目それぞれ◎が推奨の書き方です)

||ファイル名|コンポーネント名|メソッド名|props|$emitのカスタムイベント|
|:-:|:-:|:-:|:-:|:-:|:-:|
|パスカルケース<br><font color="Orange">P</font>ascal<font color="Orange">C</font>ase|◎||||||
|キャメルケース<br><font color="YellowGreen">c</font>amel<font color="YellowGreen">C</font>ase||◎<br>※DOMテンプレートでは<br>ケバブが必須|◎|prop内はキャメルが◎||
ケバブケース<br>kebab<font color="Red">-</font>case||||HTML内はケバブが◎|◎|
例|<img width="200px" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/746705/6670baac-8929-5297-8684-7c0cd46c8323.png">|< template><br>< <font color="YellowGreen">s</font>ample<font color="YellowGreen">W</font>ord><br>< /<font color="YellowGreen">s</font>ample<font color="YellowGreen">W</font>ord><br>< /template><br><br><br>export default {<br>components: {<br> <font color="YellowGreen">s</font>ample<font color="YellowGreen">W</font>ord<br>}}|<...v-on:click "<font color='YellowGreen'>s</font>ample<font color="YellowGreen">M</font>ethod">|-親comp側-<br>< sampleHuman<br>first<font color="Red">-</font>name="suzuki"<br>last<font color="Red">-</font>name="itiro"/><br><br>-子comp側-<br>export default {<br>props: {<br><font color="YellowGreen">f</font>irst<font color="YellowGreen">N</font>ame: String<br><font color="YellowGreen">l</font>ast<font color="YellowGreen">N</font>ame: String<br>}}<br>|< template><br>< button v-on:click=<br>"this.$emit<br>('create<font color="Red">-</font>button<font color="Red">-</font>click')" ><br>< /button>
</template>|

#結論
まとめてみてわかったことですが  
・Vueファイル名、は「パスカルケース」
・Javascript内では「キャメルケース」
・HTML内では「ケバブケース」

という風に分けるのが一番シンプルでわかりやすいかなと思います！
間違っている点などありましたらご指摘頂けますと幸いです。
DjangoのtemplateのVuejsの変数を表示する

##問題点
現場ではDjangoのフレームワークのtemplateにVuejsを導入しました。

DjangoのtemplatesにCDN方法でVuejsを導入すれば、Vuejsから渡したデータは表示されないことになります。

##原因
Djangoでは、変数を表示するために{{ 変数名 }}という書き方を使われます。
それと、"Mustache"構文を利用したVuejsの表示方法は同じなので、
Vuejsの方は表示されないです。

##解決方法
[Vuejsのdelimitersオプション](URL"https://jp.vuejs.org/v2/api/index.html#delimiters")を使用すれば、
Vuejsの表示方法を変更でき、データは表示されることになります。


```html:index.html
...
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
...

...
<body>
<!--Vuejs-->
<div id="app">  
 <p>[[ message ]]</p>
</div>

<script>
 const app = new Vue({
    delimiters: ['[[',']]'],
    el: '#app',
    data: {
        message: 'hello Vuejs'
    }
 });
</script>
</body>
```

上記のVuejs表示方法を改修すれば、DjangoとVuejsお互いに影響がなく、変数を表示できます。
MySQL group by句を体験してみる

# 目的

- 自分のgroup by句に対する知識があやふやなので基本的な部分を固めてみる。
- 下記の記事で書いているのに若干まだ理解できていない。これは恥ずかしい。
    - [SQL group by句を使用して結果をまとめて表示する](https://qiita.com/miriwo/items/29c383686ed1f66f15ab)

# 環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

# 情報

- Macに直接MySQLのサーバーを立てて実際にSQLを実行してgroup by句を体験してみることとする。
- 「環境」に記載された条件でgroup by句を体験してみる。

# 条件

- MySQLにターミナルからログインする事ができること。（パスワードなどがわからなくなってしまった方はこちら→[Mac ローカル環境の MySQL 8.x のrootパスワードを忘れた時のリセット方法](https://qiita.com/miriwo/items/1880e9d2ebcfd3c0e60d)）
- 下記SQLを実行してテスト用データベースとテーブルを作成した。

    ```sql
    create database group_by_test;
    use group_by_test;
    create table users(
        id int,
        user_flag int,
        age int,
        name varchar(255)
    );
    insert into users value(1, 1, 20, 'user1');
    insert into users value(2, 1, 22, 'user2');
    insert into users value(3, 2, 18, 'user3');
    insert into users value(4, 1, 16, 'user4');
    insert into users value(5, 2, 22, 'user5');
    insert into users value(6, 1, 10, 'user6');
    ```

- 上記のSQLを実行したあとのusersテーブルの状態を下記に記載する。

    ```
    mysql> select * from users;
    +------+-----------+------+-------+
    | id   | user_flag | age  | name  |
    +------+-----------+------+-------+
    |    1 |         1 |   20 | user1 |
    |    2 |         1 |   22 | user2 |
    |    3 |         2 |   18 | user3 |
    |    4 |         1 |   16 | user4 |
    |    5 |         2 |   22 | user5 |
    |    6 |         1 |   10 | user6 |
    +------+-----------+------+-------+
    ```

# 体験

1. 下記を実行してuser_flagが1と2のユーザーの年齢の平均値を別々に出力してみる。

    ```sql
    select user_flag, avg(age) as avg_age from users group by user_flag;
    ```

1. 下記のように出力された。

    ```
    +-----------+---------+
    | user_flag | avg_age |
    +-----------+---------+
    |         1 | 17.0000 |
    |         2 | 20.0000 |
    +-----------+---------+
    ```

1. group by句は「出力結果を指定したカラムでまとめてくれる」とおぼえておこう。
React + Firebase Authenticationでログイン機能を簡単に実装する


##はじめに

FirebaseのAuthenticationを使って、超簡単にReactアプリケーションのログイン(認証)機能を実装します。
いくつか既に記事はあるかと思いますが、ちょっと古かったり、動かなかったりしたので、記事に残してきます。
ご参考になれば幸いです！

## 前提

* ```npx create-react-app```等でReactプロジェクトの作成が完了していること
* Firebaseコンソール上でのプロジェクト作成、登録が完了していること


**Firebase上での作業がまだの方は、下記などを参考に進めてください。**
https://yanou.jp/react-firebase-authentication/


## ざっくり流れ

1. Firebase SDKをReactアプリケーションで読み込む
2. ユーザー登録、ログイン機能を実装する

なお、記事が長くならないように、
※CSSは書いておりません
※ユーザー登録とログインボタンが同一コンポーネント内にありますがご容赦ください...

それでは詳細を見ていきましょう。

##手順①Firebase SDKをReactアプリケーションで読み込む

SDKの場所は、下記の**設定マーク→プロジェクトを設定→ページ下部**にあります。
![スクリーンショット 2021-02-28 18.58.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526830/d346480a-3764-f384-cd1a-e1e9ba13ffff.png)

### 1. firebaseをインストール

```
npm i firebase
```


### 2. src配下にfirebaseファイルを作成する

```firebaseConfig.ts
import firebase from 'firebase/app'
import 'firebase/auth'

const firebaseConfig = {
  apiKey: "hogehoge",
  authDomain: "hoge.firebaseapp.com",
  projectId: "hoge",
  storageBucket: "hoge.com",
  messagingSenderId: "hoge",
  appId: "hogehogehoge"
}

const fire = firebase.initializeApp(firebaseConfig)

export default fire

```

## 手順②ユーザー登録、ログイン機能を実装する

```tsx
import React, { useState } from "react";
// firebaseConfigからfireをインポートする
import fire from "./firebaseConfig";

export const App: React.FC = () => {
  //ユーザー管理用state
  const [user, setUser] = useState("");
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");

  //ログインメソッド
  const handleLogin = () => {
    fire
      .auth()
      .signInWithEmailAndPassword(email, password)
  };

  //ユーザー登録メソッド
  const handleSignup = () => {
    fire
      .auth()
      .createUserWithEmailAndPassword(email, password)
  };
  
  //ログインしているかをチェックするメソッド
  const isLogin = () => {
    fire.auth().onAuthStateChanged((user) => {
      if (user) {
        setUser(user);
      } else {
        setUser("");
      }
    });
  };
  
  //レンダー後にisLoginを実行する
  useEffect(() => {
    isLogin();
  }, []);

  return (
    <div>
      {/* userのstateでコンポーネントを切り替えている */}
      { user ? (
         {/* ログイン後に表示したいコンポーネントを書く */}
      ) : (
        <div>
          <label htmlFor="email">メールアドレス</label>
          <input
            id="email"
            type="text"
            placeholder="メールアドレス"
            value={email}
            onChange={(e) => setEmail(e.target.value)}
          />
        </div>
        <div>
          <label htmlFor="password">パスワード</label>
          <input
            id="password"
            type="password"
            placeholder="パスワード"
            value={password}
            onChange={(e) => setPassword(e.target.value)}
          />
        </div>
        <div>
          <button
            type="button"
            onClick={handleSignup}
          >
            ユーザー登録する
          </button>
          <button
            type="button"
            onClick={handleLogin}
          >
            ログインする
          </button>
      </div>
      )}
    </div>
  );
};
```

**これで完了です🙌**

## 終わりに

これだけの記述で認証機能が実装できるのは本当に楽ですね。
長い記事にしたくなかったので、コードの詳細は端折っております。何か質問があれば、コメントください！
Markdownの折り畳みのコマンドラインショートカット


# できること

実行結果をそのまま GitHub のコメントなどに貼り付けてプレビューすることができる。

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480312/e350a261-f8fc-2e97-a6ee-e4a08b8e4020.gif)

# ショートカット登録

gh-details 関数を .bashrc / .zshrc に追記

```bash
function gh-details() {
  [ -n "$1" ] && summary="<summary>$1</summary>\n\n" || summary=""
  echo "<details>\n\n${summary}\`\`\`console\n$(cat -)\n\`\`\`\n\n</details>"
}
```

# 使用例

## 標準出力

```console
$ echo "so\nlong\nlong\nlog\noutput" | gh-details execution_log
<details>

<summary>execution_log</summary>

```console
so
long
long
long
output
``` #<- Qiita でのマークダウン表示のためのエスケープ

</details>

```

## コマンドのログからGitHubの折り畳み構文を構築してクリップボードにコピーする

```console
$ echo "so\nlong\nlong\nlog\noutput" | gh-details execution_log | pbcopy
```

## クリップボードの内容からGitHubの折り畳み構文を構築してクリップボードにコピーする

```console
$ pbpaste | gh-details clipboard_title | pbcopy
```