OmniAICreator/Qiita-1.07M huggingface dataset:
再帰関数を使わずに木構造を処理する

# 再帰関数を使わずに木構造を処理する
ディレクトリ構造等、木構造を連想配列（jsonとか）で表現しているようなデータを再帰関数を使わずにパースします。
再帰する代わりにスタックを使いノードデータをpushしてpop（又はshift）します。本記事のサンプルは２分岐ではなく複数の枝が付いている場合の実装となります。
メモリの容量であったりノード数を制限したい場合等に有用かと思います。

## 実装

ソースコード

``` python
def parse(data):
    stack = data
    depth = [0] * len(data)
    preDepth = 0
    currentDepth = 1
    while len(stack) > 0:
        idepth = depth[-1] + 1
        v = stack.pop()
        d = depth.pop()
        
        # 階層が深くなった時の処理
        if d > preDepth:
            currentDepth += 1
        # 深い階層から戻ってきた時の処理
        if d < preDepth:
            currentDepth -= 1
        
        preDepth = d
        print("{}".format("    " * currentDepth), end="")
        print("{}({})".format(v["name"], d))
        if "next" in v:
            stack.extend(reversed(v["next"]))
            nsize = len(v["next"])
            depth.extend([idepth] * nsize)

def main():
    data = [
        {
            "name": "root",
            "next": [
                {
                    "name": "next1-1",
                    "next": [
                        {
                            "name": "next1-1-1",
                        }
                    ]
                },
                {
                    "name": "next1-2",
                    "next": [
                        {
                            "name": "next1-2-1",
                        },
                        {
                            "name": "next1-2-2",
                        },
                    ]
                },
                {
                    "name": "next1-3",
                    "next": [
                        {
                            "name": "next1-3-1",
                        },
                        {
                            "name": "next1-3-2",
                            "next": [
                                {
                                    "name": "next1-3-2-1",
                                },
                            ]
                        },
                    ]
                },
                {
                    "name": "next1-4",
                    "next": []
                }
            ]
        }
    ]
    parse(data)

if __name__ == "__main__":
    main()
# python main.py
```

実行結果

```
    root(0)
        next1-1(1)
            next1-1-1(2)
        next1-2(1)
            next1-2-1(2)
            next1-2-2(2)
        next1-3(1)
            next1-3-1(2)
            next1-3-2(2)
                next1-3-2-1(3)
            next1-4(1)
```


以上です。
積分とかいろいろ

　私は、数学が好きなので今回はC言語で積分(ついでに微分）するプログラムを書いてみました。
#ソースプログラム
 ```c
#include<stdio.h>
int sekibunn(int x[], int bottom, int top) //定積分の計算
{
    int ans, t[6] = {1, 1, 1, 1, 1, 1}, b[6] = {1, 1, 1, 1, 1, 1}, i;
    t[1] = top;
    b[1] = bottom;
    for (i = 0; i < 2; i++)  //2乗の計算
    {
        t[2] *= top;
        b[2] *= bottom;
    }
    for (i = 0; i < 3; i++) //3乗の計算
    {
        t[3] *= top;
        b[3] *= bottom;
    }
    for (i = 0; i < 4; i++) //4乗の計算
    {
        t[4] *= top;
        b[4] *= bottom;
    }
    for (i = 0; i < 5; i++) //5乗の計算
    {
        t[5] *= top;
        b[5] *= bottom;
    }
    ans = ((t[5] * x[4] / 5) + (t[4] * x[3] / 4) + (t[3] * x[2] / 3) + (t[2] * x[1] / 2) + (t[1] * x[0])) - ((b[5] * x[4] / 5) + (b[4] * x[3] / 4) + (b[3] * x[2] / 3) + (b[2] * x[1] / 2) + (b[1] * x[0]));
    return ans;
}
 
int main(void)
{
    int x[] = {0, 0, 0, 0, 0};
    int i;
    int or, top, bottom;
    printf("整数を入力してください。\n");
    for (i = 4; i >= 0; i--)
    {
        printf("x^%dの係数:", i);
        scanf("%d", &x[i]);
    }
    printf("y=(%d)x^4+(%d)x^3+(%d)x^2+(%d)x+(%d)\n", x[4], x[3], x[2], x[1], x[0]);
    printf("微分or定積分...1 / 0:");
    scanf("%d", & or);
    if (or == 0)
    {
        printf("範囲は？");
        printf("下のほう :");
        scanf("%d", &bottom);
        printf("上のほう :");
        scanf("%d", &top);
        printf("面積は%dです。", sekibunn(x, bottom, top));
    }
    else if(or == 1){
        printf("y=(%d)x^3+(%d)x^2+(%d)x+(%d)", x[4]*4, x[3]*3, x[2]*2, x[1]);
    }
    return 0;
}
```
　結果としてはあまり正確な数字は出せませんでした。小数点以下があって整数部分が2桁以上となる数字の型が無いし、組み合わせてうまく表現する方法も思いつきませんでした。しかし、整数部分ではだいたい正しくなるように作れたのでよかったです。
#実行結果（定積分）
```math
2\int_{0}^{2}(x^4-8x^2+16)dxを計算してみました。
実際の答えが\frac{512}{15}となります。
```

```c
/*整数を入力してください。
x^4の係数:2
x^3の係数:0
x^2の係数:-16
x^1の係数:0
x^0の係数:32
y=(2)x^4+(0)x^3+(-16)x^2+(0)x+(32)
微分or定積分...1 / 0:0
範囲は？下のほう :0
上のほう :2
面積は34です。*/
```
512/15は34.13333となるのでだいたい正しくなりました。
#（微分）
```math  
y=x^4+4x^3+4x^2-1を微分せよ。実際の答えはy'=4x^3+12x^2+8xです。
```
```c
/*整数を入力してください。
x^4の係数:1
x^3の係数:4
x^2の係数:4
x^1の係数:0
x^0の係数:-1
y=(1)x^4+(4)x^3+(4)x^2+(0)x+(-1)
微分or定積分...1 / 0:1
微分結果
y'=(4)x^3+(12)x^2+(8)x+(0)*/
```
とこんな感じになりました。
#感想
　次に書く機会があれば、分数を表せるような仕組みを考えたいと思います。
#おまけ
```c
#include <stdio.h>
//方程式とx軸,xの範囲で囲まれた面積を近似で出すことができる。
int main(void)
{
    //今回の場合y=4xで範囲は0~2
    double y = 0, x, s = 0, haba = 0.001;
    int i, n = (2 / haba);
   x = haba;
    for (i = 0; i < n; i++)
    {
        y = 4 * x;
        printf("y=%f\n", y);
        s += haba * y;
        printf("面積=%f\n", s);
        x += haba;
        printf("x=%f\n\n", x);
    }
    printf("面積=%f", s);
    return 0;
}
```
本当は面積=8
結果:面積=8.004000 
![082A4CB3-E0BD-403D-B5EA-021264D5250E.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869445/c4098606-f787-86cd-fc1e-7f7f28ef4c56.jpeg)

　単なる思い付きだったのですが、区分求積法も再現したら本当に近似値が出るのかと思って試してみました。
　xの値、求める範囲の”n=(2/n)”の2を変えると好きな範囲でできるので、もしよかったら遊んでみてください。ちなみにhabaを小さくし過ぎるとめっちゃ時間がかかります。
Docker　サーバーの起動状態をリアルタイムで表示するコマンド watch "docker ps"

watchコマンドを使った監視方法

2秒ごとにコマンドを入力してくれるので、フォアグラウンドでリアルタイム更新される。
使っているTerminalを画面分割して、監視用の画面を作るとやりやすい。

```terminal
watch "docker ps"

# ヘッダを表示しない。よりスッキリした画面になる
watch -t "docker ps"

# 時間間隔指定
watch -n 1 "docker ps" 
```

[【 watch 】コマンド――コマンドを一定間隔で繰り返し実行する：Linux基本コマンドTips（220） - ＠IT](https://www.atmarkit.co.jp/ait/articles/1806/29/news037.html)
PythonのPandasのDataFrameの扱い方

PythonのPandasのDataFrameでデータを柔軟に扱いたかったので、個別に扱う方法を調べた。


####csvデータ
https://www.kaggle.com/canggih/anime-data-score-staff-synopsis-and-genre

####ソースコード
https://github.com/CoffCookie/dataframe.git


```animedata.py
import sys
import pandas as pd 

args = sys.argv
file_name = args[1]

print(file_name)
print(type(file_name))

anime_datalist = pd.read_csv(file_name)
print(anime_datalist.head())
print(anime_datalist.columns)

row_count = 0
all_row_num = len(anime_datalist)
print(all_row_num)

print(anime_datalist['Title'][1])

while row_count < 50:
    print(anime_datalist['Title'][row_count])
    row_count = row_count + 1

```

まず、データを
anime_datalist.head()
で先頭から5行までを表示し、行名と列名を確認。
このデータだと行は数値で表せる事がわかる。


```
                              Title   Type Episodes            Status  ... Scored by  Members Favorites                                        Description
0  Fullmetal Alchemist: Brotherhood     TV       64   Finished Airing  ...    719706  1176368    105387  "In order for something to be obtained, someth...
1                    Kimi no Na wa.  Movie        1   Finished Airing  ...    454969   705186     33936  Mitsuha Miyamizu, a high school girl, yearns t...
2                          Gintama°     TV       51   Finished Airing  ...     70279   194359      5597  Gintoki, Shinpachi, and Kagura return as the f...
3                     Steins;Gate 0     TV       23  Currently Airing  ...     12609   186331      1117  The dark untold story of Steins;Gate that lead...
4                       Steins;Gate     TV       24   Finished Airing  ...    552791   990419     90365  The self-proclaimed mad scientist Rintarou Oka...

```

列名を詳しく知りたいので、
anime_datalist.columns
で確認。

```
Index(['Title', 'Type', 'Episodes', 'Status', 'Start airing', 'End airing',
       'Starting season', 'Broadcast time', 'Producers', 'Licensors',
       'Studios', 'Sources', 'Genres', 'Duration', 'Rating', 'Score',
       'Scored by', 'Members', 'Favorites', 'Description'],
      dtype='object')
```

ここまで調べれば、そのまま2次元配列として扱えるので、

```py
print(anime_datalist['Title'][0])
```

と言う直接指定や

```py
while row_count < 50:
    print(anime_datalist['Title'][row_count])
    row_count = row_count + 1
```

などのように個別に扱う事ができる。
【Ruby】FizzBuzzの問題

こんにちは、あおい( https://twitter.com/aoi_programming )です。
今回はRubyのFizzBuzz問題を解いていきます！

いくらRuby on RailsでWebアプリケーションを開発できるようになっても、それはRubyのフレームワークに過ぎないので、プログラミングの本質を磨くには生のRubyを勉強する他ないと思いまして、これからは、Ruby本体も毎日コツコツ勉強していこうかと。

そこで、今回は初心者プログラマーがまずぶち当たる壁「FizzBuzz」の問題に挑戦してみます。
もっと良いコードがあればご提示していただけると嬉しいです！

# RubyのFizzBuzz問題
- 3で割り切れる数値を引数に渡すと「Fizz」と返す
- 5で割り切れる数値を引数に渡すと「Buzz」と返す
- 15で割り切れる数値を引数に渡すと「FizzBuzz」と返す
- それ以外の数値はその数値を文字列に変えて返す
- 改行はしない
- ひとつの数字につき、間に「,（カンマ）」をいれる

問題は上記の通りです。
実行方法は以下の通りです。

## 実行方法

```
% ruby test.rb
数字を入力してください。 # 31の場合
1,2,Fizz,4,Buzz,Fizz,7,8,Fizz,Buzz,11,Fizz,13,14,FizzBuzz,16,17,Fizz,19,Buzz,Fizz,22,23,Fizz,Buzz,26,Fizz,28,29,FizzBuzz,31
```

それでは実装していきましょう。
※これより下は答えとなります。

##回答

```test.rb
def fizzbuzz(nums)
  nums.times do |num|
   num += 1
   if num % 15 == 0
    print "FizzBuzz"
   elsif num % 3 == 0
    print "Fizz"
   elsif num % 5 == 0
    print "Buzz"
   else
    print num
   end
  if num == nums
   print ""
  else
   print ","
  end
 end
end
 
 puts "数字を入力してください"
 n = gets.to_i
 fizzbuzz(n)

```
【Angular】現在開いているページのurlを取得する

####やりたいこと
・ヘッダーでurlに応じてCSSの変更をしたい
・ページを切り替えるたびにurlを取得したい

##Routerでイベントを監視
```ts
import { NavigationEnd, Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { filter } from 'rxjs/operators';

export class HeaderComponent implements OnInit,OnDestroy {
  activeUrl:string;
  urlSubs:Subscription;
  constructor(private router:Router) { }

  async ngOnInit() {
    const navigationEndUrl = 
      await this.router.events
      .pipe(filter<NavigationEnd>(e => e instanceof NavigationEnd));
    this.urlSubs = navigationEndUrl.subscribe(active=>{
      this.activeUrl = active.url;
      console.log(this.activeUrl);
    });
  }

  ngOnDestroy(){
    if(this.urlSubs){
      this.urlSubs.unsubscribe();
  }
}

```
router.eventsをsubscribeするとurlについての情報が色々流れてくるのですが
いっぱい流れてくるので今回欲しい情報があるNavigationEndのイベントの時だけ取得するようfilterで絞り込みます

![スクリーンショット 2020-11-27 10.08.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607742/d35950a1-bfbf-b37e-1f71-0d0d39785ad2.png)
urlが取れました

あとは[クラスバインディング](https://qiita.com/frtklog/items/83b595fcb0c1808da95c)でurlを条件にしたら実現できました

```html
   <li class="nav-item">
      <a 
         class="nav-link"
         [class.active]="activeUrl == '/user'"
         routerLink="/user">User
      </a>
   </li>  
```


ページを開いた時一回だけurlを取得したい時の例

```ts
    import { filter, first, map } from 'rxjs/operators';

    // 最初の一回だけurlを取得する
    const navigationEndUrl = 
    await this.router.events
    .pipe(filter<NavigationEnd>(e => e instanceof NavigationEnd))
    .pipe(first())
    .toPromise();
```
MacとLinuxでdocker を使う際に嵌ったこと

# landscapeの構築について

landscape ：https://github.com/cncf/landscape というOSSを一覧で管理するソフトウェアをローカル環境に構築を行う際の出来事について記載する。
構築を社内のLinuxサーバでyarn コマンドでプロキシ を突破できない課題があった。
そのため、以下の2つの方針で行動を行った

1. 各個人が所有しているプライベートPCを用いてdocker で環境を構築
2. 社内Linuxサーバでyarnコマンドでプロキシを突破できるよに模索
		
私が所有しているPCはMacだっため、Mac上にdockerをインストールして、landscape の構築を行った。
その際、社内LinuxサーバとMacの環境を同じにしているにも関わらず、社内Linuxサーバで突破しているyarn によるサーバ起動コマンドでエラーを出力し、回避を行うことができなかった。

```	
root@c6f9ee4050c2:~/graphql-landscape# yo ※サーバ起動コマンド
Internal Error: Assertion failed: Expected workspace to have been resolved
at se.refreshWorkspaceDependencies (/root/landscapeapp/.yarn/releases/yarn-berry.js:31:175850)
at se.restoreInstallState (/root/landscapeapp/.yarn/releases/yarn-berry.js:31:200252)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async tt.execute (/root/landscapeapp/.yarn/releases/yarn-berry.js:71:88275)
at async tt.validateAndExecute (/root/landscapeapp/.yarn/releases/yarn-berry.js:25:318779)
at async e.run (/root/landscapeapp/.yarn/releases/yarn-berry.js:31:458286)
at async e.runExit (/root/landscapeapp/.yarn/releases/yarn-berry.js:31:458420)
```	

構成は以下である

|  社内Linuxサーバ |  Mac  |
| ---- | ---- |
|  landscape  |  landscape  |
|  Ubuntu  |  Ubuntu  |
|  docker  |  docker  |
|  Ubuntu(Host OS)  |  Mac(Host OS)  |
	
docker のコンテナはホストOSに依存しない仮想化技術であるる認識であった。しかし、dockerのコンテナはホストOSとカーネルを共有するため、ホストOSに依存したソフトウェアである。そのため、前述のエラーが発生したと思われる。
ホストOSに依存しない仮想化技術を用いるなら、VMによる構築を行うべきであった(VM ware/VirtualBox 等)。
しかし、VMの場合でもアーキテクチャには依存する(CPU(Intel, AMD, 32bit/64bit), ハードウェアの構成)可能性があることから、留意すべきである。
【Rspec Capybara】confirmダイアログが2回表示されるsystem specを書く


### やり方

<br>

単純にダイアログの回数分、

**accept_confirm** をネストすればOK。

<br>

```
# 1回目のダイアログ
page.accept_confirm do

  # 2回目のダイアログ
  page.accept_confirm do

    # ダイアログが全てOKなら実施したい何らかの処理
    first('div[data-cell="sample"]>div>form>button').click
  end
end
```

<br>
<br>
<br>

- accept_confirmリファレンス

[https://www.rubydoc.info/github/jnicklas/capybara/Capybara%2FSession:accept_confirm:embed:cite]

<br>
<br>
<br>
EKS で node とそれが載っている nodegroup 一覧を得る方法

後続のためのメモ。EKS の (Managed Nodegroup で作られた)ノードには自動で nodegroup-name というラベルが付与されている

```
$ kubectl describe nodes/ip-10-173-30-116.ap-northeast-1.compute.internal
Name:               ip-10-173-30-116.ap-northeast-1.compute.internal
Roles:              <none>
Labels:             beta.kubernetes.io/arch=amd64
                    beta.kubernetes.io/instance-type=m5.large
                    beta.kubernetes.io/os=linux
                    cluster-name=my-cluster
                    eks.amazonaws.com/nodegroup=my-nodegroup
                    eks.amazonaws.com/nodegroup-image=ami-04574e0c4fb2f03fc
                    failure-domain.beta.kubernetes.io/region=ap-northeast-1
                    failure-domain.beta.kubernetes.io/zone=ap-northeast-1a
                    kubernetes.io/arch=amd64
                    kubernetes.io/hostname=ip-10-173-30-116.ap-northeast-1.compute.internal
                    kubernetes.io/os=linux
                    nodegroup-name=my-nodegroup
```

なので kubectl get nodes に -L nodegroup-name を付けてそのラベルも出力してあげれば一覧を取れる

```
$ kubectl get nodes -L nodegroup-name
NAME                                               STATUS   ROLES    AGE   VERSION                NODEGROUP-NAME
ip-10-173-30-116.ap-northeast-1.compute.internal   Ready    <none>   61d   v1.16.12-eks-904af05   my-nodegroup
ip-10-173-35-117.ap-northeast-1.compute.internal   Ready    <none>   15h   v1.16.12-eks-904af05   my-nodegroup
ip-10-173-57-100.ap-northeast-1.compute.internal   Ready    <none>   11h   v1.16.12-eks-904af05   another-nodegroup
```

なお、GKEの場合はノード名がノードプール名からそれっぽく自動生成されるため、ノード名だけ見れば大体わかる。こういう機能が欲しいと思ったこと自体がない。
30代からのプログラミング勉強　3日目

仕事が休みだった事もあり専属メンター(身内)によるPythonアプリケーション講座...の予定だったもののほぼほぼ環境構築で終了。

## 学習内容

### ターミナルの活用方法

```shell:現在地
$ pwd
```

```shell:移動
$ cd ○○○○
```

```shell:現在地のファイル一覧
$ ls
```

他にも事前に環境出来てればpipenv shellで仮想環境に入れるとかあったけどあまり理解は出来てない。要学習。

### HTML/CSS

Udemyにて。

```html:CSSの内部参照
<style>
  p{font-size: 20px;}
</style>

※headの中に書き込むことにより対応したタグのスタイルを一括で設定できる。
```

```html:CSSの外部参照
<link rel="stylesheet" href="ファイル名">
    
※headの中に書き込むことにより外部のCSSを引っ張ってこれる。同一ページ内に記載されないのでコードが見やすくなる。
```

上記二つを併記した場合は下に書いてある方が後に実行されるため優先されて表示される。

一行だけスタイルを変えたい場合は一番最後に実行されるようにインラインで書く。
【Ruby】puts / printの違い

# Rubyで使うputsとprintの違い

結論、改行がされるかされないか。
printは改行されず、putsは改行される。

## 記述方法
```first.rb
puts "Hello World" #改行あり
puts "Hello World" #改行あり

```

## 実行結果
```
% ruby first.rb
Hello World
Hello World
```

## printの記述方法
```second.rb
print "Hello World" #改行なし
print "Hello World" #改行なし
```

## 実行結果
```
% ruby second.rb
Hello WorldHello World
```
【超シンプル】Gitで作業中の変更情報を一時避難する方法【stash】

<br>
**「緊急で対応しないといけない仕事ができた！ブランチを切り替えないといけない！でも今作業してるところで、まだコミット前の作業が残ってる。。。」**

そんな時に便利なGitのコマンド **stash** について解説！実務でも使用する場面があるかもなので、まだ知らない方は必見！早速いきましょう！
<br>
<br>


## stash
stashとは、ワーキングツリーやステージングエリアとは別の領域の事で、例えばワーキングツリーで変更した内容や、ステージングエリアに移動させた変更情報を、一時的に避難させる事(保存と同じような事)ができる領域になります。

<br>

ここでは主に、

<ul>
  <li>stashへの避難のコマンド</li>
  <li>stashした情報の確認コマンド</li>
  <li>stashした情報の復元コマンド</li>
  <li>stashした情報の削除コマンド</li>
</ul>
これらを解説していきます。
<br>
<br>

### save
まずはstash領域に、現在のワーキングツリーの変更情報と、ステージングエリアに移動した情報を、避難させる方法です。コマンドはこちら。

```html
$ git stash save
```
このコマンドを行うと、作業しているリポジトリ内が最新のコミットの状態に戻ります。その為、ワーキングツリーやステージングエリアの情報を気にせず、安心してブランチの切り替えを行うことができます。

<br>

また、saveコマンドは省略して、以下のように書く事も可能です。

```html
$ git stash
```
どちらを使用しても動作自体は変わりません。
<br>
<br>

### list
次にstashエリアに避難させた情報を、リストで表示して確認する方法です。コマンドはこちら。

```html
$ git stash list
```
これは復元したい時に、スタッシュ名が必要になりますので、それの確認などに使用します。またstash情報が複数ある場合も、これで確認することができます。
<br>
<br>

### apply
次にstashエリアに避難させた情報を、復元する方法です。コマンドはこちら。

```html
<!-- スタッシュ名が *stash@{1}* のワーキングツリー情報を復元 -->
$ git stash apply stash@{1}
```
このコマンドは、ワーキングツリーの情報のみの復元コマンドになります。その為、ステージングエリアの情報までは復元されません。

<br>

もし、ステージングエリアも含めて復元したい場合のコマンドはこちら。

```html
<!-- スタッシュ名が *stash@{1}* のワーキングツリー情報とステージングエリア情報を復元 -->
$ git stash apply --index stash@{1}
```
こちらのコマンであれば、ワーキングツリー情報に加え、ステージングエリア情報も復元することができます。
<br>
<br>

### drop
最後にstashエリアに避難させた情報を、stashエリアから削除する方法です。コマンドはこちら。

```html
<!-- スタッシュ名が *stash@{1}* のワーキングツリー情報とステージングエリア情報を削除 -->
$ git stash drop stash@{1}
```
stashエリアは、あくまでも作業を一時避難させる為のエリアです。そのため、stashエリアに情報を残しておくのは、あまり得策とは言えません。

もし復元が終わり、不要になったstashエリアの情報は、その都度消していくようにしましょう。

<br>

また、stashエリアに存在する全てのスタッシュを削除する場合のコマンドはこちら。

```html
$ git stash clear
```
これでstashエリアが、まっさらな状態になります。
<br>
<br>
<br>

## まとめ
Gitの使い方は、stashに限らず複雑に見られることが多いですが、蓋を開けてみたら今回のように、非常にシンプルと言うことが多いです。またstashコマンドは実務でも使用する機会があるかもしれないので、頭の片隅にでも覚えておくと、役に立つかもしれません。ぜひ習得してみてください！

最後までご覧いただき、ありがとうございました！

<br>
<br>
<br>

筆者：yuki｜学習10日目で初案件獲得→現在はフルスタックエンジニア転職に向けて学習中
Qiita：https://qiita.com/yuki4839
Twitter：https://twitter.com/yuki35522891
Serverless Frameworkを使用して AWS Lambdaにデプロイ

## 環境
* Mac OS Catalina 10.15.7
* AWS Lambda
* Serverless Framework standalone (
    * Framework Core: 2.11.1 (standalone)
    * Plugin: 4.1.2
    * SDK: 2.3.2
    * Components: 3.3.0

## Serverless Framework スタンドアロンのインストール
nodeのバージョン依存に関係なく使用するため、npmでのインストールではなくスタンドアロンを使用した
[Get started with Serverless Framework Open Source & AWS](https://www.serverless.com/framework/docs/getting-started/) に記載の通り

```
curl -o- -L https://slss.io/install | bash
```


## AWSのクレデンシャルの設定

[AWS - Credentials](https://www.serverless.com/framework/docs/providers/aws/guide/credentials/)を参考にCredentialを作成し、それをローカルに適用する.
適用の方法はいくつかあるが、環境変数に設定する方法で対応した



```
sls plugin install -n serverless-python-requirements
```

## serverless.ymlを作成

```
service: funcname

plugins:
  - serverless-python-requirements
package:
  individually: true
  exclude:
    - package.json
    - package-lock.json
    - ./**

custom:
  pythonRequirements:
    usePipenv: false
    dockerizePip: true

provider:
  name: aws
  runtime: python3.8
  stage: dev
  region: ap-northeast-1

functions:
  fnc:
    runtime: python3.8
    handler: funcname.handler
    package:
      include:
        - "src/*.py"
```
### dockerize Trueの場合

Dockerのインストールが必要なので、Dockerをインストールする -> [参考](https://qiita.com/nemui_/items/ed753f6b2eb9960845f7)

## packageのインストール

必要なパッケージをインストールする

### serverless-python-requirements

[serverless-python-requirements](https://www.serverless.com/plugins/serverless-python-requirements) はpythonの依存パッケージをインストールするための仕組み
```serverless.yml``` と共にrequirements.txtを配置しておくと依存パッケージをまとめてLambdaにアップロードしてくれる

```
sls plugin install -n serverless-python-requirements
```

## AWS Lambdaにデプロイ

```
sls deploy -v
# -v:ログの詳細表示
```


## AWS Lambda削除

```
sls remove -v
```


### 参考

[qiita-Serverless FrameworkでAWS Lambdaをデプロイ](https://qiita.com/t_okkan/items/6843afba84d684068341)
KeycloakのFAPI-SIGについて

日立製作所　中村　雄一

OpenID Foundationで策定が進むプロファイルである「Financial-grade API(FAPI)」へのKeycloakの対応のための開発を筆者のチームで進めています。昨年度の活動状況は[こちらの記事](https://qiita.com/yuichi-nakamura/items/53b35a9cbaf663fab441)に紹介しています。その後、Keycloakコミュニティの中でもFAPI対応への関心が高まり、日立の [乗松さん]( https://github.com/tnorimat)を技術リーダーとしてFAPI-SIG(Special Interest Group)が立ち上がりました。Keycloakコミュニティでは初となるSIGとなります。本記事ではFAPI-SIGを紹介します。

### FAPI-SIGの活動概要
 FAPI-SIGの活動は、GithubのKeycloak Project配下の、[kc-sig-fapiリポジトリ]( https://github.com/keycloak/kc-sig-fapi)で実施されています。活動状況はオープンで、Projectタブを見ると開発の進捗もわかるようになっています。記事執筆現在、FAPI Certificationの取得に向けた活動、CIBAの対応のための開発、Client Policyのエンハンス、が行われています。

### FAPI Certificationの取得
OpenID FoundationのFAPI Conformance Testをパスし、FAPI Certificationの取得を目的として、テスト環境の整備と自動化のための試みが行われています。テストの実行の仕方もkc-sig-fapiリポジトリのトップページに記載されています。記事執筆時点で、Conformance Testを開発環境でパスすることができるようになっています。

### CIBAへの対応
 OAuthのフローの中で認証デバイスを分離する規格である、FAPIのCIBA(Client Initiated Backchannel Authentication)プロファイルへの対応を目的としたプロジェクトです。開発規模が大きくなるため、[作業リポジトリ]( https://github.com/tnorimat/keycloak/)を設け、5人ほどの開発者によって分担して開発が順調に進んでいます。

### Client Policyのエンハンス
 KeycloakがFAPIに対応した機能を備えたとしても、設定・運用面で問題があります。例えば、KeycloakをFAPI用に設定しようとする場合、従来のKeycloakでは、全部のクライアントに対してFAPIが設定されてしまいますので、FAPIを使いたくないクライアントがある場合に困ります。またFAPIを設定する場合も設定項目が膨大で設定が大変です。
　このような問題を解決するために、Client Policyというクライアント単位の設定のためのフレームワークが乗松さんを中心に開発され、Keycloak 12より取り込まれています。本フレームワークの概要については、[こちらの講演資料](https://www.slideshare.net/ssuserbeb7c0/css2020-client-policies-on-keycloak)を参照ください。このClient PolicyはKeycloak 12では隠し機能の状態であり、これを使えるようにするためのREST APIや画面の整備、またClient Policyの設定部品の整備も進められています。

### 参加するには
 FAPIの仕様は日々エンハンスされていますので、Keycloak側でも継続な対応が必要になってきますので、開発協力者が常に求められる状況にあります。開発に興味がある方は、[kc-sig-fapiリポジトリ]( https://github.com/keycloak/kc-sig-fapi)のIssueをウォッチし、自分でも手を上げられそうなものに参加するとよいでしょう。また、Web会議の予定と議事録も[FAPI-SIGディレクトリ](https://github.com/keycloak/kc-sig-fapi/tree/master/FAPI-SIG)で公開されており、Web会議に参加し議論することもできます。
【@デコレータ使用篇】Pythonの関数を辞書（dict）のValueに格納して、Keyに応じた関数を呼出す


__前回__の__記事[「Pythonの関数を辞書（dict）のValueに格納して、Keyに応じた関数呼出しをする方法」](https://qiita.com/Afo_guard_enthusiast/items/3d6d1c7398f6cfef05c5)__の続編です。

###（ 参考にした書籍 ）
__（書籍）Julien Danjou（著）『Python ハッカーガイドブック』*pp.142-143*__所収のサンプルコードを拡張しました。

```Python3:iPython(Python3.9.0)
functions_dict = {}

def register(f):
	global functions_dict
    functions_dict[f.__name__] = f
    return f 

@register
def sample_func1():
	return 'bar'

print(functions_dict['sample_func1'])
# 実行結果
<function sample_func1 at 0x1085bf940>

print(functions_dict['sample_func1']())
# 実行結果
bar

@register
def sample_func2():
	return 'foo'

print(functions_dict)
# 実行結果
{'sample_func1': <function sample_func1 at 0x1085bf940>, 'sample_func2': <function sample_func2 at 0x10843b550>}

print(functions_dict['sample_func2']())
# 実行結果
foo
```

---

###（ 参考 ）関数オブジェクト.__name__で関数名を*str*型で取り出すことができる

```Python3:iPython(Python3.9.0)
def sample_func1():
    return 'bar'

```

###関数名.__name__で、関数の名称を*str*型オブジェクトとして取得できる。

```Python3:iPython(Python3.9.0)
print(sample_func1.__name__)
# 実行結果
sample_func1

print(type(sample_func1.__name__))
# 実行結果
<class 'str'>

```
---

###以下はエラー

辞書オブジェクト[Key名]はエラー。
辞書オブジェクト['Key名']はOK。Keyは*str*型オブジェクトを渡す必要があります。

```Python3:iPython(Python3.9.0)
print(type(sample_func1.__name__))
# 実行結果
<class 'str'>

print(functions_dict[sample_func1])
# 実行結果
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-63-32923bc8e62e> in <module>
----> 1 print(functions_dict[sample_func1])

KeyError: <function sample_func1 at 0x1085bf940>

In [64]: print(functions_dict[sample_func1]())
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-64-af09e15405cf> in <module>
----> 1 print(functions_dict[sample_func1]())

KeyError: <function sample_func1 at 0x1085bf940>
```
ホスティングサービスNetlifyでWebサイトをラクラク公開！　(備忘録)


個人的に制作したWebサイトを公開したいと思い、いろいろホスティングサービスを探していました。そこで**Netlify**という簡単に公開できるサービスを見つけたので使い方を備忘録として残します。
（筆者はWeb系初心者です）

2020年11月27日現在の方法です。

#手順
###Netlifyのサイトにアクセス&アカウント作成
こちらからサイトにアクセスして、アカウントを作成します。
https://www.netlify.com/

画面右上の**Sign up**を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/f65a9e3e-d934-54d8-f6b0-cda3f01804f5.png)

アカウントはどのように作成するか選択画面が開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/22e307e9-56a7-360c-67b3-db04c8ecaa07.png)

以降は連携したいサービスまたはメールを選択してアカウント情報を入力します。

###ホスティング
ログインできると次のような画面となります。**Sites**の箇所に公開したいWebページをフォルダごとドラッグ&ドロップしてアップロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/678c645b-7656-bcea-f5be-97a3e4fd0fc0.png)

アップロードが完了すると次のような画面となります。左上に「https://～」とあるURLをブラウザで開くと、アップロードしたWebサイトにアクセスできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/ec661fcb-e55c-009f-64a4-59f8e88d6d81.png)


###ドメイン設定
このままだとドメインがランダムなので、固定にします。
URLが表示されているあたりに「**Domain settings**」とあるのでこれを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/787cd509-bb4d-6fe5-c13a-b23beced501a.png)

次に**Custom domains**の**Options**->**Edit site name**を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/591b1c53-aeb2-6a23-e7a3-d65d2486f52f.png)

**Site name**に設定したドメイン名を入力します。入力したらSaveします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/59ba9f8b-1c79-1a29-6a2b-0882048b66dc.png)

先程Webサイトン公開したURLが設定したドメインに変わっていれば完了です。
【Salesforce】承認プロセスで複数の承認者を設定した場合の不具合について

#承認プロセスで複数承認者を設定
　Salesforceの承認プロセスについてです。
　承認者には、特定のユーザ、キュー、特定の項目に設定されている値のユーザなどが設定可能ですが、
　誰が承認したらステップを進めるか？という点について下記の２つの設定方法が挙げられます。

　①承認者に設定されたいずれか１名のユーザが承認をした場合
　②承認者に設定された全てのユーザが承認をした場合

　今回は②のパターンについて筆者が遭遇した問題について記載します。

#複数の承認者が全員承認する必要がある場合の問題点
　複数承認者を指定している承認プロセスでは、承認申請が行われたタイミングで、
　承認履歴の関連リストに下記のような表示のされ方をします。
　①
　ステップ名　｜　日付　　　　　　　　　｜　状況　｜　割り当て先　　｜　承認者　｜　コメント
　〇〇申請　　｜　２０２０／１１／２０ ｜ 未承認 ｜　XXXXXXXXXXX　｜　Ａさん　｜
　〇〇申請　　｜　２０２０／１１／２０ ｜ 未承認 ｜　XXXXXXXXXXX　｜　Ｂさん　｜



　この状態からAさんのみ承認を行った場合、下記のようになります。
　②
　ステップ名　｜　日付　　　　　　　　　｜　状況　｜　割り当て先　　｜　承認者　｜　コメント
　〇〇申請　　｜　２０２０／１１／２０ ｜ 承認済 ｜　XXXXXXXXXXX　｜　Ａさん　｜　承認します。
　〇〇申請　　｜　２０２０／１１／２０ ｜ 未承認 ｜　XXXXXXXXXXX　｜　Ｂさん　｜ 


　Bさんまで承認が完了すれば、下記のような形で、次のステップに進む仕様です。
　③
　ステップ名　｜　日付　　　　　　　　　｜　状況　｜　割り当て先　　｜　承認者　｜　コメント
　〇〇申請　　｜　２０２０／１１／２０ ｜ 未承認 ｜　XXXXXXXXXXX　｜　Ⅽさん　｜
　〇〇申請　　｜　２０２０／１１／２０ ｜ 承認済 ｜　XXXXXXXXXXX　｜　Ａさん　｜　承認します。
　〇〇申請　　｜　２０２０／１１／２０ ｜ 承認済 ｜　XXXXXXXXXXX　｜　Ｂさん　｜ 承認します。



　今回直面した問題はこの後にあります。
　この状態でCさんが却下した場合には、下記の通り、Aさん、Bさん２名の承認待ちになるところまでは想定通りの動作です。
　④
　ステップ名　｜　日付　　　　　　　　　｜　状況　｜　割り当て先　　｜　承認者　｜　コメント
　〇〇申請　　｜　２０２０／１１／２０ ｜ 未承認 ｜　XXXXXXXXXXX　｜　Ａさん　｜
　〇〇申請　　｜　２０２０／１１／２０ ｜ 未承認 ｜　XXXXXXXXXXX　｜　Ｂさん　｜



　この状態からAさん、Bさんいずれか１名の承認を行った段階で下記のとおり次のステップが進んでしまう現象が発生しました。
　本来は却下後も２名の承認が完了するまでは次の承認ステップに進まないのがあるべき姿です。
　⑤
　ステップ名　｜　日付　　　　　　　　　｜　状況　｜　割り当て先　　｜　承認者　｜　コメント
　〇〇申請　　｜　２０２０／１１／２０ ｜ 未承認 ｜　XXXXXXXXXXX　｜　Ⅽさん　｜
　〇〇申請　　｜　２０２０／１１／２０ ｜ 承認済 ｜　XXXXXXXXXXX　｜　Ａさん　｜　承認します。
　〇〇申請　　｜　２０２０／１１／２０ ｜ 無回答 ｜　XXXXXXXXXXX　｜　Ｂさん　｜ 　


#検証
　この状態になってから下記のことを試しました。
　Salesforceへの問合せを行い、下記の方法を試した結果です。

　・別のレコードで再実施してみる。
　　⇒　再現

　・承認者に別のキューを割り当ててみる
　　⇒　再現

　・別環境を用意して、同じ承認プロセスを再度作成
　　⇒　再現せず

　・承認プロセス自体をコピーして作り直す
　　⇒　再現せず

#結論
　Salesforce側でも当現象の根本的な原因はつかめず、プロセスの作り直しによる解決をとることしかできませんでした。
　ただ同じような事例は過去にもあったようで、環境をSFサポートに開放して調べて頂いた調査結果として
　「現状対象の承認プロセス特有の事象であるかとお見受けしております。」との回答を頂きました。
　私個人の意見ではありますが、特定条件下でのみ発生するバグの一種ではを推測しています。

　もし同じような事象を目にすることがあれば、作り直しによる解決も可能ではありますが、
　是非SFサポートとの連携で根本的な原因を確認して頂ければと思います。
【Salesforce】Lightningでの新規登録画面の初期値設定について注意点

#Lightning環境化での標準画面への初期値設定についての注意点

　Lightning環境でも新規登録画面遷移時にURLパラメータで初期値をプリセットすることができるようになりました。
　詳しい内容については他のエンジニアさんも載せているので、そちらをご参照ください。

　今回はそれらを実装する際の落とし穴を紹介します。
　※意外と触れられておらず、筆者も詰まった箇所なので参考になれば幸いです。



#レコードタイプの指定時に大文字小文字に注意する
　
　ClassicではURL上で「RecordType=[レコードタイプID]」と指定することで初期値を設定できました。
　Lightning版では「recordTypeId=[レコードタイプID]」と指定することで初期値を設定できます。

　ここで注意すべきなのは「recordTypeId」の記述の仕方についてです。
　「RecordTypeId」「recordTypeID」「RecordTypeID」「recordTypeid」などでは正常に動作しません。
　
　必ず大文字小文字を守って「recordTypeId」と指定してください。
　※筆者はこれで数時間悩みました。

　あまりこの大文字小文字について触れているエンジニアさんがおらず、
　また大文字小文字を誤った状態で載せている方もいらしたので、自身と同じ詰まり方をする方が少しでも減ってくれればと考えています。


#参照系の項目について
　
　Classicの時には、参照・主従系の項目に対して初期値を設定する場合は、対象の１つの項目に対して
　「Name」「Id」の両方を設定する必要がありました。

　例）
　　CFXXXXXXXXXXXXXXXXX={!Account.Name}&CFXXXXXXXXXXXXXXXXX_lkid={!Account.Id}

　Lightningでは、対象の項目に対して「Id」のみを指定することで初期値が設定可能です。

　例）
　　myObject__c.Account__c={!Account.Id}
　

#標準ボタンの動作と若干異なる？

　検証した結果、下記の通りとなりました。

　・標準の新規ボタンの動作
　　Aオブジェクトの関連リストから新規ボタン押下　⇒　Bオブジェクトレコードの新規登録画面　⇒　保存　⇒　Aオブジェクトの詳細画面に遷移

　・カスタムの新規ボタンの動作
　　Aオブジェクトの関連リストからカスタムの新規ボタン押下　⇒　Bオブジェクトレコードの新規登録画面　⇒　保存　⇒　Bオブジェクトの詳細画面に遷移

　標準のボタンではClassicにおける「saveURL=」に該当する何かが設定されているものを推測されますが、
　Lightningにおける「saveURL」に相当するものが調査しても見つけられず、表示された「保存」ボタンの動作依存になっている状況です。


#最後に
　初期値設定のボタンは意外と利用頻度の高い内容など思いますので、何かの参考になれば幸いです。
　また継続して検証や調査はしますので、続報があればまた投稿します。
Two ways to trigger event in react component.

###Extend react.Component class
1.   Use bind(this)

```tsx
import * as React from 'react';

export interface TempProps {
    title: string;
    onButtonClick: (v: string) => void;
}

export class TempComponent extends React.Component<TempProps> {
    public componentDidMount() {
        this.handleOnButtonClick = this.handleOnButtonClick.bind(this);
    }

    public render() {
        return (
            <div>
                <button onClick={this.handleOnButtonClick}>aaaa</button>
            </div>
        );
    }
    private handleOnButtonClick() {
        this.props.onButtonClick(this.props.title);
    }
}
```
2.Use arrow method()=>{}

```tsx
import * as React from 'react';

export interface TempProps {
    title: string;
    onButtonClick: (v: string) => void;
}

export class TempComponent extends React.Component<TempProps> {

    public render() {
        return (
            <div>
                <button onClick={_ => this.handleOnButtonClick()}>aaaa</button>
            </div>
        );
    }

    private handleOnButtonClick() {
        this.props.onButtonClick(this.props.title);
    }
}
```


### Use hook

2. Use arrow method

```tsx

import * as React from 'react';

export interface TempProps {
    title: string;
    onButtonClick: (v: string) => void;
}

export const TempComponent: React.FC<TempProps> = ({ title, onButtonClick }) => {
    const handleOnButtonClick = () => {
        onButtonClick(title);
    };

    return (
        <div>
            <button onClick={handleOnButtonClick}>aaaa</button>
        </div>
    );
};
```

2.Without using bing this, it also works in react hook.

```tsx

import * as React from 'react';

export interface TempProps {
    title: string;
    onButtonClick: (v: string) => void;
}

export const TempComponent: React.FC<TempProps> = ({ title, onButtonClick }) => {
    function handleOnButtonClick() {
        onButtonClick(title);
    };

    return (
        <div>
            <button onClick={handleOnButtonClick}>aaaa</button>
        </div>
    );
};
```
惰滅のサーバ

#  紅蓮禍

強くなれるモジュールを知った　mod_proxy_balancerを連れて進め

負荷だらけのApacheに酔う　こわばる心
1台構成では捌けないものがある　それだけさ
Nagiosのアラートに空睨んでも
変わっていけるのは冗長構成だけ　それだけさ

強くなれるモジュールを知った　mod_proxy_balancerを連れて進め

どうしたって！
消せないアラートも　止まれないサーバも
ユーザのために強くなれるなら
ありがとう　Connection timeoutよ
トラフィックに打ちのめされて負ける意味を知った
紅蓮のアラートよ咲き誇らないで！　運命を照らして

ApacheBenchの雑音が耳を刺す　戸惑う心
負荷分散だけじゃ守れないものがある？　わかってるけど
ステージング環境で絡まる負荷テスト　成功して見える結果に感動
逸材のF5より　挑み続け咲いたLBが美しい

乱暴に敷き詰められた　クソだらけのコードも
本気の僕だけに現れるから　乗り越えてみせるよ
簡単に片付けられた　通らなかった稟議も
無償のApacheに根を生やし　このモジュールに宿ってる

人知れずローンチ　散りゆく結末
無情に破れた　悲鳴の風吹く
ユーザの笑う影　PMの泣き声
誰もが幸せを願ってる

ほんばんで！
消せないアラートも　止まれないサーバも
ユーザのために強くなれるなら
ありがとう　Proxy timeoutよ
トラフィックに打ちのめされて負ける意味を知った
紅蓮のアラートよ咲き誇らないで！　運命を照らして

----
----
----

# ステージングの負荷テストはうまくいったのだからそれで十分だろう

サーバ1台でApache+Tomcatで動くJavaアプリケーションを運用していたのですが、1台ではピークトラフィックを耐えることができなかったので、サーバを1台追加し、Apacheにmod_proxy_balancerを入れてLBにし、2台の冗長構成にすることにしました。

構成を組んだあと、ApacheBenchで負荷テストをして、その結果が問題なかったので負荷テストも問題なしとし、本番ローンチに進むことに。

# 死んだApacheが蘇ることはないのだ

本番ローンチした結果、パフォーマンス改善どころかむしろ以前より悪化しており、Nagiosの管理画面はアラートで紅蓮に染まりました。

# 殆どの人間がそうしている

ApacheBenchの結果ではなぜか全てのトラフィックを正常終了としていたのですが、実際には殆ど捌き切れておらず、負荷をかけているときにブラウザでアクセスするとレスポンスが返ってこず、最後に502 Gateway timeoutになる始末でした。

冗長構成が組めて、数回ApacheBenchを実行してその結果が良かっただけで満足してしまい、ログの確認や高負荷状態のサーバのモニタリングなど何も確認していなかったのがすべての元凶です。

また、そもそもApacheBenchでは１種類のリクエストしかテストできないので、負荷テストツールとしては不十分でした。Jmeterなど、現実に近い複数リクエストのトラフィックを起こすツールを使ってでの負荷テストじゃないと意味は薄いです。

# なぜお前たちはそうしない

理由は一つ

私たちが異常者・・・ではなく怠惰だからです

![Dyc5BL3UwAAzSE7.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21645/623c4bfc-5a72-8ca9-259f-b50f1b11c897.jpeg)
werckerでエラー「You have reached your pull rate limit.」

# 背景
会社で使用しているデプロイ用で使っている無料CIの中でwerckerがあります。無料なのでちょっと不便なところやトリガーが動かない等の問題点も有りましたが使い続けていました。

最近になって以下のエラーが出る頻度が多くて困りまして、調査＆対応を纏めて見ました。

# エラー
エラー内容は以下のような物でした。

```
fetch failed to pull image *****: API error (500): {"message":"toomanyrequests: You have reached your pull rate limit. You may increase the limit by authenticating and upgrading: https://www.docker.com/increase-rate-limit"}
```
最初なんだこれ！！って感じでした。よくよく調べると認識してなかったですが、無料でPullする回数の制限が掛かったわけです。
参考：https://www.docker.com/blog/what-you-need-to-know-about-upcoming-docker-hub-rate-limiting/

# 制限
pull時のダウンロード比率の制限が11月2日から変更となったとのことです。

- 認証していない（anonymous ユーザ）場合は、100ダウンロード/6時間
- 認証している場合（Free アカウント）は 200 ダウンロード/6時間
- Docker Pro / Team 有償アカウントでログイン時は無制限

参考：https://www.docker.com/blog/scaling-docker-to-serve-millions-more-developers-network-egress/

# 確認
実際あっているか確認をして見ました。必要なツールは以下の二つが必要なので、インストールしてください。
- curl
- jq

参考：https://www.docker.com/blog/checking-your-current-docker-pull-rate-limits-and-status/

## 認証なし
こちらは基本IPで判断するらしいです。認証なし使用するTokenの取得します。

```
$ TOKEN=$(curl "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)
```

上記で取得したTokenを利用して現在使用率を確認します。

```
$ curl --head -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest 2>&1 | grep RateLimit

< RateLimit-Limit: 100;w=21600
< RateLimit-Remaining: 99;w=21600
```
RateLimit-Limit：最大Pull回数（６時間）
RateLimit-Limit：残りPull回数（６時間）

## 認証有り：無料ユーザー
こちらはアカウント別で管理されるようです。同じくTokenを取得します。

```
$ TOKEN=$(curl --user '{{username}}:{{password}}' "https://auth.docker.io/token?service=registry.docker.io&scope=repository:ratelimitpreview/test:pull" | jq -r .token)
```
上記の「{{username}}:{{password}}」のところ実際お持ちしているアカウント情報を入れてください。

上記で取得したTokenを利用して現在使用率を確認します。

```
$ curl --head -H "Authorization: Bearer $TOKEN" https://registry-1.docker.io/v2/ratelimitpreview/test/manifests/latest 2>&1 | grep RateLimit

< RateLimit-Limit: 200;w=21600
< RateLimit-Remaining: 197;w=21600
```

こんな感じで確認しました。

# Werckerの対応
デプロイ設定ファイルは以下の感じでした。

## 修正前

```
box: {{dockerイメージのID}}
no-response-timeout: 25
build:
  steps:
    - script:

    ・・・・・・・
```
見てみましょう！実際dockerhubからpullする際にアカウント情報がとこにもないです。結論としては**全ユーザーがwerckerで使用しているIP三つで100回ずつ３００回を使い分けている**感じですね。

確かにこれは大問題ですね〜〜〜

## 修正後
参考：https://devcenter.wercker.com/administration/containers/private-containers/

```
box:
  id: {{dockerイメージのID}}
  username: {{username}}
  password: {{password}}
  tag: latest
no-response-timeout: 25
build:
  steps:
    - script:

    ・・・・・・・
```
これで一応持っているアカウントの２００回をこの設定をしているプロジェクトのデプロイが使えることになります。。。。。本当かな？ どこにもそんな記事もないし。

## 確認方法
実際アカウントを設定に入れてwerckerによるデプロイが行った後に上記の「認証有り：無料ユーザー」を実行すれば「RateLimit-Remaining」が減って来るので確認できます。
RustでTwitterAPIを非同期に呼んでみる

# 目的
同時にTwitterAPIを呼んでみました。
Stackoverflowのカービーの回答を参考にしました。
[How can I perform parallel asynchronous HTTP GET requests with reqwest?](https://stackoverflow.com/questions/51044467/how-can-i-perform-parallel-asynchronous-http-get-requests-with-reqwest)
適当にピックアップしたツイートIDを非同期に取得してみます。

# プログラム
```rust:Cargo.toml
[package]
name = "tw"
version = "0.1.0"
edition = "2018"

[dependencies]
anyhow = "1.0.34"
futures = "0.3.8"
tokio = { version = "0.2.23", features = ["macros"] }
twapi-reqwest = "0.1.3"
```

```rust:main.rs
use anyhow::Result;
use futures::{stream, StreamExt};
use std::env;
use twapi_reqwest::*;

const PARALLEL_REQUESTS: usize = 10;

#[tokio::main]
async fn main() -> Result<()> {
    let consumer_key = env::var("CONSUMER_KEY").unwrap();
    let consumer_secret = env::var("CONSUMER_SECRET").unwrap();
    let access_key = env::var("ACCESS_KEY").unwrap();
    let access_secret = env::var("ACCESS_SECRET").unwrap();

    let ids: Vec<i64> = vec![
        1331969354494164996,
        1332080137202847744,
        1331999525309857793,
        1332074865323479041,
        1331960277269508096,
        1332078310726062080,
        1331945614947414016,
        1331938585126137856,
        1332067717176643584,
    ];

    let retweet_counts = stream::iter(ids)
        .map(|id| {
            let consumer_key = consumer_key.clone();
            let consumer_secret = consumer_secret.clone();
            let access_key = access_key.clone();
            let access_secret = access_secret.clone();
            tokio::spawn(async move {
                let url = "https://api.twitter.com/1.1/statuses/show.json";
                let id: &str = &id.to_string();
                let query_options = vec![("id", id)];
                v1::get(
                    url,
                    &query_options,
                    &consumer_key,
                    &consumer_secret,
                    &access_key,
                    &access_secret,
                )
                .await?
                .json::<serde_json::Value>()
                .await
                .and_then(|json| Ok(json["retweet_count"].as_i64().unwrap_or(0)))
            })
        })
        .buffer_unordered(PARALLEL_REQUESTS);

    retweet_counts
        .for_each(|retweet_count| async move {
            match retweet_count {
                Ok(Ok(retweet_count)) => println!("retweet_count {}", retweet_count),
                Ok(Err(e)) => eprintln!("Got a twapi::Error: {}", e),
                Err(e) => eprintln!("Got a tokio::JoinError: {}", e),
            }
        })
        .await;

    Ok(())
}
```
【TypeScript】Objectのkeyによってvalueの型を推論するテクニック

# :question: Problem
次の関数`changeValueByKey`ようにObjectのkeyによってvalueを変更する関数を**型安全に**作りたい！

```ts
type State = {
  text: string;
  isActive: boolean;
};

let state: State = {
  text: "",
  isActive: false
}

const changeText = (value: string) => {
  // OK
  state['text'] = value;
}

const changeIsActive = (value: boolean) => {
  // OK
  state['isActive'] = value;
}

const changeValueByKey = (key: 'text' | 'isActive', value: string | boolean) => {
  // Type Error
  state[key] = value;
}
```

# :star2: Solution
- こちらのStack Overflowを参考にしました
  - [Is there a valueof similar to keyof in TypeScript?](https://stackoverflow.com/questions/49285864/is-there-a-valueof-similar-to-keyof-in-typescript)

```ts
type State = {
  text: string;
  isActive: boolean;
};

let state: State = {
  text: "",
  isActive: false
}

const changeValueByKey = <K extends keyof State>(key: K, value: State[K]) => {
  state[key] = value;
}

// OK
changeValueByKey('text', 'test')
changeValueByKey('isActive', true)

// Type Error
changeValueByKey('text', true)
changeValueByKey('isActive', 'test')
```
- 解説
  - `keyof`を使うことでプロパティ名のtypeを参照することができます
  - `keyof State`でStateのプロパティ名を参照し、それを`extends`継承したtype`K`をGenericsとして用意します
  - 第一引数`key`はプロパティ名なのでそのまま`K`を使用し、第二引数`value`はStateのプロパティ`K`のvalueの型なので`State[K]`とします
  - これでkeyは`text | isActive`となり、keyを指定した時にvalueの型が決まるようになります
  - keyに`text`を指定した時にvalueは`State['text']`なので`string`に、`isActive`を指定した時にvalueは`State['isActive']`なので`boolean`しか渡せないようになりました
- 今すぐ動作を確認してみたい方はこちら
  - [TypeScript Playground Link](https://www.typescriptlang.org/play?#code/C4TwDgpgBAysCGxoF4oG8BQUpIB7AC4oBnYAJwEsA7AcwG4soLiBBAY2AoDcIiAjAPYCANhHhUGAXwYZRwEgiRE4iFOkZ5CUAETaANI2btOPIgDN4w4hAySMGNgKqkobABbiaEAGqWArhAAQiAA0hAgUKgAPCFQEPgQVAAmxFAA1uECZrCKEAB8ABQZIEQhelBc-rw5qgDaIQC6AJSReerYpHXFDZEVVVL2APSDUADyIQ4etD5VwWEgBQDkmovlyxCki02TnjPCAXPhS0Yc3BCrOGQB2xjDUAAq4NAAomRkAmQ70777QaFH63wF3I1y+Xh+B3+C0WJxM5zWSE22yAA)


TypeScriptに対応したEditorならサジェストも出ます
![スクリーンショット 2020-11-26 21.57.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178077/b6220615-a543-dda5-09fc-6a842463b6ae.png)


# :pencil: Demo
- Reactの`useState`にObjectを入れて実際に使ってみた時のサンプルはこちら
  - [Code Sandbox Demo: change object value type by key](https://codesandbox.io/s/demo-change-object-value-type-by-key-piz10?fontsize=14&hidenavigation=1&theme=dark&file=/src/App.tsx)


<p class="codepen" data-height="369" data-theme-id="dark" data-default-tab="js,result" data-user="mikan3rd" data-slug-hash="eYdYzgy" style="height: 369px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Demo: change object value type by key">
  <span>See the Pen <a href="https://codepen.io/mikan3rd/pen/eYdYzgy">
  Demo: change object value type by key</a> by mikan3rd (<a href="https://codepen.io/mikan3rd">@mikan3rd</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

↑ Code SandboxはQiitaに埋め込みできないようなのでCodePenを埋め込んであります
  （ただしCodePenではType Errorなどは出ません・・・）
SQLアンチパターン輪読会

#目的

- 書籍「SQLアンチパターン」を通してsql学ぶ
- リレーショナルDBとDBの設計について学ぶ


#一覧

- 第1回
- 第2回
- 第3回
- 第4回
- 第5回
- 第6回
- 第7回
- 第8回
Python3 PermissonError解決策


今回python３で簡易アプリケーションを作成後AWS　EC2でデプロイしようとした時に発生したエラーについて原因と解決策を書いてみました

* * *
## エラー内容

Djangoの管理サイトからPostsアプリケーションで投稿を行うと

![スクリーンショット 2020-11-27 7.29.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368036/54d26fa3-04b0-6682-dd99-396d6c789290.png)
PermissonError
![スクリーンショット 2020-11-27 6.41.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368036/39a352bd-d3af-7fb0-0cf7-4708694f510a.png)


* * *
## 原因

 [Filezilla](https://filezilla-project.org/ "Filezilla")を使用してローカルからサーバーへプロジェクトをアップロードする際に

```bash:
$sudo unzip [プロジェクト名].zip
```
としていたためrootがオーナーになっておりsudoをつけてroot権限で解凍してしまったのが原因で、サーバープロセスから書き込みが出来なくなっていた。

![スクリーンショット 2020-11-27 6.50.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368036/a0db1631-5867-3694-4a2e-0e49157e0a3d.png)

* * *

## 解決策１

アップロードしたプロジェクトを一回削除してsudoを使用せず、プロジェクトのzipファイルを解凍し直す方法

```bash:
$unzip [プロジェクト名].zip
```
sudoを使わないコマンドで実行すると一般ユーザーであるubuntuユーザーがオーナーとしてファイル群が生成される
* * *

## 解決策２

パーミッションを変更する方法

```bash:
$sudo chown -R ubuntu:ubuntu [プロジェクト名]
```

を実行することでオーナーを変更できる
シェルスクリプトで開発環境の自動構築

こんにちは. 今回はシェルスクリプトに軽く触れたので初心者向け&備忘録です．

# シェルスクリプトとは
OSを操作するためのシェル上で実行できる簡単ななプログラミング言語のこと．また、そのような言語によって書かれた、複数のOSコマンドや制御文などを組み合わせた簡易なプログラムを指します．一行がシェルにおける一行のコマンド入力に対応しており、複数のコマンド実行の流れをまとめて指定することができます．

# シェルとは？
シェルはOSと対話するためのインターフェースであり，コマンド等を制御する環境でもあります．
<img width="400" alt="shell.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266405/216bd3de-351c-7cd8-08c4-b6c1d85b7730.png">
上図のようにUbuntuの核となるカーネルを覆っている核がシェルだと考えるとわかりやすいです．
シェルやカーネルやターミナルの関係図は以下の図のようにあらわすことができます．
<img width="500" alt="tarminal.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266405/2662871b-3904-4b09-e681-07d5f49401cb.png">
シェルがあることでユーザーからのコマンドを受け付け，OSとの対話を可能とする．
シェルはコマンドを実行する際にカーネルが解釈可能な形へ変換し，カーネルは実行を行う．
この実行結果を私たちが私達が日頃ターミナルで見ているような形へ変換してくれるのもシェルなのである．
CUI環境においてシェルは最も身近なインターフェースの1つとなっています．
UbuntuをはじめとするLinuxのディストリビューションにおいて一般的なシェルに「bash」があります．
今回はこのbashを用いてやっていきます．

# 世界へこんにちは
世界へ挨拶するためのファイルを作成します．

```shell
#!/bin/bash

echo "Hello, World!"
```

シェルスクリプトのファイルは基本的に`.sh`の拡張子で作成します．
実際に動作させるコードの前に`#!/bin/bash`を書き，システムにこれはシェルスクリプトですよ～と知らせるものです．
単純にシェルスクリプトを実行させたい場合は`#!/bin/sh`でも構いません．

実行方法は，まずファイルを実行ファイルに変えます．

```
$ chmod 755 [ファイル名].sh
$ ./[ファイル名].sh
```

そして以下のどちらかのコマンドで実行できます．

```
$ sh [ファイル名].sh
```
```
$ bash [ファイル名].sh
```

ファイルを実行すると，`Hello, World!`と世界に挨拶できます.

# 環境構築
ターミナルで実行しているコマンド群を1つにまとめることができるため，今回はそれを用いて環境構築をしていきます．
今回はpythonとSQLiteデータベースの環境を自動構築したいと思います．

```shell
#!/bin/bash

sudo apt update
sudo apt upgrade
sudo apt install -y python3 python3-pip python python-pip build-essential libncursesw5-dev libgdbm-dev libc6-dev zlib1g-dev libsqlite3-dev tk-dev libssl-dev openssl libbz2-dev libreadline-dev sqlite3
python3 create_db.py
sudo apt autoremove
```

```create_db.py
import sqlite3

conn = sqlite3.connect([ファイル保存先パス])
curs = conn.cursor()
curs.execute("CREATE TABLE [テーブル名]([要素])")
conn.commit()
curs.close()
conn.close()

```

このように何度も行うような依存関係のインストールや別ファイルの実行などを書いてあげることが可能です．
さらに，システムでcronなどを用いて定期実行させたいという場合にもシェルスクリプトで書いてあげることが可能です．

```shell
#!/bin/bash

crontab -l > tempfile
echo "*/10 * * * * python3 hello_world.py" >> tempfile
crontab -u pi tempfile
sudo rm ./tempfile
```

一時的に今保存されているcronの状況をファイル出力させることで追記可能にしています．

# おわりに
シェルスクリプトをはじめてちゃんと触り，便利だな～と思いました(今更).
みなさんも是非使ってみましょう！

## 参考
[【1分でわかる】シェルスクリプトとは？](https://eng-entrance.com/linux-shellscript-what)
target="_blank"での別タブ表示は、実は危険！？

target="_blank"を用いて別タブ表示を実装しようと思い、色んな記事を見ていたのですが、
セキュリティ面とパフォーマンス面の2点で脆弱性があるとの記事を見かけたので、対策を実施。

```html:HTML
<a href="リンク" target="_blank" rel="noopener noreferrer">
```

noopenerと、noreferrerの2つを加えてあげれば対策になるようです。

noopener を指定することで、リンク先からwindow.openerを使ってリンク元が参照できなくなる。さらに、リンク先とリンク元が別のものとして扱われるためパフォーマンスに対しての対策にもなる。

しかし、ブラウザによっては、noopenerがサポートされていないため、noopenerと合わせてnoreffererを指定するのが好ましい。

noreffererを指定することで、リンク先にリンク元のリンク情報が送られないようになるため、 noopenerと同じくリンク先からの参照ができなくなる。

らしいです。


参考サイト
--
https://wwg.co.jp/blog/3807
Sorceryで複数モデルを扱う

## 2021/9/3　追記
複数モデルで`login`メソッドを利用する時のことを書いていなかったので追記

## Sorcery
https://github.com/Sorcery/sorcery

## How

例：　AdminモデルとUserモデルが存在して、両方でSorceryを使いたい場合
前提として、AdminかUserのどちらかでSorceryの導入が完了している

```ruby:users_controller
def current_user
  User.find_by(id: session[:user_id])
end
```

```ruby:config/initializer/sorcery.rb
config.user_class = 'Admin'
```

こうすると指定したcontroller内だけでcurrent_userの中身がuserになり、それ以外ではadminになる
controllerごとに`def current_user`を書くのも手間なので,個人的には階層を分けて`application_controller`内に書いている。
上記のuserとadminを逆にしてもいいので、あまり使わない方をcontrollerに指定するとよさそう

current_userがセットされているので、`before_action :require_login`も普通に動く

これだと呼ぶたびにSQLが走ってしまうので、viewなどで使う際には`@current_user = current_user`として`@current_user`を渡して使うこと。

## login
Sorceryを導入するモデルが増えると、`login`メソッドを使う際に困ると思う。

僕の場合は、Sorceryの`config.user_class`にしたモデルでは`login`メソッドをそのまま利用し、
それ以外では以下のようにsessionに書き込んでいた。

１からインクリメントしていくレコードのidを渡すと複数モデル間で絶対被るので注意

```ruby
session[:user_id] = @user.uuid
```

@motoyasu-yamada さんの書いてくれた記事に別の方法があるので、こちらも参照
https://qiita.com/motoyasu-yamada/items/9894195c40172bd43a0a

# 所感

Single Table Inheritanceを使うやり方もあるらしいがこっちがシンプル
[Power Automate] SharePoint list の item を全削除する


# はじめに

ファイル管理のために Power Automate を使ってみましたが、いろんな Q&A サイトやブログを検索しながらかなりの試行錯誤してしまったので、備忘録として調べた内容をまとめておきます。他に良い方法などあれば教えてください。

# SharePoint list の item を全削除する flow

まずは全体像から。[Get items](https://docs.microsoft.com/ja-jp/connectors/sharepointonline/#get-items) で list のアイテムを読み込んで、Apply to each で 1 つずつ [Delete Item](https://docs.microsoft.com/ja-jp/connectors/sharepointonline/#delete-item) で削除します。なんとなく効率が悪い気がするが・・。


![Capture1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/304df744-7782-ccb0-4473-0371bd5f476b.png)

# 変数定義（オプション）

削除した個数を後で確認できるように変数を定義するのも良し。削除されるたびに Increment variable で値を 1 ずつ増やすことにします。

![Capture2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/6f78e9f1-e3ca-c077-d7e2-4039f914832d.png)

# Get items

Site Address と List Name を指定するだけ。これはドロップダウンメニューで出てくるので簡単。それぞれ変数で定義することも可能。

![Capture3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/5f637139-40c2-c7de-817b-eb0dfdafa3dd.png)

## 最大取得可能数

どうやらデフォルトでは 100 までしか取得しないとの情報もあり。右上の [・・・] から Settings を選んで、Pagination を On にし、Threshold を設定します。5000 以上の値は設定できないとの情報もあり。

![Capture3-1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/dc8500d2-947c-ba33-4988-978abcb9b27f.png)


# Apply to each からの Delete item 

ここも Get items と同様、Site Address と List Name を指定する。Get item との設定違いが発生しないように、それぞれ変数で定義したほうが分かりやすいかも。また、value と ID を選択していますが、それぞれ Dynamic Content から選択するだけ。

![Capture4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149511/320d155c-60e3-5de2-4bcc-bbf92988dbc5.png)

処理が複雑になって Action 数が増えてくると Dynamics Content の一覧に表示が出てこない・・など発生することがありました。その時は Expression 側で設定も可能。例えば今回のケースだと value と ID はそれぞれ

また、value と ID を選択していますが、それぞれ Dynamic Content から選択するだけ。

```
outputs('Get_items')?['body/value']
items('Apply_to_each')?['ID']
```

() の中身は各アクションの名前、そして [] 内にプロパティ名を入れる感じです。

# 参考にしたサイト

- [Miscrosoft Doc: Get items](https://docs.microsoft.com/ja-jp/connectors/sharepointonline/#get-items)
- [Miscrosoft Doc: Delete Item](https://docs.microsoft.com/ja-jp/connectors/sharepointonline/#delete-item)
- [Microsoft Power Automate guides: How to delete all items from a list?](https://spblog.net/post/2020/02/20/microsoft-flow-guides-how-to-delete-all-items-from-a-list)
- [Microsoft Power Automate Community: Delete all items from a SharePoint list](https://powerusers.microsoft.com/t5/Building-Flows/Delete-all-items-from-a-SharePoint-list/td-p/450832)
- [How to get more than 5000 items from SharePoint Online in Flow](https://alextofan.com/2019/08/22/how-to-get-more-than-5000-item-from-sharepoint-online-in-flow/)