OmniAICreator/Qiita-1.07M huggingface dataset:
良い命名はwhatやwhyから作られるという話

コードレビューをしている時、コードとしては美しいのに読みにくいと感じたことがあり、毎回同じ指摘を書いているので、ちゃんと言語化してみたいと思います。


# 対象者
* 基本的なリーダブルコードをかける人
* その上でまだコードが読みにくいと感じている人
* 命名に困っている人

# ソースコードはhowしか教えない
前提として、ソースコード自体が教えてくれることはどうやって処理をしているかという`HOW`のみです。
例えば以下のコードをみてましょう。

```typescript
function createAndUpdate(user: User) {

    if(user.status == UserStatus.ONE) {
        createUser()
    }

    if(user.status == UserStatus.TWO) {
        updateUser()
    }
}
```

雑に書いていますが、ソースコードはユーザーのステータスを識別して作成処理、更新処理をぞれぞれしています。


但しこれで得られる情報は、ステータスがnだったらxをやるという処理の分岐のみで、なぜユーザーを作る必要があるのか？、そもそもこの関数はサービスとしてどういった処理なのか？といった`WHY(なぜこの処理が必要なのか？)`や`WHAT(何をやっているのか？)`を知ることはできません。

今回は短いコードがから良いですが、複雑な処理やデータアクセスも混ざると、それぞれの関数定義を行ったり来たりして、確認していかないと処理の概要がわからなくなります。

`HOW`だけのソースコードは、処理手順だけを教えるだけで意図は教えてくれないのです。

# WHATやWHYを含む書き方
では`WHAT`や`WHY`をどう表現するかというと変数や関数の命名です。

先程のサンプルコードの

* createAndUpdate
* createUser
* updateUser

などの`HOW`の内容をそのまま命名している関数をリファクタしてみたものがこちらになります。

```typescript
function contract(user: User) {

    if(user.isNoContract) {
        temporaryContract()
    }

    if(user.isTemporaryContract) {
        applyContract()
    }

}

```

関数名を全部サービスの業務名に置き換えました。
契約という処理があって、まだ契約をしていないなら、仮契約を、そうでなければ、本契約を結ぶという感じに業務的な名前に置換しました。

こうすると、上から順に目を通すだけで、契約の処理をしていて、契約有無の判定が必要であることが明確にソースコードをみただけでわかります。

また、生の値を比較していたenumの類は全てUserクラスに格納したので、ユーザーにどういった属性があるかなどの情報もコードから読み取れるようになりました。

# 終わりに
よくコードを書くときにソースコードの美しさだけに目を向けがちですが、チームで開発している場合は、関数や変数の命名の方にも目を向けて欲しいと思います。
【Vue.js】vue.jsでフォームを作成する。

##type number の入力フォーム

```vue
<template>
  <div>
    <input type="number" v-model.number="inputNumber" />
    {{ typeof inputNumber }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputNumber: 10,
    };
  },
};
</script>
```
v-modelにnumber修飾子をつけないと、inputNumberが変更した場合、型がStringになってしまう。

.number修飾子あり
![7f933e93f935ce966c9ece3714b53358.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/41ef055a-c43e-23e5-188e-32a220f4f885.gif)

.number修飾子なし
![4cc29e0a1a0e1586b9f8f7600eee1e1e.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/50f6a077-7815-071f-5d98-c5a90be59d7e.gif)

##単体のチェックボックス

```vue
<template>
  <div>
    <input type="checkbox" v-model="isPrivate" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      isPrivate: false,
    };
  },
};
</script>
```
単体のチェックボックスの場合、v-modelに与える値は、boolean型となる。

##複数のチェックボックス

```vue
<template>
  <div>
    <input type="checkbox" value="10" v-model="target" />
    <input type="checkbox" value="20" v-model="target" />
    <input type="checkbox" value="30" v-model="target" />
    <p>{{ target }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      target: [],
    };
  },
};
</script>

<style>
h1 {
  color: red;
}
</style>
```
複数のチェックボックスの場合、v-modelに与える値は、配列型となる。

##ラジオボタン

```vue
<template>
  <div>
    <input id="a" type="radio" value="a" v-model="target" />
    <label for="a">a</label>

    <input id="b" type="radio" value="b" v-model="target" />
    <label for="b">b</label>

    <p>{{ target }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      target: "a",
    };
  },
};
</script>

```
target に初期値を設定しておく。

##セレクトボックス

```vue
<template>
  <div>
    <select v-model="eventData.location">
      <option v-for="location in locations" :key="location">
        {{ location }}
      </option>
    </select>
    <p>{{ eventData.location }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      locations: ["東京", "大阪", "名古屋"],
      eventData: {
        location: "東京",
      },
    };
  },
};
</script>
```
v-modelにバインドする初期値を与える。
【Ｅｘｃｅｌ】列で重複しているものに印をつける

#やりたいこと
下図のように、列内で文字が重複しているものがあるときに、
重複しているものに何かしらの印をつけたい。

#方法
[1. 重複している部分に色を付ける](#1-重複している部分に色を付ける)
[2. 重複している部分の行頭にマークを付ける](#2-重複している部分の行頭にマークを付ける)

#今回使う表
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/e473013e-f77e-02cd-b169-b4b79d3bea0e.png)


## 1. 重複している部分に色を付ける
1. 重複をチェックしたい部分を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/b695b2dc-9eb7-343e-ceaa-c6512903e901.png)

2. ホームタブ＞条件付き書式＞新しいルール(N) の順にクリック
![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/f2d420c4-1b4c-3966-569b-b8e5ae939c15.png)

3. 「数式を使用して、書式設定するセルを決定」を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/1eb771ef-5fd4-5e3b-08e4-76ef29980fe3.png)

4. 下枠に下記の数式を記載する（重複を確認する範囲によって適宜変更してください。）
 =COUNTIF(\$B\$3:\$B\$7,B3)>1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/55991a42-58ff-c19e-de2f-b81f59cf32ad.png)

5. 「書式」ボタンをクリックして、つけたい印を選択する（今回は重複するセルをオレンジ色に塗ります。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/3cffbcb4-b77f-cd65-ddac-1e01dc6de4f4.png)

6. OKボタンをクリックすると、重複している部分がオレンジ色に塗られる 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/1143a8bc-977d-3454-4ffe-1d97229be582.png)

## 2. 重複している部分の行頭にマークを付ける
今回は重複する行の左列に●を付けることにします。
1. 左行に下記の数式を記載する（重複を確認する範囲によって適宜変更してください。）=IF(COUNTIF(\$B\$3:\$B\$7,B3)>1,"●","")
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/ba7c3f9b-7c27-99be-acde-1ca7182f174b.png)

2． 重複を確認するすべての行に適用させると、●がつく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877109/7a60701f-665d-3730-c0ab-c4bd753b3422.png)
郵便がポストに届いたらメールで通知がくるようにした

# はじめに

[郵便がポストに届いたら LINE で通知がくるようにした](https://qiita.com/task_jp/items/85ccc04a00982569f6c5) という記事の [今後の予定](https://qiita.com/task_jp/items/85ccc04a00982569f6c5#%E4%BB%8A%E5%BE%8C%E3%81%AE%E4%BA%88%E5%AE%9A) に書いた、SORACOM の「[IoT 体験キット 〜磁気センサー〜](https://soracom.jp/store/5237/)」を試してみました。

# やったこと

[SORACOM レシピ：IoTでドアの開閉モニタリング](https://soracom.jp/recipes_index/2966/) に書いてあることを一通りやりました。

ほんとそのままで、15分くらいでできました。

# つまったところ

ケーブルの接続ですが以下の公式の説明のように灰と赤を接続してもうんともすんとも言わなかったのですが、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/5b67a508-da05-369d-b1d1-2680379f6c53.png)
試しに **白と赤を接続** したところ、意図したとおりの動作になりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/6ddb68fe-4556-678b-dec2-b94c1fc4740c.png)
（原因や理由はよくわかってません）

# 設置

![mailbox2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/d682c263-0f61-9367-56d1-90cf95381e7f.gif)

（ケーブルはストローの中を適当に通しました）

# 郵便が届いた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/4f350f13-6576-191d-9008-b9ef423d2d17.png)

# おわりに

前回よりも簡単に同じ仕組みを作ることができました。

## 今回の方が良い点
- 構成がシンプルなので不具合が起きにくくてメンテナンスも楽
- 公式のチュートリアルを倣うだけで誰でもできる
- 郵便ポストと家の距離が遠くても機能する
- 乾電池の交換が簡単

## 今回の方が悪い点
- ポストの中がごちゃごちゃする(Twelite Cue が小さいので)
- ランニングコスト([利用料100円/月+通信料150円くらい？](https://soracom.jp/services/air/cellular/price_specific_area_sim/#plan-km1))がかかる
- 通信経路が多いためか、メールのせいか、前回の仕組みと比べると数十秒通知がとどくのが遅い

## 今後の予定
- ケーブルが無駄に長いので限りなくコンパクトにする

## 2021/03/03 追記
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/cb889cf8-c588-589f-90ef-41eadfa077b4.png)
基本料金が月100円で、通信料は無料利用枠内でした。
MacBook Pro(M1)でVirtualBoxが動かないのでParallelsを使う

M1 MacBook ProにVirtualBoxを入れようとしたらインストールに失敗しました。
->　後にインストール出来ましたが仮想マシンの立ち上げに失敗しました。
仮想マシンはまだ、Rosetta上で上手く動かないみたいです。
![Screen Shot 2021-02-06 at 9.02.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/f9b2d512-9e9a-42cd-a648-3da48264f20e.png)
M1で仮想マシンを動かす方法を探してたらParallels Desktop 16 for M1が使えそうなのでインストールしてみます。
[Parallels Desktop for Mac with Apple M1 chip](https://www.parallels.com/blogs/parallels-desktop-apple-silicon-mac/)
![Screen Shot 2021-02-06 at 9.10.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/a2d1dc9a-35bd-a179-6126-c9cf943fd953.png)

#Parallels Desktop 16 for M1のインストール
M1向けのParallels Desktop 16はまだ開発段階らしいので[ここ](https://my.parallels.com/desktop/beta?_gl=1%2aa8gisk%2a_gcl_aw%2aR0NMLjE2MTI1NjkyODEuRUFJYUlRb2JDaE1Ja2JyOXFfalQ3Z0lWUzJvcUNoM0J3UU1RRUFBWUFTQUFFZ0lwSFBEX0J3RQ..&_ga=2.162181433.48370037.1612569192-705587956.1612569192&_gac=1.238284340.1612569281.EAIaIQobChMIkbr9q_jT7gIVS2oqCh3BwQMQEAAYASAAEgIpHPD_BwE![Screen Shot 2021-02-06 at 9.18.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/cb88c4dd-6f4e-ca72-fcfb-83a2b7efa82a.png)
)からアクティーベーションキーを取得します。まだアカウントを持ってない方は登録してください。
![Screen Shot 2021-02-06 at 9.18.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/52adeea4-1246-bb16-b638-b4aad497bf6f.png)
リンク先のページを読んでいくとStep3にダウンロード用のリンクがあるのでクリック、これでダウンロードできます。アクティーベーションキーも表示されます。
![Group.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/f1fe48e5-85e1-dd5c-ab7b-70b8a2a50278.png)
ダウンロードしたら、ファイルを開いてインストールします。
![Screen Shot 2021-02-06 at 10.13.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/947efa72-8741-4e01-f8ec-d90d2ad87354.png)
インストールを進めると以下の画面が出るので
![Screen Shot 2021-02-06 at 9.37.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/73c5c47d-e7b3-6d0a-596b-96e9a507e098.png)
Choose Manuallyを選択してisoかVHDXファイルを選択しましょう。(既にOSイメージがある場合は表示されるはずです！)
#Windows10を動かしてみる
今回は[ARM版Windows10](https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewARM64)で試してみます。
ここでアクティーベーションキーの入力が求められるので、取得したキーを入力します。
![Group.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/672b0751-0c4a-7bfd-8346-d517e1fb8ae1.png)
デスクトップが表示されました！！！
![Screen Shot 2021-02-06 at 10.38.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/f9496233-b883-be32-9a76-d90fbd2f118e.png)

Settings>Update & Security>Activation>Change product keyよりWindowsのアクティベーションを行いましょう。
![Screen Shot 2021-02-06 at 10.46.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/b33a245f-eed6-3f87-d7bc-d41860520e9a.png)
認証も大丈夫そうですね。
![Screen Shot 2021-02-06 at 10.51.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1083406/921a9167-1007-0891-f7fb-fe7f5b0b9b51.png)
お疲れ様でした！
パスは正しいのにJSPにCSSが反映されない

JSPにCSSが反映されないときに確認するべきことを書いておきます。
#パスを確認
CSSを反映させるには、JSPに以下のようなリンクタグを書きます。
```
<link rel="stylesheet" href="CSSへのパス">
```
まずはこのパスが正しいかどうかを確認します。
#ダブルクオーテーションが全角になっていないか
私はこのパターンでハマりました。
何処かのサイトからコピペしてくるときはより気をつけてください。
splitメソッド

参照
[Ruby 3.0.0 リファレンスマニュアル:String#split](https://docs.ruby-lang.org/ja/latest/method/String/i/split.html)

## splitメソッド
splitメソッドとは文字列を分割して配列にするためのメソッド
第１引数に区切り文字を指定することができるが、引数を指定しない場合は空白文字で区切ることができます。
例）

```ruby:ruby
str = "Hello World"
array = str.split
p array
#実行結果
["Hello", "World"]
```

#####第１引数にカンマ(,)を指定した場合

```ruby:ruby
str = "Hello,World"
array = str.split(",")
p str
# 実行結果
["Hello", "World"]
```

文字列を指定することもできます。

```ruby:ruby
str = "HelloWorld"
array = str.split("W")
p str
# 実行結果
["Hello", "orld"]
```

１文字ずつ分割することもできます。その場合は引数にブランク("")を指定します。
charsメソッドでも同じ実行結果を得られます。
参照
[Ruby 3.0.0 リファレンスマニュアルString#chars](https://docs.ruby-lang.org/ja/latest/method/String/i/chars.html)

```ruby:ruby
str = "HelloWorld"
array = str.split("")
p str
# 実行結果
["H", "e", "l", "l", "o", "W", "o", "r", "l", "d"]
```

##### 分割数を制限する方法
分割数を指定することで分割した後の配列の上限を指定することができます

```ruby:ruby
str = "HelloWorld"
array = str.split("", 3)
p str
# 実行結果
["H", "e", "lloWorld"]
# 第2引数に3を指定したので配列の要素数は3つになる
```

添字で取得したい箇所を指定することもできます

```ruby:ruby
str = "HelloWorld"
array = str.split("", 3)
p str[1]
# 実行結果
"e"
```

正規表現で「分割することもできるのでその辺りもしっかりと学習していきます。
DatabricksにてGithubからdbcファイルをインポートする方法

## 概要
Databricksはウェブサイトよりノートブックをインポートすることが可能であり、Githubにあるdbcファイルをインポートする方法を共有します。
dbcファイルをインポートすることで複数のノートブックを一括で取り込むことができ、トレーニングや情報共有する際にdbcファイルで提供することが最適です。

dbcファイルだけでなく、Jupyter notebook（IPython Notebook）やソースコードも、ノートブックとして取り込むことができます。

## 手順
### 1. インポートするファイルのURLを取得
#### 1-1. インポートするdbcファイルがあるレポジトリにて、dbcファイルのリンクをコピーする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/642e1990-7ab3-c40f-24a7-fbb598c9a4c7.png)
引用元：[LearningSparkV2/notebooks at master · databricks/LearningSparkV2 (github.com)](https://github.com/databricks/LearningSparkV2/tree/master/notebooks)

### 2. Datbricksにてdbcファイルをインポート
#### 2-1. Databricksにて、"Workspace"タブにて、インポートしたいフォルダに移動後、右クリックして"Import"を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/68a70a44-1b81-224f-3da1-2a424642e30f.png)

#### 2-2. "Import from"を"URL"にチェックし、1の手順のURLを貼り付けて"Import"を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/bfdaff10-a81a-8935-df0b-a8295d66b1da.png)

#### 2-3. ノートブックがインポートされたことを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0d1ec704-4225-adf1-84fd-65b4d111ccad.png)

## 注意事項
特になし
データベースでSQL文が実行できない原因

データベースに値をインサートしたり更新するときに、SQL文を実行できないことがありました。
とても初歩的ですが、一応記録に残しておきます。
#文字列はダブルクォーテーションではなく、シングルクォーテーションで囲む
SQL文では、文字列を囲むときにはシングルクォーテーションで囲みます。
これがルールです。
データベース管理ソフト内では、ダブルクォーテーションが使える場合もあるそうですが、SQL文で文字列を使うときは、シングルにすると決めた方がいいでしょう。
#SQLでダブルクォーテーションは使わないのか？
文字列の場合は使ってはいけませんが、テーブル名やカラム名などの識別子の場合には使います。
Pythonで学ぶアルゴリズム　第31弾：圧縮アルゴリズム

# #Pythonで学ぶアルゴリズム< 圧縮アルゴリズム >

##はじめに
基本的なアルゴリズムをPythonで実装し，アルゴリズムの理解を深める．
その第31弾として圧縮アルゴリズムを扱う．

##圧縮アルゴリズム
同じ文字が連続する場合，その文字の出現回数を数えて圧縮するアルゴリズム．例えば，0と1の２つの文字だけで構成される文字を表現する．これは，FAXの圧縮などで使われている方法．

##実装
上の説明に従って，Pythonでの実装を行う．ただし，ここでは0と1の２つの文字と限定するのではなく，任意に与えられ文字列を自動で圧縮してくれるプログラムを組むこととした．さらに，後で元のデータの復元ができるように，何を圧縮したのかの記録も出力できるものとしている．詳しくは，ソースコードの中で説明している．以下にソースコードとそのときの出力を示す．

#####ソースコード
```python:compress.py
"""
2021/02/05
@Yuya Shimizu

圧縮アルゴリズム
"""

def compress(data):
    counter = {}            #各要素の連続出現数を格納する辞書型配列
    count_chr = data[0]     #カウントすべき文字を格納する変数
    factors =[count_chr]    #カウントする文字を順に格納する配列
    i = 0                       #カウントする文字の変更回数を0から数える変数
    counter[i] = 0          #i番目の文字の出現数を0で初期化
    
    for factor in data:
        if count_chr != factor:
            """文字の連続が途切れたら以下を実行"""
            count_chr = factor  #カウントすべき文字を更新
            factors.append(count_chr)   #カウントする文字を順に格納
            i += 1              #カウントする文字の変更回数を1増加
            counter[i] = 0      #i番目の文字の出現数を0で初期化
            
        counter[i] += 1         #i番目の文字の出現数を1増加

    new_data = []
    [new_data.append(counter[j]) for j in range(len(factors))]

    return [new_data, factors]  #圧縮されたデータと，その各要素を返す

if __name__ == '__main__':
    DATA = '000111000022455666aaauuああああ'

    compressed_data, factors = compress(DATA)

    print(f"{DATA} → {compressed_data} (factors: {factors})")
```

#####出力
```
000111000022455666aaauuああああ → [3, 3, 4, 2, 1, 2, 3, 3, 2, 4] (factors: ['0', '1', '0', '2', '4', '5', '6', 'a', 'u', 'あ'])
```

確かに，0と1以外であっても対応できており，さらに数字以外の文字であっても対応できていることも分かる．

##感想
今回をもって，今まで使ってきていた参考書（参考文献）の学習が終了した．これでとりあえず基本的なアルゴリズムを少しは学べたこととする．ただし，アルゴリズムはまだまだ数多く存在し，まだ学ぶべきものは多くあるはずである．また，今後学習を進める中で，新たに学習すべきものも出てくるであろう．よって，「Pythonで学ぶアルゴリズム」のシリーズが終わるわけではない．これが終わる時は，Pythonで学ぶアルゴリズムがこの世からなくなるときである．しかし，それはないだろう．学びに終わりはないと思っている．
次回からは，「Javaによるはじめてのアルゴリズム入門　　河西 朝雄　著　技術評論社」という参考書を使って学習を進めることとする．この教材はなかなか分厚いが，今回学んだものと一部重複するところもあるため，効率よく進めていきたい．

##参考文献
Pythonで始めるアルゴリズム入門　伝統的なアルゴリズムで学ぶ定石と計算量
　　　　　　　　　　　　　　　　　　　　　　　　 増井 敏克　著　　翔泳社
NW.js

## Download

* https://dl.nwjs.io/v0.14.7
    * nwjs-v0.14.7-win-ia32.zip  (XP対応版)


```
nwjs-v0.14.7-win-ia32
app\
  index.html
  package.json
```

という構成にしてファイルの準備


## ファイル

```json:package.json
{
  "name": "app1",
  "version": "0.0.1",
  "main": "index.html"
}
```

```html:index.html
<a href="https://qiita.com"> qiita.com </a>
```

## 実行


```sh:実行
cd nwjs-v0.14.7-win-ia32

nw ../app
```

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/1061b16b-fd9b-df2d-2d91-bfc7ee65c164.png)


## (チラシの裏)

* 既存のWEBアプリを見せる場合、Electronより書き換える箇所が少なくてすむかも。
* XPでも動く
    * しかしjsが古くて利用できない命令もある。XPは切り捨てて最新バージョンを使用するのが吉。
    * XP版だと、window.open()でウィンドウサイズの指定が効かなかった（？）
    * 最新版(v0.51 or v0.52beta)で、最新chromeでは動くjsが動かなったので書き換えがいくつか必要っぽい。（もしくは通信速度の問題かも。要確認）
「http://java.sun.com/jsp/jstl/core」のタグライブラリ記述子が見つかりません　の解決方法

タイトルの通り、「http://java.sun.com/jsp/jstl/core」のタグライブラリ記述子が見つかりませんというエラーの解決方法を書いておきます。
Eclipseでの方法になります。

#①JSTLをダウンロード
以下のURLにアクセスし、Filesのjarを選択します。
https://mvnrepository.com/artifact/org.glassfish.web/javax.servlet.jsp.jstl/1.2.1
どこかにダウンロードします。（場所を覚えておく）
「javax.servlet.jsp.jstl-1.2.1.jar」という名前のファイルがダウンロードされたことを確認する。
※もし違うバージョンのJSTLや、タグライブラリを使う場合はそれを使ってください。
#②Eclipseでの設定
「javax.servlet.jsp.jstl-1.2.1.jar」をコピーする。
「プロジェクト名」/WebContent/WEB-INF/libに右クリック貼り付け。
#何がダメだったのか
タグライブラリをプロジェクト内に配置していなかったこと。
プロジェクト内のWebContent/WEB-INF/libに配置する。
VRCHAT イベントカレンダーの設置方法

#1. この記事は

イベントカレンダーの入手、設置方法について説明します。

![54.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/b9cd61cf-c8f9-d981-2bc7-3e5a83b6b08f.jpeg)


#2. 方法

(1)下記のアドレスからアセットをダウンロードします。
https://booth.pm/ja/items/2401621

(2)vrchat-potersフォルダをオープンにし、SDK3-posters.prefab(SDK2でワールドを作成してる場合は、SDK2-posters.prefab)をSceneにドラッグ&ドロップする。

![58.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/b70c988e-afbf-62ee-7536-13c21305a3c2.jpeg)

(3)あとは、配置する場所を調整してください。
特定をプロジェクトでRubyのバージョンを変更する方法

現在関わらせていただいているプロジェクトとローカル環境のRubyのバージョンがことなりクローンしたあとに少し手間取ったので、今回記述します。


### 環境
- プロジェクト `Ruby 2.6.6`
- ローカル `Ruby 2.7.2`
- macOS `10.13.6`

そもそも`rbenv`というRubyのバージョン管理ツールで複数のバージョンを切り替えできるので、何も焦ることはない。

###### 現在のRubyのバージョンを確認する

まずはローカル環境のバージョンを確認する

```terminal
$ ruby -v

ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin17]
```
次に対象のバージョンをインストールする
今回の場合は`2.6.6`

```terminal
$ rbenv install 2.6.6
```

インストール完了後、インストールされているバージョンを確認する


```terminal
$ rbenv versions

  system
  2.5.0
  2.5.1
  2.6.6
* 2.7.2 (set by /Users/owner/.rbenv/version)
```

上記の結果だと`*`がついているバージョンが適用されています。

私の場合は普段、`2.7.2.`を採用しているので、特定のプロジェクトのみに`2.6.6`を適用したいので以下のコマンドを実行します

```terminal
$ rbenv local 2.6.6
```

バージョンが変更されているか確認します。

```terminal
 $ rbenv versions

  system
  2.5.0
  2.5.1
* 2.6.6 (set by /Users/owner/test_app/.ruby-version)
  2.7.2

```

上記のように、対象のディレクトリのバージョンが変更されています。


ちなみに新たにインストールした`Ruby`のバージョンを環境全体に適用したい場合は以下のコマンドでできます。

```terminal
$ rbenv global バージョン
```

手軽にバージョンの変更ができるのはいいですね。
IntersectionObserverのAPI

#監視API

IntersectionObserverのAPIは非常にシンプルです。IntersectionObserverオブジェクトを作成し、交差を監視したい要素をobserveするだけです。

以下は例である。

```
// IntersectionObserverオブジェクトを作成する。
// 交差時に実行するコールバック関数を渡す。
const observer = new IntersectionObserver((entries) => {
  for(const e of entries) {
    console.log(e);
  }
});

// 監視したい要素をobserveする。
observer.observe(document.querySelector('.target'));
```


使い回し用。
main.js

```
document.addEventListener('DOMContentLoaded', function () {

    const cb = function (el, isIntersecting) {
        if(isIntersecting) {
            //行いたいこと
        }
    } 

    const so = new ScrollObserver(//キーとなるクラス⇨'.cover-slide', cb);
});

```

scroll.js

```
class ScrollObserver {
    constructor(els, cb, options) {
        this.els = document.querySelectorAll(els);
        const defaultOptions = {
            root: null,
            rootMargin: "0px",
            threshold: 0,
            once: true
        };
        this.cb = cb;
        this.options = Object.assign(defaultOptions, options);
        this.once = this.options.once;
        this._init();
    }
    _init() {
        const callback = function (entries, observer) {
            entries.forEach(entry => {
                if (entry.isIntersecting) {
                    this.cb(entry.target, true);
                    if(this.once) {
                        observer.unobserve(entry.target);
                    }
                } else {
                    this.cb(entry.target, false);
                }
            });
        };

        this.io = new IntersectionObserver(callback.bind(this), this.options);

        // @see https://github.com/w3c/IntersectionObserver/tree/master/polyfill
        this.io.POLL_INTERVAL = 100;
        
        this.els.forEach(el => this.io.observe(el));
    }

    destory() {
        this.io.disconnect();
    }
}

```
addEventListenerの使い方

#addEventListenerの使い方

getElementByIdなどで要素（ターゲット）を取得し、その要素にイベント発生時の処理を書きます。

```
<div id="js-target">click</div>
```

上記のようなHTMLのclickと書かれた要素がクリックされた時の処理を書いてみます。

````
let target = document.getElementById('js-target');
```

```
target.addEventListener('click', function() {
  // クリックされた時の処理を書く
  console.log('click');
});
```

定義された関数を実行するには、以下の様に書きます。

```
let target = document.getElementById('js-target');

target.addEventListener('click', eventFunc);

function eventFunc(){
  // クリックされた時の処理を書く
  console.log('click');
}
```

##主なイベント一覧
| 引数 | イベント発火のタイミング|
|:-:|:-:|
|  click |  クリック時 |
|  mousedown |  マウスのボタンが押下された時 |
|  mouseup |  マウスのボタンを離した時 |
| mouseover  | カーソルがターゲットに侵入した時  |
| mousemove  |  カーソルがターゲット内を動いている時 |
|  mouseout |  カーソルがターゲットの外に出た時 |
| load  | ページの読み込みが完了した時  |
|  scroll | スクロールされた時  |
| resize  |  ブラウザのウィンドウ等のサイズが変更された時
 |


##関数に引数を渡す

```
let target = document.getElementById('js-target');

target.addEventListener('click', function(e) {
  console.log(e.target); // クリックされた要素
  console.log(e.clientX); // ブラウザ内の左上からのX座標
  console.log(e.clientY); // ブラウザ内の左上からのY座標
  console.log(e.pageX); // HTML全体の左上からのX座標
  console.log(e.pageY); // HTML全体の左上からのy座標
  console.log(e.offsetX); // クリックターゲットの要素左上からのX座標
  console.log(e.offsetY); // クリックターゲットの要素左上からのy座標
});
```


以下のような書き方もある。

```
let target = document.getElementById('js-target');

target.addEventListener('click', eventFunc);

function eventFunc(e) {
  console.log(e.target); // クリックされた要素
  console.log(e.clientX); // ブラウザ内の左上からのX座標
  console.log(e.clientY); // ブラウザ内の左上からのY座標
  console.log(e.pageX); // HTML全体の左上からのX座標
  console.log(e.pageY); // HTML全体の左上からのy座標
  console.log(e.offsetX); // クリックターゲットの要素左上からのX座標
  console.log(e.offsetY); // クリックターゲットの要素左上からのy座標
}
```
Intellij IDEAで「リリース・バージョンはサポートされていません」と出たときの対処法

## 経緯

モジュールが複数あるプロジェクトをクローンした際に、バージョンが古すぎて、タイトルのようなビルドエラーが出てしまった。
Intellijの設定からバージョンを変更しても、モジュールの設定で上書きされてしまうためか、反映されず困っていた。
色々調べて、やっとこさ解決策が見つかったので、備忘録として残しておく。

## 試したこと

Java CompilerからProject bytecode versionを変更する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346267/30316590-cabc-1927-b830-088adbebdd25.png)

ビルドしてみたが、やはり同じようなエラーが出てしまった。
どうやら、個々のモジュールで設定がされており、そちらで上書きされてしまうようだ。

## 解決策

1.プロジェクト直下の.ideaフォルダにあるcompiler.xmlを修正する。

```
target="1.5"
```
のように古いバージョンになっていると思うので、これを新しいバージョンにする。
(以下は11に書き換えたもの)

```
target="11"
```

2.ターミナルでカレントディレクトリをプロジェクト直下にして、以下のコマンドを実行する。

```bash
find . -type f -name "*.iml" -print0 | xargs -0 sed -i "" "s/JDK_1_5/JDK_11/g" 
```

これですべてのモジュールの設定が変更されたので、ビルドすると、それらの設定が反映される。

## 参考

[How do I change language level for all modules in IntelliJ](https://stackoverflow.com/questions/22504126/how-do-i-change-language-level-for-all-modules-in-intellij)
「AWS KMS を使用した CloudWatch Logs でのログデータの暗号化」は効きません

# 概要

AWS Cloudwatch LogsにはKey Management Store(KMS)を利用して暗号化する機能が公式で紹介されていますが、これで閲覧制限はできません。

# 詳細
[前回](https://qiita.com/sista05/items/b547e0db3b0caefd01f3)に引き続いて、KMSの利用ができなかった話です。
AWSの開発環境では重要データを扱うことももちろん多いので、皆がログなどを閲覧することができないようにするためにIAMではなくてKMSを使って閲覧制限をしようと考えました。
AWSのCloudwatch Logsには、KMSのKey ARNを指定する項目があり、これがあればKMS(Customer Managemented Keys:CMKs)で暗号化できる旨が「[AWS KMS を使用した CloudWatch Logs でのログデータの暗号化]
(https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/encrypt-log-data-kms.html)」として公開されています。


![スクリーンショット 2021-02-06 8.33.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244490/e0897d3b-14f7-e9f5-7d86-fc8afae0c86a.png)
**しかし、この方式で閲覧制限はできません。**

KMSで特定のユーザだけ閲覧できるようにした後、他のユーザから「logが閲覧できるんだけれど」という連絡がありました。設定は間違いないようなので、AWSのサポートに連絡しました。

```
お世話になります。
KMS(CMK)を使用してCloudwatch LogsのLog Groupの閲覧を制限しようとしています。
以下のような設定で、期待した挙動としてはPrincipalで指定したassumed-roleユーザの私(tanaka.tarou)だけが
Cloudwatch Logsを参照できるようになることでした。
ですが、実際の挙動としては、該当のAWSアカウントにおける他にassumed-roleされたユーザも
Cloudwatch Logsを参照することができました。
assumed-roleのユーザに対してCloudwatch LogsのLog Groupを閲覧制限する方法についてご教示お願い致します。
なお、以下の設定は公式の手順に則っています。
・・・・・・・
```

待つことおよそ5日、ようやくAWSサポートから回答が来ました。

```
ロググループのデータは常に CloudWatch Logs で暗号化され、また、CloudWatch Logs はリクエストがあるといつでもデータを復元いたします。
CloudWatch Logs に対する KMS 利用の許可は、キーポリシーの "Service": "logs.<Region>.amazonaws.com" の Principal で行われております。
そのため、大変恐縮ではございますが、ユーザーやロールごとに復号を許可することは現状できません
```
・・・じゃあ暗号化ってなんのためにしているの？

ちなみに、これはAWS側でも検証漏れだったのだろうと思っていつ直るか聞いてみたところ、まあそう答えるだろうな、という回答でした。
他のリソースに使用しているKMSキーポリシーの挙動まで不安になりますよね。

```
AWS サポートでは、今後のサービス予定などに関するご質問につきましては、一般に公開された情報以外にご案内をすることができません。
そのため、KMS のキーポリシーにおけるアクセス制限が今後可能になるかに関しましてもご案内いたしかねますことをご了承くださいますと幸いでございます。
明確な回答ができず大変心苦しく存じますが、何卒ご理解賜りますようお願い申し上げます。
```

というわけでご注意を！！
エンジニアと英語（その２）

[その１](https://qiita.com/infinite1oop/items/1da592ec87fd23d6688e)の続きである。いつも使う手法などを述べたい。

## まずは
### 挨拶
- 挨拶は基本。「Hello」や「How are you?」で十分。会話のきっかけをつかむためにも挨拶は大事。
- 天気の話題は全世界共通のように思える（少なくとも私の経験では）。
- いまなら、コロナの話になってしまうこともあり。

### コーヒーブレイク、食事、合間に
- 訪問国で人気のあるスポーツの話題。欧州ならサッカー、米国ならアメフトとか。オリンピックの話題もよいだろう。
- 話し相手がある程度年配であれば、大昔の有名選手の話をする。フランス人にはプラティニやジレス、スウェーデン人にはボルグとかステンマルク、米国人にはモンタナとか。（名前で世代がバレる）　米国出張時にリムジンなど長距離乗る際、運転手から話しかけらたれたとき、この手をよく使った。タクシーの運転手も話し好きが多いので。
- 政治や宗教の話は個人の思想もあるので、ある程度相手を理解している相手でないと難しいかもしれない（信頼できる部下にはこういった話をするが）。

## 仕事で
### 事前準備
- 準備が大事。話したいことを事前に要約（英訳）。箇条書き（リスト）がよい。終えたらリストにチェックをつける。
- 筋書きどおり、紆余曲折、話の中でどう転ぶかわからないのが普通。要約作成時に、自分なりのストーリーを複数作る。
- ベストケース、最悪ケースなど。会議などでは、妥協できる点を用意しておくこともベター。

### 会話中
- 相手が話している内容を理解できないことは頻繁にある。想像しながら聞くこともよくやる。
- 相手が話し終えたら、自分なりの簡単な言葉で言い変えてみることが大事。最後に「Is it correct?」、「Am I right?」と言ってみる（これは国際会議（後述）である会社のＥさんの話し方から学んだもの）。理解度を上げる。
- 最近は「Are you saying (相手が言っていると思われること)...」を使うことが多い。

## 余談
### 文化の違い
- 外国ではよくYes/Noを明確に求められるとか言うが、私の感覚では当てはまらないことも多い。あえて「Yes/No」で答えられるように聞くのだが、「Yes/No」が聞けないことがある。
- 何かしらの終わり間近で重要なDiscussionは避けるべき。特に会議で。早く終わりたいのだ。金曜日の会議設定（特に午後）は避けた方がよいような。すでに週末モード。

### 国際会議（少人数だったけど）
- 議長（司会）や議事録を担当したことで英語スキルがあがった感あり。
- 議長となると会議中に発言者の内容を理解できなくても、色々な理由にかこつけて、後でその方に堂々と聞けるというメリットがある。事前にも聞ける。こんな感じで理解を深めていた。
- では、なぜこんな立場になった？　きっと、Give&Takeではなく、GiveGiveGive&Takeだったからか。
- 面倒なことを担当すると、スキルがあがる。


## 最後に（話は若干逸脱）
- ソフト屋にとっては、ソースコードがすべてかもしれない。スマートな奴ほど、図など書かない。全部、頭に入っている。もうすぐ辞めてしまうが、今の部下の一人がそんな感じ。
- できる限りゆっくり話すよう心がける。これも言わなければあれも、、と焦るのが良くない。が、実は難しい。
- Communicationとは行動である。[その１](https://qiita.com/infinite1oop/items/1da592ec87fd23d6688e)にも述べたが、手段は何でもよい（英語でなくとも）。
- 自らの経験では、あらゆる手段を使ったCommunicationを通じて信頼を得ることで、英語が話せるようなになった感がある。
- 結局は使い続けること。今でも理解できないこと度々。

やはりその３はなし。多少なりとも、参考になれば幸いである。
投資quest:pyhtonでシステムトレードを作る(３)ゴールデンクロス

##pythonでシステムトレード：ゴールデンクロスを計算する

### ゴールデンクロス、デッドクロスとは
マネックス証券のＨＰの説明を転載します。
https://info.monex.co.jp/technical-analysis/indicators/001.html


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/336017/46984630-30bb-24af-8e91-79939e339877.png)

つまり、長期の移動線と短期の移動線のうちどちらが上にあるか、下にあるかを見ればわかりますので、簡単です。

```Python
#n日目
n = 5
#n×５日目
m = n*5
#短期５日移動平均、長期２５日移動平均

#５日間移動平均線を計算
df[n_ave]=df["end_price"].rolling(n).mean().round(1)

#２５日間移動平均線を計算
df[m_ave]=df["end_price"].rolling(m).mean().round(1)

#ゴールデンクロスデットクロスを求める    
#デフォルトはゼロで、ゴールデンクロスとデッドクロスの列を作る。
df['golden'] = 0
df['dead'] = 0

#短期が上ならば、ゴールデンクロスの列に１を入れる。
#短期が下ならば、デッドクロスの列に１を入れる。
df['golden'] = df['golden'].where(df[n_ave] > df[m_ave],1)
df['dead'] = df['dead'].where(df[n_ave] < df[m_ave],1)

```

これで、ゴールデンクロス、デッドクロスの列ができました。

とりあえず、ボリンジャーバンドとゴールデンクロスができたので、これで一回予想してみようと思います。

それは次の[「投資quest:pyhtonでシステムトレードを作る(４)ランダムフォレスト編」](https://qiita.com/motoyuki1963/items/0aa402e0f4256228edab)で
GraphQLについて詳しく調べてみた



##GraphQLとは

GraphQLを案件で使う機会があったので今回勉強してみました。
以下、ブログ記事に書いておりますので、是非見に来ていただければと思います。

[GraphQLについて詳しく調べてみた](https://goelibe.com/?p=23)
linuxから windowsへ sftp と ssh

俺のWINは　**HOME** が好きで...

```
https://www.youtube.com/watch?v=pz7_Z4vGCkY
の
「あたい　男をやめないわ」
の
フレーズ
```

https://wave.hatenablog.com/entry/2019/02/23/080800
で勉強させていただきました


１）まず　sshサーバーのインスト

設定ー＞アプリー＞オプション機能ー＞機能の追加　から


![IMG_20210206_082416704.jpg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211097/14282129-0fe9-0d30-4a97-156a75d88cbc.jpeg)

を導入します



２）openssh サービスの自動起動で


スタートメニューを右クリック => コンピュータの管理
サービスとアプリケーション => Open SSH SSH Serverー＞右クリックー＞プロパティ
スタートアップの種類 => 自動
サービスの状態 => 開始

の順ですが、参考画像をつけます


![IMG_20210206_085644904.jpg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211097/d85c83a0-9bc7-20e5-e6c0-4cd584885c5f.jpeg)

![IMG_20210206_085710652.jpg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211097/aea6328a-8269-18bb-6d3e-1863b2381d45.jpeg)


![IMG_20210206_085759360.jpg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211097/0f089d36-8b9a-c38d-65c3-aaa838003b2a.jpeg)










```
ssh tyoka@192.168.31.107
にて
ーーーーーーーーーーー
Microsoft Windows [Version 10.0.19042.789]
(c) 2020 Microsoft Corporation. All rights reserved.

tyoka@DESKTOP-GFRS3U6 C:\Users\tyoka>

```
と出来上がってます


ssh より　大事なのは
$ sftp tyoka@192.168.31.107
tyoka@192.168.31.107's password: 
Connected to 192.168.31.107.
sftp> 
のほうで　ファイルのやりとりができる！

##LINUXでは　プリンタードライバーがないので印刷できないファイルを　WIN10に送って　WIN10で印刷ですねー


## 自動でBIOSアプデートまでしてくれます、親切
![IMG_20210206_150207840.jpg.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211097/86ca1d04-a72e-ab7d-cc7c-8833f1bdebf4.jpeg)
manimの作法 その43

#概要

manimの作法、調べてみた。
作品、作ってみた。
ＶＪです。

#生成した動画

youtubeにアップしたら、「著作権侵害の申し立て」が、付いた。

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

以上。
cronoがある日突然停止していた原因と対策

# 概要

私はモバイルアプリのバックエンドAPIに Ruby Rails + Grape を docker (compose)にのせて使用していて、同時に、dockerと親和性の高いcronoを動かしてます。

が、二か月くらい安定稼働してたのにある日突然停止!(^^;)。(二か月というのがヤバい)

cron系は止まるのはやばいので、書いておきます。

# 原因

個人アプリだったので、cronoの設定は、あまり考えずに設定してました(汗)。

危険な話ですが、ログが溜まりすぎると停止します(環境によっては停止しないのかもしれないが、自分の環境では見事に停止してくれてました)。

cronoは、dbテーブルを自前で持っているわけですが(導入時migrateすると思います)、そこに管理情報を入れるのだが、何もしないとそのフィールドにログをしこたま突っ込んでくれます(笑)。

なんで止まったんだろうと思い、phpmyadminで覗いて、そこのフィールドのデータを削除してあげると、とたんに動き出したのでそれが原因で間違いありませんでした。

# 対策

truncateする設定をしないといけませんね。

```ruby:config/cronotab.rb
#Crono.perform(AggregateJob).every 10.minutes
Crono.perform(AggregateJob).with_options(truncate_log: 1000).every 10.minutes
```

# 感想

私が不注意だったとはいえ、crono大丈夫かよ・・という感じです。開発も止まってるようだし、業務ではやはり使わないほうがいいんだろうか？

誰か教えてください。
よく使うGitコマンドを短縮！別名を付ける

Gitコマンドに少しずつ慣れてくると、`git commit`や、`git checkout`は文字数多く感じて面倒くさくなってきますよね…
そんなときは、短い別名を付けておくと、コマンド入力が楽になって作業が捗ります！

# 別名の設定方法

```bash:ターミナル
git config --global alias.ci commit
git config --global alias.br branch
git config --global alias.co checkout
git config --global alias.st status
```
**設定後、`git ci` とコマンド入力するだけで、 `git commit`と同じように使えるようになります！**

- `git config` とは、設定を変更するコマンド
- `alias`（エイリアス）とは、別名のこと
- `--global`を付けると、PC全体の設定になる。もし `--global` を付けないと、今自分がいるプロジェクトの下の .git/config ファイルのほうに設定が反映される（特定のプロジェクトで使いたいというよりも、コマンドを短くして便利にしたいだけの場合は、PC全体の設定にするのがオススメ！）


```bash
#git commitと同じことができている
$ git ci
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
```
```bash
#git statusと同じことができている
$ git st
On branch main
Your branch is up to date with 'origin/main'.

nothing to commit, working tree clean
```

簡単ですが以上です！
読んでいただき、ar
yarnでSassの環境構築をする手順と方法


yarnでSassの環境を構築する方法です。

## ディレクトリを作成
まずはディレクトリを作成します。

```terminal
mkdir src\scss      
mkdir public\css
```
srcディレクトリがSass。publicディレクトリにcssを出力するようにします。

## Sassをインストール

```
yarn init -y   
yarn add sass --dev     
```
上記コマンドでSassをインストールします。

## package.json

```js:package.json
{
  "scripts": {
    "sass": "sass src/scss:public/css"
  }
}
```
package.jsonに上記を記述します。

## srcディレクトリにSassファイルを作成する。

![sass.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/347f0c14-4981-1933-4017-a94c91254637.jpeg)

画像のようにsrcディレクトリにSassファイルを作成します。

```
yarn sass
```
を実行することでcssファイルが出力されます。
![sass2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/5dc88c80-7b98-1b75-6701-ed95c88f1a06.jpeg)

## Sassを変更したらリアルタイムでcssファイルを更新する

上記だけでもSassをcssに変換できますが、変換するには`yarn sass`コマンドを都度実行する必要があります。
sassを変更したらリアルタイムでcssファイルを更新するように設定を追加します。

```
yarn add watch browser-sync --dev
```
をインストール後にpackage.jsonに下記を記述します。

```js:package.json
{
  "scripts": {
    "sass": "sass src/scss:public/css",
    "sass-watch": "sass --watch src/scss:public/css" // 追加
  }
}
```
これで設定は完了です。

```
yarn sass-watch
```
上記コマンドを実行することで、scssの変更を検知できるようになります。
リアルタイムで変更がcssに反映されます。

## 最後に
本記事では、yarnでSassの環境構築をする方法についてまとめました。
さらに、VS CodeのプラグインLive Serverを使えば、ブラウザにもリアルタイムで反映できるようになるのでオススメです。
![liverserver.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/2d4cf2fd-3792-0494-3b66-7fe0ea3847a6.jpeg)
ASP.NET Core (5.x)でMVCにおける認証機能（Identity)付きテンプレートの生成と動作確認


基本的には[こちら](https://docs.microsoft.com/ja-jp/aspnet/core/security/authentication/identity?view=aspnetcore-5.0&tabs=netcore-cli)を見れば書いてありますが、記述がwebapp(Razor Pages)ベースだったり（私はMVCで使いたい）、ちょっとわかりにくいので動作検証。

## 環境など

* Mac上でdotnet 5.xを利用しています。（が、他の環境、3.1.xでも動くと思います）


## プロジェクト生成


```bash
dotnet new mvc --auth Individual -o identity_mvc_test
cd identity_mvc_test
```

>現在、dotnet new コマンドで生成できる認証テンプレートは[Individual]のみのようですが、カスタマイズすれば他の認証にも対応可能なようです。

>何もオプションを指定しないとsqliteが利用されるようです。 -uld オプションをつけるとlocalDB（簡易SQL）で生成されるようです。

## 各種認証用DBの生成

プロジェクト生成時に何もオプションを指定しないとsqliteベースでDBが作られるみたいです。
生成ファイル群を見るとマイグレーションとかしてないのにapp.dbってのが作られてますね。

![スクリーンショット 2021-02-06 5.54.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/275f680a-c282-a349-86f2-318b7fd62aab.png "スクリーンショット 2021-02-06 5.54.20.png")

### 中身を少し確認

sqliteにログインして、テーブルを表示してみます。Identityが利用する各種テーブルが作られていますね。

```bash
sqlite3 app.db

sqlite> .table
AspNetRoleClaims       AspNetUserLogins       AspNetUsers          
AspNetRoles            AspNetUserRoles        __EFMigrationsHistory
AspNetUserClaims       AspNetUserTokens     
```

>sqliteから抜けるには.exitと入力します。

## 動作を確認

```bash
dotnet run
```

### TOPページ

では実行されたページにアクセスしてみます。標準では http://localhost:5001 です。
MVCのテンプレートにRegister, Loginボタンが追加されています。

![スクリーンショット_2021-02-06_6_03_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/0d1c227c-6889-92c3-a80e-f5d423539793.png "スクリーンショット_2021-02-06_6_03_46.png")

> SSL/TLSを利用する場合は dotnet dev-certs https --trust で証明書をインストールしておく必要があります。

### Registerページ

ではRegisterリンクをクリックしてみます。すると登録用のページが表示されます。
登録してみましょう。


![スクリーンショット_2021-02-06_6_04_45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/fb693d3a-f329-81f8-e3f7-ab79e4ca9247.png "スクリーンショット_2021-02-06_6_04_45.png")

登録後はEmailの（架空）コンファームが必要なようなのでクリックします。
実際のアプリでは確認メールが送信され、送信されたメール中の確認リンクをクリックすることになります。

>sqliteのAspNetUsersにデータが記録されていることを確認してみましょう。

![スクリーンショット_2021-02-06_6_04_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/591251b9-2fe1-b1ad-50de-d072dc63406f.png "スクリーンショット_2021-02-06_6_04_55.png")

### Loginページ

では、次にLoginリンクをクリックします。するとログイン画面が現れるので先程登録したID,PWでログインしてみてください。

![スクリーンショット_2021-02-06_6_05_19-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/9da8e0f1-a490-5cb7-fe63-ef9934d3871b.png "スクリーンショット_2021-02-06_6_05_19-2.png")

>このとき、パスワード忘れ対応のリンク等も生成されていることが確認できます。

### ログイン後ページ

ログインすると、右上のヘッダ部にログインユーザー名が表示され、LoginリンクはLogoutリンクへと変化します。


![スクリーンショット_2021-02-06_6_05_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/bdf39df4-4694-853e-b6c2-ba9ea571228c.png "スクリーンショット_2021-02-06_6_05_28.png")

ユーザー名をクリックするといわゆるMyPage的な内容が表示され内容の変更・確認やMFA等の雛形が実装されています。

![スクリーンショット_2021-02-06_6_05_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55188/5eede0ed-ba5a-5faf-d002-9aef468fd68d.png "スクリーンショット_2021-02-06_6_05_34.png")

## 一旦まとめ

Identityおよびそのテンプレートを利用すれば近代的Webサービスにおいて必要となる認証・認可機能の基本部分をひな形として生成してくれます。一方で、各機能を理解し、使いこなす（カスタマイズする）ためには一定の知識と慣れが必要となります。まずは雛形のコードを眺めながら不明な点を１つ１つ調査するとよいでしょう。
生まれてはじめてGitHubの他人作成リポジトリにプルリク投げてみたの

# 生まれてはじめてGitHubの他人作成リポジトリにプルリクエストを投げてみた経緯と感想
* オッス！ここでは俺が生まれてはじめてGitHubの他人作成リポジトリにプルリクエストを投げてみたらどんな感じだったのか共有させてもらうぞ！

## 動機
* 最近何かと話題の、GitHubでの活動実績などからスコアを算出するあのサービスやこのサービスでスコアを少しでも上げたかったので

## 手順
1. まずは下手の横好きな競技プログラミング関連で良い感じのリポジトリを見つけてみた
  * 単純に「procon」をキーワードにGitHub内で検索してみた
  * そこでたまたま[procon-qa](https://github.com/monkukui/procon-qa)なるWebサービスのリポジトリを見つけた
2. ひとまずissuesを開いてみて、自分が解決できそうな課題があるか探ってみた
  * しかし無かった
3. 実際にcloneしてソースコードを読み解いてみて、潜在的な課題がないか探ってみた
  * 運良く、タブインデントでほぼ統一されている中にスペースインデントが混入しているファイルを発見した
4. 早速issueを新しく切ってみた
5. 当然1分もかからず修正できたので、自分で立てたissueを自分で即座に解決するための~~不毛な~~ブランチを作成してcommitした
6. GitHubの仕組みがまだよくわかっていなかったので、とりあえずブランチを切ってるから良いだろうという考えでpushした
  * が、ブランチを作成する権限が無いのでフォークすれば？と相棒エディタVSCodeが勧めてきたので、その通りにした
7. 作成したフォークリポジトリでの前述したブランチを、本家リポジトリのmasterにマージするためのプルリクをここでようやく投げてみた

## 結果
* 無事、本家のmasterにマージされて他人作成リポジトリへのプルリク初体験を成功で終えた

## 感想
* GitHubで何の見返りも求めずにコントリビュートするのって、最高に楽しいんですね……。
* 何はともあれ、これでOSS界隈の端くれとしてひとまずデビューできた（のか？）ことが嬉しい！
* 画面の前のみんなもまだ未体験なら、絶対に近いうちに生まれてはじめてGitHubの他人作成リポジトリにプルリクエストを投げてみてくれよな！
Streamパッケージを初めて使ってみた話。

レガシーマンなので、Java8から導入されたというStreamパッケージを生まれて初めて使った。
確かどこかで聞いた説明で「ラムダ式はStremパッケージのおまけ」と話してたのでかろうじて記憶に残ってた。

処理としては、Beanオブジェクトに入ってるフィールド（プロパティ）Aの重複を除外して件数を判定する。


レガシーマンのコード

```
public class AbcInfo {
    private String id;
    private String name;

    ～ getter & setter 略 ～
}

public class AbcServiceImpl implement AbcService {
    ～ 略 ~

    protected boolean isOneName(List<AbcInfo> abcList) {
        // -------------------------------------------------------
        // nameの文字列が1種類か判定する。
        // -------------------------------------------------------
        // nameのみ抽出する。
        List<String> nameList = new ArrayList<String>();
        for(AbcInfo abc : abcList) {
            nameList.add(abc.getName);
        }
        // nameの重複を排除する
        List<String> list = new ArrayList<String>(new HashSet<>(nameList));
        if(list.size() == 1) {
            return true;
        }

        return false;
    }
}

```



Streamパッケージ使ったコード

```
public class AbcInfo {
    private String id;
    private String name;

    ～ getter & setter 略 ～
}

public class AbcServiceImpl implement AbcService {
    ～ 略 ~

    protected boolean isOneName(List<AbcInfo> abcList) {
        // nameの文字列が1種類か判定する。
        long nameCount = abcList.stream()
                .map(info -> info.getName())
                .distinct()
                .count();
        if(nameCount == 1) {
            return true;
        }

        return false;
    }
}

```

参考：http://kusamakura.hatenablog.com/entry/2016/12/07/Java8_%E3%81%A7%E5%B0%8E%E5%85%A5%E3%81%95%E3%82%8C%E3%81%9F_Stream_%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9%E3%82%92%E3%81%AF%E3%81%98%E3%82%81%E3%81%A6%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B
Firebase Authentication for ruby

# 概要
Java や Node などは Firebase Admin SDK を使用することで、Firebase Authentication の操作をサーバーサイドで行うことが出来ますが、ruby には gem が用意されていません。
そのため、google-apis のライブラリを利用する必要があります。
その使い方のメモです。

# 利用可能なAPI
[github のレポジトリ](https://github.com/googleapis/google-api-ruby-client) の `generated/google-apis-identitytoolkit_v3` にライブラリのソースコードが配置してあります。(`v3` 部分が変わっているかもしれません)
https://github.com/googleapis/google-api-ruby-client/tree/master/generated/google-apis-identitytoolkit_v3

[lib/google/apis/identitytoolkit_v3/service.rb](https://github.com/googleapis/google-api-ruby-
client/blob/master/generated/google-apis-identitytoolkit_v3/lib/google/apis/identitytoolkit_v3/service.rb) 内にAPIクライアント、
[lib/google/apis/identitytoolkit_v3/classes.rb](https://github.com/googleapis/google-api-ruby-client/blob/master/generated/google-apis-identitytoolkit_v3/lib/google/apis/identitytoolkit_v3/classes.rb) 内にAPI実行時に使用するクラスがあります。


# ライブラリの利用

## ライブラリインストール

```ruby:Gemfile
gem 'google-apis-identitytoolkit_v3'
```

## 認証

#### FirebaseConsole でダウンロードしてきたサービスアカウントのファイルを利用する場合

```ruby
service_account = "/path/to/serviceAccountKey.json"
client = Google::Apis::IdentitytoolkitV3::IdentityToolkitService.new
client.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
  json_key_io: File.open(service_account),
  scope: 'https://www.googleapis.com/auth/identitytoolkit'
)
```

#### 環境変数を利用する場合

以下の環境変数を設定しておきます。値はFirebaseConsoleからダウンロードできるサービスアカウントのファイル内の値です。

* GOOGLE_ACCOUNT_TYPE
* GOOGLE_CLIENT_ID
* GOOGLE_CLIENT_EMAIL
* GOOGLE_PRIVATE_KEY

```ruby
client = Google::Apis::IdentitytoolkitV3::IdentityToolkitService.new
client.authorization = Google::Auth::ServiceAccountCredentials.make_creds(
  scope: 'https://www.googleapis.com/auth/identitytoolkit'
)
```

## APIの利用
uid は、FirebaseConsole の Authentication ページの Users タブ内で確認できます。

### アカウント情報取得

```ruby
uid = 'uid'
request = Google::Apis::IdentitytoolkitV3::GetAccountInfoRequest.new(local_id: [uid])
account = client.get_account_info(request)
pp account.users[0]
```

### ユーザー作成

```ruby
request = Google::Apis::IdentitytoolkitV3::SignupNewUserRequest.new(
  display_name: display_name,
  email: email,
  password: password,
  email_verified: true
)
result = client.signup_new_user(request)
```

### ユーザー情報更新

```ruby
uid = 'uid'
request = Google::Apis::IdentitytoolkitV3::SetAccountInfoRequest.new(
  local_id: uid,
  display_name: display_name_changed,
  email: email_changed,
  password: password_changed
)
result = client.set_account_info(request)
```

### ユーザー削除

```ruby
uid = 'uid'
request = Google::Apis::IdentitytoolkitV3::DeleteAccountRequest.new(
  local_id: uid
)
client.delete_account(request)
```

### パスワードリセット、メールアドレス確認メール等を ruby から送る

ユーザー情報更新メソッドを利用することで、パスワードの変更や、`email_verified` の値を書き換えることが出来るため、ワンタイムトークンを発行しメールに記載する等の方法で実装できそうです。


# 参考
https://qiita.com/asflash8/items/17775895e35272ae7ec8
【Rails】rails g devise:installで遭遇したUser does not respond to 'devise' method.について

状況にぴったりの日本語記事がなさそうなので書いておきます。次のエラーにお困りのかたへ。

```
User does not respond to 'devise' method. This usually means you haven't loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb' (RuntimeError)
```

# 原因： rails g devise:install を後からやろうとしていませんか？
先走って、さきにモデルやら何やら作成して、急に思い出して`rails g devise:install` しようとして次のエラーにかかります。私のことです。

```
$ rails g devise:install
Traceback (most recent call last):
    63: from bin/rails:4:in `<main>'
    62: from /Users/USER_NAME/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.2.4.4/lib/active_support/dependencies.rb:291:in `require'
    61: from /Users/USER_NAME/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.2.4.4/lib/active_support/dependencies.rb:257:in `load_dependency'
    60: from /Users/USER_NAME/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activesupport-5.2.4.4/lib/active_support/dependencies.rb:291:in `block in require'
    ・
    ・
    ・       
/Users/USER_NAME/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/devise-4.7.3/lib/devise/rails/routes.rb:510:in `raise_no_devise_method_error!': User does not respond to 'devise' method. This usually means you haven't loaded your ORM file or it's being loaded too late. To fix it, be sure to require 'devise/orm/YOUR_ORM' inside 'config/initializers/devise.rb' or before your application definition in 'config/application.rb' (RuntimeError)
```

# 解決法
今回は`routes.rb`の `devise_for`〜を削除したところ、`rails g devise:install`ができるようになりました（先走りすぎ？）。そのほかdeviseのメソッドを呼び出そうとしている箇所があれば疑ってみると良さそうです。

# 参考
以下を参考にしました。
[getting error from devise “User does not respond to 'devise' method” when running “rails generate devise:install”](https://stackoverflow.com/questions/9247334/getting-error-from-devise-user-does-not-respond-to-devise-method-when-runnin) - stack overflow
venvでPythonの仮想環境を作成するときにプロンプトに表示される名前を設定する．

# プロンプトに表示される名前
venvで仮想環境をactivateしたときに，プロンプトの左端に表示される`(.venv)`っていうやつ．
例えばよくある`python3 -m venv .venv`で仮想環境を作成すると以下のように表示される．

```bash
(.venv) name@hogeeeee$ code .
```
# 仮想環境作成時にオプションで表示名を指定できるみたい
`--pronpt PROMPT_NAME`を付けて仮想環境を作成すると自動でプロンプトに表示される名前をPROMPT_NAMEとしてくれる．
例えば`python3 -m venv .venv --prompt hogeee`とすると，以下のように表示される．

```bash
(hogeee) name@hogeeeee$ code .
```
という感じ．

作成済みの仮想環境の表示名を変えるなら，`.venv/bin/activate`と`.venv/pyvenv.cfg`をちょろっとイジればよろしいみたい．
ただなんかあとから変えるのって気持ち悪いし環境作成時に設定するほうがやっぱりスッキリする．

```bash:.venv/bin/activate
略
PS1="(hogeee) ${PS1:-}"#←ここのhogeeeをイジる．
略
```

pyvenv.cfgのほうは`prompt = 'hogeee'`を追記すればいいみたい．必要ないかもしれないけど．

# 感想
なんでみんな仮想環境のディレクトリは.venvって名前で作るんだろう？
.gitignoreとかには.venvはデフォルトで記載されてるから，慣習的なものか．

とりあえずこれで自分がどの仮想環境にいるかということがわかってイイ感じ．
あとはvscodeの左下に表示される名前も変えられたらいいなあ……．

んでもまあ，詳しいことはわがんねえ．

# 参考
[公式ドキュメント](https://docs.python.org/ja/3/library/venv.html)
[Issue35661: Store the venv prompt in pyvenv.cfg](https://bugs.python.org/issue35661)
AWSのEC2にgit cloneする方法（GitHub）

##はじめに
AWSで初めてデプロイしている時に本当にできてるのかな？と心配になったので忘れないように書き込みます。

##前提
Amazon Linux 2でGitHubを使っています。

##デプロイ方法
はじめにssh接続でAWSにログインします。
ログインしてから、まだgitをインストールしてない人は、

```
$ sudo yum install -y git
```
でインストールします。
次にSSHキーを作成します。

```
$ ssh-keygen -t rsa -b 4096
```
出てくる質問はすべてEnterで構いません。
次に作成されたキーをコピーします。
（ssh-rsa~から全て含みます）

```
$ cat ~/.ssh/id_rsa.pub
```
次にGitHubにログインしてSettingsを開き、SSH and GPG keysにいきます。
そこにNew SSH keyボタンがあるのでクリックします。
titleは各自自由に入力してもらい、keyのところに先ほどコピーしたキーを貼り付けます。
次に、

```
$ ssh -T git@github.com
```
を入力して、質問にyesと答えます。

```
Hi name! You've successfully authenticated, but GitHub does not provide shell access.
```
と出てきたら、AWSとGitHubの通信ができるようになります！
最後にcloneします。

```
$ sudo git clone https://github.com/××××××××/××××××××
```
これでデプロイできているはずです！

##その後
修正して、GitHubにpushした内容をデプロイする方法はgit pullでできます。

```
$ sudo git pull
```
GitHubの名前とパスワードを聞かれるので答えたらvimに飛ぶと思います。
:wqで保存できるので入力したら修正された箇所をデプロイすることができます！

##参考
[Ruby on Rails + MySQLアプリをDockerで構築し、AWSにデプロイする(6)]
(https://qiita.com/sho_U/items/5ef6693f7ae8f1c27bb7)

とても参考になりました！ありがとうございます！！
Oracle Cloudのminimal UbuntuのInstanceで外からつながらない問題

# 環境
- Oracle Cloudインスタンス
- Image: Canonical-Ubuntu-20.04-Minimal-2020.12.10-0
- Shape: VM.Standard.E2.1.Micro

# 原因
iptablesのルールである

```
-A INPUT -j REJECT --reject-with icmp-host-prohibited
```

# 解決策
```
/etc/iptables/rules.v4
```
の17行目にある

```
-A INPUT -j REJECT --reject-with icmp-host-prohibited
```

をコメントアウトして再起動。（すべてのポートが晒されるので注意）
python初心者がWindowsでDjangoを触ろうとして、くっそ苦労したので忘備録。

#背景
最近、友達とWebアプリケーション作成を行おうと思っており、基本的に私の仕事は進捗管理と要件定義なのだが、自身にwebの知識はほとんどなく（プログラミング自体は4年経験しているがIOS、android、windowsアプリケーション作成などで、Webアプリケーション作成はほぼ未経験。）自分でも軽いWebアプリケーションくらいは作れるようにならなければならないと感じたため。
#初学で触ろうとしたもの
VSCode --- Webアプリケーション作成にはほぼ必須スキルと感じているため、webアプリケーション作成には必須みたいな空気あるので触ってみたかった。
python3.8.7 --- 一応AIを動かすために触ったこと自体はある。汎用性と将来性がありそうなので選定。コードを１から書き上げた経験はなし。
Django3.1 --- 初めて触る。何なら存在すら知らなかった。VSCodeで触る前に、自分コマンドプロンプト上で触ったらめちゃめちゃ便利そうだったので触ることに。
（https://code.visualstudio.com/docs/python/tutorial-django）

#くっそハマった点。

1.WindowsでVSCode上からの仮想環境の呼び出し。
解決策：powershell上で実行ポリシーの変更。
(https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.)
パワーシェルって何？
(https://wa3.i-3-i.info/word12683.html)
ずーとVSCode内のターミナル上で行っていた。。。。
何をしたのかよくわかっていない。（なんかPCのセキュリティを甘くしたことはわかる）

Set-ExecutionPolicy -ExecutionPolicy ＜PolicyName＞ -Scope ＜scope＞

本来こっちを使うのが正しいのだろうが

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

こっちを使うことで解決した。
スコープって何を引き数にすればいいのか不明（おそらくこのディレクトリ内？だけでこのセキュリティを適用みたいなことだと思う）。
Lambdaでスクレイピングしようとしたら、requests, bs4がなくて苦労した

AWS lambda でスクレイピングを使った簡単なアプリを作りたいと思い、以下のようなimport文を書いた。

```py
import requests
import bs4
```

```
No module named 'requests'
```

lambdaのテストすると、上記のようなエラーメッセージが表示された。解決策としては、必要なライブラリを一つのフォルダに入れて圧縮し、それをlambdaのコンソール画面操作でアップロードするという方法。

- 苦労した点
  - レイヤーに追加してもimportエラー（なぜ！）
  - アップロードするとlambda_function.pyが消える（！！）


# レイヤー使えなかった

関数用意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/7412058c-5ea2-bfd3-6e9c-1a797c48b841.png)

レイヤー用意。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/d80be4ba-d1a8-2fe0-8dcc-6a33a6e0ea78.png)

だめじゃん！！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/b18d63da-fb36-d953-6899-00f2767690c7.png)


# 手順

まずは以前pip3でローカルにインストールしたrequestsライブラリをアップロードした。

実行するが失敗。なんだこれ。chardetなんて初めて聞いた。

```
No module named 'chardet'
```

調べてみると確かにrequests/\_init\_.pyで使っていた。

```py
import chardet
```

じゃあ次はchardetも一緒に圧縮して、、、これをあと何回繰り返せばいいんだ・・・
この時点で絶望した。
案の定また出た。次はcertifi。ってなんだこれ。

```
No module named 'certifi'
```

調べてみると証明書が信頼できるかどうか検証するために使っているらしい。
https://requests.readthedocs.io/en/master/user/advanced/

>Requests verifies SSL certificates for HTTPS requests, just like a web browser. By default, SSL verification is enabled, and Requests will throw a SSLError if it’s unable to verify the certificate:

日本語訳
Requests は、Web ブラウザのように HTTPS リクエストの SSL 証明書を検証します。デフォルトでは SSL 検証が有効になっており、証明書を検証できなかった場合には SSLError がスローされます。

どうすれば漏れなくアップロードできるのだろうか。そこで次の記事を参考にした。
https://qiita.com/afukuma/items/b7191025700a7829967c

なるほど。これは思いつかなかった。pipでディレクトリ指定できるのか。

# アップロードするとlambda_function.pyが消える

lambda_function.pyが存在する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/0e713d6a-9460-4c89-ee28-6c45a387db2b.png)

アップロード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/15237571-10c3-6306-2ddb-fcd0f49f1df9.png)

lambda_function.pyが消えた！


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/bb244391-dfed-9c12-21f9-800f99ab34b0.png)


ブラウザ上で直接編集していた場合、たまったもんじゃない。


# 参考記事
【Lambda】import requests が使えるようにする【python】
https://qiita.com/afukuma/items/b7191025700a7829967c

Requests: HTTP for Humans™ Advanced Usage
https://requests.readthedocs.io/en/master/user/advanced/