OmniAICreator/Qiita-1.07M huggingface dataset:
C#のSQLServerでトランザクションを導入する


処理の中にトランザクションを組み込んだので、やり方をメモしていく。

使用環境：
VisualStudio 2017
SQLServer
C#

**必要なusing記述**
```c#
using System.Data.SqlClient;
```
App.configからDB接続情報を指定する場合こちらも↓
```C#
using System.Configuration;
```


## トランザクション処理について

複数の処理をひとかたまりにし、それらの処理がすべて終わるまでは確定を行わないようにする仕組み。(意訳)

**BEGIN**　…トランザクションの始まりの宣言　
**COMMIT**　…トランザクションの終わりの宣言(変更を確定する)
**ROLLBACK**　…トランザクションの終わりの宣言(変更を取り消しする)

これら3つをコードの中に配置していく。
※必ず3つ使う。

## C#のSQLServerでトランザクションを導入する




SQL文の実行のためにDBへ接続する。

DB接続情報の記述方法↓
https://qiita.com/suzuki_q/items/e0e061c559b3f3f22a64

```C#
//接続文字列を取得
string connStr = ConfigrationManager.ConnectionStrings["sqlsvrconnect"].ConnectionString;

using (var conn = new SqlConnection(connStr))
{
    // データベースの接続開始
    conn.Open();

    using (SqlCommand command = conn.CreateCommand())
    {
        //トランザクションの開始
        command.Transaction = conn.BeginTransaction();

        StringBuilder sb = new StringBuilder();
        sb.AppendLine(@"INSERT INTO example_teble")
        .AppendLine("(")
        .AppendLine("ID,")
        .AppendLine("PASSWORD,")
        .AppendLine("MONEY")
        .AppendLine(")")
        .AppendLine("VALUES")
        .AppendLine("(")
        .AppendLine("@ID,")
        .AppendLine("@PASSWORD,")
        .AppendLine("@MONEY")
        .AppendLine(")");

        //sbをString型に明示的に変換する
        command.CommandText = sb.ToString();

        command.Parameters.Add("@ID", SqlDbType.Int).Value = id;
        command.Parameters.Add("@PASSWORD", SqlDbType.NVarChar).Value = password;
        command.Parameters.Add("@MONEY", SqlDbType.Money).Value = money;
    
        try
        {
            //SQLの実行
            command.ExecuteNonQuery();
        }
        catch(Exception e)
        {
            //変更を取り消しする
            command.Transaction.Rollback();
            return;
        }
    
        //Parameterのクリア
        command.Parameters.Clear();

        //変更を確定する
        command.Transaction.Commit();

    }
    // データベースの接続終了
    conn.Close();
}
```
<br>

他の人の記事に乗っていた
`SqlTransaction tran = sqlconn.BeginTransaction();`
や
`transaction.Rollback();`
`transaction.Commit();`
などの書き方をすると、

**System.InvalidOperationException**：
コマンドに割り当てられた接続が保留状態であるローカルのトランザクションにあるとき、トランザクション オブジェクトを持つコマンドが必要です。コマンドの Transaction プロパティがまだ初期化されていません。

というエラーが発生してしまい、だめでした。

`SqlCommand command = conn.CreateCommand()`のcommandを使ったところうまく行った。
<br>



#### 参考
- https://learn.microsoft.com/ja-jp/dotnet/framework/data/adonet/local-transactions
ElixirでGitHubに公開されているがHexには公開されていないパッケージを読み込みたい

意外と初学者にわかりにくくなっていたので，急遽書きました．

# パターン1 Livebookなどで `Mix.install` を用いる場合で，かつ`README.md`に説明が書かれている場合．

例としては拙作のPelemayBackendです．

https://github.com/zeam-vm/pelemay_backend


`README.md`にはたいてい次のような記述があります．

```elixir
## Installation

To use `PelemayBackend`, describe the following `deps` in `mix.exs`.

def deps do
  [
    {:pelemay_backend, "~> 0.1.0-dev", github: "zeam-vm/pelemay_backend", branch: "main"}
  ]
end
```

Livebookでインストールする場合には，次のようにします．

```elixir
Mix.install([
    {:pelemay_backend, "~> 0.1.0-dev", github: "zeam-vm/pelemay_backend", branch: "main"}
])
```

# パターン2 `mix new`で作ったプロジェクトに組込む場合で，かつ`README.md`に説明が書かれている場合．

`mix new`で作ったプロジェクトの`mix.exs`に次のような記述があると思います．

```elixir
  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end
```

PelemayBackendの場合，ここに次のように入れます．

```elixir
  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
      {:pelemay_backend, "~> 0.1.0-dev", github: "zeam-vm/pelemay_backend", branch: "main"}
    ]
  end
```

その後，`mix deps.get`を実行します．

# パターン3 `README.md`が存在しない場合

まず該当のGitHubの`mix.exs`の`def project`と書かれているところを読んでいきます．

`app: :(アプリ名)` みたいに書かれているところはないでしょうか？

例えば拙作のPelemayBackendでは次のようになっています．

```elixir:mix.exs
defmodule PelemayBackend.MixProject do
  use Mix.Project

  @version "0.1.0-dev"
  @source_url "https://github.com/zeam-vm/pelemay_backend"

  def project do
    [
      app: :pelemay_backend,
      version: @version,
      elixir: "~> 1.13",
      start_permanent: Mix.env() == :prod,
      deps: deps(),
      docs: docs(),
      compilers: [:pelemay_backend, :elixir_make] ++ Mix.compilers(),
      aliases: [
        "compile.pelemay_backend": &compile/1
      ]
    ]
  end
...
```

`app: :pelemay_backend`と書かれていますね．

実はこの `app:`の後のアトム`:pelemay_backend`はアプリ名を表します．

これは前述の

```elixir
    {:pelemay_backend, "~> 0.1.0-dev", github: "zeam-vm/pelemay_backend", branch: "main"}
```

のタプルの第1要素に入れるものです．

タプルの第2要素には `version:` で指定されているバージョン番号を元にして入れます．
PelemayBackendの場合では，`version: @version`とありますので，その前にある`@version "0.1.0-dev"`から`"0.1.0-dev"`を拾ってきます．

そのバージョン以降をインストールする場合には，`~> 0.1.0-dev`のように指定します．

タプルの第3要素には，`github: "ユーザー名/レポジトリ名"`を入れます．

PelemayBackend では https://github.com/zeam-vm/pelemay_backend なので，`github: zeam-vm/pelemay_backend`を入れます．

タプルの第4要素には`branch: "ブランチ名"`を入れます．

これでどのように入れたらいいかわかると思うので，あとは，`Mix install`を使うのか，`mix new`で作ったプロジェクトに入れるのかで，前述のやり方を用います．
Ruby9

# 問題
次の要件を満たすプログラムを実装しましょう。

・1~10の数値を順番に足し合わせる
・足し算の合計値がターミナルに出力される

しかし、以下のような順番に並べて、足し算しただけのプログラムはNGです。

```Ruby:NGコード
sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
```

ループ処理を用いて実装しましょう。

## 💡ヒント💡
times文を用いることで、ループ処理を実装できます。
ループ処理とは、特定の条件下にて、任意の処理を繰り返すことでした。
今回の問題にループ処理を当てはめると、

0に1を足し、
その結果に2を足し、
その結果に3を足し、
その結果に4を足し、
その結果に5を足し、
...と10まで繰り返していきます。

<br>
<br>
<br>

# 模範解答

```Ruby:模範解答１
sum = 0

10.times do |i|
  sum = sum + i + 1
end

puts sum
```
```Ruby:模範解答２
sum = 0

10.times do |i|
  sum += i + 1
end

puts sum
```

# 【解説】
今回の作成するのは、1〜10までの数字を順番に足し合わせていくプログラムです。

このプログラムの考え方は以下になります。

①合計値を保存しておく変数sumを用意する
②変数sumに1〜10の数値を順番に足していく
③順番に足していく処理をtimes文の繰り返しで置き換える
④変数sumの値をターミナルに出力する

### ①合計値を保存しておく変数sumを用意する
1に2を足し、
その結果に3を足し、
その結果に4を足し、
その結果に5を足し、...と10まで繰り返していきます。

よって常に結果を保存しておく変数が必要になります。これを変数名sumとして定義します。
まだ何も足してない状態なので、sumには0を代入しておきます。

### ②変数sumに1〜10の数値を順番に足していく

```Ruby:NGコード
sum = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
```
問題文にある通り、上記のコードは使用できないためループ処理が可能なtimes文を使用します。

### ③順番に足していく処理をtimes文の繰り返しで置き換える
times文を使えば、何度も繰り返される同じ処理をまとめることができます。

times文は繰り返したい回数.timesと記載して繰り返す数を決めます。
今回は1〜10まで順番に足していくため、10回同じような処理が繰り返されます。よって繰り返したい回数は10回です。

```Ruby:sum += 数値を繰り返す
sum = 0

10.times do |i|
  sum += 数値
end
```
数値の部分は繰り返す回数ごとに変わります。
1回目は1、2回目は2、3回目は3となります。つまり、繰り返しの回数と同じです。
times文では、変数iの中に繰り返しの回数が数値として自動で代入されます。よって、変数iを使えば繰り返しの回数を変数sumに足していくことができます。
ただし、プログラムなので1回目のiの数値は0となります。よってsumに足すのは1増やしたi + 1にしましょう。

```Ruby
sum = 0

10.times do |i|
  sum += i + 1
end
```

### ④変数sumの値をターミナルに出力
最後にputsメソッドでsumをターミナルに出力できるようにすれば終了です。

<br>
<br>
<br>
０から順に足されることに注意してプログラムを記述することです。
`bootsnap`を`1.16.0`にバージョンアップしたら`Psych::DisallowedClass`エラーが発生した

# 事象

`bootsnap`をバージョン`1.16.0`にバージョンアップしたら以下のエラーが発生しました。

```ruby
Psych::DisallowedClass:
 Tried to load unspecified class: Time
```

# 原因

`ruby`の`YAML`パーサーライブラリ`Psych`において、バージョン`4.0.0`以降セキュリティ脆弱性対策として`YAML.load_file`メソッドの挙動がデフォルトで`safe_mode`という厳格なパースを行うように変更されている様です。
※ これまでの挙動と同じにするには`YAML.unsafe_load_file`を使う必要がある様です。

https://github.com/ruby/psych/pull/487

上記に付随して`bootsnap`でも `Date`と`Time`の値とエイリアスを適切に拒否する様に対応がされました。

https://github.com/Shopify/bootsnap/issues/434

```ruby
Psych::DisallowedClass:
 Tried to load unspecified class: Time
```

## 対応
調査したところ`committee`というライブラリで`YAML.load_file`を呼び出しておりエラーが発生していました。
`committee`では`5.0.0`で`Psych`の`4.0.0`に対応されていたのでバージョンアップしたら解消されました。

https://github.com/interagent/committee/pull/335
【2023年最新版】Raspberry Pi をキーボード，ディスプレイなしで初期設定する

2022年4月ごろからRaspberry Pi OSをキーボード，ディスプレイなしでセットアップする方法が変わったっぽい．日本語だと古い情報しかなかったので書いた記事．

具体的には起動時に自動的にユーザを作成し，SSHサーバを立ち上げる方法を解説する．このうち自動的にユーザを作成する部分が変わった．

ユーザ作成の公式情報元は以下．

https://www.raspberrypi.com/news/raspberry-pi-bullseye-update-april-2022/

# 前提
- Raspberry Pi OS
- Raspberry Pi Imagerを使わない
  - 使う場合はGUIで設定できるらしいので解説するまでもないと思う
- 有線LANで接続する
- （ほかにLinuxマシンがある）
  - なくてもできるのだが，ない場合はパスワードハッシュの生成が面倒なので，素直にRaspberry Pi Imagerを使った方が良いと思われる

# 手順
## イメージファイルダウンロード
以下のリンクからインストールしたいバージョンのOSイメージをダウンロードする．

https://www.raspberrypi.com/software/operating-systems/

ダウンロードしたファイルは圧縮されているので解凍しておく．Windowsなら[7-Zip](https://sevenzip.osdn.jp/)で解凍できた．

## イメージファイル書き込み
解凍したイメージファイルをSDカードに書き込む．Windowsなら例えば[Win32 Disk Imager](https://sourceforge.net/projects/win32diskimager/)が有名．

## 起動時に自動でユーザを作成する
書き込みが終わるとSDカードの中身が見えるようになる．二つのパーティションが存在するが，その内FAT32の方のルートディレクトリを開く．というか，もう一方はext4でWindowsやMac OSでは非対応なので開こうと思っても開けない．中身は以下のような感じ．

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/1db7f0f9-1c85-6b94-f57b-03b43d5e8187.png)

このディレクトリ直下に`userconf.txt`という名前のテキストファイルを作成する．Windowsなら右クリックから「新規作成」→「テキスト ドキュメント」と選び，ファイル名は`userconf.txt`にする．

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2354612/05438a94-8a8d-c698-4cda-485d46d0f3d4.png)

作成したファイルをダブルクリックしてメモ帳で開き，中身を`username:encrypted-password`という一行にして保存する．ただし，`username`の部分を作成したい任意のユーザ名，`encrypted-password`の部分を以下で説明するハッシュ化したパスワードにする．

ハッシュ化したパスワードは別のLinuxマシンがあるならコンソールから

```console
$ echo 'mypassword' | openssl passwd -6 -stdin
```
で出力できる．ただし`mypassword`の部分を任意のパスワードにする．

別のLinuxマシンがないなら例えば[このサイト](http://webadmin.jp/toolhash/)の「SHA512-CRYPT」の出力欄から先頭「{SHA512-CRYPT}」の文字を削除した部分として得ることもできる．が，他人にパスワードを知らせることになるので推奨はできない．ローカルで生成することも当然できるのだが，わりと面倒になるのでここでは解説しない．`/etc/shadow`のパスワードハッシュの仕組みについて調べればいけるが，それならRaspberry Pi Imagerを使った方がいい気がする．

例えばユーザ名を`test`，パスワードを`password`にするなら`userconf.txt`の中身の一例は

```:userconf.txt
test:$6$tgP0Jx6tNRffDjk3$sv/3zx64GZ0tjwuBtPzyuMkD9XpVStNY7ivO4rWKFRa18WXxIAMrc/9voF16qCw.BuJ3RvuTUchHnVnx8zHPh1
```

となる．ただし，ハッシュ化したパスワードの部分は同じパスワードを使っても同じ文字列になるとは限らないので一致はしない．

## 起動時にSSHサーバを有効にする
`userconf.txt`を作成したのと同じディレクトリに`ssh`というファイル名の空のファイルを作成する．Windowsなら同じように右クリックから「新規作成」→「テキスト ドキュメント」と選び，ファイル名を`ssh`（末尾の`.txt`は削除）とする．この時拡張子が変わったと警告がでるが，「はい」を選んで続行する．`ssh`ファイルの方の中身は空で良いので以上．

## 起動・SSH接続
SDカードをRaspberry Piに挿してLANケーブルをつなぎ，電源を入れる．作成したファイルに従って初期設定が行われるので数分待った後，別のマシンからホスト名`raspberrypi.local`でSSH接続する．ユーザ名とパスワードは設定したものを用いる．

`raspberrypi.local`で接続できない場合もある（私はできなかった．）．その場合はIPアドレスを自分で調べる必要がある．私はDHCPサーバのリース記録から調べた．

# あとがき
もともとはユーザ名`pi`，パスワード`raspberry`の固定で初期化されていたのが，必ず個々に決めさせるようになった形だ．初期値をそのまま使ってしまう人が一定数いて，セキュリティ的な問題が多かったから変えたようだ．一部の国では法律でインターネットに接続する機器にデフォルトの認証情報を持たせるのを禁止しているところもあるらしい（最上部の公式情報のリンクより）．
Vimの基本操作おさらい

Vimでよく忘れる基本操作まわりをまとめた備忘録

# コマンド

## ファイルを閉じる

ノーマルモードで `:q` でファイルを閉じます。
qはquitの略です。

## インサートモードへ切り替え

`i` 入力でターミナル最下部に`-- INSERT --` と表示されれば切り替え成功です。

## ノーマルモードへ切り替え

`esc` キー押下でターミナル最下部の`-- INSERT --` が消えれば切り替え成功です。

## ファイルを保存する

ノーマルモードで `:w` でファイルを保存します。
wはwriteの略です。

## 強制的にファイルを閉じる

ノーマルモードで `:q!` でファイル内容の変更を保存せずに終了できます。

## カーソル移動

`h` でカーソルを左に移動。
`j` でカーソルを上に移動。
`k` でカーソルを下に移動。
`l` でカーソルを右に移動。

最初は慣れないかもですが、全て右手のホームポジション近くにキーがあるので便利です。
またこれらのコマンドは指定回数分繰り返すことができます。
`5l` で右に5個カーソルを移動させます。

### 行での移動

`0` その行の最初に移動します。
`^` その行の最初の空白以外の文字に移動します。
`$` その行の最後に移動します。
`G` 最後の行の空白以外の文字に移動します。
`gg` 最初の行の空白以外の文字に移動します。

### 単語での移動

Vimには2種類の単語オブジェクトがあります。
小文字のwordと大文字のWORDで、 `word` は空白で区切られた文字・数字・アンダースコアからなる文字列で、 `WORD` は空白で区切られた空白以外の全ての文字からなる文字列です。

`w` で次の単語(word)に移動。
`e` で最も近い単語(word)の末尾(end)に移動。eはendの略です。
`b` で単語(word)の先頭に戻る(backword)移動。bはbackwardの略です。

WORD単位での移動に切り替えたい場合は上記のコマンドを大文字にすることで可能です。

`W` で次の単語(WORD)に移動。
`E` で最も近い単語(WORD)の末尾に移動。
`B` で単語(WORD)の先頭に戻る移動。

### オブジェクト単位での移動

`(` で文単位で後ろに戻る。
`)` で文単位で前に進む。
`{` で段落単位で後ろに戻る。
`}` で段落単位で前に進む。

## 編集

`x` でカーソルのある文字が削除されます。
`dd` でカーソルのある行が削除されます。
`yy` でカーソルのある行がコピーできます。Vimではヤンク(yank)と呼びます。
`p` で記録されたテキストをペーストできます。Vimではプットと呼びます。
Githubコマンド入門コマンド（備忘録）

皆さんGithub使ってますか？
先日久しぶりにGithubを使用しようとしたところ、コマンドを一部忘れてしまっていた為、また忘れたとき用に備忘録を作りたいと思います。

##### Gitをインストールします 

 ```cmd:
$ sudo apt-get install git
 ```

##### Gitの初期設定
 ```cmd:
$ git config --global user.name "Your Name"
$ git config --global user.email "youremail@example.com"
 ```
##### ローカルリポジトリの作成

 ```cmd:
$ mkdir myproject
$ cd myproject
$ git init
 ```

##### リモートリポジトリを追加

 ```cmd:
$ git remote add origin https://github.com/username/myproject.git
 ```

##### ファイルの追加
ここではREADME.mdをサンプルとして使用します。

 ```cmd:
$ echo "Hello World" > README.md
$ git add README.md
 ```

##### コミット

 ```cmd:
$ git commit -m "Initial commit"
 ```

##### プッシュ

 ```cmd:
$ git push -u origin master
 ```




##### GitHubリポジトリのクローン

 ```cmd:
$ git clone https://github.com/username/myproject.git
 ```
[備忘録] jestで現在時刻をmockする

# TL;DR

```ts
describe('timer mock', () => {
  beforeEach(() => {
    jest.useFakeTimers()
  })

  it('test', () => {
    jest.setSystemTime(new Date('2023-02-01T12:05:13.354+09:00'))
    // TODO assert
  })

  afterEach(() => {
    jest.useRealTimers()
  })
})
```

# `useFakeTimers`しないと...

下記がターミナルに表示され、現在時刻はmockできない。

```terminal
A function to advance timers was called but the timers APIs are not replaced with fake timers. Call `jest.useFakeTimers()` in this test file or enable fake timers for all tests by setting 'fakeTimers': {'enableGlobally': true} in Jest configuration file.
    Stack Trace:
```

# Reference

https://jestjs.io/ja/docs/jest-object#jestsetsystemtimenow-number--date
ショートカットキー一覧

 # はじめに
業務でネットを使うことが多く、ショートカットキーを知っていればとても便利だなと思ったので、記事にします。この記事に記載しているキーは個人的にすごい便利だと思ったキーのみ記載します。

 # ショートカットキー一覧
|項目|キー|
|:----|:----|
|画面を切り替える|Alt + Tab|
|ショートカットメニューを表示する|Sshift + F10|
|エクスプローラを起動する|Windows + E|
|新しいタブを開く|Ctrl + T|
|一つ左のタブに移動する|Ctrl + PageDown|
|一つ右のタブに移動する|Ctrl + PageUp|
|タブを閉じる|Ctrl + W|
|検索窓に移動する| /|
githubにPushするまでによく使うコマンド

## はじめに
githubへコミット、Pushする上でいくつかコマンドを叩く必要がある。
毎日叩いていると忘れることはないが、頭を整理する意味で少しまとめてみる。

## ブランチの作成
いきなりmainブランチにコードを書くのではなく、現在やっている作業に応じたブランチを作成してあげてそこに作業をしていくのが一般的。
そうすることで複数人で作業をする際でも競合することがなく、同時並行で作業をすすめることができる。
```terminal
$ git branch ブランチ名
```

## ブランチの切り替え
ブランチを作成したら切り替えられているか確認する。
作成後は自動で切り替えがあると思うが、`git branch` で現在のブランチを確認した上で、`git checkout` コマンドを使って必要に応じて移動する。

```terminal
// 現在のブランチ確認
$ git branch
```

```terminal
$ git checkout 移動したいブランチ名
```

## 作業後Pushまでの流れ
### ステータスの確認
変更したファイルの確認だったりで、`git status` コマンドを使って、変更ファイルが間違っていないか確認する。
```terminal
// ステータスの確認
$ git status
```

### ステージエリアにファイルを追加する
コミットをする前にステージエリアに対象ファイルを移動させる必要があります。
`git add` コマンドを使って操作します。

```terminal
// ステージエリアにファイルを追加する
$ git add .
```
### ファイルをコミットする
ステージエリアに追加することができたら、ファイルをコミットさせます。
```terminal
// ファイルをコミットする
$ git commit -m "メッセージ"
```

### コミットしたファイルをPushする
ローカル環境にあるファイルをPushしてリモート環境(github)に反映させる作業です。
`git push` コマンドを使って操作してあげます。

```terminal
//  pushする
$ git push origin ブランチ名
```

これで一旦Pushまでは完了です。

### リモートリポジトリにあるファイルをPullする
Pushとは逆にリモートリポジトリにあるファイルをPullすることもよくあります。
誰か他の人が作業した際、変更点を自身のローカル環境に反映させる場合に使います。

```terminal
// リモートリポジトリからPullする
$ git pull
```

ブランチを指定する場合は、
```terminal
$ git pull ブランチ名
```
とすることができます。

以上
初めてVizをパブリッシュするまでの７ステップ

「自分でVizを作ってみたいけど、どこから手を付けたら良いのかわからない…」
Tableauを始めたばかりの方で、このように迷われることも多いと思います。

そこで、Vizを作成してパブリッシュするまでのHow toを簡単にまとめてみました。
少しでもお役に立てれば幸いです！<br><br>
## １．Tableau Publicをインストールする
まず、[こちら](https://public.tableau.com/ja-jp/s/)からTableau Publicをインストールしましょう！
ローカルPCへ保存するためには製品版の購入が必要ですが、完成したVizをパブリッシュ（一般公開）する場合は、無料版であるTableau Publicで大丈夫です。
オンライン上に公開されるので、**秘匿性の高いデータ・個人情報を用いたVizはNG**です。
## ２．Taskを決める
続いて、パブリッシュするVizを作っていきます。
最近の出来事の中で、下の**４つの疑問点**がないか、思い返してみましょう。

* When（いつ）：「ここに旅行するにはいつがいい？」
* Where（どこ）：「どこにある施設が一番人気なんだろう」
* Who（誰）：「どの年齢層が多いのか気になる」
* What（物）：「病床はいくつ使われているのかな」

**自分の感情が動いたもの**を軸に探すと、見つかりやすいと思います。また、自分の自然な疑問点をTaskに挙げることで、この後の掘り下げがとてもスムーズになります。
どうしても思い浮かばない場合は、実際のデータから４つの疑問点に沿って探すのも手です！
##  ３．データを探してダウンロードする
一般に公開するVizを作成するため、主に**オープンデータ**を使用します。
１で決めたTaskのオープンデータがないか探してみましょう。
もし見つからなければ、[気象庁](https://www.data.jma.go.jp/gmd/risk/obsdl/)・各自治体のデータから探すのもおすすめです。
## ４．データの整理
オープンデータは様々な形で準備されていますが、中でも**CSV形式**が多いと思います。
CSVとは「Comma Separated Value」の略称で、「コンマで区切った値」を指します。
Excelで開くことができるので、Excelで不要な行・列を削除します。
<img width="1000" alt="Excelから開く" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3122923/8aef6eee-dd98-7b70-adf5-f1b10f4914b8.png">
右クリックから任意のプログラムで簡単に開くことができます！（mac）<br>
<img width="1000" alt="Excel形式へ変更" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3122923/6e6c2eb1-f752-0dff-d617-080b3a767389.png">
CSV形式をExcel形式に変えて保存してから操作しましょう。
Excel「データ」タブ内「フィルター」を使うと楽に作業できると思います。
## ５．Tableau Publicで分析
３で整理したExcelファイルをTableau Publicに取り込んで、いよいよここから分析です！
「何を見ればTaskが解決するのか」を考えながら、グラフを作成していきます。

「どこから始めれば良いのかわからない！」という場合は、一旦以下のグラフをたくさん作って、ざっくりとした**全体像**を把握してみましょう。

* ディメンションごとの棒グラフ
* 推移
* ヒストグラム

すると気になる点が出てくると思うので、その箇所をピンポイントに掘り下げていきます。
自分で探索している時は、最初から完璧な１シートを作るのではなく、あえて「ダッシュボードのパーツを作る」と意識すると整理しやすいかもしれません。
データの土地勘がつくまでは、まず色々なグラフをガシガシ作ってみましょう！

そして探索中に「この分析はVizを見る人にも見せたいな」と思うシートが出てくると思います。
Taskの理解に必要なプロセスだと感じたら、レイアウトを整えてシートを仕上げましょう。
## ６．ダッシュボードを組み立てる
Taskの理解に必要なシートがいくつかある場合は、**ダッシュボード**にまとめます。
インタラクティブにさせたいシートにフィルターを設定すると、Vizに動きが出て楽しいです！笑
もちろん楽しいだけではなく、選択したデータに対応させることで、より簡単にそのデータの詳細を理解することができます。
**データの引用元**もしっかりと記載しましょう。

「どうしても無駄な隙間ができてしまう」という場合には、**空白・テキスト**を使用するとレイアウトが整います。余ったスペースに簡単な操作説明を書いておくと、ぐっと親切になります。
<img width="1000" alt="シート非表示" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3122923/48e50794-c844-12f9-d8d9-e2aa8e2b0c2f.png">
ダッシュボードにまとめた場合は、シートを非表示にしておくとシンプルになります。<br>
<img width="1000" alt="Excel形式へ変更" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3122923/d529a2ea-83b5-f76b-d72e-c1c539634c7e.png">
凡例を浮動にすると、より細かくレイアウトを整えることができます。
「**Vizを初めて見る人が何を思うか**」を意識しながら組み立てましょう。
## ７．完成したらパブリッシュ！
最後にシートごとに見直して、不要なピル・フィルター・タブを削除したら完成です！
<img width="1000" alt="パブリッシュ方法" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3122923/92333ee4-8c0b-d97c-b2d2-920dc4d42c9f.png">
「ファイル」内の「Tableau Publicに保存」からパブリッシュが可能です。
少しレイアウトがズレることがあるので、パブリッシュしたシートも忘れずに確認しましょう。<br><br><br>
以上、初めてVizをパブリッシュするまでの７ステップでした。


最初の１つが完成すると、一気に感覚が掴めると思います！
気軽に作ってパブリッシュできるので、気になることをどんどん可視化してみましょう。
<br><br>
【相対パス】【絶対パス】ターミナルを使うのに最低限の基礎知識

# はじめに
ターミナルの基礎中の基礎を備忘録としてまとめていきます。

# 環境
Windows
GitBash

# そもそもターミナルとシェルの違いは？
・ターミナル
黒い画面でコマンドをポチポチ打ってシェルに命令を送る為のソウフトウェア。
（例）GitBash,ターミナル（Macにデフォルトで入っているソフトウェア）


・シェル
ターミナルで受け取ったコマンドをOSの中枢であるカーネルに伝えるソフトウェア。
（例）bash, zsh, tcsh

ターミナルで自分が使っているシェルを確認するには下記コマンド。
```
$ echo $SHELL
```
↓
```
/usr/bin/bash
```
私はbashを使っていたようだ。

# 各ディレクトリの違い
最低限、理解しておかなくてはならないディレクトリが下記の3つだ。
・ルートディレクトリ
・ホームディレクトリ
・カレントディレクトリ

それでは順番に説明していこう。

1.ルートディレクトリ
一番上のディレクトリの事。
記号ではスラッシュ「/」で表記される。
それではここでターミナルで確認してみよう。
試しにpwdコマンドを打ってみると下記のように表示されるはずだ。
```
$ pwd
```
↓
```
/c/Users/ユーザ名
```
pwdコマンドはルートディレクトリからカレントディレクトリ（現在自分がいるディレクトリ）までのパスを表示してくれるコマンドだ。
スラッシュ「/」から始まっているだろう？これがルートディレクトリだ。

2.カレントディレクトリ
前述したとうり現在自分がいるディレクトリの事。

3.ホームディレクトリ
ユーザ事に用意されたPCの保管領域の事。
小難しく言ったが、要はUsers配下にある名前のフォルダ。
田中太郎君のPCならtaroとかいう具合。
記号ではチルダ「~」で表記される。
ターミナル起動時の初期ディレクトリはデフォルトではホームディレクトリになっているんだ。
さて、それではターミナルを開いてみよう。
下記のようにプロンプトの一番右にチルダ「~」があるだろう？
※プロンプトとはターミナルを開いたときに、最初から表示されている文字列。
プロンプトが表示されているという事は"入力を受け付けてまっせ！"という状態。
```
taro@myPC MINGW64 ~
```

# 相対パス・絶対パス
相対パスはカレントディレクトリからのパス。
絶対パスはルートディレクトリからのパス。
それは分かってんだけど、絶対パスからの指定ってイマイチ分かっていないんだよな～って人の為に両者の指定方法の違いを説明。

1.相対パス
例えばカレントディレクリ直下のディレクトリに移動する時は普通にcdコマンドでOK
※カレントディレクトリ配下にtestディレクトリがある前提。
```
$cd test
```

2.絶対パス
ルートディレクトリからのパス。
記述する時は、スラッシュ「/」から書き出せばOKだ。
※ルートディレクトリ配下にbinディレクトリがある前提。
```
cd /bin
```
カレントディレクトリがどこであろうと、絶対パスで記述すれば一発で移動できるのは便利だ。
絶対パスを書きたい時はスラッシュから書けばOKと覚えておけばいいだろう。

ちなみに一気にホームディレクトリに戻りたい時は引数ナシcdコマンドでOK。
またホームディレクトリを意味する「~」に会えるぞ。
読み方は何だっけ？そう。チルダだ。

# まとめ
駆け出しエンジニアの方の一助になれば幸いです。
また、誤った記述があった際などお気軽にコメントいただけると嬉しいです。
dockerのコマンドが毎回めんどくさいのでbashテンプレ化


# まえがき
毎回イメージ名打ち込んだり面倒でスクリプト作ってたので、テンプレに起こした
aliasやmakeでもよかったけど、都度ちょいちょい変わるのでリポジトリ別に設置できるよう

(2023/02/06) 追記 docker-compose用書いた
[docker\-composeのコマンドが毎回めんどくさいのでbashテンプレ化 \- Qiita](https://qiita.com/Azumahata/items/e4eebf79247ac16425ad)

# 注意点
- 前提として私用開発用(雑)、自己責任で煮るなり焼くなりどうぞ
    - 肥大化する場合は別の手段を考える事を推奨
- 一階層掘った場所を想定(ex `$ ./scripts/ctl`)
- `# execute`のところで雑にコールしてるので脆弱性に繋がる可能性あり
    - 定義とusageで2箇所の編集に留めたかった
    - 定義済関数を呼び出せるので、心配ならcaseにして呼び出しに制限を
    - 露出しないよう除外など推奨(ciでrm、dockerignore/gitignore)

# script

```bash:scripts/ctl
#!/bin/bash
SCRIPT_DIR=`dirname "${0}"`
SCRIPT_NAME=`basename "${0}"`

# cd to exec dir
cd "${SCRIPT_DIR}/../"
IMAGE_NAME=`basename "$(pwd)"`
VERSION='latest'
IMAGE="${IMAGE_NAME}:${VERSION}"


# --------------------------------------------------
# args
CTL_CMD="${1}"
shift

while getopts h OPT
do
  case $OPT in
     h) OPT_HELP=1;;
     *) ;;
  esac
  shift
done

REST_ARGS="${@}"


# --------------------------------------------------
# functions
usage() {
  cat << EOS

Usage: ${SCRIPT_DIR}/${SCRIPT_NAME} COMMAND [REST_ARGS]

Options:
  -h Print usage

Commands:
  build   `type _build | grep '^ '`
  run     `type _run   | grep '^ '`
  exec    `type _exec  | grep '^ '`
  stop    `type _stop  | grep '^ '`

EOS
  exit 1
}


_build() {
  docker build -t "${IMAGE}" . ${REST_ARGS}
}

_run() {
  docker run -it "${IMAGE}" ${REST_ARGS}
}

_psq() {
  docker ps -q --filter "ancestor=${IMAGE}"
}

_exec() {
  _psq | head -1 | xargs -I{} docker exec -i "{}" ${REST_ARGS}
}

_stop() {
  _psq | xargs docker stop
}


__main() {
  if [ "${OPT_HELP:-0}" -eq "1" ] || [ -z "${CTL_CMD}" ]; then
    usage
  fi

  type "_${CTL_CMD}" > /dev/null 2>&1

  if [ "${?}" -eq "0" ]; then
    # execute
    _${CTL_CMD}
  else
    echo "-${0}: ${SCRIPT_NAME}: ${CTL_CMD} command not found" 1>&2
    usage
  fi
}

__main

```

# ex. usage
```
$ ./scripts/ctl

Usage: ./scripts/ctl COMMAND [REST_ARGS]

Options:
  -h Print usage

Commands:
  build       docker build -t "${IMAGE}" . ${REST_ARGS}
  run         docker run -it "${IMAGE}" ${REST_ARGS}
  exec        _psq | head -1 | xargs -I{} docker exec -i "{}" ${REST_ARGS}
  stop        _psq | xargs docker stop

$ ./scripts/ctl run echo 'Lorem ipsum'
Lorem ipsum
```

# あとがき

突貫なので不都合出てきたら修正するかも。
もっと良い感じにできそうだったら教えて頂けますと幸いです。
Amazon Linux 2 で PHP7.4 から 8.1 にアップグレードする方法



以前書いた記事の PHP 7.4 -> PHP 8.1 バージョンアップ版です。(Amazon Linux Extra を使用する前提)

以前の記事 -> [Amazon Linux 2 で Nginx, MariaDB, PHP7.2 から 7.4 にアップグレードする方法
](https://qiita.com/katzueno/items/0f2de17b719e9d16c749)


ISO 127001 認証を取得しているセキュアかつ簡単な操作が可能で開発もしやすい [Concrete CMS](https://concrete5-japan.org) をインストールしているサーバーで

- PHP7.4.x -> PHP8.1.x

にアップデートした時のコマンドメモです。

めっちゃくちゃざっくりです。

アップグレード元のバージョンが違ったり、レポジトリが違ったりあって、
いろんなケースの手順をまとめてます。

**PHP+MySQL のサーバーに詳しい人しか参考にしないでください。**

## 旧バージョンの Amazon Linux Extra のレポジトリを Disable

```
sudo amazon-linux-extras disable php7.4
```

## 新バージョンのレポジトリを enable

```
sudo amazon-linux-extras enable php8.1
```

## 単純に yum update でアップデート。カーネルのアップデートとかもあるし

多分、カーネルとかいろいろアップデートあると思うので、ついでにしましょう。サーバー再起動が必要になります。

```
sudo yum update
```

サーバー再起動がNGであれば、PHP だけ。

```
sudo yum update php*
```


## スタートアップ起動しているか確認

注意) Nginx + php-fpm 想定

```
sudo systemctl is-enabled php-fpm
sudo systemctl is-enabled nginx
```

Disable だったら、enable (サーバー再起動時に起動するように)。

```
sudo systemctl enable php-fpm
sudo systemctl enable nginx
```

## (Nginx サーバーだったら) PHP キャッシュ・セッション系のオーナーが apache に変わるので Nginx に戻す

```
sudo chown -R nginx:nginx /var/lib/php
```

## 再起動

サーバー再起動であれば

```
sudo reboot
```

PHP プロセスの再起動だけであれば

```
sudo systemctl restart php-fpm
```

多分、これでOK
Lambdaコンテナをローカルでデバッグする方法


## 概要
Lambdaをコンテナ毎デプロイすることができるようになりましたが、
今回は、ローカル環境でデバッグする方法について書き記します。
わざわざデプロイしてクラウド環境上でテストする手間が省けます。

## 方法

ファイル構成は以下となります（ServerlessFrameworkを利用しています）
```
aws-python-docker-demo
├── Dockerfile
├── README.md
├── app.py
├── requirements.txt
└── serverless.yml
```

今回デバッグ用に用意したコードはこちらです。
シンプルにリクエストの結果を返却するコードを書いています。

```app.py
import json
import requests

def handler(event, context):

    res = requests.get("http://example.com")

    response = {
        "statusCode": 200,
        "body": res.content
    }

    return response

```


1. まずDockerCLIを使用して、`debug` コンテナイメージをローカルでビルドします。
     ```
    docker build -t debug .
     ```
1. 1.でビルドしたコンテナイメージをローカルで起動します。ローカルの9000番ポートをコンテナ内部の8080番ポートにバインドします。
    ```
    docker run -d -p 9000:8080 debug:latest
    ```
1. curl を使用して関数呼び出しをテストします。ここでは、空のJSONペイロードを渡しています。
    ```
    curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'
    ```
    結果は、無事に意図したデータが返却されました。

    ```
    {"statusCode": 200, "body": "<!doctype html>\n<html>\n<head>\n    <title>Example Domain</title>\n\n    <meta charset=\"utf-8\" />\n    <meta http-equiv=\"Content-type\" content=\"text/html; charset=utf-8\" />\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />\n    <style type=\"text/css\">\n    body {\n        background-color: #f0f0f2;\n        margin: 0;\n        padding: 0;\n        font-family: -apple-system, system-ui, BlinkMacSystemFont, \"Segoe UI\", \"Open Sans\", \"Helvetica Neue\", Helvetica, Arial, sans-serif;\n        \n    }\n    div {\n        width: 600px;\n        margin: 5em auto;\n        padding: 2em;\n        background-color: #fdfdff;\n        border-radius: 0.5em;\n        box-shadow: 2px 3px 7px 2px rgba(0,0,0,0.02);\n    }\n    a:link, a:visited {\n        color: #38488f;\n        text-decoration: none;\n    }\n    @media (max-width: 700px) {\n        div {\n            margin: 0 auto;\n            width: auto;\n        }\n    }\n    </style>    \n</head>\n\n<body>\n<div>\n    <h1>Example Domain</h1>\n    <p>This domain is for use in illustrative examples in documents. You may use this\n    domain in literature without prior coordination or asking for permission.</p>\n    <p><a href=\"https://www.iana.org/domains/example\">More information...</a></p>\n</div>\n</body>\n</html>\n"}% 
    ```
Mapbox GL JSでヒートマップを作成する

Mapbox GL JSで膨大なポイントデータを視覚化できるヒートマップを作成する方法をご紹介します。公式の[サンプル](https://docs.mapbox.com/mapbox-gl-js/example/heatmap-layer/)や詳しい[チュートリアル](https://docs.mapbox.com/help/tutorials/make-a-heatmap-with-mapbox-gl-js/)もご覧ください。

まず、スタイルに「ヒートマップ」タイプのレイヤーを追加します。
```
map.addSource('earthquakes', {
   type: 'geojson',
   data: 'earthquakes.geojson'
});
map.addLayer({
   id: 'earthquakes',
   source: 'earthquakes',
   type: 'heatmap'
});
```
ヒートマップは用途に応じて様々なカスタマイズが必要です。Mapbox GL JSでは、レイヤーの外観を制御するためのスタイルプロパティを提供しています。各項目を見ていきましょう。

# heatmap-radius
このプロパティは、各ポイントの「影響半径」をピクセル単位で設定することで、ヒートマップの詳細を設定できます。
値を高くすると、より滑らかで一般的な外観になります。このプロパティでは、ズームインしたときの見た目を調整することができます。
![image9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516459/f61c4ef8-c834-b092-c151-9c1c0ef6df55.png)
▲ヒートマップ半径の調整：5（左）、40（右）
```
map.addLayer({
   ...
   paint: {
       'heatmap-radius': 40
   }
});
```
# heatmap-color
このスタイルプロパティは、ヒートマップデザインの重要な側面である、マップ上の各ピクセルの「密度」値をどの色に変換するかを制御します。
![image10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516459/8d17d353-719a-60a9-0fd2-977756371085.png)
▲ヒートマップカラーの値の違いによる例

このプロパティの値は、0.0〜1.0の密度値を色にマッピングする関数です。この例では、最も疎らな場所を青にし、混雑している場所では黄色から赤へと徐々に移行するように設定しています。
```
"heatmap-color": {
   "stops": [
       [0.0, "blue"],
       [0.5, "yellow"],
       [1.0, "red"]
   ]
}
```
# heatmap-intensity
このプロパティは、ヒートマップの外観を調整することができます。値が高いほど、各ポイントが見た目に与える "重み"が大きくなります。
例えば、heatmap-intensityを10.0に設定すると、データセットを10回複製し、デフォルトの1.0の値でレンダリングすることと同じになります。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516459/cc7e5066-2442-e817-a9d5-2c35ad575ab3.png)
▲heatmap-intensityの調整：0.1（左）、1（右）

heatmap-intensityは、異なるズームレベルに対してヒートマップの見た目を調整するのに便利です。これを一定のままにすると、低いズームレベルのヒートマップは、ポイントが視覚的に近くなるため、より重く見えます。
# heatmap-weight
このスタイルプロパティは、データ駆動型であること以外は、heatmap-intensityと同じ働きをし、個々のポイントの特徴的な特性に応じた強度を調整することができます。
```
"heatmap-weight": {
   "type": "identity",
   "property": "point_count"
}
```
この例では、point_countの値が100のポイントは、point_countが1の100ポイントと同じに見えます。クラスタリングと組み合わせることで、描画するポイントの数を大幅に減らし、ヒートマップの性能を向上させることができます。
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516459/d908f657-f5a6-bc45-5bff-47d7aeeb21c9.png)

# heatmap-opacity
このプロパティは、ヒートマップレイヤーの不透明度を制御します。
![image6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516459/257c3a9e-f4cb-4fd8-7080-38dd40aa2706.png)

▲ヒートマップ-不透明度1.0（左）、0.5（右）のヒートマップ

heatmap-opacityの便利な応用として、ズームインしたときにヒートマップをフェードアウトしてより詳細に見えるようにすることができます。
![image8.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2516459/813cb1b8-0180-77c0-25f2-6402ffd21e65.gif)
hey siri で 指定したurlからjsonを取得


# ショートカットアプリを開く

iphoneのショートカットアプリを開き、マイショートカットを選択。

![nagare1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/105f2747-c5cb-0904-337f-7de5a36fee40.png)

右上の プラス をタップして新規ショートカットの作成

![nagare2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/4092e9d2-cae6-f07c-f103-a065af43822e.png)

# ショートカットの構築

アクションの追加について、

一番下部の赤枠Appおよびアクションを検索に () 内の値を入力し検索すると
アクションが表示される。
次のアクションの提案というのが表示されるが、無視する

・指定したURLの内容を取得
(URLの内容を取得)

・今回は json をリターンしているので、 json内のresの値を辞書に入れる
（辞書の値を取得）

・辞書の値を res に追加
（変数に追加）

・このresを表示
（結果を表示）


![nagare3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/9b411ec4-9229-4624-039c-6907445a144a.png)

右下の矢印をタップすると再生される。

また、ここで選択したタイムスタンプを教えてという名前に変更すると
siriに「タイムスタンプを教えて」というと、結果を表示、読み上げしてくれる。

applewatchを使っている場合、上記の設定だけでapplewatchでも有効になる





ちなみに、laravelで構築したサーバサイドは以下のようになっている

```

public static function test(request $request)
{
    $res = "只今のタイムスタンプは" . time() . " です";
    return response()->json(['res'=> $res]);
}

```

# 最終出力

hey! siri! タイムスタンプを教えて

で、タイムスタンプを教えてだと、うまく表示されないので、
タイトルをタイムスタンプ叩いてにして使っている。

![Fn3S5n0acAE8Pjv.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/445ce9cb-521c-b8ec-4a6a-3fa6e518e62f.jpeg)
ServerlssFramework でLambdaコンテナをデプロイ


## 概要

Lambdaの関数コードをコンテナイメージでデプロイすることができますが、
今回はServerlessFrameworkを使って簡単にクラウド環境にデプロイする手順を書き記します。

## 手順

1.サンプルコードを作成
 
```
$ serverless create --template aws-python-docker --path aws-python-docker-demo
✔ Project successfully created in "aws-python-docker-demo" from "aws-python-docker" template (3s)
```

2.デプロイコマンド実行

```
$ serverless deploy

Deploying aws-python-docker-demo to stage dev (ap-northeast-1)

✔ Service deployed to stack aws-python-docker-demo-dev (187s)

functions:
  hello: aws-python-docker-demo-dev-hello
```

3.確認

LambdaとECRそれぞれにデプロイされていることが確認できました。

**Lambda**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658983/8543377b-e5e2-7d04-8ca5-7e36c8fdf7e2.png)
**ECR**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658983/edd2dc71-d979-d12e-cb58-08431e93a80d.png)

## ハマりポイント
* `Runtime.InvalidEntrypoint` エラーが発生した
    * M1 Macで環境構築したため、コンテナイメージが`arm64`アーキテクチャでビルドされたのが原因でした。 `serverless.yml` にアーキテクチャを指定することで解決しました。
```serverlss.yml
provider:
  name: aws
  ecr:
    images:
      appimage:
        path: ./
  stage: dev
  region: ap-northeast-1
  architecture: arm64 <- ここ
```

## 関連記事
https://qiita.com/knakazono10111/items/e8aaf884142715d1c135
Django マイグレーションで起きた　Please select a fix

既存のモデルにフィールドを追加しマイグレーションをすると次のような文が

It is impossible to add a non-nullable field '追加したフィールド名' to モデル名 without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
 1) Provide a one-off default now (will be set on all existing rows with a null value for this column)
 2) Quit and manually define a default value in models.py.


翻訳すると
デフォルトを指定せずにモデル名に null 非許容フィールド '追加したフィールド名' を追加することはできません。 これは、データベースが既存の行に入力するために何かを必要とするためです。
修正を選択してください:
  1) 今すぐ 1 回限りのデフォルトを提供します (この列の null 値を持つすべての既存の行に設定されます)
  2) 終了し、models.py でデフォルト値を手動で定義します。

つまり表示されているフィールドはNullの指定もDefaultの指定もしていないのでなにかしら値を入れてくださいということだと思う

2を選択して自分でフィールドを操作する

指定したフィールドに
null=True,blank=True
を指定してもう一度マイグレーションを実行するとうまくいった
プリザンターは楽観的排他制御だった！

 # はじめに
プリザンターを使って業務を行うとき、誰かが更新したためにページをリロードしなくてはいけない場面があります。そのような事態が先日頻発したため、今回は排他制御についての記事を記載します。

 # 排他制御(同時実行制御)とは・・・？
排他制御というのはあるトランザクション単位でロックをかけることです。Aさんが内容を変更している最中にBさんがその内容を上書きできないようにする仕組みです。もう少し掘り下げていきましょう。

 # トランザクションとは・・・？
トランザクションとはある一連の処理のことをまとめてそう言います。例えば、Aさんの銀行口座から1,000円Bさんの銀行口座へ振り込んだ場合、Aさんの出金とBさんの入金は一連の処理(1つのトランザクション)と判断できます。

 # ロックとは・・・？
その名の通り、鍵をかけることを言います。この場合、データベースなどの情報にロックをかけて変更ができないようにすることです。

 # 排他制御の考え方
上記を踏まえて、排他制御とは振り込み(Aさんの出金とBさんの入金)の間、データベースの書き込みができないようにロックをかけ、正常に振り込みが完了したらロックを解除するという考え方です。そして、この制御があることで安心して振り込みができるのです。もし仮に排他制御がないと次のようになってしまいます。振り込みをした際にAさんの出金処理は正常に完了したけど、Bさんの入金処理は正常に完了しなかった場合、Aさんの預金残高は減っている(DB上では引き算されている)けど、Bさんの預金残高は増えていない(DB上では足し算されていない)というちぐはぐな状況になってしまいます。そして、銀行など重要な情報を持っているシステムでは悲観的排他制御という考えのもと排他制御しています。一方で、楽観的排他制御という考えもあります。

 # 悲観的排他制御
悲観的排他制御の考え方は他の人も同じデータを高頻度で更新するだろうという考え方のもとに行う排他制御です。例えば、ある人がロックをかけているとします。すると、他の人はまったく更新できなくなってしまうということです。これは、少しわかりづらいので、楽観的排他制御を理解したほうがわかりやすいかもしれません。

 # 楽観的排他制御
楽観的排他制御の考え方は他の人も同じデータを高頻度で更新することはないだろうという考え方のもとに行う排他制御です。例えば、ある人が画面を開いていたとしても、他の人のほうが更新時間が早ければ更新可能です。つまり早い者勝ちなのです。それに画面を開いたまま変えられてしまった場合、悲観的排他制御だったら大変なことになりますよね。そうならないためにも楽観的排他制御という考え方も必要なのです！

 # プリザンターの排他制御は？
プリザンターの排他制御は楽観的排他制御です。一つのレコードに対して複数人が開いていた場合、先に変更した人の変更は受け入れられ、遅かった人は画面をリロードする(変更を画面に反映させる)必要があります。そのため、遅かった人は少し面倒ですが、画面をリロードしなくてはいけませんが、悲観的排他制御を採用するといつまでもレコードのロックが解除されず、可用性が下がってしまいます。そのため、楽観的排他制御なのですね。

 # 最後に
排他制御・トランザクション・ロック・悲観的排他制御・楽観的排他制御に関して記事にまとめました。プリザンターという便利なツールを快適に・安全に使っていただくためにはとても必要な知識だと思います。私ももっと勉強して、プリザンターを理解しなくては・・・！

 # 参考文献

https://rainbow-engine.com/optimistic_lock_pessimistic_lock/
Firebase EmulatorでのポートNGエラーの解決方法

## 概要
- Firebase Emulatorを再起動した際に、『ポートが空いていないよ～』とエラーが発生する場合があります。
- その解決策をまとめました。
- （参考情報）ちなみに、Unit Testでエラーが発生し、強制終了した際にこの現象が発生することが度々ありました。


## 環境
Windows10
Node.js: 16.14.2
firebase-tools: 10.9.2
Visual Studio Code: 1.74.3

## エラー発生状況
- まずは Firebase Emulator を起動します。
    - FirestoreやStorageのデータをimportしない場合は、`--import=tests/firebase` は不要です。
    - [Firebase Emulator の公式リンク](https://firebase.google.com/docs/emulator-suite/connect_and_prototype?hl=ja&database=Firestore)

```terminal:my-project
firebase emulators:start --import=tests/firebase
```
- するとこんなエラーが発生する場合があります。

```
!  emulators: Support for Java version <= 10 will be dropped soon in firebase-tools@11. Please upgrade to Java version 11 or above to continue using the emulators.
i  emulators: Starting emulators: auth, firestore, hosting, pubsub, storage
!  emulators: It seems that you are running multiple instances of the emulator suite for project hino-solutions. This may result in unexpected behavior.
i  emulators: Shutting down emulators.
i  hub: Stopping emulator hub
!  firestore: To select a different host/port, specify that host/port in a firebase.json config file:
      {
        // ...
        "emulators": {
          "firestore": {
            "host": "HOST",
            "port": "PORT"
          }
        }
      }
i  emulators: Shutting down emulators.

Error: Could not start Firestore Emulator, port taken.
```
- `Error: Could not start Firestore Emulator, port taken.` と書いてある通り、port確保ができなくてFirestoreの起動を失敗したみたいです。

## ポート番号調査
- 確保したかったFirestoreのport番号を調べます。
- firebase.jsonのfirestoreの設定値を確認します。

```my-project/firebase.json
{
  "hosting": {
    "public": "dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ],
    "rewrites": [
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  },
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "storage": {
    "rules": "storage.rules"
  },
  "emulators": {
    "auth": {
      "port": 9099
    },
    "firestore": {
      "port": 8083
    },
    "hosting": {
      "port": 5000
    },
    "pubsub": {
      "port": 8085
    },
    "storage": {
      "port": 9199
    },
    "eventarc": {
      "port": 9299
    },
    "ui": {
      "enabled": true
    },
    "singleProjectMode": true
  }
}

```

```my-project/firebase.json　の抜粋です
...
    "firestore": {
      "port": 8083
    },
...
```
- 8083 ですね。

## 該当portは何に使われているか調査
- コマンドプロンプトで以下のコマンドを入力します。
    - 8083 の部分に任意の調べたいport番号を記載してください。
```
netstat -nao | find "8083"
```

- するとこんな応答が出ます。(内容は、人によって異なると思います。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834744/7d6706e0-5949-349b-e49e-9d8de0ffb37a.png)

```
TCP  127.0.0.1:8083  0.0.0.0:0  LISTENING  912
```
- 末尾の `912` がPIDなので、それを手がかりにしてさらに調べます。

## PIDを手がかりに調査
- タスクマネージャーを起動します。
- 詳細タブを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1834744/8f04c70f-dd29-616c-7ebe-90d9730c4962.png)

- 犯人は `java.exe` でした。
- 右クリック -> タスクの終了 で強制終了させます。

- 以上です。お疲れ様でした。
Rails migrateエラー解決備忘録

# 概要
この度railsを触っているのですが、migrateのあたりが苦手で、よくエラーが
起きてしまって困っていたので、自分で忘れないようにメモをさせていただきます。

# 環境
Rails 6.1.7
ruby 3.1.2
AWS 
cloud9

# 起きたエラー集
#### SQLite3::SQLException: table "tags" already exists
これが起きた背景は、タグ機能をgemなしで作っていたところに、gemを導入したことがきっかけです。
結局その後、gemを使わずにタグ機能の運用をしようとして、rails db:migrateしたことでエラーが起こりました。
考えなしに入れたり消したりしたらダメですね。

今回のSQLite3::...のエラーを解決していきます。

###### 手順
まず、tagsのテーブルが被っているので、テーブルを削除します。

```ターミナル(cloud9).
ec2-user:~/environment/アプリ名 (main) $ rails db
↑SQLite3にアクセス
```

```ターミナル(cloud9).
sqlite> .table
↑SQLite3でtableの一覧を確認
```

```ターミナル(cloud9).
sqlite> drop table tags;
↑これで被っていたtagsのテーブルの削除をします！
```

そしたら、sqlite> .tableでテーブル一覧を確認したらtagsが消えています！

#### SQLite3::SQLException: no such table: tags
SQLite3::SQLException: table "tags" already existsを解決した後、テーブルを作り忘れて、rails db:migrateを行うと、今回のタイトルのエラーが起きます。
単純にテーブルを作成してやれば、一発解決です！

```ターミナル(cloud9).
ec2-user:~/environment/アプリ名 (main) $ rails db
↑SQLite3にアクセス
```

```ターミナル(cloud9).
sqlite> create table tags(id, tag_name);
↑SQLite3でtagsのtableを作成
```

create table tags(id, tag_name);
のかっこの中はカラムです。

作成した後
```ターミナル(cloud9).
sqlite> .table
↑SQLite3でtableの一覧を確認
```
これでtagsのテーブルがあることを確認してからrails db:migrateをすれば解決です！

####
BizRobo!運用者必見、MCのバックアップをコマンド一発で取得する方法

## はじめに

システム運用においてバックアップは重要な要素です。定期的に取得しているユーザーさんも多いと思います。
BackUpを取得するには毎回　Admin ユーザーとしてMCにログインする必要がありますが、できるだけAdmin での作業は避けたいものです。

長いこと忘れてましたが、そういえば「こんなことができますよ。」というtipsを思い出したので書き留めておこうと思います。

:::note info
以下、BizRobo! v11.3.0.2 で実行していますが、v10.4 の頃から利用しています。
:::

## バックアップ取得コマンド
```shell:バックアップ取得コマンド
curl http://{username}:{password}@{hostname}/secure/Backup --output {filename}.zip
```

Management Console のバックアップ／リストア権限を保持しているユーザーは admin ユーザーのみなので、それ以外のユーザーアカウントを指定しても権限エラーでバックアップは取得できません。

|項目 | 説明 |
|:-:|:-|
|username | admin ユーザー名   |
|password | admin ユーザーのログインパスワード  |
|hostname | バックアップを取得する Management Console のホスト名（80や443以外のポートを使っているときにはポートの指定も必要）  |
|filename |バックアップファイルを出力するファイル名（ファイルパス\ファイル名）|

:::note warn
本件は `http://localhost` で MC にアクセスできる場合を例に `hostname` を指定していますが、場合によって `http://localhost:8080/mc` で MC にアクセスしている場合には `hostname` 部分を `localhost:8080/mc` で読み替えて試してみてください。
:::

### 実行例
```console
C:\Users\hoge>curl http://admin:hogeo@localhost/secure/Backup --output hogeBackup.zip
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 2356k    0 2356k    0     0  6520k      0 --:--:-- --:--:-- --:--:-- 6545k
```
出力先フォルダを指定していないので、コマンドを実行したフォルダにバックアップファイルが出力されます。

## ブラウザからの実行方法

```shell:バックアップ取得URL
http://{username}:{password}@{hostname}/secure/Backup
```
アドレスバーにURLを入力することでもバックアップの取得が可能です。

![extractBackup.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090491/3134bb8e-6d58-be66-03bb-0f87f4b7fe9c.gif)

## まとめ

定期的にバックアップを取るようであれば、バッチとして取得してもいいですし、専用のロボットを作成してもいいですね。
Qiita Night ~PHP~ で「PHPアプリケーションにおけるアーキテクチャメトリクスについて」というLTをしてきた

2023/01/25(水)に[Qiita Night～PHP～](https://increments.connpass.com/event/270421/)というイベントでLTしてきましたのでその報告です。

https://www.youtube.com/watch?v=oNJijNiKUYU

https://speakerdeck.com/isanasan/architecture-metrics-in-php-applications

## モチベーション

PHPerKaigi2023に以下のようなプロポーザルを提出していたのですが、残念ながら採択ならず、悔しいな~と思っていたところ、たまたまLTの機会を頂いたのでアーキテクチャメトリクスについてお話ししてきました。

https://fortee.jp/phperkaigi-2023/proposal/047f399d-8045-4e1b-a626-72ef4ce3f6ec

発表内容の元ネタはこちらの書籍です。

https://www.oreilly.com/library/view/software-architecture-metrics/9781098112226/

deeeetさんがおすすめしていたので読みました。

https://twitter.com/deeeet/status/1607544977864916992?s=20&t=TBvPPAx34Qli5onI2p-ovw

実際とても良い本だったし、洋書ですがサクっと読めるので気になる方は是非チェックしてみてください。

あと全然関係ない超余談なのですが、LT当日に10Xさんが下記のようなブログをポストしていて、ソフトウェアアーキテクチャについても計測して改善するというアプローチは今後トレンドになっていくだろうなーと思ったのでした。

https://product.10x.co.jp/entry/fitness-function-in-stailer

## こぼれ話

LT内で扱えなかったトピックがあるので補足しておきます。

### 可視化と運用について

時間の関係で扱えなかった内容として、計測したメトリクスをどう運用するのかという点があります。
twitterの方でどんぴしゃな質問なども寄せられていました。

https://twitter.com/hnw/status/1618193475220148228?s=20&t=TBvPPAx34Qli5onI2p-ovw

計測したメトリクスは時系列で可視化して日々のPDCAサイクルに組み込んで活用する必要がありますが、可視化についてはこれといったソリューションがあるわけではないので、個々の現場で使い慣れているデータストアを利用して頂ければ良いかと思っています。

筆者の場合は計測ツールをCIで定期実行し、BigQuery + redashという構成で可視化しています.
※ 可視化していますと言いつつ実際は計測したいメトリクスは全然とれていないのでやっていきという感じです。

### 紹介しきれなかったメトリクスについて

LTの最後にちょっとだけ触れた以下のアーキテクチャメトリクスですが、実は筆者が知る限りPHPで使える計測ツールはありません。

- 累積コンポーネント依存度(CCD)  
- 平均コンポーネント依存度(ACD)
- 伝搬コスト(PC)
- 相対循環依存度(RC)
- 構造的負債指数(SDI)

何かよいソリューションをご存知の方がおられましたら是非お知らせください。

## 最後に

発表資料やトーク内容について、同僚が快くレビューをしてくれたおかげでよいLTができたと思います。
また、企画から準備、当日の運営に至るまで非常にスムーズで、ストレス無くトークすることが出来ました。
改めて関係者のみなさんに感謝をお伝えしたいです。
2023年2月 AIOps 定点観測

# 概要
AIOps の動向や学習のため、Google で AIOps を検索した結果を記録している記事です。

# 2023年2月1日の検索結果 (リスティング広告)

![20230201_AIOps_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/e6ecfd6d-7f53-d256-ddcf-0f9c8df8f961.png)

* IBM

IBM がトップに返り咲きましたが、なんと広告はこの1社のみです。

先月の結果はこちら --> [2023年1月 AIOps 定点観測](https://qiita.com/mkodera/items/e94ce87a8f1e43d0f6db)

# 2023年2月1日の検索結果 (広告以外)

![20230201_AIOps_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2345504/198cab34-b855-f2b2-3283-5b2ef5cdba40.png)

* Splunk
* ServiceNow
* ITmedia
* 日立
* intra-mart (NTTデータ イントラマート)
* JBSVC

広告以外では Splunk がトップです。上位3位までは先月と変わりません。 NTTデータ イントラマートが初登場です。

先月の結果はこちら --> [2023年1月 AIOps 定点観測](https://qiita.com/mkodera/items/e94ce87a8f1e43d0f6db)
備忘録１

自分の備忘録を載せておきます。
# データフレームから座標を順に読み取ってリストに格納する方法
~~~
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}) #dfの作成
df_list = [] #空リスト作成
for n in range(3):
    result = [df.iloc[0+n,0],df.iloc[0+n,1]]
    df_list.append(result)
~~~
# 辞書型からリストに変換する方法
~~~
d = {'a': 1, 'b': 2, 'c': 3}
keys = list(d.keys())
values = list(d.values())
~~~
TypeScript の const について

TypeScript は JavaScript の superset で、JavaScript の機能を拡張したものです。その中でも const という文法があります。

const は、定数を表します。定数は値を変更できない変数のことです。定数を宣言するには、変数名の前に const を付けます。例えば、次のように記述します。

```typescript
const myConst = "This is a constant";
```
このように定数を宣言することで、プログラムの中で値が変わってしまうことを防ぐことができます。これは、プログラムの誤りを防ぐためにも重要な役割を持っています。

また、定数は let と同様にブロックスコープを持ちます。つまり、const を使って宣言された定数は、そのブロック内でのみ有効なので、別のブロック内で同じ名前の変数を宣言することもできます。

さらに、const を使って宣言された変数は再代入不可能です。例えば、次のように記述してもエラーになります。

```typescript
const myConst = "This is a constant";
myConst = "This is a new value";  // Error: Cannot assign to 'myConst' because it is a constant
```
このように、TypeScript の const は定数を扱う上で重要な文法です。使用することで、プログラムの誤りを防ぐことができます。
【なぜ】ipaファイルのサイズがビルドする度に毎回違う

# ipaファイルのサイズがビルドする度に毎回違う
理由を知っている人がいればぜひ教えて頂きたいです。
また、自分だけの現象なのかというのも知りたいので皆さんの環境ではどうなのかも教えていただけると嬉しいです。

iOSアプリ（ipaファイル）をXcodeでビルドしたとき、毎回ファイルサイズが数十バイト程度違っています。
以下は全く同じ手順で3回ビルドをしてみたときのファイルサイズを比較したものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/574728/f9d02dbd-431b-d01e-5358-e488f8db32ad.png)

同じアプリの内容であれば出来上がるファイルサイズも同じになるはずだと思っていますが、なぜiサイズが異なっているのでしょうか、、、？（実際、Androidアプリ（apkファイル）は何度ビルドしても同じファイルサイズでした。）

（2年ほどiOS/Androidアプリの保守を担当していましたが、今回初めて気づきました。。。）
【Django】viewsで定義した変数やオブジェクトをformで使う

## 想定した仕様

本の検索サイトの著者のプロフィール欄で、その著者が書いた本を選択できるフォームを作成。
同じformsファイルのBookFormを使っても著者によって選択肢（choices）を変える必要がある。

## コード

~~~python:views.py
...
def get(self, request, id):
    ...
    # 著者のidを取得して、formに渡す
    author = AuthorModel.objects.get(id=id)
    form = BookForm(author_id=author.id)
    ...
...
~~~
ポイントはフォームを宣言したときにauthor_id=author.idを引数に取っていること。
そうすればforms.pyではkwargs.pop('author_id')で取得できる。

~~~python:forms.py
class BookForm(forms.Form):
    # フォームを作成
    book_select = ChoiceField(
        widget=Select(),
    )
    # 初期化関数
    def __init__(self, *args, **kwargs):
        if kwargs.get("author_id"):
            self.author_id = kwargs.pop('author_id')
        else:
            self.author_id = None
        super().__init__(*args, **kwargs)

        author = AuthorModel.objects.get(id=author_id) # 著者を取得
        books = BookModel.objects.filter(author=author) # その著者の本を取得
        books_choices = [(book.id, book.name) for book in books] # 本を配列に格納
        self.fields['book_select'].choices = books_choices # 配列をchoicesに指定
~~~

このコードで動作は確かめていないが、とにかくkwargs.pop('author_id')で取得できるんだという備忘録。
【Flutter】ダイアログの下にSnackBarが表示される

# はじめに
showDialogを使って表示したダイアログからSnackBarを呼び出すと、下記のようにダイアログの下にSnackBarが表示されてしまったので、
解決方法を調べました。

![Simulator Screen Shot - iPhone 14 Pro - 2023-02-01 at 15.08.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/f6103ea3-aee8-4039-aa09-5bce6dc41d37.png)

# 解決前のコード
解決前のコードは、普通に`showDialog`メソッドのbuilderでダイアログを作成して表示しています。
SnackBarはAlertDialogの「はい」ボタン押下時に出るように実装しています。

```dart
  void _showAlertDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (context) => createAlertDialog(context),
    );
  }

  AlertDialog createAlertDialog(BuildContext context) {
    return AlertDialog(
      contentPadding: EdgeInsets.zero,
      title: Container(color: Colors.lightBlue, child: const Text("Title")),
      titlePadding: EdgeInsets.zero,
      content: Container(
        color: Colors.lightBlue,
        child: const Text("エラーが発生しました。\n再度実行しますか"),
      ),
      actions: [
        TextButton(
          child: const Text("はい"),
          onPressed: () {
            ScaffoldMessenger.of(context)
                .showSnackBar(const SnackBar(content: Text("pressed!!")));
          },
        ),
        TextButton(
          child: const Text("いいえ"),
          onPressed: () {
            Navigator.of(context).pop();
          },
        ),
      ],
    );
  }

```
# 解決後のコード
解決後のコードは、`showDialog`で表示するところまでは一緒ですが、
`builder`の部分で`Scaffold`を使用しています。
明示的に`Scaffold`を使うことで、このダイアログと同じ階層にSnackBarを表示できます。
注意として、`backgroundColor`に`Colors.transparent`を指定することを忘れないでください。
透明にしておかないとデフォルトの背景色が表示されてしまうからです。

```diff
  void _showAlertDialog(BuildContext context) {
    showDialog(
      context: context,
+       builder: (context) => Scaffold(
+       backgroundColor: Colors.transparent,
        body: createAlertDialog(context),
      ),
    );
  }
```
![Simulator Screen Shot - iPhone 14 Pro - 2023-02-01 at 15.10.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/966e4579-402e-d8a6-1849-bd6da1336b1e.png)
Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「ロール定義」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「ロール定義」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure での ID とガバナンスの管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-identities-governance/)
◇対応するモジュール
[ロール定義を作成する](https://learn.microsoft.com/ja-jp/training/modules/configure-role-based-access-control/3-create-role-definition)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Azure RBAC」](https://qiita.com/fsd-jume/items/19426ff0bba0ba7424d4)

## ロール定義
・実行できる操作が登録されたアクセス許可のコレクション
⇒JSONファイルにプロパティで定義されている
・使用環境によりプロパティの表示が異なる
　-PowerShellを使用した場合
　-Azure Portal/Azure CLI/REST APIを使用した場合

### ロール定義のプロパティ例
```:PowerShell
Name
Id
IsCustom
Description
Actions []
NotActions []
DataActions []
NotDataActions []
AssignableScopes []
```
```:Azure Portal / Azure CLI / REST API
roleName
name
roleType
type
description
actions []
notActions []
dataActions []
notDataActions []
assignableScopes []
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/a406af34-e3a9-8d79-ab27-979828696b9d.png)

### アクションの形式
・`{Company}.{ProviderName}/{resourceType}/{action}`
・`{action}`部分の種類
　-`*`：すべてのアクション
　-`read`：読み取りアクション(GET)
　-`write`：書き込みアクション(PUT/PATCH)
　-`action`：VMの再起動(POST)などのカスタムアクション
　-`delete`：削除アクション(DELETE)

**◆アクションの例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/df4247da-df59-c1f1-baa6-ab477cd26b7f.png)

### ActionsとNotActions
・アクセス許可の付与/拒否を調整可能
・NotActionsはワイルドカード(`*`)アクションから特定のアクションを取り除きたい時に使用
⇒拒否割り当てとは異なる

**◆組み込みロールにおける例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/681f747c-e994-873e-b13c-1801fc4ff5cb.png)

### スコープの指定(AssignableScopes)
・ロール定義を割り当て可能なスコープを指定
・カスタムロールを必要とする下記で割り当てを利用可能にする
　-管理グループ
　-サブスクリプション
　-リソースグループ
・例：AssignableScopesでサブスクリプションAを指定した場合
⇒下記のスコープにそのロールの割り当てが可能になる
　-サブスクリプションA
　-サブスクリプションA内の任意のリソースグループ
　-サブスクリプションA内の任意のリソース
・組み込みロールではルートスコープ(`/`)が設定されている
⇒すべてのスコープでそのロールを割り当て可能

**◆スコープの指定方法の例**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/8fb5359f-9f7f-860e-bf0b-8c87741ac7a3.png)

## 次の学習内容
**◆ロールの割り当て**

https://qiita.com/fsd-jume/items/1c6bee555c85d57d1e51

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
Spring boot で　ダウンロード機能 memo

# 非同期通信
エラーも吐かないし、正常にレスポンスしている。
なぜか、ダウンロードが開始されない。

**非同期通信 (ajax) でダウンロードをするとブラウザのダウンロード機能が死にます。**

# ブラウザの仕様
POST メソッドでダウンロードできない。
**ブラウザにもよるが仕様により GET メソッド じゃないと ブラウザのダウンロード機能が死にます。**