OmniAICreator/Qiita-1.07M huggingface dataset:
[Django REST Framework] Serializerの使い方

## 実行環境
MacOS BigSur -- 11.2.1 
Python3 -- 3.8.2
Django -- 3.1.7
djangorestframework -- 3.12.2

## Django REST Framework(DRF) のシリアライザーとは？！
さて、現在DRFとReactによるWebアプリケーションを作成中なのですが、Djangoでは出てこなかったSerializerでつまづいたのでその使い方をメモがてらにまとめようと思います。

### serializerとは
一言で表すと、データの入出力を扱い、モデルでの橋渡しをするクラスのことです。

- シリアライズ（入力）：複雑な入力値をモデルに合わせてバリデーションしてレコードに伝える
- デシリアライズ（出力）：Model（レコード）を適切な形式にフォーマットしてpythonで扱えるようにする

これらの役割を担っています。DjangoにおけるFormと同じような位置付けのようです。

### ModelSerializer
さて、今回はModelSerializerを使用します。
ModelSerializerは、Modelに紐付くFieldを自動的に定義してくれると言う便利なものだそうです。要するにDjangoのModelFormの様なイメージですね。実際にModelSerializerを使用してCURD処理の実装をしてみます。

## Serializerを用いてCURD処理の実装
### Model
まずは簡単なPostモデルを作成しました。

``` models.py
class Post(models.Model):
    title = models.CharField('タイトル', max_length=50)
    text = models.TextField('テキスト')
    created_at = models.DateField('作成日', auto_now_add=True)
    updated_at = models.DateField('更新日', auto_now=True)

    def __str__(self):
        return self.title
```

### Serializer
ModelSerializerを用いてPostSerializerを作成します。

``` serializers.py
from rest_framework import serializers
from backend import models
from backend.models import Post

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = ('title','text','created_at','updated_at','id')
        read_only_fields = ('id',)
```

```fields = ('title','text','created_at','updated_at','id')```
で指定したカラムを表示できるようになっています。
ちなみに、
```read_only_fields = ('id',)```
で特定のカラム（ここでは id ）を更新不可にできます。この際にread_only_fieldsにはリストまたはタプルでカラムを指定しないとエラーが出ます。

### Viewとurl
あとはViewでserializerを指定して、urlに追加するだけで簡単にCRUD処理を実装できます。

```views.py
from rest_framework import viewsets
from .models import Post
from .serializers import PostSerializer

class PostViewSet(viewsets.ModelViewSet):
    """PostオブジェクトのCRUD"""
    queryset = Post.objects.all().order_by('-created_at')
    serializer_class = PostSerializer
```

```urls.py

router = DefaultRouter()
# Viewでquerysetの記述があればbasenameの設定はいらない
router.register('post',views.PostViewSet)

urlpatterns = [
    path('', include(router.urls)),
]
```

## serializerを使わない場合

```views.py
class PostAll(APIView):
    def get(self, request):
        try:
            post = Post.objects.all().order_by('-created_at')
            res_list = [
                {
                    'id': p.id,
                    'date': p.created_at,
                    'title': p.title,
                }
                for p in post
            ]
            return Response(res_list)
        except:
            return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR)
```

ちなみに、これまではserializerを用いておらず、viewにこのような記述をしていました。どっからどう見ても非効率でした。。。
と言うことで、このようにシリアライザーを用いて簡単にCRUD処理を作成できます！！

## 参考
以下のページが非常に分かりやすく、参考にさせていただきました。
- https://note.crohaco.net/2018/django-rest-framework-serializer/
- http://i-plug-tech.hatenablog.com/entry/2017/02/10/174050
- https://pigblog.org/django-restframework-basic5
整数の画像座標と0~1のUV座標の変換

稀に良くコードを書き捨てるが毎回よくわからなくなるのでメモ。
整数のインデックスでアクセスする画像座標xyはピクセル中心が基準だがfloatで0.0~1.0のUV座標uvはピクセル端が基準となる（環境が多い、ほぼ100％）。
そこで横方向のピクセルだけを考え図示すると以下のようになる。wは画像の幅（x方向のピクセル数）である。xのインデックスの本来の最小値は0で最大値はw-1である。

![図3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/250024/d5b36cd2-8a84-ebaf-002b-2bff38c0e93d.png)

ピクセル端はピクセル中心から0.5ピクセルだけずれている。
つまりx=-0.5がu=0.0に対応しx=w-0.5がu=1.0に対応する。
これをもとに考えるとxyからuvへの変換は以下の式になる（y方向のピクセル数=画像の高さはhとし、慣習に倣ってvはyに対して上下反転させている）。

```math
u=\frac{x+0.5}{w}
\hspace{20pt}
v=1.0-\frac{y+0.5}{h}
```

同様にuvからxyへの変換は

```math
x=u*w-0.5
\hspace{20pt}
y=(1.0-v)*h-0.5
```
となる。しかしこのままだとfloatでありピクセルにそのままアクセスできないので必要に応じてround()でNearest Neighborサンプリングしたり、あるいはbilinearサンプリングしたりすればよい。


やりがちな次の式、w-1といった**整数インデックスの最大値で正規化するやり方は間違い**。

```math
u=\frac{x}{w-1}
\hspace{20pt}
v=1.0-\frac{y}{h-1}
```

気づかないことも多いが画像サイズが小さい時にずれが目立つ。
【paiza】【Java編】Cランクレベルアップメニュー　標準入出力　STEP: 1 単純な入出力　解いてみた！


はじめまして、Aybeeです！

Javaのスキルアップのために、「paizaラーニング」さんの問題を解き始めました。
記録用ですが、お役に立てれば幸いです:innocent:


#はじめに

この記事では、「paizaラーニング」さんの以下の問題について記載しています。
より良くするためのアドバイス、お待ちしております！

https://paiza.jp/works/mondai/c_rank_level_up_problems/c_rank_std_in_out_step1


※当問題は、以下のように作成したコードを公開することが推奨されています。
![スクリーンショット (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424017/37c5fead-bd3a-909f-8a4e-d2d8b745aaa2.png)



#問題

文字列 s が与えられるので s をそのまま出力してください。

##入力される値

入力は以下のフォーマットで与えられます。

s

文字列 s が 1 行で与えられます。

入力値最終行の末尾に改行が１つ入ります。
文字列は標準入力から渡されます。 標準入力からの値取得方法はこちらをご確認ください


##期待する出力

入力された文字列をそのまま出力してください。

s

末尾に改行を入れ、余計な文字、空行を含んではいけません。


##条件

すべてのテストケースにおいて、以下の条件をみたします。

・s は数字または大文字・小文字のアルファベットからなる長さ 1 以上 10 以下の文字列



#作成したコード

```java

import java.util.*;


public class Main {
    public static void main(String[] args) {
        // 自分の得意な言語で
        // Let's チャレンジ！！
		Scanner sc = new Scanner(System.in);
		String data = sc.nextLine(); // ⓵Scannerで入力された値を変数「data」に入れる

		System.out.println(data); // ⓶変数「data」の値を出力する
		sc.close();
	}
}
```


#解説

「Scanner」クラスを通じて入力された値を、
⓵「nextLine()」メソッドで変数に設定し、
⓶「System.out.println()」で出力しました！

ポイントは、「Scanner」クラスと「nextLine()」メソッドかな？

「paizaラーニング」さんの他の問題も解いていますが、ほとんど「Scanner」クラスから値を取得するので、これから慣れていきそうです。

おわり:smile:
Jest --watch Error: EMFILE: too many open files, watch

急に`jest --watch`ができなくなったので、調べてみた。

## 現象
```console
❯ yarn test:watch
yarn run v1.22.10
$ cross-env NODE_ENV=test jest --config=jest.config.json --watch
2021-03-23 20:35 node[59503] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-22)
2021-03-23 20:35 node[59503] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-22)
2021-03-23 20:35 node[59503] (FSEvents.framework) FSEventStreamStart: register_with_server: ERROR: f2d_register_rpc() => (null) (-22)
events.js:292
      throw er; // Unhandled 'error' event
      ^

Error: EMFILE: too many open files, watch
    at FSEvent.FSWatcher._handle.onchange (internal/fs/watchers.js:178:28)
Emitted 'error' event on FSWatcher instance at:
    at FSEvent.FSWatcher._handle.onchange (internal/fs/watchers.js:184:12) {
  errno: -24,
  syscall: 'watch',
  code: 'EMFILE',
  filename: null
}
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```

## 環境
```
ProductName:    Mac OS X
ProductVersion: 10.13.6
BuildVersion:   17G14033

❯ node -v
v14.15.4
❯ yarn -v
1.22.10
❯ yarn jest --version
v20.0.4
```


最初はwatchmanはない。
yarnだとwatchmonがあるので間違いに注意。

```console
❯ which watchman
watchman not found
❯ brew install watchman
```

長い更新時間

```console
❯ which watchman
/usr/local/bin/watchman
```

## 実行結果
```
❯ yarn test:watch
yarn run v1.22.10
$ cross-env NODE_ENV=test jest --config=jest.config.json --watch

 PASS  src/tests/components/Header.test.js
 PASS  src/tests/components/ExpenseDashboardPage.test.js
 PASS  src/tests/components/AddExpensePage.test.js
 PASS  src/tests/actions/expenses.test.js
 PASS  src/tests/components/EditExpensePage.test.js
 PASS  src/tests/components/ConfModal.test.js
 PASS  src/tests/components/LoginPage.test.js
 PASS  src/tests/actions/auth.test.js

Test Suites: 8 passed, 8 total
Tests:       25 passed, 25 total
Snapshots:   6 passed, 6 total
Time:        7.874s, estimated 8s
Ran all test suites related to changed files.

✨  Done in 240.85s.
```
確かに実行できるようになった。


## 参考
[JestのwatchがError watching file for changes: EMFILE でコケるときの対処](https://qiita.com/terrierscript/items/6490aa94b32a9e4211ea)
[macOS Sierra ＃1767でウォッチモードが機能しなくなりました](https://github.com/facebook/jest/issues/1767#issuecomment-248883102)
Ajaxとは。APIとは。

#【Ajaxとは。 APIとは。】

現場で使う可能性の高い技術である。
バックエンドエンジニアを目指しているので身につけたい。
ポートフォリオにAjaxで実装したところを最低1つ作ってみる。

##Ajax

Ajax（Asynchronous JavaScript and XML）
　→　Webブラウザ上で動作するJSでサーバからXMLデータを取得し、取得したデータをコンテンツに動的に反映する。

Asynchronousとは、非同時性の、非同期の。という意味。

※Ajaxを実装するには、APIを実装しなくてはいけない。
　AjaxとAPIの知識が身に付くので一石二鳥。

##非同期通信

ページを遷移することなく、ページの一部だけを更新することが可能な通信。
　→　サーバーからレスポンスが返ってこなくても他の作業ができる。

webプラウザから一部の情報をリクエストするので、それ以外の部分は変わらない。
　→　Webページの画面が白くなることがない。

##API（Application Programming Interface）

自分のアプリケーションとは全く異なるものの情報を操作する仕組み。
　→　アプリケーション、ソフトウェアとプラグラムを繋ぐ。

ソフトウェアにAPIという外部とやりとりする窓口を作る。
外部アプリとコミュニケーションや連携ができる状態にする。

##APIのメリット

APIで組み込むことが可能な信頼できるプログラムが既に存在している。
それらを使用することで、ソフトウェア開発の効率化をはかることができる。
トータル開発時間とコストの削減に繋がる。

API連携が可能な各種サービスと別アプリケーションログインによる、ログイン認証によって、セキュリティの向上になる。

　例）GoogleアカウントログインやTwitterアカウントログインなど。
JavaScriptの変数と宣言

# JavaScriptの変数と宣言
プログラミング言語には、文字列・数値などのデータに名前を付ける事によって
繰り返し利用する`変数`という機能がある


JavaScriptでは、「これは変数だ。」といった宣言を行うキーワードとして
以下の3つが使用されている。

1. `const`
2. `let`
3. `var`

>
`var`はもっとも古くからある変数宣言のキーワード
ただ、意図しない動作を作りやすい問題が知られています。 
そのためECMAScript 2015で、`var`の問題を改善するために
`const`と`let`という新しいキーワードが導入されました。

`const`、`let`、`var`どのキーワードも共通の仕組み
変数同士を,（カンマ）で区切ることにより、同時に複数の変数を定義可能


## const
再代入できない変数の宣言と、その変数が参照する値（初期値）を定義可能
constキーワードに続いて変数名を書き、代入演算子（=）の右辺に変数の初期値を書いて変数を定義

```javascript:const
//const  変数名  =  初期値;
const QiitaTitle = "JavaScript学習";
```

###複数の値を宣言する方法

const、let、varどのキーワードも共通の仕組みですが、
`変数同士を,（カンマ）で区切る`ことにより、
同時に複数の変数を定義することが可能

```javascript:const
const QiitaTitle = "JavaScript 学習",
      QiitaCategory = "プログラミング";
```

constは再代入できない変数を宣言するキーワード
そのため、constキーワードで宣言した変数に対して、後から値を代入することは不可能

値を再代入する必要がない場合は、constキーワードで変数宣言することを推奨


## let

値の再代入が可能な変数を宣言可能
letの使い方はconstとほとんど同じ

```JavaScript:let
let QiitaTitle = "JavaScript 学習";
```
>
QiitaTitleという変数を宣言し、初期値を"JavaScript Primer"という文字列であることを定義している

### letとconstの差

letはconstとは異なり、初期値を指定しない変数も定義可能
初期値が指定されなかった変数はデフォルト値としてundefinedという値で初期化される（undefinedは値が未定義ということを表す値）


```JavaScript:let
let QiitaTitle;
// `QiitaTitle`は自動的に`undefined`という値になる
```
>
QiitaTitleという変数を宣言しています。 このときQiitaTitleには初期値が指定されていないため、デフォルト値としてundefinedで初期化される

このletで宣言されたQiitaTitleという変数には、代入演算子（=）を使うことで値を代入可能

```JavaScript:let
let QiitaTitle;
QiitaTitle = "JavaScript 学習";
```
>
代入演算子（=）の右側には変数へ代入する値を書きますが、ここでは"JavaScript 学習"という文字列を代入している

letで宣言した変数に対しては何度でも値の代入が可能

```JavaScript:let
let count = 0;
count = 1;
count = 2;
count = 3;
```

## var

varキーワードでは、値の再代入が可能な変数を宣言可能
varの使い方はletとほとんど同じ

```JavaScript:var
var QiitaTitle = "JavaScript 学習";
```

varでは、letと同じように初期値がない変数を宣言でき、変数に対して値の再代入も可能

```JavaScript:var
var QiitaTitle;
QiitaTitle = "JavaScript 学習";
QiitaTitle = "新しいタイトル";
```

### varの問題

varはletとよく似ているが、varキーワードには同じ名前の変数を再定義できてしまう問題がある

letやconstでは、同じ名前の変数を再定義しようとすると、構文エラー（SyntaxError）が発生する

```JavaScript:var
// "x"という変数名で変数を定義する
let x;
// 同じ変数名の変数"x"を定義するとSyntaxErrorとなる
let x; // => SyntaxError: redeclaration of let x
```
>
間違えて変数を二重に定義してしまうというミスを防ぐことが可能

一方、varは同じ名前の変数を再定義可能

```JavaScript:var
// "x"という変数を定義する
var x = 1;
// 同じ変数名の変数"x"を定義できる
var x = 2;
// 変数xは2となる
```
>
意図せずに同じ変数名で定義してもエラーとならずに、値を上書きしてしまう


他にもvarには変数の巻き上げと呼ばれる意図しない挙動があり、letやconstではこの問題が解消されている
そのため、「letはvarを改善したバージョン」という認識でも問題ない

varにはさまざまな問題がある
ほとんどすべてのケースでvarはconstかletに置き換えが可能
>
varを利用することは避けたほうがよい印象
データフロー

#目次
[computeRelative 変換](#computeRelative 変換)
[dim2mea 変換](#dim2mea 変換)
[flatten 変換](#flatten 変換)
[flatten 変換](#flatten 変換)
[update 変換](#update 変換)

#computeRelative 変換
![スクリーンショット 2021-03-23 23.09.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385774/c0ebf7ed-17ae-cecf-7597-b625dc55b2ee.png)

####パーティション基準

グルーピングする項目をさす。いわゆる、どのグループで折り返しさせるかを設定する

####並び替えの基準
どの項目を基準に並び替えするか。

以下のようなデータがあったとする
![スクリーンショット 2021-03-23 23.36.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385774/478854cc-4fcd-75e0-9f8d-d1cc5fac8a18.png)

都道府県でNO1の人口数のみを表示させる項目を追加したい

![スクリーンショット 2021-03-23 23.37.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385774/f4bace86-bf29-b6e2-bad3-19c6c0e79636.png)

#dim2mea 変換
ディメンション値を基準に変換するだけ

![スクリーンショット 2021-03-24 9.56.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385774/61f69aed-07a9-f284-d5a4-d768067d3407.png)

#flatten 変換
 黒字が追加されている、「ロール」、「ROLEPATH」を項目として生成。正直使いどきあんまわからん

![スクリーンショット 2021-03-24 10.42.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385774/26170476-93f4-2f95-b39a-d6afe398b0d9.png)

#update 変換
キーで紐付けし、その当該キーで紐付けた行のみ、更新する。
何を更新するかを指定する
右　name 左　AccountName 

![スクリーンショット 2021-03-24 13.05.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385774/dbdf6003-56e8-3641-8984-b365267897c3.png)



＃参考文献
[Tableau CRM データフローの変換](https://help.salesforce.com/articleView?id=sf.bi_integrate_tranformation_overview.htm&type=5)
AWS + Docker で オウム返しLinebotの作成     

#構成図
![diaglam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532785/7d0e816a-2ba7-b88e-bb4f-2a9de991d2a0.png)

#できるもの
![デモ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532785/5a0f37a5-bf03-7941-069f-901fa441b65b.png)

#注意点
Route53使ってるため、完全無料ではないです。
ドメイン登録をRoute53で行うなら、さらに料金が発生します。

#AWS
[Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂3版](https://www.amazon.co.jp/Amazon-Services-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E6%A7%8B%E7%AF%89-%E6%94%B9%E8%A8%823%E7%89%88/dp/4296105442/ref=sr_1_8?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=aws&qid=1616507734&sr=8-8)

#Docker
[さわって学ぶクラウドインフラ　docker基礎からのコンテナ構築](https://www.amazon.co.jp/%E3%81%95%E3%82%8F%E3%81%A3%E3%81%A6%E5%AD%A6%E3%81%B6%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%82%A4%E3%83%B3%E3%83%95%E3%83%A9-docker%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E6%A7%8B%E7%AF%89-%E5%A4%A7%E6%BE%A4-%E6%96%87%E5%AD%9D-ebook/dp/B089VZXX63/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=docker&qid=1616507829&sr=8-3)
###Nginx Image
###Python Image
#### Flask
#### line-bot-sdk
#### gunicorn

#HTTPS
[WebサイトをnginxコンテナでHTTPS化する(using Let’s encrypt)](https://blog.1mg.org/20190711_01/)
[Certbot を使い3分で無料の SSL 証明書を取得する](https://dev.classmethod.jp/articles/how-to-use-certbot-with-nginx/)
###Certbot
EC2のパブリックIPv4 DNSでは、CertbotでSSL証明書が発行できませんので、独自ドメインを取得してください。


#Line Messaging API
js debounce throttle

違いを分かるように codepen に作りました。
https://codepen.io/koryovip/pen/mdRJJrP

以下参考サイト
https://segmentfault.com/a/1190000018428170
https://blog.csdn.net/jiaojsun/article/details/99330712
http://demo.nimius.net/debounce_throttle/


Event.preventDefault()
https://developer.mozilla.org/ja/docs/Web/API/Event/preventDefault


Event.stopPropagation()
https://developer.mozilla.org/ja/docs/Web/API/Event/stopPropagation
主なWebサイト構造設計


サイト構造設計の種類

1. レスポンシブWebデザイン
2. シングルページ・レイアウト
3. アダプティブ・デザイン
4. ワンカラム・レイアウト
5. マテリアル・デザイン

### 1. レスポンシブWebデザイン
機種の画面サイズ、ウィンドウのサイズに応じてレイアウトを最適化するWebデザイン。
PC用画面の設計を行った後、タブレット・モバイル用画面を設計するのが主流だったが、現在ではモバイル用画面を先に設計する「モバイルファースト」の傾向がある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210256/cba4077d-9f0c-f847-2506-6586006c758b.png)

### 2. シングルページ・レイアウト
スクロール型の1項ページ内にすべてを記述し、表示遅延をなくす。
特にモバイルを配慮した設計。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210256/8cd2fd97-449b-bc5b-c111-14265eef64c2.png)

### 3. アダプティブ・デザイン
ユーザーのプロファイルや状態・状況に応じて表示内容を動的に最適化するデザイン手法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210256/19bd4131-58ca-01b0-272c-0bc6e249c987.png)

### 4. ワンカラム・レイアウト
ユーザーの導線を解りやすくするために画面枠内の情報量を絞った単純化レイアウト
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210256/bc14a887-2265-cb15-5218-9c4830fde2da.png)

### 5. マテリアル・デザイン
Googleの定義するデザイン・システム
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1210256/cd3a7c48-ad74-e009-1ab7-1249014206ab.png)
Arduino IDEをダークモードにする [for Mac]

##やったこと
Arduino IDEの白い画面が苦手だったので、ダークモードにしてみました。
ですが、Macだと少しつまずいたので共有します。


##用意した物
[
DarkArduinoTheme](https://github.com/jeffThompson/DarkArduinoTheme)
こちらのZIPファイルをダウンロードして解凍してください。
必要な物は「thema」というフォルダです。

##テーマ変更
IDEを右クリックして「パッケージ内容を表示」を選択
あとは
/Applications/Arduino.app/Contents/Java/lib
内に先ほどの「thema」というフォルダを入れます。そしてIDEを再起動すれば変わっているはずです。

##それでも見えづらい
ダークモードにはなりますが、それでも変数名は「#5E6D03」という

<font color="DarkOliveGreen">こんな感じの地味な色</font>

になります。
ここのカラーを変える時は、theme/theme.txtを編集すれば変更できます。
私は「#a5f20a」に変更しました。
結果がこちら↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/c5942b9c-79a7-3bdc-71fa-f310d0d4f193.png)

これで多少はマシになりましたね！！

##参考文献
[Arduino IDEをダークテーマに設定しただけ[1.8.7]](https://qiita.com/ioComk/items/52fd70f4b24f38b5203f)
GOでファイルを分ける時

##初めに
Goって公開されてるパッケージを組み合わせてなんやかんやするのがメインで
ファイルがすんごく長くなる事ってあんまり考えないのかな？
普通に見にくくなっちゃうと思うので、ファイルを分ける方が好きだったりします。

そして、ファイルを分けるのにドはまりしたので、書いておく
一応Windowsの場合です。

##長くなったmain.goを分割する
**フォルダ構成はこうしたい！**
※一応[公式の推奨フォルダ構成](https://github.com/golang-standards/project-layout)を参考にした

```
GOPATH/
  src/
  └ test/ <-今回のプロジェクトルート
    ├ cmd/
    │ └ textApp/
    │   └ main.go
    └ intarnal/
      └ sub/
        └ sub.go
```

##まずはとりあえず、go mod init 〇〇〇〇　する
CMDで以下を実行

```
cd GOPATH<皆良い感じに変えてほしい>/test
go mod init locl.l/test
```

**ポイント**

`go mod init locl.l/test`の「.(ドット)」は絶対に**<span style="color:#f00;">必要</span>**らしいwww
なんじゃそれ！？


###そうすると、こうなる

```
GOPATH/
  src/
  └ test/ <-今回のプロジェクトルート
    ├ cmd/
    │ └ textApp/
    │    └ main.go
    ├ intarnal/
    │ └ sub/
    │   └ sub.go
    └ go.mod
```
go.modの中身

```go:go.mod
module local.l/test

go 1.16
```

##sub.goの中身

```go:/internal/sub/sub.go
package sub

import "fmt"

func Rectangle(l int, m int) int {
	return l * m
}

func Intro() {
	fmt.Println("これはsubです。")
}
```

##main.goの中身

```go:/cmd/testApp/main.go
package main

import (
	"fmt"
	"local.l/test/internal/sub"
)

func main() {
	fmt.Println(sub.Rectangle(4, 5))
	sub.Intro()
}
```

##実行する

CMDで

```
go run cmd/testApp/main.go
```
すると以下が表示されたのでOK！！

```
20
これはmypkgです。
```

##ついでにビルドする

推奨のフォルダ構成に則ってbuildフォルダを作る

```
GOPATH/
  src/
  └ test/ <-今回のプロジェクトルート
    ├ cmd/
    │ └ textApp/
    │    └ main.go
    ├ intarnal/
    │ └ sub/
    │   └ sub.go
    ├ go.mo
    └ build/ <-この中にコンパイルしたexeファイルを入れたい
```
cmdで実行

```
go build -o build/test.exe cmd/testApp/main.go 
```

そしたら、buildフォルダの中に`test.exe`ができた！

```
GOPATH/
  src/
  └ test/ <-今回のプロジェクトルート
    ├ cmd/
    │ └ textApp/
    │    └ main.go
    ├ intarnal/
    │ └ sub/
    │   └ sub.go
    ├ go.mo
    └ build/ 
       └ text.exe　<-　exeファイルができた！
```

##毎回長いコマンド叩くのめんどいからbatファイルを作る

推奨のフォルダ構成に則ってbuildするshとかbatファイルはscriptフォルダ入れるらしい

```
GOPATH/
  src/
  └ test/ <-今回のプロジェクトルート
    ├ cmd/
    │ └ textApp/
    │    └ main.go
    ├ intarnal/
    │ └ sub/
    │   └ sub.go
    ├ go.mo
    ├ build/ 
    │ └ text.exe
    └ script/ <-　scriptフォルダを作った
      └ test_build.bat　<- ビルドコマンドを実行するバッチファイルを作った
```

実行する

```
script/test_build.bat
```

##コンパイルしたexeファイルを実行する

```
build\test.exe
```

```
20
これはsubです。
```
OK！
rails db:migrateエラー

rails g migration ChangeSampleNameNotNullでNotNull制約を追加するファイルを作成しました。

```
class ChangeSampleNameNotNull < ActiveRecord::Migration[5.2]
  def change
    change_column_null :Sample, :name, false
  end
end

```

追加したファイルの中身を編集しrails db:migrateしようとするとエラー
#エラーの原因？
前に行ったコマンドのmigrationで何らかの手違いがあると思います。おそらく、migration処理の途中からエラーが起きていて、テーブルは生成されているが、テーブルを生成したmigrationは未実行のまま。といった状態なのかな？と思います

#解決法

```
＄rails db:migrate:reset
```
リセットする前に「これリセットする必要あるかな？なんか違う方法ないか？？？」と考えた結果まずは、dbのステータスを見てみようと思い↓実行してみました

```
$rails db:migrate:status
```

どうやら、一番下のマイグレーションファイルが怪しい。。。
エディタを確認したところ
同じマイグレーションファイルを二回作成していました。。
なので、一番下のマイグレーションファイルを削除してみます。
※downの状態だったら、手動でファイルを削除しても問題ない

```
Status   Migration ID    Migration Name
--------------------------------------------------
  up    20210323042143  Create posts
  down  20210323042144  Change sample text not null
```
↓のコマンドで削除

```
rm db/migrate/20210323123633_change_sample_text_not_null.rb 
```

これで問題なくマイグレートできる？？


**あ〜〜またエラーダァ！！！**

NoMethodError: undefined method `null=' for nil:NilClassと出てきたけど余裕だった
change_column_null テーブル名　カラム名　false　のカラム名を間違えただけだった。しっかり確認しよう。

#最後に
**いや〜沼った沼った…これからはこうゆうことがなるべく起こらない様に気をつけなきゃな〜。**


#補足
ActiveRecord::UnknownMigrationVersionErrorが出た時はこの方の参照
https://qiita.com/shellingford/items/d244c4bd61b2724f713e


**rails:db:rollbackとbundle exec rake db:migrate:down VERSION=**

```
Status   Migration ID    Migration Name
--------------------------------------------------
  up    20210323042143  Create posts
  up  20210323042144  Change sample text not null
  up  20210323042142  ~~~~~~~~~~~sample2
```
上から２つ目の奴をupからdownにさせたい…こうゆう時はbundle exec rake db:migrate:down VERSION=
(要は複数マイグレーションファイルがある場合。）
https://qiita.com/usizou/items/6dcdea46ec0b4a89c661
IBM CloudのCloud Foundryデプロイの無料枠のメモリ制限


IBM Cloudを試してみてます。

無料枠を使って試してましたが2個目のアプリケーションのデプロイを試そうとしたら下記エラーでした。

`You have exceeded your organization's memory limit: app requested more memory than available`

無料枠の制限を超えたようですね。

```bash
$ ibmcloud cf push    
'cf push' を起動しています...

nobisuke@xxxx.xxx.xxx としてマニフェストから組織 n0bisuke / スペース dev にプッシュしています...
マニフェスト・ファイル /Users/n0bisuke/playground/get-started-node/manifest.yml を使用しています
アプリ情報を取得しています...
これらの属性でアプリを作成しています...
+ 名前:       n0bisuke-testapp2
  パス:       /Users/n0bisuke/playground/get-started-node
+ メモリー:   256M
  経路:
+   n0bisuke-testapp2-xxxxxxxxx.mybluemix.net

アプリ n0bisuke-testapp2 を作成しています...
経路をマップしています...
ローカル・ファイルをリモート・キャッシュと比較しています...
Packaging files to upload...
ファイルをアップロードしています...
 37.27 KiB / 37.27 KiB [=====================================================================================================================] 100.00% 1s

API がファイルの処理を完了するのを待機しています...

アプリをステージングし、ログをトレースしています...
You have exceeded your organization's memory limit: app requested more memory than available
失敗
```

## 256Mまでは無料らしいのでどう割り当てるか問題らしい

1個目のアプリケーションで256M/256Mを利用してしまっていたのでこうなる模様

> ![スクリーンショット 2021-03-23 22.16.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/b17cd909-5b77-2dcd-eacd-454b94ce768a.png "スクリーンショット 2021-03-23 22.16.14.png")

### 256Mアプリケーションを2つ作ろうとしていた

* アプリ1

```manifest.yml
---
applications:
 - name: n0bisuke-testapp
   random-route: true
   memory: 256M
```

色々間省略するけど

```bash
$ ibmcloud cf push
```

一つ目はこれでデプロイ

* アプリ2

```manifest.yml
---
applications:
 - name: n0bisuke-testapp2
   random-route: true
   memory: 256M
```

二つ目も256Mでデプロイしてた

などにしてnameを別のものにして新規アプリケーションとしてデプロイしようとすると今回のようなエラーになりました。

## メモリ再割り当て

* アプリ1を64M

```manifest.yml
---
applications:
 - name: n0bisuke-testapp
   random-route: true
   memory: 64M
```

* アプリ2を128M

```manifest.yml
---
applications:
 - name: n0bisuke-testapp2
   random-route: true
   memory: 128M
```

こんな割り当てにしたら二つのアプリケーションを無料枠内でデプロイできまました。

## 64Mx4まで作れるか実験

* アプリ1を64M

```manifest.yml
---
applications:
 - name: n0bisuke-testapp
   random-route: true
   memory: 64M
```

* アプリ2を64M

```manifest.yml
---
applications:
 - name: n0bisuke-testapp2
   random-route: true
   memory: 64M
```

* アプリ3を64M

```manifest.yml
---
applications:
 - name: n0bisuke-testapp3
   random-route: true
   memory: 64M
```

* アプリ4を64M

```manifest.yml
---
applications:
 - name: n0bisuke-testapp4
   random-route: true
   memory: 64M
```

> ![スクリーンショット 2021-03-23 22.34.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/61229816-0d21-55d7-1178-9fd55425152b.png "スクリーンショット 2021-03-23 22.34.32.png")

問題なく4つまでいけました。

5つ目を作ろうとするとエラーですね

```
You have exceeded your organization's memory limit: app requested more memory than available
失敗
```

## まとめ

IBM CloudのPaaS無料枠 雰囲気掴んできました。

メモリが最大256Mまで割り当てで、一つのアプリの最低割り当てが64Mなので

* 64M * 4つ
* 128M * 2
* 128M * 1 + 64M * 2
* 256M * 1

など各自選択して利用できそうです。
findコマンドで○分以内に編集したファイル一覧を表示

#概要
ターミナルからファイルを最終編集日時から取得したいときの
方法を今まで知らなかったのでメモします。

#方法
15分以内に編集したファイルを取得したい場合はこのコマンドです。

    find . -mmin -15


ちなみに時間ではなく日付で絞り込みたい場合は

    find . -mtime -2

-mtimeを利用します。
[Rails]頼む…！ マスタデータの更新を マイグレーションでやる… それだけは しないでくれ！

マスタデータの更新を、`db/seeds.rb` ではなくマイグレーションファイルでやってしまった案件で私が体験した地獄を紹介します。

# まずは前提から

・タスク管理アプリの機能追加案件
・`task_categories` テーブルがマスタデータとして存在する
・マスタデータが変更されたら、都度マイグレーションファイルで `ActiveRecord::Base.connection.execute` で更新する運用
・マスタデータは `db/seeds.rb` でも設定している
・`task_categories` のテーブル構造（一部抜粋）
　・`code` カテゴリ識別名 (new、todo、finished 等) **uniq成約あり**

# 何が起きたか？

マスタデータ更新時に、マイグレーションだけ追加して `db/seeds.rb` をメンテナンスしていなかったために、
**dbを新規作成してrake db:seed を実行すると、uniq成約に引っかかりエラーで落ちるようになりました。**
また、db/seeds.rb がメンテナンスされてないため、ソースを見ても何が正しいデータなのかわからなくなりました。（コンソールなどで直接データを覗かないと正しいデータがわからない）

### そのとき起きたやり取りを簡単に再現します。


上司「俺君、次はタスク管理アプリの改修案件を着手してくれ。環境構築手順はドキュメントにかいてるからそのとおりでよろしく。」

俺「わかりました。」

~数分後~

俺「すみません、手順書通りに `rake db:seed` やったらエラーで落ちました。」

上司「悪いけどエラー原因調べてくれない？」

~数分後~

俺「ユニーク成約に引っかかってました。マイグレーションで `task_categories` のマスタデータを追加・更新した後に、 `rake db:seed` で同じ `code` のレコードを追加しようとしたためにエラーになったようです。」

上司「すまないけど、マイグレーションで作成したデータをもとに `db/seeds.rb` を集成してくれ。」

俺「え、でも `task_categories` のレコード数死ぬほど多いので大変ですよ。」

上司「頑張ってくれ。」

# ![gnyaa.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1218605/189eebd3-515e-8220-8413-f249f30ba6ee.jpeg)

# あとがき

今回は説明をシンプルにするためにテーブル数1つで解説しましたが、実際にはマスタデータのレコード数が多いだけでなく、アソシエーションが孫階層までつながってたので、芋づる式に **4桁分のレコードの db/seeds.rb を書き換える羽目になりました。コードの行数だけでいうと5桁の変更がありました。**
流石に手動でそこまで変更するのは無理なので、スクリプトを組んで良しなにやりました。
とはいえ、あまりにも変更箇所が多すぎてスクリプト実行中にメモリ不足で落ちる、差分が多すぎてgitlabで差分が表示できない等、別の苦労もありました。

この記事が少しでも多くの人に見てもらい同様の被害が少しでも減ることを祈っております。
OctaveをJupyterで走らせたい

#OctaveをJupyterで走らせたい
### Octaveを使い始めた理由、感じたこと
前回VS CodeでOctaveを走らせました。

https://www.gnu.org/software/octave/index

しかしながら、結局はVS Code上のTerminalで走らせない限り、CouseraのMachine Learning Classのコードは改変しなければなりませんでした。※ただしGNU Octave GUIよりはいい感じ。

今度はコードを改変すること前提で、Jupyter上でOctaveが走る環境を構築します。

###試した環境
* Computer: Apple MacBook Air Late 2020 M1 (Apple Silicon ARM)
* OS: Mac OS Big Sur version 11.2.3
* Anaconda3: version 3
* GNU Octave: version 6.2.0 

###Anaconda3のインストール
GUIでサクッとインストール。

https://www.anaconda.com/products/individual

今回使う機能は、

* Anacondaのコマンドで仮想環境を構築する
* Anacondaをインストールするともれなく一緒にインストールされるJupyter-Lab

です。

### 仮想環境の構築
Octaveのための環境を構築します。

Python3.8の環境を構築しました。

```bash

$ conda create -n py38 python=3.8 anaconda
```
構築できたら、仮想環境に移動します。

```bash

$ source activate py38
```

仮想環境にoctave_kernelをインストール。

```bash

py38$ pip install octave_kernel
```

パッケージの作成。

```bash

py38$ ls /Users/username/opt/anaconda3/envs/py38/lib/python3.8/site-packages/ | grep octave_kernel
py38$ $ octave_kernel-0.32.0-py3.8.egg
```

Jupyter-Labの起動

```bash

py38$ jupyter-lab
```
カレントディレクトリをコードを実行したい環境にして、グラフ描画をしてみます。

### Jupyter上でグラフを表示する

下記サイトを参考にしました。

https://stackoverflow.com/questions/65511187/jupyter-octave-kernel-inline-graph-windows

Notebookの最初で次のコマンドを実行しておきます。

```matlab

graphics_toolkit ("gnuplot");
```

次のようなデータを読み込ました。

* X1:１回目のテストの結果
* X2:2回目のテストの結果
* y:最終合否

|  X1  |  X2  |y|
| ---- | ---- | ---- |
|  83  |  95  | 1  |
|  10  |  23  | 0  |

下記のようなコードを書いて２系列データの散布図を描画しました。

```matlab

%% Initialization
clear ; close all; clc

%% Load Data
%  The first two columns contains the exam scores and the third column
%  contains the label.

data = load('ex_data.txt');
X = data(:, [1, 2]); y = data(:, 3);

pos = find(y==1);
neg = find(y==0);
plot(X(pos,1),X(pos,2),'k+',X(neg,1),X(neg,2),'ko')

% Put some labels 
hold on;
% Labels and Legend
xlabel('Exam 1 score')
ylabel('Exam 2 score')
```

無事描画できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1230168/b4b3fe53-16ba-5437-a411-3e70dc8f44af.png)
k8s ingressの後ろでFastAPIのDocsを見たい

# 動機
* FastAPI使いたい
* k8sとnext.jsと一緒に使いたい
* パスを楽に設定したい
* 開発中は**swaggerのdocsにもアクセスしたい** ← ココ！

# 結論

* この設定でいける

1. FastAPIのroot_pathを設定する
2. Ingressのrewrite-targetを設定する

# 環境
* Hyper-VにUbuntu 20.04
* minikube

# 前提
* Dockerイメージを用意している
    * お好きなようにFastAPIのアプリを用意
* /etc/hostsにingressのIPとdev用ドメインを定義している
    * https://kubernetes.io/docs/tasks/access-application-cluster/ingress-minikube/


# 1. FastAPIのroot_pathを設定する
## 1-1. DeploymentとServiceの定義

* ```ROOT_PATH```環境変数を定義するだけ
* FastAPIから取得するため

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-depl
spec:
  replicas: 1
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
        - name: myapp
          image: me/fastapi-myapp
          env:

　　　　　 # !!!ROOT_PATH環境変数の設定!!!
          - name: ROOT_PATH
            value: '/api/v1/myapp'

---
apiVersion: v1
kind: Service
metadata:
  name: myapp-srv
spec:
  selector:
    app: myapp
  ports:
    - name: myapp
      protocol: TCP
      port: 8000
      targetPort: 8000
```

## 1-2. FastAPIの設定

* ```root_path```に1-1で定義したパスを設定

```python
import os
from fastapi import FastAPI, Request
from routers import my_module

# 詳細はここ https://fastapi.tiangolo.com/advanced/behind-a-proxy/ 
app = FastAPI(root_path=os.getenv('ROOT_PATH', ''))

@app.get("/")
def read_root(request: Request):
    return {"message": "Hello World", "root_path": request.scope.get("root_path")}
```


# 2. Ingressの定義



```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-service
  annotations:
    kubernetes.io/ingress.class: nginx
    # cluster外（ブラウザとか）からのリクエストパスを書き換えてくれる設定
    # https://kubernetes.github.io/ingress-nginx/examples/rewrite/
    nginx.ingress.kubernetes.io/rewrite-target: /$2

    nginx.ingress.kubernetes.io/use-regex: 'true'
spec:
  rules:
    - host: fastapi.dev
      http:
        paths:
　　　　　 # 正規表現で2番目にマッチしたパスに書き換えてFastAPIにリクエストする
          - path: /api/v1/myapp(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: myapp-srv
                port:
                  number: 8000

```



# 確認

* ```http://fastapi.dev/api/v1/myapp/docs```にアクセス
    * ローカルでhttpだとwarningページになるので```thisisnsafe```で確認してね
    * https://sig9.hatenablog.com/entry/2020/04/17/000000
* いい感じ


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351017/36f0c922-896a-8ce0-5c75-5e9d9548a90b.png)


バックエンド側のパスを書き換えずに、yamlと```main.py```の設定だけでできました。超絶楽ちん。すばらし！
[OutSystems]REST APIからHTMLを返す

OutSystemsでBasic認証をかけたURLから任意のHTMLを返す方法がないかな、と考えてみました。
Expose REST APIの機能であれば、プロパティの設定だけでBasic認証をかけられるので、REST APIを作って、希望のHTMLを返せればOKですね。

# Content-Type
実験してみたところ、Expose REST APIのHTTPレスポンスに出力されるContent-Typeの値は、デフォルトでは「text/plain; charset=utf-8」（出力変数の型がTextのとき）か「application/json; charset=utf-8」（複雑な型のとき）のようです。

データとしてHTMLをかえすなら、text/plainでも構いませんが、「text/html; charset=utf-8」にしたければ、HTTPRequestHandler ExtensionのAddHeader Actionで上書きできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/15631013-f52e-b8a5-5a13-fed82d11f8a3.png)


# 方法1：Text出力変数にHTMLを直接出力する
Text型の出力変数を1つだけ持つREST API Methodを用意し、その変数に直接HTMLを書き込む方法です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/a4ce9de6-d911-b816-7abc-7f99e46ddf91.png)


# 方法2：On Response CallbackでJSONをHTMLに変換する
REST API Methodから、HTMLの材料となるデータを出力変数に書き込みます。
複雑な出力変数はJSON形式になるので、これを出力の直前に処理を差し挟めるOn Response Callbackで変換（JSONから元のデータに戻し、ロジックでHTMLを整形）する方法です。
当初構想段階ではこちらの方法が良いかと思ったのですが、実装の手間が方法1とあまり変わらないですね。On Responseは同じREST APIにぶら下がる全API Methodに対して後処理として動作するので、複数のAPI Methodが同じデータ形式を返す場合は方法2を取る機会もあるかもしれません。

なお、On Response自体については、[Expose REST APIのOnResponseを試す](https://qiita.com/jyunji_watanabe/items/db85f7a04dccf08fbf06)を参照。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/9edb71f3-0f6c-74a3-6344-7e72a5abfe7e.png)
【MySQL】Error Code: 1175. You are using...の対処方法

>Error Code: 1175. You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.  To disable safe mode, toggle the option in Preferences -&gt; SQL Editor and reconnect.   0.060 sec

MySQLWorkbenchで、DELETEや UPDATEのSQLコマンドを実行すると、このようなエラーが発生することがあります。

#対処方法
MySQLWorkbenchのPreferencesを選択します。

![スクリーンショット-2020-07-14-22.02.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1178764/4eff6110-1006-a08a-34d1-b1addcf8d1ac.png)


左のタブでSQL Editorを選択し、Other欄のSafe Update (rejects UPDATEs and DELETEs with no restrictions)のチェックを外します。

![スクリーンショット-2020-07-14-22.04.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1178764/400d03ee-96ba-86d8-9657-d16884eee51b.png)


チェックを外すと、エラーが取れていると思います。
（それでもダメな場合は、再接続・再起動を試してください）

#tips
SQLのUPDATEやDELETEコマンドは非常に強力です。

たった一行で、全てのデータを書き換え、全てのデータを消すことができてしまうのです。
誤って実行してしまうと考えたらやばいですよね。

そこで、今回のようなチェックボックスを設けることで、DBを守るという仕組みになっているのです。

チェックボックスがついたままだと、WHERE句で指定をしないと、UPDATEやDELETEは使えないと思います。
環境構築無しでReactを触ってみよう！

#Reactを環境構築無しで使ってみよう。
初めてReactを使う時、環境構築で躓く人も多いと思います。
そこでおすすめなのが[**CodeSandbox**](https://codesandbox.io/?from-app=1)です。

##CodeSandboxとは

CodeSandboxとは環境構築不要でJavaScript（React,Vue.js,Angular）などが使用可能です。
環境構築で躓くようでしたら、とりあえずCodeSandboxで学んでみるのも良い手でしょう。

![スクリーンショット 2021-03-23 21.39.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/d08d5004-dd76-741e-4ffb-12f2c7b22c0e.png)

##Reactの環境構築をサクッと作ってみよう

1.[**CodeSandbox**](https://codesandbox.io/?from-app=1)にアクセス
![スクリーンショット 2021-03-23 22.05.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/9d3b5aae-f02a-e7ed-442f-e8391484bd1a.png)

2.**CreateSandbox**を選択

3.使用フレームワークを選択
![スクリーンショット 2021-03-23 21.39.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/902e82c1-6626-89be-ec9e-22a2191e4636.png)

4.完了
![スクリーンショット 2021-03-23 22.00.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1202267/f0d2289e-fe00-9010-af54-338781b6491c.png)

#最後に
Githubの連携であったり、ファイルの保存なども出来るので非常に便利です！
是非、使ってみてください。
Spring Security + SPA(Nuxt.js)でX-XSRF-TOKENヘッダーが無くてCSRFで拒否される

REST APIとSPAの環境構築をした際、CSRFでハマった。
CSRF用のCookieのやりとりは上手くいってたが、X-XSRF-TOKENヘッダーが送付されておらずエラーになっていた。

Spring Securityやnuxt/axiosが色々やってくれるので、背景知識が足りず深くハマってしまった。

## 状況
**SPA**

- Nuxt.js 2.14.5
- APIとの通信はnuxt/axiosを使用
- S3 + CloudFrontで環境構築
    - ドメインは https\://foo.com

**REST API**

-  Kotlin 1.4.0
- Spring Boot 2.3.2
- Spring Security
- ECSで環境構築
    - ドメインは https\://bar.com


**Spring SecurityのCSRF設定**

```kotlin:SecurityConfig
@EnableWebSecurity
class SecurityConfig(): WebSecurityConfigurerAdapter() {

    @Throws(Exception::class)
    override fun configure(http: HttpSecurity) {
        http
            .authorizeRequests()
            ...
            .and()
            .csrf()
            .ignoringAntMatchers("/home")
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
```
.ignoringAntMatchers() で /homeへのCSRFを無効にしています。

```kotlin
  .ignoringAntMatchers("/home")
```

CookieCsrfTokenRepositoryを使用する際は.withHttpOnlyFalse()の記述をすると、JavaScriptからCookieを扱う事ができます。

```kotlin
  .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
```

## 何が起きたか
local環境ではうまくいっていたが、ECS + S3で環境を構築をしデプロイするとCSRFではじかれた。
最初のアクセス /home（csrf無効）後に、次のアクセス /login（csrf有効）するとエラー。

```
Invalid CSRF Token 'null' was found on the request parameter '_csrf' or header 'X-XSRF-TOKEN'.
```

CSRF Tokenがnullと言われる。
Google Chrome Developer ToolsでNetworkを確認する。

最初の/home（csrf無効）のResponseのHeadersにset-cookie: XSRF-TOKEN=xxx; が返ってきて、
次の/login（csrf有効）のRequestのCookiesに、XSRF-TOKEN xxxx が入っている。

ただそのHeadersに、X-XSRF-TOKENの記載がない。
nuxt/axiosの仕様では

```javascript:nuxt.config.js
axios: {
    credentials: true
}
```
と記載しておけば、Cookieを自動で付けてくれる。
CookieにXSRF-TOKENがいる場合は、X-XSRF-TOKENというヘッダーを生成してくれる。



## なぜX-XSRF-TOKENのHeaderがないのか
JavaScriptは自身と異なるドメインのcookieを操作する事ができない。という事がわかった。
いわゆる3rd party cookieというやつの操作ができない。

今回の場合だと

フロント： https\://foo.com
サーバ： https\://bar.com

なので、foo.comのjsはbar.comで発行されたCookieを操作する事ができない事になる。
よって、axiosはCookieのXSRF-TOKENを、X-XSRF-TOKENというヘッダーに付け替える事ができず、nullになってしまった。

## 解決策
CSRF Token取得用のControllerを作成。

```kotlin:CsrfController
@RestController
class CsrfController {

    @GetMapping("/csrf")
    fun issueCsrfToken(csrfToken: CsrfToken): CsrfToken {
        return csrfToken
    }
}
```

返却するcsrfTokenの中身はこんな感じ

```
{
  parameterName: "_csrf",
  token: "xxx-xxxx-xxxx",
  headerName: "X-XSRF-TOKEN"
}
```

JavaScriptで /csrf を叩いてcsrfTokenを取得しcookieに保存。

```javascript
const csrf = await this.$axios.$get('https://bar.com/csrf')
document.cookie = `XSRF-TOKEN=${csrf.token}`
```

このようすればJavaScriptでcookieを扱う事ができるので、
次の通信の際に、axiosがX-XSRF-TOKENヘッダーを作成してくれる。
～ 基本演算 ～ チートシート

#目次
[べき乗](#べき乗)　`pow(x,n,MOD)`
[実数を整数にする](#実数を整数にする)
　丸め処理(四捨五入)　`round()`
　切り捨て `math.floor()`
　切り上げ `math.ceil()`


[四則演算](#四則演算)　`+` `-` `*` `/`　商`//` 余り`%`　べき乗`**`
[最小値_最大値](#最小値_最大値)　`min()` `max()` 
[平方根](#平方根)　`math.sqrt()`

#はじめに

チートシートの扱いついては[ここ](https://qiita.com/ysys_Ba/items/d27282b888abbd1f43e7#%E3%83%81%E3%83%BC%E3%83%88%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)を読んでください

#べき乗

```python:calculation.py
print(pow(2,10))
```

```python:出力
>>> 1024
```

`pow(x,n)`は`x**n`と同じ

```python:calculation.py
print(pow(2,1024,1000000007))
```

```python:出力
>>> 812734592
```

第三引数にMODを入れると、MODで割った余りを出力する
`pow()`繰り返し二乗法を用いて実装されているので、乗数が大きくなったりしても早く計算できる

#平方根

```python:calculation.py
import math
print(math.sqrt(144))
```

```python:出力
>>> 12
```

`pow()`とか`**`で求めてもよいが、`pow()`が１番早い（らしい）
まあそこまで大きな時間差にもならないだろうし、正直どれ良さそう（`import math`するのめんどくさいし）

#実数を整数にする

##丸め処理(四捨五入)

```python:calculation.py
print(round(114514.1919))
```

```python:出力
>>> 114514
```

厳密には四捨五入ではないが、ほぼ四捨五入みたいなもん

```python:calculation.py
print(round(114514.1919, 2))
print(round(114514.1919, 1))
print(round(114514.1919, 0))

print(round(1145141919, 0))
print(round(1145141919, -1))
print(round(1145141919, -2))
```

```python:出力
>>> 114514.19
>>> 114514.2
>>> 114514.0

>>> 1145141919
>>> 1145141920
>>> 1145141900
```

四捨五入する位の位置を指定すると有効数字を変えられる

##切り捨て

```python:calculation.py
import math
print(math.floor(114514.1919))
```

```python:出力
>>> 114514
```

`floor` : 英語で「床」

```python:calculation.py
print(int(114514.1919))
```

```python:出力
>>> 114514
```

`int()`も切り捨てなので代用可能

```python:calculation.py
print(33/4)
print(33//4)
```

```python:出力
>>> 8.25
>>> 8
```

int同士を割り算した結果を切り捨てたいなら、商を求める`//`を使えばいい
`math.floor()`よりこっちのほうが早いらしい


##切り上げ

```python:calculation.py
import math
print(math.ceil(114514.1919))
```

```python:出力
>>> 114515
```

`ceil` : 英語で「天井」

```python:calculation.py
print(33/4)
print(-(-33//4))
```

```python:出力
>>> 8.25
>>> 9
```

int同士を割り算した結果を切り上げたいなら、これも商を求める`//`を使えばいい（これ思いついた人賢い）

#四則演算

```python:calculation.py
print(33 + 4)
print(33 - 4)
print(33 * 4)
print(33 / 4)
```

```python:出力
>>> 37
>>> 29
>>> 132
>>> 8.25
```
`Hello, world!`の次にやった気がするし、まあ...

```python:calculation.py
print(33 / 4)
print(33 // 4)
print(33 % 4)
```

```python:出力
>>> 8.25
>>> 8
>>> 1
```

商と余りも出せる

```python:calculation.py
print(-33 // 4)
print(-33 % 4)
```

```python:出力
>>> -9
>>> 3
```

商が負になる場合は、余りが正になるように計算される

```python:calculation.py
print(2**10)
```

```python:出力
>>> 1024
```

べき乗も計算可能

#最小値_最大値

```python:calculation.py
print(min(114,514,810))
print(max(114,514,810))
```

```python:出力
>>> 114
>>> 810
```

3つ以上でもOK
データ分析関連の職業を整理する


# はじめに

色々なデータ分析系の職業を見た中で、その分類を自分なりにまとめることが趣旨の記事です。
こちらの記事([機械学習・AI関連の職業をざっくりとまとめてみた](https://qiita.com/calderarie/items/04cb3c7a9b36f70a1363))のアップデート版です。

自分用なので、内容も薄く、まとめ方も洗練されていないと思います。
気が向いたらまた更新します。

# まとめ方について

ここでは、おおまかに具体的に何をやっているのか「職務」によって各職業を分類し、それに対応する「スキル」を整理します。

データ関係の職業に求められるスキルセットは、一般的に「ビジネス」「データサイエンス」「エンジニアリング」の３つに分類されています。

各スキルをどのくらいの割合で保有しているかでなんとなくのイメージをおいています。(スキルの習熟度ではなく割合です)


# 各職業

## Biz系

### データアナリスト

- 職務
    - 課題に対して、データを用いた検証設計とその検証を行い、課題解決に繋げる
- スキルイメージ
    - ビジネス / データサイエンス / エンジニアリング： 70% / 20% / 10%
- 具体のスキル
    - データを用いた問題解決能力(課題を発見、分析し、解決案を提案・実行し、効果を検証する）をもつ

### 分析プロジェクトリーダー

- 職務
    - 機械学習モデルの構築やデータ基盤開発などのプロジェクトを実行する
- スキルイメージ
    - ビジネス / データサイエンス / エンジニアリング： 50% / 25% / 25%
- 具体のスキル
    - プロジェクトマネジメント

### 分析コンサルタント

- 職務
    - 組織のデータ利活用の導入やリテラシー教育を推進する
- スキルイメージ
    - ビジネス / データサイエンス / エンジニアリング： 80% / 20% / 10%
- 具体のスキル
    - 組織の課題をヒアリング、分析、適切な解決策を提案・実行できる

## Dev系

データサイエンティスト、MLエンジニア、MLリサーチャーはかなり重複している部分があると思います。

### データサイエンティスト

- 職務
    - 機械学習等のアルゴリズムの構築
- スキルイメージ
    - ビジネス / データサイエンス / エンジニアリング： 30% / 50% / 20%
- 具体のスキル
    - 要求に合わせて適切な手法を選択し、OSSなどを活用したアルゴリズムの実装力と適切な検証ができる

### MLエンジニア

- 職務
    - 機械学習等のアルゴリズムのプロダクトへのデプロイ
- スキルイメージ
    - ビジネス / データサイエンス / エンジニアリング： 20% / 40% / 40%
- 具体のスキル
    - 実サービスで運用可能なMLパイプライン、システムの設計や構築能力がある

### MLリサーチャー

- 職務
    - 最新の機械学習や人工知能アルゴリズムのR&D
- スキルイメージ
    - ビジネス / データサイエンス / エンジニアリング： 10% / 60% / 30%
- 具体のスキル
    - 要求に合わせて、論文などから適切な手法を参照し、スクラッチで開発、高度化できる


### BIエンジニア

- 職務
    - BI環境の構築やその運用
- スキルイメージ
    - ビジネス / データサイエンス / エンジニアリング： 30% / 10% / 60%
- 具体のスキル
    - BIツールやデータパイプラインの構築、設計

### データエンジニア

- 職務
    - 分析用にビッグデータ処理基盤やデータマートを構築・運用する
- スキルイメージ
    - ビジネス / データサイエンス / エンジニアリング： 20% / 20% / 60%
- 具体のスキル
    - 適切なクラウドインフラストラクチャや分散処理フレームワークを用いて分析基盤を設計できる
Nuxt.jsでSSGしたサイトをGitHubからXserverへftpsで自動デプロイする

# 背景
- クライアントさんがXserverをご所望。
- mainブランチへpushしたら自動でdeployしたい。
- 手動deployもできてほしい。
- すごく急ぎだったため設定にかける時間は最小限に。（ということでrsyncは断念）

# Xserverの準備
サブFTPアカウントを作っておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398513/dace5a04-ff30-b636-992b-bce4740e93d7.png)

# GitHub Actionsの設定

**想定**
- パッケージマネージャはyarnを使用。
- Node.jsは14.xを使用。

## FTPのホスト・アカウントをリポジトリのsecretに設定する

リポジトリのSettingsタブ→Serets ページで[New repository secret]ボタンを押して各パラメーターを入力しておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398513/e3833c15-6d93-e751-e000-976f8911cce1.png)

## Actionを作成する

```yml:/.github/workflows/main.yml
name: Deploy

on:
  push:
    branches:
      - main
  workflow_dispatch:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2

    - name: Use Node.js
      uses: actions/setup-node@v1
      with:
        node-version: '14.x' # プロジェクトに合わせて

    - name: Get yarn cache directory path
      id: yarn-cache-dir-path
      run: echo "::set-output name=dir::$(yarn cache dir)"

    - name: Cache Node.js modules
      id: yarn-cache
      uses: actions/cache@v2
      with:
        path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
        key: ${{ runner.OS }}-yarn-${{ hashFiles('**/yarn.lock') }}
        restore-keys: |
          ${{ runner.OS }}-yarn-

    - name: Install dependencies
      run: yarn install --frozen-lockfile --prefer-offline

    - name: Build
      run: yarn generate

    - name: Deploy
      uses: SamKirkland/FTP-Deploy-Action@2a4e9b1312ebeb73a1f72b9330c71831c1e4ce01 # v4.0.0 のコミットハッシュ
      with:
        server: ${{ secrets.FTP_HOST }}
        username: ${{ secrets.FTP_USER }}
        password: ${{ secrets.FTP_PW }}
        protocol: ftps
        security: strict
        local-dir: dist/
        server-dir: public_html/
        state-name: ../ftp-deploy-sync-state.json # 管理ファイルは公開フォルダの外に置く
        exclude: .nojekyll # Nuxtが親切に作ってくれるけどXserverには要らない
```

# 備考
syncではないからゴミが溜まる？ 頻繁に更新するサイトやサイズが大きいサイトなら真面目にsyncの仕組みを設定する、いやむしろNetlifyあたりを提案する方がいいかも。



# 参考

- https://github.com/actions/cache/blob/master/examples.md#node---yarn
- https://github.com/SamKirkland/FTP-Deploy-Action
ActiveStorageを使用した画像保存

# ActiveStorageを使用して画像を保存、表示させる
※ただのアウトプットノート感覚で使っています。

### ActiveStorageを導入する

```
$ rails active_storage:install
```
このコマンドを使用するとactive_storage_blobs とactive_storage_attachments
といった二つのテーブルが作成されたマイグレーションファイルができある
出来上がったマイグレーションファイルを確認できたら<br>

```
rails db:migrate
```
を実行する。

### modelに対してActiveStorageの設定をする
user.rbにActive Storageを設定する例でやっていきます。カラムの名前はavatarでいきます。<br>
まず一つの画像ファイルを保存したい場合の記述は

~~~ruby
has_one_attached :avatar
~~~
と書きます。次に複数の画像ファイルを保存したい場合の記述は

~~~ruby
has_many_attached :avatar
~~~
と記述します。

 次に画像を保存できるようにする。

 ここではdeviseを使用する例でいきます。<br>

 ~~~ruby

 <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %>
  <%= render "devise/shared/error_messages", resource: resource %>
  ~~~
  この中に下記を追加します。

  ~~~ruby
  <div class="field">
   <%= f.label :avatar, "プロフィール画像" %><br/>
   <%= f.file_field :avatar %>
  </div>
  ~~~
  上記のコードを書くことで簡単に保存フィールドが出来上がリマス。
  ### 保存した画像をviewで表示させる
  表示させたいviewファイルに画像を表示させるコードを書いていきます

  ~~~ruby
  <%= image_tag user.avatar %>
  ~~~
  僕はこのコードで表示できずエラーなりました。
  なので書き方を変えてこのコードで表示に成功することができました。

  ~~~ruby
  <%= image_tag(url_for(@user.avatar)) %>
  ~~~
  今気づいたのですがもしかしたら一行目のコードはインスタンス変数を使用していないから表示されてないのでは？と気づきましたがまた後日確認してみます(笑)
  もしかしたら一行目も@user.avatarとすれば表示できるかもしれませんね！
  さすが初心者の僕ですね！！<br>
  
  
  おしまい。
配列の要素をまとめて削除したい！　delete_if, reject!を使う

# 概要
配列から、条件に当てはまったものを削除しようとした際、`配列.each`で要素を一つ一つ取り出して、`if`で検証してその要素を`delete`しようとしたのですが、以下のように失敗しました。

```Ruby:Ruby
# 2つの配列 a, b において、 b に含まれている要素を a から取り除く
a = [*1..10]  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [2, 3, 5, 7, 8]

a.each do |num|
  if b.include?(num)
    a.delete(num)
  end
end
p a  # => [1, 3, 4, 6, 8, 9, 10]
# 期待していた出力 => [1, 4, 6, 9, 10]
```
調べてみると以下の記事が参考になりました。

参考:配列の複数要素の削除はdelete_ifかreject、-なんかを使おう
https://qiita.com/zom/items/4461d786c35ae9eced0b

今回の場合、配列 a において、添字が 1 である数値 2 が削除された際に、その空いた添字 1 を埋めるように、配列 a の数値 3 以降の要素が左にズレることになり、元々添字が 2 であった数値 3 が添字 1 となり、イテレータ（繰り返し処理）の中で、数値 3 に対する処理が飛ばされてしまっていました。（数値 8 についても同様）
念の為、pメソッドを用いて、処理の途中で配列 a がどうなっているか確認しました。

```Ruby:Ruby
a = [*1..10]  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [2, 3, 5, 7, 8]

a.each do |num|
  if b.include?(num)
    a.delete(num)
    p a
  end
end

=> [1, 3, 4, 5, 6, 7, 8, 9, 10]  # 数値 2 に対してdeleteが行われた直後、数値 3 が添字 1 に
=> [1, 3, 4, 6, 7, 8, 9, 10]  # 数値 5 に対してdeleteが行われた直後、数値 6 が添字 3 に
=> [1, 3, 4, 6, 8, 9, 10]  # 数値 7 に対してdeleteが行われた直後、数値 8 が添字 4 に

# 5回出力されるのを期待していたのが、3回しかされていないのは、数値 3 と 8 に対する処理が飛ばされたから

```
そこで、配列の中から条件に合った要素をまとめて削除する方法はないかと調べたところ、`delete_if`と`reject!`というArrayクラスのメソッドがあったので、備忘録としてまとめました。

# delete_if
delete_ifの機能は以下になります。
>要素を順番にブロックに渡して評価し、その結果が真になった要素をすべて削除します。 delete_if は常に self を返します。

参考:Ruby 3.0.0 リファレンスマニュアル
https://docs.ruby-lang.org/ja/latest/method/Array/i/delete_if.html

each, if, deleteがひとまとめになったようなメソッドですね。
では使ってみます。

```Ruby:Ruby
# 連続した数字を要素にもつ配列から偶数の要素を取り除く
numbers = [*1..10]  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.delete_if {|n| n.even?}
p numbers  # => [1, 3, 5, 7, 9]


# 2つの配列 a, b において、 b に含まれている要素を a から取り除く
a = [*1..10]  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [2, 3, 5, 7, 8]
a.delete_if do |num|  # a の要素を順番にブロック変数に渡す
  b.include?(num)  # 配列 b に num があるかどうかを調べ、あった場合（trueのとき）、 a から num を削除する
end
p a  # => [1, 4, 6, 9, 10]
```
要素をまとめて削除することができました。

# reject!
基本的に機能はdelete_ifと変わりませんが、以下の部分が異なります。
>delete_if は常に self を返しますが、reject! は要素が 1 つ以上削除されれば self を、 1 つも削除されなければ nil を返します。

参考:Ruby 3.0.0 リファレンスマニュアル
https://docs.ruby-lang.org/ja/latest/method/Array/i/delete_if.html

```Ruby:Ruby
# 連続した数字を要素にもつ配列から偶数の要素を取り除く
numbers = [*1..10]  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.reject! {|n| n.even?}
p numbers  # => [1, 3, 5, 7, 9]


# 2つの配列 a, b において、 b に含まれている要素を a から取り除く
a = [*1..10]  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
b = [2, 3, 5, 7, 8]
a.reject! do |num|
  b.include?(num)
end
p a  # => [1, 4, 6, 9, 10]


# delete_if は常に self を返す
numbers = [1, 3, 5, 7, 9]
p numbers.delete_if {|n| n.even?}  # => [1, 3, 5, 7, 9]

# reject! は要素が1つ以上削除されれば self を、1つも削除されなければ nil を返す
numbers = [1, 2, 3, 5, 7, 9]
p numbers.reject! {|n| n.even?}  # => [1, 3, 5, 7, 9]

numbers = [1, 3, 5, 7, 9]
p numbers.reject! {|n| n.even?}  # => nil
```

以上です。