OmniAICreator/Qiita-1.07M huggingface dataset:
【JS】reduceとconcatで新たな配列を作成する方法とforEachでの書き換え。

個人メモです。

reduceとconcatを使うことで新たな配列を作成することができる。

##目次

1. reduce & concat
2. forEach & concat
3. forEach & push
4. reduce & push

##reduce & concat
例えば、index番号が偶数の場合のみ要素を取り出す処理の場合

```js:reduce
arr = ["a", "b", "c", "d"]

res = arr.reduce( (ary, elem, index) => {
    if (index % 2 == 0 ){
        return ary.concat(elem)
    } else {return ary}
}, [])

console.log(res)
// ["a", "c"]
```

**▼ポイント**

・reduceの初期値に`[]`をセット

```js:
.reduce( (処理結果, 要素, インデックス番号) => 処理, 初期値 )
```

・concatなので非破壊処理


<br>
##forEach & concat
同様の処理をforEachで書くこともできる。

```js:
arr = ["a", "b", "c", "d"]

res2 = []
arr.forEach( (elem, index) => {
    if (index % 2 == 0 ){
        res2 = res2.concat(elem)
    }
})

console.log(res2)
// ["a", "c"]
```

**▼ポイント**

・事前に初期値`[]`を宣言しておく。
`res2 = []`




<br>
##forEach & push
非破壊のconcatに対し、破壊的なpushで記述することも可能。

```js:
arr = ["a", "b", "c", "d"]

res = []
arr.forEach( (elem, index) => {
    if (index % 2 == 0 ){
        res.push(elem)
    }
})

console.log(res)
// ["a", "c"]
```


<br>
##reduce & push
reduceでも破壊のpushを使って記述することができる。

```js:
arr = ["a", "b", "c", "d"]

res2 = arr.reduce( (ary, elem, index) => {
    if (index % 2 == 0 ){
        ary.push(elem)
        return ary
    } else {return ary}
}, [])

console.log(res2)
// ["a", "c"]
```

**▼ポイント**

・reduceは各処理毎に一つの処理結果を返す必要があるため、aryをpushで破壊処理した後、`return ary`を返す。


<br>
##filter
本来の目的とは外れるが、今回の処理であればfilterを使うことも可能。

```js:
arr = ["a", "b", "c", "d"]

res4 = arr.filter( (elem, index) => {
    return index % 2 == 0
})

console.log(res4)
// ["a", "c"]
```

**▼ポイント**
filterはtrueかfalseを返す必要があるため、if
のカッコ内の条件式と異なり**returnが必要**。
NetlifyにデプロイしたサイトからXserver上のWordpressのREST APIを実行する際にはまった

Xserverの設定で`REST API アクセス制限`をOFFにする必要があった
![IMG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252168/29c7bbce-97dd-db8f-d993-317b6e871293.png)
データ分析コンペに初めて参加してみた[nishika]

# はじめに
　データサイエンティストへ職種を変え、学習の一環として、nishikaの「Jリーグ出場時間予測」コンペに参加しました。本記事では、コンペ参加までの学習内容、コンペの内容・感想を紹介します。

# 学習内容
　前職はインフラエンジニアで運用保守を行っていました。そのため、プログラミング言語に触れた経験も無かったため、Pythonの基礎から学習できる教材として、「[東京大学のデータサイエンティスト育成講座](https://books.google.co.jp/books/about/%E6%9D%B1%E4%BA%AC%E5%A4%A7%E5%AD%A6%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B5%E3%82%A4%E3%82%A8%E3%83%B3%E3%83%86.html?id=34K3DwAAQBAJ&source=kp_book_description&redir_esc=y )」を購入し、読み進めました。

　本書籍は機械学習のための統計数学も説明があり、ハンズオン形式で学習が可能であることなど、未経験の方でも学びやすい教材かと思います。学習モデルはsklearnのみですが、検証やパラメータチューニングまで網羅しています。

　その他の学習モデルとして、先輩方からLightGBMを紹介されたので、ネットの情報を頼りに学習を行いました。

# コンペ概要
- Jリーグ選手の出場時間予測（https://www.nishika.com/competitions/6/summary ）
　開幕時のJ1選手データから、その年の試合出場時間合計を予測するテーブルデータの回帰問題

- 期間：2020年8月〜2020年10月、参加者数：409名

- 評価指標：RMSE
- データ：
　訓練データは2016年～2018年のJ1選手データ（1414行 × 37列）
　テストデータは2019年のJ1選手データ（488行 × 37列）
　その他、1試合毎の出場時間、退場記録や、チーム移籍情報のjsonファイル
　※異常値あり（年俸の欠損、国名のtypo など）

- 特徴量：
　数値は年俸、身長、体重、誕生日、過去3年間各々の出場時間合計・出場試合数など
　カテゴリは国籍、在籍チーム、登録ポジション、ユース経験、過去3年間各々の在籍チームなど

# 取り組み
　学習モデルは LightGBM 、パラメータチューニングは Optuna を利用し、特徴量エンジニアリングで精度を向上させていきました。有効だった特徴量は以下の通りです。

- チーム×ポジション毎の順位付け
　試合に出場するか否かは、チーム内、更には同一ポジション内での相対評価で決まると考えて、年齢や身長などの特徴量をチーム内での順位、またはチーム×ポジション内での順位に変換した特徴量を追加した。

- ポジション毎の予測値
　ポジション毎に有効な特徴量は異なる(例えば、過去の得点数はGKには有効では無く、FWには有効である...等)と考え、ポジション毎に学習したモデルを使い特徴量を生成した。

- 選手移籍情報の予測値
　その他のデータである選手移籍情報を用いて、開幕情報の選手データから、その年に移籍するか否かを予測するモデルを作成した。その予測値を特徴量として追加した（リークを防ぐように気を付けていたら、上手く検証ができなくなってしまいました）。

# 最終結果
- 5位 （409名中）
　検証ができなかったため、「選手移籍情報の予測値」を追加した予測結果は最終提出に選びませんでしたが、この予測結果の最終スコアは2位に位置する精度でした。

- 上位者の解法
    - CVは選手名でのGroupKFold
    - モデルはLightGBM、CatBoost、XGBoost、RandomForest のいずれかの組合せのアンサンブル
    - 欠損値の処理（出場時間の近い選手の値、過去3年間いずれかの出場時間であれば前後の値から補完など）

# 感想
- nishika について
    - 2019年12月にオープンした比較的新しい日本のコンペサイト  
    ※Jリーグの出場時間予測では、コード共有や議論はあまり活発では無い印象でした。  
<br/>
    - 現在、開催中のコンペは下記の通り
        - 判例の個人情報の自動マスキング(https://www.nishika.com/competitions/7/summary )
        - クラシック音楽の作曲家分類(https://www.nishika.com/competitions/8/summary )


- コンペに参加してみて良かったこと

    - ドメイン知識の取得  
    　特徴量を作る上で、J1、J2の試合数や移籍する選手が多いなどのJリーグに関する知識が得られました。この経験により、全く知らない業界の知識を調べることへの抵抗感は無くなったかと思います。  
<br/>
    - データ分析の面白さ  
    　与えられたデータを確認し、仮説・検証を行い、精度として結果がでる一連の流れを経験できました。特に仮説・検証では、アイデアを形にして、結果を見るという点に魅力を感じました。
【Stereo Depth】GwcNet : Group-wise Correlationで

<h1>Group-wise Correlation Stereo Network</h1>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/c134ec33-57c7-3385-57b5-587036939008.png)
Correlationとは右と左の特徴量の相関性の事を良い、内積によって求める事が多い。
しかし、内積を使うと情報を失うというデメリットがあった。
そこでこの論文ではGroup-wise Correlationという方法を提案している。

<h1>先行研究の振り返り</h1>
<h2>Correlation</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/d038782a-023f-8e0a-a6d5-8a38b059f0a2.png)
右と左のFeatureの内積を取ることでChannel方向の特徴量を1つ(matching cost)にまとめる。
その作業を取り得るすべてのDisparityに対して行う事でCcorr(d,x,y)の3D Feature Map得られる。

<h2>Concatenate</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/4b1cd292-5d3c-d35a-2833-e7242106d158.png)
右と左のFeature MapをChannel方向に結合することで右と左の特徴量を失わずに済む。
その作業を取り得るすべてのDisparityに対して行う事でCconcat(d,x,y,2*c)の4D Feature Map得られる。

<h1>新規性</h1>
<h2>Group-wise Correlation</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/234dfc41-eeb7-ae63-f51c-2c4757387c52.png)
Correlationは内積を取るのですべての特徴が1つにまとめられてしまう。情報が欠如するから、内積を取るのをNg個のグループに分けて行おう！
Ng = 1の場合 =>Correlationと同じ完全な内積
Ng = Ncの場合 =>特徴量同士の掛け算で、それぞれ足さずに独立のMatching Costとして残しておく

Ngが1に近づくと情報量が減り、NgがNcに近づくと情報量が多くなり後々の計算量が大きくなる


<h1>結論</h1>
・CorrelationとConcatenationを合体させる事で効率的に学習をする事が出来る。
・Group-wise-CorrelationをすることでCorrelationのデメリットであった情報の損失を回避することが出来るようになった。

<h1>参考文献</h1>
Group-wise Correlation Stereo Network
https://arxiv.org/pdf/1903.04025.pdf
マルチスケールシミュレーション特論

\![Mac OS X-10.15.7](<https://img.shields.io/badge/MacOSX-10.15.7-brightgreen>) \![ruby-2.7.1p83](<https://img.shields.io/badge/ruby-2.7.1p83-brightgreen>) 


# equation <span class="timestamp-wrapper"><span class="timestamp">&lt;2020-10-28 Wed&gt;</span></span>

$$\frac{1}{4}$$


# qiita\_links

1.[README.org](https://qiita.com/Kazufumi0823/items/37ad0e3f302a09bbc339)

2.[Emacsのコマンド操作](https://qiita.com/Kazufumi0823/items/ec08c05bb19feef4fd22)

3.[第４回](https://qiita.com/Kazufumi0823/items/96446a28356680570a04)

4.[第５回](https://qiita.com/Kazufumi0823/items/3b9992ec7edfc2b28f22)

5.[第６回](https://qiita.com/Kazufumi0823/items/bbed8090ccf3ced554ba)

6.[第７回](https://qiita.com/Kazufumi0823/items/da7cde24078524239475)

7.[assert\_equal](https://qiita.com/Kazufumi0823/items/0875dad007ee96d48fd9)

[roman numerals](https://qiita.com/Kazufumi0823/items/24ef9faae3ecce28ec64)



------
 - **source** ~/grad_members_20f/members/Kazufumi0823/README.org
データカタログを使う（ガバナンス・ルール 基本編）

##ガバナンス・ルールとは
[データカタログを使う（ポリシー基本編）](https://qiita.com/takayuki-yamamoto/items/0c9452fa30ef013b9575 "データカタログを使う（ポリシー基本編)")でご紹介したポリシーとの区別がとても分かり難いのですが、ガバナンス・ルールは、ポリシーに準拠しているかどうかを判断するために使用する基準であり、行動を自然言語で記述したものです。

これは、具体例を見た方が分かりやすいと思います。例えば、ポリシーとして、**情報の保護**を定義したとします。

####ポリシーの例
<dl>
  <dt>情報の保護ポリシー</dt>
  <dd>データの安全性を確保し、プライベートデータを不正使用や開示から確実に保護し、データへの不正アクセスを防止するための要件に対応しなければならない。</dd>
</dl>
これに対して、ガバナンス・ルールは、具体的にはどのようなデータを保護するのかを定義したものです。
####ガバナンス・ルールの例
<dl>
  <dt>個人情報(PII)の匿名化/マスキングの実施</dt>
  <dd>個人情報(PII)に分類されたデータは、匿名化・マスキングを施したうえで、閲覧・分析として利用することが可能。オリジナルのデータの閲覧には、管理者の承認が必要となり、その承認プロセスは記録しなければならない。</dd>
</dl>

このように、ガバナンス・ルールでは、より具体的に何をすべきかを記載します。

ガバナンス・ルールを作成する際には、名前と説明を付けます。また、ガバナンス・ルールの関連するポリシー、関連するデータ資産も紐付けます。

##ガバナンス・ルールの作成方法
ここでは、IBM Cloud Pak for Data(CP4D)のWatson Knowledge Catalog(WKC)を例に、新しいガバナンス・ルール作成方法をご紹介します。
CP4Dにログインした直後の画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/07089994-5af0-aea6-3eef-b43af5b8f16e.png)
左上にあるメニューボタンを押して、ガバナンス -> ルールを選択します。
![スクリーンショット 2020-12-09 14.55.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/9fbf8590-0212-339e-5076-cea6631c1dcf.png)
右上にある新規ルール -> 新規ルールの作成を押します。なお、今回はご紹介しませんが、ルール定義のファイルインポートも対応しています。
**データ保護ルール**と**ガバナンス・ルール**を選択できる画面が表示されます。データ保護ルールに関しては、別の記事でご紹介いたします。
ここでは、**ガバナンス・ルール**を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/846c0c61-09fb-5bc5-8a0e-60ae0b7a5d05.png)
ガバナンス・ルール名とそのガバナンス・ルールが属するカテゴリーを選択します。また、そのガバナンス・ルールの定義を記入し、ドラフトとして保存を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/bce4aa64-327f-021d-072e-43cbf38e376e.png)
ガバナンス・ルールがドラフトとして保存されました。CP4DのWKCは、ガバナンス・ルールは**公開済**と**ドラフト**の状態で管理されます。**ドラフト**の状態場合、ユーザーには見えない状態となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/fd07b0e4-4759-52b3-1205-5f27cda90f6d.png)

また、ガバナンス・ルールはポリシーに紐付けて管理します。ここでは、親ポリシーに、事前に定義した**P03-01) 情報の保護**を指定することにします。親ポリシーの横にある＋ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/b2fb6374-466b-54a2-7feb-21e6da4e325c.png)

親ポリシーが追加されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/617bdf5f-8f8d-4fca-eefb-ce08161a6056.png)

ガバナンス・ルールは、1次カテゴリーとしてメインのカテゴリーの他に、複数のカテゴリーに２次カテゴリーを指定して保存することができます。
ここではブランクのままにします。

必要な情報を設定したら、右上にある公開ボタンを押します。
コメントを残して、公開するボタンを押すと、ポリシーがドラフト状態から公開済みとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/571926/bd12e6bc-758f-148d-c030-a91384bc5015.png)

デフォルトの設定では、公開ボタンを押すと、そのまま公開済みになりますが、CP4DのWKCのワークフロー機能を利用すれば、適切な承認プロセスを経て、ガバナンス・ルールを公開するようなフローを作成することもできます。

以上で、ガバナンス・ルールを作成いたしました。
【C#】DevExpressのSpreadSheetControlで共有ファイルを読み込みまたは保存する。

DevExpressのSpreadSheetControlで、LoadDocument(FileName)を使い共有ファイルを読み込み及び保存する際、多数のユーザーがファイルに接近することが可能になります。
この場合、共有ファイルが壊れてしまうことがよくあります。
このような状況を防ぐため、該当ファイルが使用中である場合、他のユーザーの接近を防止する処理が必要です。
その処理方法は以下の通りです。

```
//LoadDocument(FileStream, DocumentFormat)を使用
SpreadsheetControl sheetCtrl = new SpreadsheetControl();
IWorkbook workbook = sheetCtrl.Document;
FileStream fileStream = null;

try
{
    fileStream = new FileStream(outputPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
    sheetCtrl.LoadDocument(fileStream, DocumentFormat.Xlsx);
}
catch(IOException ex)
{
    ex.toString();
}

```

また、FileStreamで読み込みしたデータを加工し、保存する場合は下記のように処理すればよいです。

```
//LoadDocument(FileStream, DocumentFormat)を使用
SpreadsheetControl sheetCtrl = new SpreadsheetControl();
IWorkbook workbook = sheetCtrl.Document;
FileStream fileStream = null;

try
{
    fileStream = new FileStream(outputPath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
    sheetCtrl.LoadDocument(fileStream, DocumentFormat.Xlsx);

　/*
　　FileStreamで保存する場合、追加されたデータの保存をエラーとして認識するため、保存直前fileStream.SetLength(0)を追加します。
　*/
    fileStream.SetLength(0); 
    sheetCtrl.SaveDocument(fileStream, DocumentFormat.Xlsx);
}
catch(IOException ex)
{
    ex.toString();
}

```
@nestjs/swagger Responseの種類

@nestjs/swaggerのResponseは様々な種類があるが、http statusがどれかいちいち調べるのがめんどくさかったのでまとめた。

| code | function | description |
|:-----------|:------------|:------------|:------------|
|200|ApiOkResponse|リクエストが成功したことを示します。|
|201|ApiCreatedResponse|リクエストは成功し、その結果新たなリソースが作成されたことを示します。|
|202|ApiAcceptedResponse|リクエストは受理されたが、まだ実行されていないことを示します。|
|204|ApiNoContentResponse|リクエストに対して送信するコンテンツはありませんが、ヘッダーは有用であることを示します。|
|301|ApiMovedPermanentlyResponse|リクエストされたリソースの URL が永遠に変更されたことを示します。|
|400|ApiBadRequestResponse|構文が無効であるためサーバーがリクエストを理解できないことを示します。|
|401|ApiUnauthorizedResponse|HTTP 標準では "unauthorized" (不許可) と定義されていますが、意味的にはこのレスポンスは "unauthenticated" (未認証) です。つまり、クライアントはリクエストされたレスポンスを得るためには認証を受けなければなりません。|
|403|ApiForbiddenResponse|認証されていないなどの理由でクライアントにコンテンツのアクセス権がなく、サーバーが適切なレスポンスの返信を拒否していることを示します。|
|404|ApiNotFoundResponse|サーバーがリクエストされたリソースを発見できないことを示します。|
|405|ApiMethodNotAllowedResponse|サーバーがリクエストメソッドを理解しているものの、無効にされており使用することができません。|
|406|ApiNotAcceptableResponse|このレスポンスは、ウェブサーバーが サーバー駆動型コンテンツネゴシエーション を行った結果、ユーザーエージェントから与えられた条件に合うコンテンツが見つからない場合に送信されます。|
|408|ApiRequestTimeoutResponse|このレスポンスはクライアントが以前にリクエストを行っていない、アイドル状態のコネクションにおいて一部のサーバーが送信します。サーバーは使用していないコネクションの終了を望むことを示します。|
|409|ApiConflictResponse|このレスポンスは、リクエストがサーバーの現在の状態と矛盾する場合に送られるでしょう。|
|410|ApiGoneResponse|このレスポンスは、リクエストされたコンテンツがサーバーから永久に削除され、転送先アドレスがない場合に送られます。|
|413|ApiPayloadTooLargeResponse|リクエストの本体がサーバーで定めている上限を超えていることを示します。|
|415|ApiUnsupportedMediaTypeResponse|リクエストされたデータのメディア形式をサーバーが対応しておらず、サーバーはリクエストを拒否したことを示します。|
|422|ApiUnprocessableEntityResponse|リクエストは適正ですが、意味が誤っているために従うことができません。|
|429|ApiTooManyRequestsResponse|ユーザーは一定の時間内に大量のリクエストを送信しました ("レート制限")。|
|500|ApiInternalServerErrorResponse|サーバー側で処理方法がわからない事態が発生したことを示します。|
|501|ApiNotImplementedResponse|リクエストメソッドをサーバーが対応しておらず、扱えないことを示します。|
|502|ApiBadGatewayResponse|このエラーレスポンスは、リクエストの処理に必要なレスポンスを受け取るゲートウェイとして動作するサーバーが無効なレスポンスを受け取ったことを示します。|
|503|ApiServiceUnavailableResponse|サーバーはリクエストを処理する準備ができていないことを示します。|
|504|ApiGatewayTimeoutResponse|このエラーレスポンスは、ゲートウェイとして動作するサーバーが時間内にレスポンスを得られない場合に送られます。|
|default|ApiDefaultResponse||


statusコードの詳細は以下を参照
https://developer.mozilla.org/ja/docs/Web/HTTP/Status
『Cookieを有効にしてください』ってなによ。

<h3>[こんな方向け]

・オンラインショッピングなどで『Cookieを有効にしてください』という
メッセージをひゃくおくまんかい見てきた

・意味がわからず怖くなってページを閉じてしまったことがある

・なんかモヤッとしていて理解できていない



<h4>今回は、この憎たらしい『Cookie』とはなんなのか、有効にするとどうなるのか
を解説していきます。

<h1>
<h3>[内容]

<h4>・Cookieとは？
<h4>・有効にするとどうなるのか

<h1>

<h2>・Cookieとは？

<h5>『あなたがネット上で記入した記録などを保存してくれる』</h5>

という便利なものです。



例えば...
ネットショッピングの際に、『カートに入れる』を押したら『❶』のようにカートの右上
あたりに何かしらマークがつきますよね。（カートに商品が入っていますという表示）

このマークが、あなたがパソコンを閉じたり、ログアウトした時に
いちいち消えてしまったら大変ではないですか？

カートに入れる行為を最初からやり直し、気付いたらまたリセットされていた
なんてことが起きたら悪夢です。

しかしそのようなことはほとんど起こりません。

一度カートに入れると、ログアウトしても
パソコンをシャットダウンしても記録が残っていることがほとんどでしょう。

<h6>このように、あなた（ユーザー）がネット上で打ち込んだ情報などを記憶しておく機能が
Cookieです。


<h2>・有効にするとどうなるのか？

<h3>[有効にする＝記憶できるようにする]

ということです。


『Cookie』を有効にしないと、買い物が始められないなんてことがあります。

なぜなら、Cookieを有効にして『記憶する機能』を発動させてあげないと、お買い物の情報や
会員ログイン機能の情報を記録できないため、店側も客側も不便極まりないからです。


読んでくれてありがとう。
お疲れ様。
Apache Camelを通じて、Boxからファイルのダウンロード

pom.xmlに依頼の導入：

```
<dependency>
    <groupId>org.apache.camel</groupId>
    <artifactId>camel-box</artifactId>
    <version>${camel-version}</version>
</dependency>
```



使い方(例)：
ルートの書き方：

```
...
String fileId=...;
String fileName=...;
...
from("direct:foo")
    .setHeader("CamelBox.fileId", constant(fileId))
    .setHeader("CamelBox.output", constant(output))
    .to("box://files/download")
    .to("file://...");
```

注意点：
**ダウンロードのBoxファイルのリンクと目的のローカルのリンクは".to()"の中に書く。**

ルートの使用：
.to("direct:foo")で呼び出すことが可能ですが、
別のルートを使わない場合：

```
try{
　　　template.sendBody("direct:foo", "This is a test message,please download the file");
}catch(CamelExecutionException e){
     System.out.println(e);
}
```

"direct"はcamelの二つコンポネートの間に連携用のコンポネートです。
"direct:foo"について、"foo"をほかの自分で定義する名でも可能です。


Camel Box:
https://camel.apache.org/components/latest/box-component.html
Camel direct:
https://camel.apache.org/components/latest/direct-component.html
ポート番号とは

##ポート番号とは
ポート番号とは、webサイトを閲覧したり、データベースとやりとりするなど、アプリケーションと会話するための番号のことです。

##Webサイトを閲覧する場合に例えると
マンションを例に説明すると、
・住所の番地までが「IPアドレス」
・部屋番号が「ポート番号」
です。

Webサイトを閲覧したい時は、通常80番の部屋番号（ポート番号）を利用する。
メールの送受信をしたい時は、25番または110番の部屋番号（ポート番号）を利用する。


##代表的なポート番号

```
TCP 20 : FTP (データ)
TCP 21 : FTP (制御)
TCP 22 : SSH
TCP 23 : Telnet
TCP 25 : SMTP
UDP 53 : DNS
UDP 67 : DHCP（サーバ）
UDP 68 : DHCP（クライアント）
TCP 80 : HTTP
TCP 110 : POP3
UDP 123 : NTP
TCP 443 : HTTPS
```

##ポート番号の種類
ポート番号は、0から65535まで存在します。

###ウェルノウンポート番号（0~1023）
通信方式（プロトコル）により登録されています。
TCP/IPやUDPにおいて通信で利用されるポート番号のうち、メジャーなサービスやプロトコルが利用するために予約されているポート番号のこと。
80がHTTP、22がSSHとあるように、メジャーなサービスはポート番号が一般的に決め打ちされている。
サービスごとに設定ファイルを編集し、変更することも可能だが、基本的にはウェルノウンポート番号を使用するようにする。

###登録済みポート番号（1024~49151）
アプリケーションにより登録されている。
特定のアプリケーションなどが使用することになっているポート郡です。

###ダイナミック・プライベートポート番号（49152～65535）
ユーザが自由にとりあつかえるポート番号です。
Ruby初心者のメモ



# 概要

Ruby初心者のメモ.


# qiitaのリンク集

1.  [README.org](https://qiita.com/Takahiro-Nishikawa/items/6321decb019ad0303a97)
2.  [入力と出力](https://qiita.com/Takahiro-Nishikawa/items/bdc631ed8742f76ed47d)
3.  [変数とメソッド](https://qiita.com/Takahiro-Nishikawa/items/4ba469eb8bb3656e3b9b)
4.  [leap\_year](https://qiita.com/Takahiro-Nishikawa/items/46aa11ff50eaf4cedbfd)
5.  [assert\_equal](https://qiita.com/Takahiro-Nishikawa/items/6f43b0eaa57984846759)
6.  [fibonacci](https://qiita.com/Takahiro-Nishikawa/items/6cd83f29868759736a57)
7.  [hello\_class](https://qiita.com/Takahiro-Nishikawa/items/9527634af49cc09feb5b)　
8.  [roman numerals](https://qiita.com/Takahiro-Nishikawa/items/6de0e6c3486ba22d38d5)



------
 - **source** ~/grad_members_20f/members/Takahiro-Nishikawa/README.org
Androidで白い影を削除する方法

# 目次
1. はじめに
2. 実装方法
3. まとめ

# はじめに
今回はFlexScrollContainerウィジェットをAndroidで使用する際に、
デフォルトで白いインナーシャドウが付いてしまいます。

以下の動画だと**Test5**の文字にシャドウがかかっています。
<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/cRq8cezW1c">pic.twitter.com/cRq8cezW1c</a></p>&mdash; Kony (@Kony12763790) <a href="https://twitter.com/Kony12763790/status/1336540875715801094?ref_src=twsrc%5Etfw">December 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

上記のインナーシャドウの削除の方法について、
ウィジェットのプロパティリストに表示されないため、
記事にて紹介しようと思います。

# 実装方法
FlexScrollContainerでshowFadingEdgesをfalseにすることで、
上記のインナーシャドウを削除することができます。

showFadingEdgesはFlexScrollContainerのエッジ部分にシャドウ表示するか設定するメソッドになります。
[FlexScrollContainer Properties **#showFadingEdges**](https://docs.kony.com/konyonpremises/Subsystems/Widget_User_Guide/Content/ScrollBox_Platform_Specific_Properties.htm#showFadi)

本記事の作成の際はFormのpreShowにて以下処理を呼び出すように実装しました。

```Form1Controller.js
  preShow: function() {
    this.view.flxTest.showFadingEdges = false;
  }
```

![スクリーンショット 0002-12-09 14.22.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/0ba5247e-e7d4-7eca-da55-cb955d35b12f.png)

実装後の動作はこうなります。
<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/BYyYJDyucL">pic.twitter.com/BYyYJDyucL</a></p>&mdash; Kony (@Kony12763790) <a href="https://twitter.com/Kony12763790/status/1336543328578404353?ref_src=twsrc%5Etfw">December 9, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

👆の動画だと**Test5**の文字がはっきりと表示されるようになりました！

# まとめ
今回は、AndroidのFlexScrollContainerに付く白いインナーシャドウの削除方法を説明しました。
FlexScrollContainerの白いインナーシャドウはこのように削除可能なため、柔軟にUI編集が可能です！
ぜひ試してみてください:wave:
GCEのCent(7/8)でyum/dnfの自動updateがデフォルトonだった

タイトル通りなんですが結構衝撃だったので。


### 環境
ちょっとした趣味でGCEでCent7のインスタンスにtd-agentを入れ、実行ユーザをrootにして走らせてました。
rootで実行さすことの是非は今件では特に問いません。

### 何かトラブルですか
特に何も特殊な操作をした覚えがないというかログインさえしていないのに、
GCEダッシュボードを見ると、「パフォーマンス向上したほうがええで」との推奨事項。
ログインしてみるとCPU使用率が90%超え。

### 原因
どうにもtd-agentがめっちゃCPU使ってるっぽい。
でも今までtd-agentがこんな困ったちゃんだった経験はない。
色々確認してみると、確かに実行ユーザをtd-agentからrootに変更して実行したはずなのにtd-agentになってる。
td-agent.serviceもどうにもデフォルトに戻ってる。

td-agent.serviceの更新時間近辺のmessagesログを見ると、何故かsystemdのReloadが走っていて、
td-agentプロセスを殺そうとしてpermission deniedが出ており、にも関わらずtd-agentがupdateされたっぽいログが。
一瞬ｽﾊﾟｰﾊｶｰか！？と思いかけたが、secureログは特におかしいところなし。

### 犯人
list-unit-files確認したら入れた覚えのないyum-cronが鎮座してた上にapply_updatesがyesでした。
cent8でもdnf-automatic.timerがデフォルトで鎮座してます。apply_updatesはやっぱりyesです。

### 結論
勝手にminimalだと信じるのは やめよう。
fibonacci



# 目標

　fibonacci数列を求めるプログラム(fibonacci.rb)を使い,再帰を理解する.


# 解説


## フィボナッチ数列とは

フィボナッチ数列(fib(n))は以下の漸化式で表すことが出来ます.

    fib(0)=0
    fib(1)=1
    fib(n+2)=fib(n)+fib(n+1)　n>=0

これらを求めるプログラムを作っていきます.


## fib(0) = 0の時

フィボナッチ数列の初項を表示します．

```ruby
def fib(n)
  if n==0
    return 0
  end
end
```

その際に前回assert\_equalを使い,第1項と第2項とそれ以外を判定するものを作成します.

```ruby
require './assert_equal_final.rb'
puts assert_equal(0, fib(0))
```

requireで他のプログラムを持ってくることが出来ます.


## fib(1) =1の時

次は第2項を表示します.

```ruby
def fib(n)
  if n==0
    return 0
  end
  if n==1
    return 1
  end
end
```

ここから配列を使ってテストを行っていきます.

```ruby
require './assert_equal_final.rb'
[[0,0],[1,1]].each do |pair|
  puts assert_equal(pair[0], fib(pair[1]))
end
```


## fib(2) = fib(1) + fib(0) = 1の時

次は第3項を表示していきます.

```ruby
def fib(n)
  if n==0
    return 0
  end
  if n<=2
    return 1
  end
end
```

それに伴って配列の受け取り方を少し変えます.

```ruby
require './assert_equal_final.rb'
[[0,0],[1,1],[2,1]].each do |index, expected|
  puts assert_equal(expected, fib(index))
end
```

第3項を表示するプログラムは以下のように簡略化できます.

```ruby
def fib(n)
  return 0 if n==0
  return 1 if n<=2
end
```


## fib(n+2) = fib(n) + fib(n+1)

一般項はfib(n) = fib(n-1) + fib(n-2)として扱います.

```ruby
require './assert_equal_final.rb'
def fib(n)
  return 0 if n==0
  return 1 if n==1
  return fib(n-1)+fib(n-2)
end
[[0,0],[1,1],[2,1],[3,2],[4,3],
[5,5],[6,8],[7,13],[8,21],[9,34],
].each do |index,expected|
  puts assert_equal(expected, fib(index))
end
```

    >expected :: 0
    >result   :: 0
    >succeeded in assert_equal.

    >expected :: 1
    >result   :: 1
    >succeeded in assert_equal.

    >expected :: 1
    >result   :: 1
    >succeeded in assert_equal.

    >expected :: 2
    >result   :: 2
    >succeeded in assert_equal.

    >expected :: 3
    >result   :: 3
    >succeeded in assert_equal.

    >expected :: 5
    >result   :: 5
    >succeeded in assert_equal.

    >expected :: 8
    >result   :: 8
    >succeeded in assert_equal.

    >expected :: 13
    >result   :: 13
    >succeeded in assert_equal.

    >expected :: 21
    >result   :: 21
    >succeeded in assert_equal.

    >expected :: 34
    >result   :: 34
    >succeeded in assert_equal.


# 参考にしたサイト

この記事を書くために以下のサイトを参考にしました.[チャート式ruby-V(Recursive Fibonacci)](https://qiita.com/daddygongon/items/1bb27b8920c201d5c520)



------
 - **source** ~/grad_members_20f/members/Takahiro-Nishikawa/ruby_fibonacci.org
leap_year



# 目標

rubyでのif,caseなどを,うるう年かどうか判定するプログラム(check\_leap\_year.rb)を用いて理解する.


# 解説


## うるう年(4年に1度)

西暦で4の倍数の時うるう年になるので,4の倍数であればtrue,違えばfalseと返すものを作ります.まずはrubyでif,else\_ifがどういう風に記述されるのかを確認します.

```ruby
if 式 [then]
  式 ...
[elsif 式 [then]
  式 ... ]
...
[else
  式 ... ]
end
```

thenの部分は省略可能です.では,これに伴って作ってみます.

```ruby
if year%4 == 0
  p true
else
  p false
end
```


## うるう年(完全版)

先ほどのものに加えて,西暦で100の倍数はうるう年ではなく,400の倍数はうるう年として扱うものにしていきます.

```ruby
p year = ARGV[0].to_i
if year%400 == 0
  p true
elsif year%100 == 0
  p false
elsif year%4 == 0
  p true
else
  p false
end
```

.to\_iはARGで受け取ったものをintに変換するものです.


# array,each,case


## array,each

先ほどのものを使ってテストを自動化していきます.その際はarray,eachを使います.arrayは配列になります.具体的な使い方は以下の通りです.

```ruby
[1, 2, 3].each do |i|
puts i
end
```

    >1
    >2
    >3 

各要素に対してブロックを評価します.ブロックが与えられなかった場合は、自身とeachから生成したEnumerator オブジェクトを返します.配列の中身を順番に処理するときには,上記のような記法が用いられます．rubyでdo-loop内で使う値は'|i|'のように縦棒で挟まれた変数名に入っていきます．これらを使って作成していきます.

```ruby
def leap?(year)
  if year % 400 == 0
    p true
  elsif year % 100 == 0
    p false
  elsif year % 4 == 0
    p true
  else
    p false
  end

end
[2000,2004,1999,1900].each do |year|
  p year
  leap?(year)
end
```

mainでloopしてpしています.

    >2000
    >true
    >2004
    >true
    >1999
    >false
    >1900
    >false


## case

caseを使って先ほどのコードをさらに短くすることが出来ます.caseの使い方は以下の通りです.

```ruby
case [式]
[when 式 [, 式] ...[, `*' 式] [then]
  式..]..
[when `*' 式 [then]
  式..]..
[else
  式..]
end
```

これを用いてコードを作っていきます.

```ruby
def leap?(year)
  case
  when year % 400 ==0 ; true
  when year % 100 ==0 ; false
  when year % 4 ==0 ;   true
  else ;                false
  end
end

[2000, 2004, 1999, 1900].each do |year|
  p year
  p leap?(year)
end
```


# 参考にしたサイト

この記事を書くために以下のサイトを参考にしました.[チャート式ruby-III(if, case, Array.each by leap year)](https://qiita.com/daddygongon/items/a550bde1ed6bff5217d8)



------
 - **source** ~/grad_members_20f/members/Takahiro-Nishikawa/ruby_leap_year.org
Rubyの変数とメソッド



# 目標

Rubyのvariable(変数),methodについて理解する.TDD(テスト駆動開発)の進め方を学ぶ.


# 解説


## 変数の取り扱いについて

まず、受け取った引数ARGV[0]をnameという変数(variable)に代入してそれを打ち出すコード,name\_variable.rbを作成します．以下はコードになっています.

```ruby
name = ARGV[0]
puts "Hello #{name}."
```

Rubyには型宣言をせずに書くことが出来ます.Rubyの変数は型を持たないらしいです.このコードを動かしてみると&#x2026;

    >ruby name_variable.rb Taro
    Hello Taro.

無事,出力されました.


## Methodについて

関数などのまとまりにするには定義(definition)が必要です.先ほどのコードをmethodにしてみましょう.

```ruby
def hello name
  puts "Hello #{name}"
end
name = ARGV[0]
hello(name)
```

Rubyでは字下げはあまり気にしないそうですが,2文字分字下げするのが主流だそうです.同様にターミナルで動かしてみます.

    >ruby hello_method.rb Taro
    Hello Taro

無事出力されました.


# TDD(テスト駆動開発)


## TDDを用いた解法

先ほどのhello\_method.rbをTDDに基づいて作成していきます.

```ruby
hello(name)
```

まずはこれで動かしてみます.

    > ruby hello_method.rb Taro
    hello_method.rb:1:in `<main>': undefined local variable or method `name' for main:Object (NameError)

nameという変数が定義されていないというエラーが出てきます.なのでnameにARGV[0]を代入します．

```ruby
name = ARGV[0]
hello(name)
```

    > ruby hello_method.rb Rudy
    hello_method.rb:2:in `<main>': undefined method `hello' for main:Object (NoMethodError)

でhelloっていうmethodが定義されていないというエラーが出てきます．なので

```ruby
def hello name
  puts "Hello #{name}"
end
name = ARGV[0]
hello(name)
```

これを動かしてみると

    >ruby hello_method.rb Taro
    Hello Taro

無事出力されました.


# 参考にしたサイト

この記事を書くために以下のサイトを参考にしました.[チャート式ruby-II(variable and method)](https://qiita.com/daddygongon/items/c51f3e0695174bb3c508)



------
 - **source** ~/grad_members_20f/members/Takahiro-Nishikawa/ruby_variable_method.org
Rubyの入力,出力



# 目標

Rubyの入力,出力を理解する.


# 解説


## Rubyでの出力

まずはhello\_worldを出力するコード,hello\_world.rbを作成します．putsを使って出力していきます.以下はコードになります.

```ruby
puts 'hello world'
```

ターミナルでは以下のように動かします.

    > ruby hello_world.rb
    hello world

無事,出力されました.


## 出力の詳細

先ほどはputsで出力しましたが他にもいろいろあるそうです.

| method | 使用状況                            |
|:-------|:------------------------------------|
| print  | 普通に使う．要改行                  |
| puts   | 次に普通に使う. 自動改行            |
| p      | codingの最中にdebugがわりに打ち出すとき|
| pp     | pのpretty print, require 'pp'が必要 |
| printf | cのがあります．formatを整えるときに便利|


## Rubyでの入力

command lineから入力するときについてです.command lineから文字を受け取り,Hello ～～と出力するコードを作成します.今回はARGV[]を使って出力します.以下はコードになります.

```ruby
# putsの場合
puts "Hello #{ARGV[0]}."
```

ARGV[0]は引数の配列の0番目を意味しています.これをターミナルで動かしてみます.

    > ruby hello_name.rb Taro
    Hello Taro.

入力したTaroが出力されました.


## 入力,出力の詳細

ARGVを使った出力のさせ方はいろいろあります.

| puts  | puts "Hello " + ARGV[0]         |
|:------|:--------------------------------|
| puts  | puts "Hello #{ARGV[0]}"         |
| print | print "Hello #{ARGV[0]}\n"      |
| print | print "Hello " + ARGV[0] + "\n" |


## 出力をテキストファイルへ

出力を他のテキストファイルへ保存する際は以下の通りです．

    > ruby hello_name.rb Taro > hello_name.txt

cat(con-cat-inate)で中身を見ることが出来ます.

    > cat hello_name.txt
    Hello Taro.

無事,確認できました.


# 参考にしたサイト

この記事を書くために以下のサイトを参考にしました.[チャート式ruby-I(puts)](https://qiita.com/daddygongon/items/1b0f0ff3fb9d60418289)



------
 - **source** ~/grad_members_20f/members/Takahiro-Nishikawa/ruby_puts.org
React Native 環境構築メモ

# はじめに

React Nativeについて理解する必要があり、実行した内容を記録します。

基本的には下記を参考にしましたが、いくつか異なる手順を実施する必要がありました。

[【入門編】React Nativeとは？メリット・デメリットからHello, Worldまで](https://udemy.benesse.co.jp/development/app/react-native.html)

# 動作確認環境
- macOS Catalina 10.15.6

下記が既にインストールされているところから始めました。

- java/javac 14.0.2
- Xcode 12.2
- Homebrew 2.6.0
- node 15.3.0
- npm 7.0.15
- ruby 2.6.3p62
- gem 3.0.3

# インストール

## Watchmanインストール
```
brew install watchman
```
```
$ watchman --version
4.9.0
```
## React Nativeインストール
```
npm install -g react-native-cli
```

```
$ react-native --version
react-native-cli: 2.0.1
react-native: n/a - not inside a React Native project directory
```

## Cocoapodsインストール
上掲サイトのコマンドではインストールに失敗したため、下記サイトを参考にしました。

[ERROR: Error installing cocoapods: ERROR: Failed to build gem native extension](https://stackoverflow.com/questions/20939568/error-error-installing-cocoapods-error-failed-to-build-gem-native-extension)

```
brew cleanup -d -v 
brew install cocoapods 
```

```
$ pod --version
1.10.0
```

# プロジェクト作成

```
react-native init <Project Name>
```

```
cd <Project Name>
```

# プロジェクト実行

上掲サイトの手順のみでは実行出来なかったため、下記サイトを参考にしました。

[React native : Unexpected token in JSON at position 0](https://stackoverflow.com/questions/54168981/react-native-unexpected-token-in-json-at-position-0)

```
npm start -- --reset-cache
```

```
react-native run-ios
```

以上で、iOSエミュレータ上でのReact Nativeの実行までが確認できました。

# 最後に

今回の手順では参考にしませんでしたが、下記のQiitaの記事ではAndroid環境についても触れられています。

[【入門】はじめての React Native](https://qiita.com/nskydiving/items/41e446ef5c821359ab79)
Installer Projectsの、依存関係の更新を設定したい

[Microsoft Visual Studio Installer Projects](https://marketplace.visualstudio.com/items?itemName=VisualStudioClient.MicrosoftVisualStudio2017InstallerProjects)
依存関係がプロジェクトを読み込む度に更新される件。

# 課題
プロジェクトが複数あると、DLLが複数配置されるので、古いバージョンは、ExcludeでTrueにしておく。
例えば、System.Net.Httpのバージョン違いで、
4.0.0.0
4.2.0.0
の2つが、配置される。
セットアップする時、古いバージョンだと、不具合が発生するので、解消しておかないといけない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/ef85f34e-d9e3-e032-4c29-26fa0541e7b4.png)

けれども、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/d314160a-811f-67a2-4c6c-5ac17f7e39cb.png)

として、保存しておいても、再読み込みしたときには、更新されてしまい元に戻るようだ。
従って、ビルドする前に、その都度、設定し直さないといけない。

手作業で設定するDLLが大量にあるので、自動化したい。

# 結論
できませんでした！
あきらめます。
[WiX](https://wixtoolset.org/)を検討します。

Installer Projects（ほぼ更新停止状態だね）は、大規模なソリューションだと、だんだんつらくなってくるので、最初から、他の方法を採用すると良いかもしれません。

# 行ったこと
## 設定を書き換え
.vdprojファイルのテキストを読み込んで、同じDLLでバージョン違いは、ExcludeをTrueにするユーティリティを作成。
vdprojは、JSONぽいけどJSONではないです。これを、XMLに相互に変換するコードがあったので、それを利用しました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/cee5f009-d6f9-0840-566d-debd2ab1416e.png)

Exclude以外にもReadonlyなど、保存した設定は、依存関係で更新されたDLLに利用されないようです。
失敗。
先に、ユーティリティを作成してしまったのも、失敗だった・・・。手作業で試してみてからがよかった・・・

## Entryを削除
画像の例では、
_5C235C6F78D70C1873A72129C1E5F0A3
の、MsmKeyやOwnerKeyがあるので、それらを全て削除しても駄目。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/132059/07266aca-6ee8-5b4c-5cfb-4f8a19ab22a6.png)



# 参考
- https://stackoverflow.com/questions/8044840/how-come-the-exclude-property-of-the-assemblies-under-detected-dependencies-in
- https://stackoverflow.com/questions/3301316/vdproj-parser-wanted
- https://social.msdn.microsoft.com/Forums/windows/en-US/ee1d8bba-73cd-430c-8354-810558afb3de/exclude-filters-overwritten-on-detected-dependencies-when-reopening-project?forum=winformssetup
PowerPlatform環境の複製

#はじめに
はじめて環境を複製したときの方法を記録しておきます。

#今回の複製の対象
+ PowerApps
+ PowerAutomate
+ ポータル

#実施に必要なもの
+ PowerPlatform管理センター　[https://admin.powerplatform.microsoft.com/](https://admin.powerplatform.microsoft.com/)　を操作できるユーザ
+ 複製元の環境

#実施手順
###1. PowerPlatform管理センターにログインする
　　+ PowerPlatform管理センターにログイン
　　+ 環境から一覧を表示

###2. 複製先のサンドボックス環境を作る
　新規　→　名前：適当に登録。　種類：サンドボックス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/11fe646e-3ead-051d-bdff-e41d0592f10f.png)

###3. データベースを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/b329c0d6-d7fa-d467-57a4-05e7dadc2b6f.png)

###4. ポータルも移行する場合は、先にポータルを作っておく
ポータルを移行しない場合は、次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/0a8d3795-5222-4601-8af6-8341ee2e9be2.png)

###5. 環境をコピーする
コピー元の環境からコピーを選択しコピーを行う。
　　※コピーは、サンドボックス環境へのみ実行できます。
　　　運用環境　→　サンドボックス環境　または　サンドボックス環境　→　サンドボックス環境
　　　**運用環境へのコピーはできません！**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/38d33739-5c84-7f36-924a-f41a5cf9862d.png)
これで、テーブル（エンティティ）とデータが、サンドボックス環境にコピーされます。

###6. ポータルを移行する
以下の手順に沿って、マイグレーションツールを使用し、ポータル移行元からポータルデータをEXPORTし、そのデータをインポートします。
ポータル構成の移行 - Power Apps - Microsoft Docs
https://docs.microsoft.com/ja-jp/powerapps/maker/portals/admin/migrate-portal-configuration
※ポータル移行の詳細は別途投稿します。 (12/10投稿は、[こちら](https://qiita.com/sorayaredai/items/8170d33fb229e9e01c7a))
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/5489fba3-72fa-be62-60db-eaa618633a6f.png)
これで、ポータルが移行されます。

###7. PowerAutomateを移行する。
フローは一括以降はできません。一つづつ、EXPORTしてIMPORTする必要があります。
EXPORT結果は、ZIPになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/88337916-7396-0d1c-0b9b-ce366804bfb9.png)

###8. 接続設定を追加する。
CDSやO365,Teamsなど使っていた接続を追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/74f73aa8-947a-6151-397b-6cbcde87a5d8.png)

###9. PowerAutomateへインポートする。
エクスポートで作成したZIPファイルを選択してインポートする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/686b673c-2456-c716-3b41-cfc2b8ad8f3b.png)
インポートの設定を、更新から新しく作成するに変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/418815/36d25997-851c-c141-387e-493094a9173d.png)
関連リソースの設定を変更。上記で作成した接続が表示されるので、接続設定を変更する。
その後インポートを行う。
フローの数だけ実行する。

**以上で、環境がコピー完了**

参考サイト）環境のコピー　https://docs.microsoft.com/ja-jp/power-platform/admin/copy-environment
※　初心者の私が、docs等を参考に実施しただけですので記載内容に間違い等があれば、ご指摘いただけるとありがたいです。
【JS】メソッドチェーンで変数の宣言をletからconstに変更する。Assignment to constant variableの対処法。

letは変数の上書き（破壊処理）が可能なため、constの使用をメインとしたいが、複数回の処理のためにletを使わざるをえない場合の対処法について。


<br>

```
"TypeError: Assignment to constant variable."
```

>エラー内容：定数には値を代入できません。。

上記のようなエラーが発生し、constをletに変更しなくてはならなくなった場合に、メソッドチェーンを使うことで変数の宣言を変えることなく解決できる。


<br>
##対処事例
ある変数の各要素をmapやfilterなどで複数回処理する場合に、個別に記述する場合は`let`を使う必要がある。


```js:letを使っている場合
arr = [1,2,3,4]

let _arr = arr.map( elem => elem * 10)
_arr = _arr.filter( elem => elem % 20 == 0 )

console.log(_arr)
//出力
20
40
```

↓　メソッドチェーン


```js:メソッドチェーン
arr = [1,2,3,4]

const _arr = arr.map( elem => elem * 10)
                .filter( elem => elem % 20 == 0 )

console.log(_arr)
//出力
20
40
```

メソッドチェーンで１つの処理で記述すればconstで宣言してもエラーにならない。


<br>
チェーン化することを、チェイニング（chaining）という。
ライブラリとフレームワーク簡単にまとめてみた。

初学者です。今回がQiita初投稿です。
ライブラリーとフレームワークの違いがよくわからなかったので、いろいろとググってざっくりと簡単にまとめました。
書き方がすごく雑です。ごめんなさい。

#ライブラリ
**ライブラリとは再利用できる部品を集めた物。**

よく使いそうな特定の機能とかを個々が１から作るのは面倒だからみんなで使い回しましょうや！ってな感じ。

ここでいう部品とは、クラスや、メソッド（関数）のこと。

ライブラリ単品では意味をなさず、呼び出してシステムにはめ込むことで機能する。

プログラムを書いてる人が必要な時に呼び出す。

#フレームワーク
ライブラリと同じ、**部品（クラス、関数）の集まりなんだけど、そこに枠組みがあるかどうか**って違い。

何かを作る際の**手順が備わっている**イメージ。
railsだったらwebアプリケーションを作成するに当たっての雛形、枠組み。

一部をチョコチョコっと自分ではめ込んで実装していく。（ちなみにこのはめ込む場所をホットスポットというらしい。）

ライブラリとは違い、フレームワークがプログラムを書いた人のコードを呼び出す。

#制御の反転（ハリウッドの法則）
プログラマーによって呼び出されるライブラリーに対し、プログラマーのコードを呼び出すフレームワーク。

この立場が逆転になっていることを**制御の反転**という。

フレームワークは便利な反面、カスタマイズ性に乏しく枠組み外のことをすることはできない。これはある意味フレームワークに書かされているとも言える。

#参考にさせて頂いた記事、サイト
「ライブラリとフレームワークの違い。」
　　https://qiita.com/azuki8/items/ad7710fdefaedc63e3f7
　　https://small-is-beautiful.net/diff-library-and-framework/#toc9
　　https://note.com/bunkei_engeneer/n/n62f9ee01b2d1
「制御の反転」
　　https://ja.wikipedia.org/wiki/%E5%88%B6%E5%BE%A1%E3%81%AE%E5%8F%8D%E8%BB%A2
CapybaraでjQueryなしでAjaxの完了を待つ

RailsにjQueryがデフォルトで入っていた頃は、CapybaraでAjaxの終了を待つ時は、`wait_for_ajax`というメソッドを作って待っていたものでした。そこでは、`jQuery.active`を使って、Ajaxをしている最中か確認したものでした。こんな感じ。

```ruby
module WaitForAjax
  def wait_for_ajax
    Timeout.timeout(Capybara.default_max_wait_time) do
      loop until finished_all_ajax_requests?
    end
  end

  def finished_all_ajax_requests?
    page.evaluate_script('jQuery.active')&.zero?
  end
end

RSpec.configure do |config|
  config.include WaitForAjax, type: :feature # => ここも昔の名残…
end
```

しかし、時代は流れ、RailsからもjQuery依存が除かれ、rails-ujsになりました。さきほどの`wait_for_ajax`はjQuery依存の実装なので、現代のRailsプログラマは違う方法でAjaxを待たなければなりません。

# 環境について

筆者の環境

* Rails 6.0.3.4
* Webpacker使用

# どうやってAjaxを検知するか？

Ajaxを開始したらカウントアップ、Ajaxが終了したらカウントダウンする仕組みを作ればいいので、このようにしました。
rails-ujsのイベントに合わせてイベントリスナを定義し、そこでカウントアップ・カウントダウンします。

rails-ujsのイベント一覧は[こちら](https://railsguides.jp/working_with_javascript_in_rails.html#rails-ujs%E3%81%AE%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%83%8F%E3%83%B3%E3%83%89%E3%83%A9)。

`handleEvent`メソッドは、自分自身をリスナとして登録したときに自動的にコールバックとして呼ばれます。
https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener

```js
class AjaxRequestCounter {
    
    static start() {
        const _this = new AjaxRequestCounter()
        window.pendingRequestCount = 0
        document.addEventListener('ajax:send', _this)
        document.addEventListener('ajax:complete', _this)
    }

    handleEvent(event) {
        switch(event.type) {
            case 'ajax:send':
                pendingRequestCount++
                break

            case 'ajax:complete':
                pendingRequestCount--
                break
        }
    }
}

export { AjaxRequestCounter }
```

これを、`app/javascript/packs/application.js`から呼び出します。

```js
require("@rails/ujs").start()
require("turbolinks").start()
require("@rails/activestorage").start()

import { AjaxRequestCounter } from "../src/ajax_request_counter";
AjaxRequestCounter.start()
```

# テストで使えるようにする

あとは、`pendingRequestCounter`の値をチェックするようにすればいいので、`WaitForAjax`モジュールの中身を修正します。

```ruby
module WaitForAjax
  def wait_for_ajax
    Timeout.timeout(Capybara.default_max_wait_time) do
      loop until finished_all_ajax_requests?
    end
  end

  def finished_all_ajax_requests?
    page.evaluate_script('window.pendingRequestCount').zero?
  end
end

RSpec.configure do |config|
  config.include WaitForAjax, type: :system # => featurespecなら:featureにしてください。
end
```

これで、我々の手元に再び`wait_for_ajax`が戻ってきました！
curlのPOSTのレスポンスヘッダを取得する方法

以下のように `-D- -o/dev/null` を付与する。
意味は分かっていないw

```
curl -D- -o/dev/null --request POST '{URL}' --form '{パラメタ名}={値}'
```

参考
https://stackoverflow.com/questions/286982/curl-post-data-and-headers-only
django.core.mail　〜send_mail()とEmailMessageクラス〜

#はじめに
今DjangoでWebアプリケーションを作成しています。

その中でメール機能をつける事があったのでDjangoが持っているメール機能の内、代表的な二つの機能について説明したいと思います。

###環境
* Django3.1
* Python3.7

#django.core.mailとは？
Djangoが搭載しているメール機能が入っているモジュールです！
これをimportすることでDjangoが搭載しているメール機能を使用することが出来ます。

```python:python.py
from django.core.mail import [クラス/メソッド名]
```

#代表的なメソッド・クラス

##send_mail()
###引数
<dl>
<dt>subject *(必須）</dt>
<dd>件名</dd>
<dd>型：文字列</dd>

<dt>message *(必須）</dt>
<dd>本文</dd>
<dd>型：文字列</dd>

<dt>from_email *(必須）</dt>
<dd>送信者</dd>
<dd>型：文字列</dd>

<dt>recipient_list *(必須）</dt>
<dd>メール受信者のリスト</dd>
<dd>型：リスト or タプル</dd>

<dt>fail_silently</dt>
<dd>falseの場合、エラーが起きた際に例外クラスを発生させる。デフォルトはfalse。</dd>
<dd>型：ブール</dd>

<dt>auth_user</dt>
<dd>SMTPユーザー認証のためのユーザー名</dd>
<dd>型：文字列</dd>

<dt>atuh_password</dt>
<dd>SMTPユーザー認証のためのパスワード</dd>
<dd>型：文字列</dd>

<dt>connection</dt>
<dd>メール送信のために使うバックエンド</dd>

<dt>html_message</dt>
<dd>送信されるメールのコンテンツタイプ</dd>
</dl>

例）

```python:example_send_email.py
from django.core.mail import send_mail

send_mail(
    'Subject here', #件名
    'Here is message', #本文
    'from@example.com', #送信者のメアド
    ['to@example.com', 'to2@example.com'], #受信者のメアドリスト
    fail_silently = False, #エラーが起きた際にsmtplib.SMTPException例外クラスを発生
)
```

##EmailMessageクラス
先ほど説明したsend_email()では高度なメール機能を使えません（BCCやファイル添付など）。

そのため、Djangoで高機能なメールを使いたい場合はEmailMessageクラスのインスタンスを作成して使うことが一般的です。

###パラメータ
<dl>
<dt>subject</dt>
<dd>件名</dd>

<dt>body</dt>
<dd>本文</dd>

<dt>from_email</dt>
<dd>送信者のメアド</dd>

<dt>to</dt>
<dd>受信者のメアドのリスト、もしくはタプル</dd>

<dt>bcc</dt>
<dd>bccに設定するメアドのリスト、もしくはタプル</dd>

<dt>connection</dt>
<dd>メールバックエンドのインスタンス</dd>

<dt>attachments</dt>
<dd>メッセージに添付するファイルのリスト</dd>

<dt>headers</dt>
<dd>メッセージに追加するヘッダーの辞書</dd>

<dt>reply_to</dt>
<dd>Reply-Toヘッダ内で使われる受信者のアドレスのリストまたはタプル</dd>
</dl>

###メソッド
EmailMessageクラスは以下のメソッドが使えます！

<dl>
<dt>send(fail_silently=false)</dt>
<dd>メッセージを送信するメソッド。キーワード引数のfail_silentlyがTrueの場合は例外を発生させない。</dd>

<dt>recipients()</dt>
<dd>to, cc, bccに設定されているメッセージの全ての受信者のリストを返す。</dd>

<dt>attach</dt>
<dd>新しい添付ファイルを作成し、メーセージに追加する。</dd>

<dt>attach_fail()</dt>
<dd>ファイルシステムのファイルを使用して新しい添付ファイルを作成する。</dd>
</dl>

```python:mail.py
message.attach_file('/images/weather_map.png')
```
Google Colabでplotlyの ```TypeError: imshow() got an unexpected keyword argument 'labels'``` エラー

# Google Colabで```TypeError: imshow() got an unexpected keyword argument 'labels'```エラー

## TL;DR
```
# plotlyをアップグレードして， Google Colabのランタイムを再起動（出荷状態に戻すとバージョンがまた元に戻るので注意）
!pip install --upgrade plotly
```

## 問題
- Google Colabで， plotlyでヒートマップなどを表示しようとして， 軸ラベルを付与しようとしたら ```TypeError: imshow() got an unexpected keyword argument 'labels'``` と怒られてしまった．

```
data=[[1, 25, 30, 50, 1], [20, 1, 60, 80, 30], [30, 60, 1, 5, 20]]
fig = px.imshow(data,
                labels=dict(x="Day of Week", y="Time of Day", color="Productivity"),
                x=['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'],
                y=['Morning', 'Afternoon', 'Evening']
               )
fig.update_xaxes(side="top")
fig.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195903/223af9de-8d4d-1a0d-e3fb-9c6ccb5f11f6.png)

## 原因
- Google Colabのplotlyのデフォルトのバージョンが```4.1.4```だが， labelsのパラメータが追加されたのが```4.14.0```なので，利用できない（参考：https://github.com/plotly/plotly.py/releases/tag/v4.14.0）

## 対策
- plotlyのバージョンをアップグレードして， Google Colabのランタイムを再起動する．
- その後， 4.14.0になりlabelsが利用できるようになる．

```
import plotly
print(plotly.__version__)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195903/c7dc4193-969b-8f4a-42ad-6788bcfd2c7f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195903/3b0593a2-a9ad-0ee0-a5bc-1bf1ba442c4c.png)
【JS】様々なループ。forEach, for, for of, map, reduce, filterの違いと使いどころ

配列から要素を一つづつ取り出す処理をmapで記述していたが、forEachで簡単に記述できることが判明。

ついでに、主なループ処理の使い所もまとめた個人用メモです。

<br>

| 項目 | メソッド/文 | 使い所 |
|:-:|:-:|:--|
| for  | 文  | 回数を指定したい場合  |
| for of  | 文  | 要素を一つ一つ抜き出したい場合。クロージャ（closure）でないので、定義した変数がグローバル（処理の外でも有効）になる。  |
| forEach  | メソッド | 要素を一つ一つ抜き出したい場合。クロージャ（closure）なので、定義した変数はローカル。余計な変数が増えない。  |
| map  | メソッド  | 要素を一つ一つ抜き出し処理を加え、結果を配列で返す。非破壊。 |
| reduce  | メソッド  | 要素を一つ一つ抜き出し処理し、一意の値を返す。非破壊。一つの値が欲しい場合に使う。  |
| filter  | メソッド  | 要素を一つ一つ抜き出し、条件がtrueとなった要素のみ残す。非破壊  |
| for in  | 文  | 対象がオブジェクト。配列ではない。 |



いずれもループで回すので、使い方によっては同じ処理ができるが、目的とする用途が異なる。

<br>
##どれを使うかの基準
大きなポイントは以下２点。

**(1) メソッドか文か？**
余計な変数を増やしたくない場合や、処理内でのみ変数を定義したい場合はメソッドを使う。

メソッドは変数を一旦クリアする文処理量は増えるが、閉じた空間で変数を使うので処理がわかりやすくなる。



**(2) 出力は何か？**
要素を一つづつ取り出し、元の配列に依存しない処理結果を返したい場合はforやforEachを使う。

元の要素を一つ一つ変換したい場合はmap。

各要素を使った処理結果から一つの値をえたい場合はreduce。

特定の要素のみ残したい場合はfilterを使う。



<br>
##ループの実例
要素を一つづつ取り出しconsole.logで出力するプログラムはいずれのメソッド・文でもできる。

```js:forEach
arr = [1,2,3,4]

arr.forEach( (elem, index) => {
    console.log(elem)
})

//出力
1
2
3
4
```

処理がクローズドの環境なのでわかりやすい。

<br>

```js:map
arr = [1,2,3,4]

_arr = arr.map( (elem, index) => {
    console.log(elem)
})

//出力
1
2
3
4
```

不要な変数`_arr`ができてしまうため、新たな配列を作る必要がない場合は不向き。


<br>

```js:for-of
arr = [1,2,3,4]

for( elem of arr ){
    console.log(elem)
}

//出力
1
2
3
4
```

forEachとほぼ同じ。メソッドか文かの違い。
処理の中でグローバルな（処理の外でも使える）変数を宣言したい場合に有効。


<br>

```js:for
arr = [1,2,3,4]

for(i = 0; i < arr.length; i ++ ){
    console.log(arr[i])
}

//出力
1
2
3
4
```

繰り返す回数に特化した処理。「n回繰り返したい」という場合に有効。


<br>

```js:reduce
arr = [1,2,3,4]

_arr = arr.reduce( (res, elem, index) => {
    console.log(elem)
}, arr[0])

//出力
1
2
3
4
```

一つの結果を得る場合に使うのがreduce。今回の用途では余計な変数`_arr`が増えるので不向き。


<br>

```js:filter
arr = [1,2,3,4]

_arr = arr.filter( (elem, index) => {
    console.log(elem)
})
//出力
1
2
3
4
```

trueになった要素のみ抜き出すfilter。今回の用途では余計な変数`_arr`が増えるので不向き。



<br>
##まとめ

単に要素を一つづつ抜き出すという目的であれば、forEachかfor-ofに絞られる。

クロージャで処理を完結に書きたければforEachを使うのがベスト。
Sprocketsを 3 -> 4にアップデートしたらmixinの変数が見つからずエラーになった場合の解決方法

Rails 5.0.7.2 -> 5.1.7
sprockets 3.7.2 -> 4.0.2

エラー

```
rails aborted!
Sass::SyntaxError: Undefined variable: "$color-cardinal-red".
/Users/jcoyne85/workspace/sul-dlss/testapp/app/assets/stylesheets/one.scss:1
Tasks: TOP => assets:precompile
```


sprocketsを3系から4系にアップデートした際、manifest.jsが作成されるが、デフォルトの記載方法だと上記の様にmixinで使っている変数が見つからないとエラーになるので解決方法。

以下がデフォルトの記載

```
manifest.js

//= link_tree ../images
//= link_directory ../javascripts .js
//= link_directory ../stylesheets .css
```

これを以下に変更

```
manifest.js

//= link_tree ../images
//= link_directory ../javascripts .js
//= link application.css <- 変更
```

参考: https://github.com/rails/sprockets/issues/597#issuecomment-489968827
【kintone】テーブルの行を並び替える（ソートする）

前回は、テーブルの値を変更する記事を書きましたが、
今回は簡単にできるテーブルの昇順並び替え機能を作ってみたいと思います。
昇順や降順に並び替えることを「ソート」と言いますので、
「ソート」という言葉を使って説明したいと思います💪
※昇順は1,2,3,・・・のような小さい順、降順は100,99,98,・・・のような大きい順の並び方です

# アプリの準備

**アプリのフィールド**

|フィールド種類|フィールド名|フィールドコード|
|:-:|:-:|:-:|
|スペース||spbtn|
|テーブル|名簿|名簿|


**テーブルのフィールド**

|フィールド種類|フィールド名|フィールドコード|
|:-:|:-:|:-:|
|数値|行番号|行番号|
|文字列(1行)|名前|名前|
|その他お好みで・・・|||


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/f3fd3eb7-a818-0a50-e9b5-c310606a015d.png" width="600px">

# JavaScriptを書く

編集画面のイベントにします。
ボタンをつけて、ボタンをクリックすると「行番号」順に並べ替える機能とします。

解説は後述します。

```js
//編集画面開いたときは'app.record.edit.show'
kintone.events.on(['app.record.edit.show'], event => {
    //ボタンを置きたいスペースフィールドの情報を取ってくる
    const sp = kintone.app.record.getSpaceElement('spbtn');

    //ボタンを作る
    const btn = document.createElement('button');
    //ボタンに表示したいテキスト
    btn.textContent='ボタン';

    //スペースフィールドにボタンを追加する
    sp.appendChild(btn);

    //ボタンをクリックしたときの動作
    btn.onclick=()=>{
        const obj = kintone.app.record.get();
        // 行番号順にソートする（行番号昇順に並び替える）
        obj.record.名簿.value.sort((a, b) => {
            //aの方の行番号が小さい時、a が先にくるようにする
            if (Number(a.value.行番号.value) < Number(b.value.行番号.value)) return -1;
            //aの方の行番号が大きい時、b が先にくるようにする
            if (Number(a.value.行番号.value) > Number(b.value.行番号.value)) return 1;
            return 0;
        });
        
        kintone.app.record.set(obj);
    }

    return event;

});    
```

## ボタンをつける

ボタンを追加する方法についてはこちらをご覧ください
→[【kintone】アプリの「スペース」フィールドにボタンを設置する](https://qiita.com/juri_don/items/53a7e8c3f4d63ca9dcca)

## サブテーブルを並び替える

「行番号」を元にソート（並び替える）機能です。

```js
// 行番号昇順にソートする（行番号の小さい順に並び替える）
obj.record.名簿.value.sort((a, b) => {
    //aの方の行番号が小さい時、a が先にくるようにする
    if (Number(a.value.行番号.value) < Number(b.value.行番号.value)) return -1;
    //aの方の行番号が大きい時、b が先にくるようにする
    if (Number(a.value.行番号.value) > Number(b.value.行番号.value)) return 1;
    return 0;
});
```


`obj.record.名簿.value` は名簿テーブルの行が格納されている配列です。
※`obj.record.名簿.value[0]` で1行目です。

配列をなにかのキーを元にソートする時は `sort()` メソッドを使います。

詳しくはこちらの「解説」のところに使い方が分かりやすく書かれています。
[Array.prototype.sort()](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)

※`Number()`は文字列を数値に変換する関数です。


ちなみに、降順ソートしたい場合はこのように書き換えます。

```js
    //aの方の行番号が大きい時、a が先にくるようにする
    if (Number(a.value.行番号.value) > Number(b.value.行番号.value)) return -1;
    //aの方の行番号が小さい時、b が先にくるようにする
    if (Number(a.value.行番号.value) < Number(b.value.行番号.value)) return 1;
```

`return 負の数;` のときは `a, b` という順番になり、
`return 正の数;` のときは `b, a` という順番になります。


# 動かしてみる

実際に動かしてみるとこのようになります。
※年齢フィールドを追加してみました。

![222.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/804f3a8f-6341-4f15-c60b-e81a1d908612.gif)


# まとめ

今回のTipsを使うと、テーブルの行を思い通りの順番に並べ替えたい時に使えるかも！？


テーブルの行は「配列」として扱うことができます。
こちらのメソッドたちも使えますので、是非研究してみてくださいね＾０＾
参考：[JavaScriptリファレンス：Array](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array)
Webデザイン学習で役立つ参考サイト・ブログ一覧

Webデザインを学ぶ上で、参考になるサイトやブログをまとめました。
技術観点、キャリア観点などの目的別や、初心者〜上級者まで、目的に合わせて参考にできるサイト・ブログです。

【Web Design Trends】
Webサイト制作・デザインに関する具体的な解説記事やお役立ち記事が豊富。デザインに迷った時、配色を検討するときなど、目的別のコンテンツが豊富。
https://webdesign-trends.net

【PhotoshopVIP】
Photoshopを中心としたデザインなど、トレンド情報含めて役立つ記事が豊富。技術的観点で重宝できるサイト。
https://photoshopvip.net

【SANKOU!】
「Webデザイン制作の参考になる国内のステキなサイト集」をコンセプトにしたサイト。デザインに迷った時、インスピレーションを高めてくれる良質なWebサイトがきれいにまとまっている。定期的にチェックしておきたい。
https://sankoudesign.com

【デザキャリ】
Webデザイナーのキャリア情報を主に発信しているサイト。特にこれからWebデザインを始めたい初心者が、どのようにWebデザインを学んでいくべきかが書かれている。未経験からWebデザイナーを目指す際に活用したい。
https://desacari.net
Rails ログインの実行


<h2>ログインの実行</h2>

ログイン画面から送られメールアドレスやパスワードを使ってログインを実行する部分を開発していく。

まずはルーティングの設定を次の1行を追加していく。

```ruby:config/routes.rb

post '/login', to: 'sessions#create'
```

続いて、このログインを実行するためのcreateアクションを
SessionsController(app/controllers/sessions_controller.rb)に追加。
送られてきたパラメータを安全化するsession_paramsメソッドも合わせて追加する。

```ruby:app/controllers/sessions_controller.rb

class SessionsController < ApplicationController
  def new
  end

  def create
    user = User.find_by(email: session_params[:email])

    if user&.authenticate(session_params[:password])
      session[:user_id] = user.id
      redirect_to root_url, notice: 'ログインしました。'
    else
      render :new
    end
  end

  private

  def session_params
    params.require(:session).permit(:email, :password)
  end
end

```

createアクションではまず送られてきたメールアドレスでユーザーを検索する。
ユーザーが見つかった場合は、送られてきたパスワードによる認証をauthenticateメソッドを使って行う。


authenticateメソッドはUserクラスにhas_secure_passwordと記述したときに自動で追加された、認証のためのメソッド。
引数で受け取ったパスワードをハッシュ化して、その結果がUserオブジェクト内に保存されているdigestと一致するか調べる。
一致していたら認証成功と言うことでUserオブジェクト自身を、一致していなければ認証失敗ということでfalseを返却する。

```ruby:
session[:user_id] = user.id

```

この部分では認証に成功した場合に、セッションにuser_idを格納している。
タスク管理のアプリケーションとして次の２種類を区別することになるという点はアプリケーションの理解においてとても重要。

1.誰もログインしていない状態。session[:user_id]がnil
2.誰かがログインしている状態。session[:user_id]にログイン中のユーザーIDが入っている。


参考書籍：現場で使える　Ruby on Rails5 速習実践ガイド
【AWS】S3の設定

# 概要
- Gemの導入
- production.rbの編集
- storage.ymlの編集

# Gemの導入
```Gemfile
gem "aws-sdk-s3", require: false
```


# production.rbの編集
- 「local」→「amazon」に変更

```config/environments/production.rb
config.active_storage.service = :amazon
```

# storage.ymlの編集
- amazon項目の追加
- ENVは環境変数なので、各種設定すること。

```config/storage.yml
amazon:
 service: S3
 region: ap-northeast-1
 bucket: バケット名
 access_key_id: <%= ENV['AWS_ACCESS_KEY_ID'] %>
 secret_access_key: <%= ENV['AWS_SECRET_ACCESS_KEY'] %>
```

以上