OmniAICreator/Qiita-1.07M huggingface dataset:
gethコマンド まとめ

## Gethインストール
```
$ brew tap ethereum/ethereum
$ brew install ethereum
```

## Geth起動
```
$ mkdir ~/main_data
$ cd ~/main_data
$ geth --dev --datadir .              // gethプロセス起動
$ geth attach geth.ipc
```

## アカウント作成
```
> eth.accounts                       // アカウント確認
> personal.newAccount("test01")      // アカウント作成
> eth.coinbase                       // etherbase (coinbase)作成
```

## マイニング
```
> miner.start()                     // マイニング開始
> eth.mining                        // マイニング中か否か              
> eth.hashrate                      // マイニング中でない場合、ハッシュ・レートは0となる。
> miner.stop()                      // マイニング終了
> eth.getBalance(eth.accounts[0])   // 持ち高表示
```

## 送金
```
> personal.unlockAccount(eth.accounts[0])  // アカウントロック解除
> eth.sendTransaction({from: eth.accounts[0], to: eth.accounts[1], value: 10000})
> eth.getBalance(eth.accounts[1])          // 確認
> eth.getTransaction('10x010x010x010x0')   // 手数料（gasPrice）確認
```

## 接続確認
```
> net.listening           // 疎通確認
> net.peerCount           // 接続されているノード数
> admin.nodeInfo
> admin.peers             // 接続されているノード情報
```

## privateネットワーク
```
$ mkdir ~/private_net
$ cd ~/private_net
$ vim Genesis.json        // Genesisファイル作成
$ geth --datadir private_net init Genesis.json
$ geth --dev --datadir .              // gethプロセス起動
$ geth attach geth.ipc
```

# 参考文献
 - [Ethereum スマートコントラクト入門：geth のインストールから Hello World まで](https://qiita.com/amachino/items/b59ec8e46863ce2ebd4a)
 - [Ethereum入門](https://book.ethereum-jp.net/)
 - [net.peerCount 0](https://github.com/ethereum/go-ethereum/issues/16269)
【Gatsby.js】対処しよう、「Error: Input file contains unsupported image format」に

# 概要

- Gatsby を Netlify で build した時に出たエラーが出る
- `Error: Input file contains unsupported image format`
- なんかパッケージを全部バージョンアップしたら治った

# トラブルシューティング

[Error: Input file contains unsupported image format, gatsby \- Support \- Netlify Community](https://community.netlify.com/t/error-input-file-contains-unsupported-image-format-gatsby/10891)

によると、以下の文言がありました。

> I tried to the suggetion but it doesn`t work.
> I think I mistook maybe.
> But I fixed it this followings:
> Find old version for sharp: npm list sharp
> Upgrade version dependencies that uses old sharp version.

やんわり翻訳すると **「Sharp のバージョンが古いからだめなんじゃね？」** ということらしいです、やんわりすぎる。

教示されたやり方でパッケージを確認したら、確かに古いパッケージが見つかりました。

```sh:terminal
$ npm list sharp
gatsby-starter-blog@0.1.0 ~
├─┬ gatsby-plugin-manifest@2.6.1
│ └── sharp@0.25.4
├─┬ gatsby-plugin-sharp@2.14.0
│ └── sharp@0.27.1
└─┬ gatsby-transformer-sharp@2.12.0
  └── sharp@0.27.1
```

じゃあこれをアップデートしたら治るんじゃね！？

**…どうやって？** (Python以外の能がない男)

# というわけで

パッケージを全部最新にしてみたらうまくいきました。

```sh:terminal
# ncuを使えるようにする
$ npm install -g npm-check-updates

# プロジェクトフォルダーに移動
$ cd ~

# バージョンのチェック
$ ncu
Upgrading ~/package.json
[====================] 29/29 100%

 gatsby                            ^2.32.0  →  ^2.32.3
 gatsby-plugin-feed                 ^2.7.0  →  ^2.13.0
 gatsby-plugin-manifest             ^2.6.1  →  ^2.12.0
 gatsby-plugin-offline              ^3.4.0  →  ^3.10.0
 gatsby-plugin-react-helmet         ^3.4.0  →  ^3.10.0
 gatsby-plugin-sharp               ^2.14.0  →  ^2.14.1
 gatsby-remark-copy-linked-files    ^2.4.0  →  ^2.10.0
 gatsby-remark-images               ^3.5.1  →  ^3.11.0
 gatsby-remark-responsive-iframe    ^2.5.0  →  ^2.11.0
 gatsby-remark-smartypants          ^2.4.0  →  ^2.10.0
 gatsby-transformer-remark         ^2.10.0  →  ^2.16.0
 react                            ^16.12.0  →  ^17.0.1
 react-dom                        ^16.12.0  →  ^17.0.1
 react-helmet                       ^5.2.1  →   ^6.1.0
 typeface-merriweather              0.0.72  →   1.1.13
 typeface-montserrat                0.0.75  →   1.1.13

Run ncu -u to upgrade package.json

# 更新かける
$ ncu -u
省略
Run npm install to install new versions.

$ npm install
省略

$ ncu
Checking ~/package.json
[====================] 29/29 100%

All dependencies match the latest package versions :)
```

## 参考

> - [npm のパッケージを最新版に更新する – ラボラジアン](https://laboradian.com/update-npm-packages/)
> - [Error: Input file contains unsupported image format, gatsby \- Support \- Netlify Community](https://community.netlify.com/t/error-input-file-contains-unsupported-image-format-gatsby/10891/4)
UITabBarControllerを非表示にする

#非表示にしたい場合
```swift:ViewController.swift
class ViewController: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.tabBarController?.tabBar.isHidden = true
    }
}
```
#表示したい場合
```swift:ViewController.swift
class ViewController: UIViewController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        self.tabBarController?.tabBar.isHidden = false
    }
}
```
AWS RDSのMySQLにLocalからつながらない問題

AWS歴100秒未満の雑魚が対象です。

# DBは作れるがローカルから接続できない
Elastic BeanstalkでDatabaseを作り、無料枠の`Single-AZ db.t2.micro`を使いたいのでMySQLをチョイスしました。デフォルトで`パブリックアクセス`を`yes`に設定されているのを確認、ユーザID、パスワード、設定ＯＫ。インスタンス作成成功！
いざ、ローカルのMySQL Workbenchを起動すると・・接続できねー！

# オフィシャルドキュメントをチェック
以下のリンクより、「デフォルトのままではセキュリティグループのインバウンドルールに自分のIPが設定されてない」ことがわかりました。
当たり前だけどけっこう固いのね。自宅のIP変わったら都度設定しなくちゃならんのか。

[MySQL データベースエンジンを実行している DB インスタンスへの接続
（https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_ConnectToInstance.html）](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_ConnectToInstance.html)

[Amazon RDS DB インスタンスに接続できない
（https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_Troubleshooting.html#CHAP_Troubleshooting.Connecting）
]
(https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_Troubleshooting.html#CHAP_Troubleshooting.Connecting)

# セキュリティをチェックせよ
`Elastic Beanstalk`の環境＞設定＞データベースの設定から`RDS`サービスに飛んで、`VPCセキュリティグループ`のリンクをたどる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248679/4413556b-3e35-285b-a708-31f976c976fe.png)

セキュリティグループの設定で、インバウンドルールをチョイス
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248679/623c625b-06b1-7261-dbf4-c999e07a18cf.png)

MySQL/Auroraの設定を追加し、`ソース`設定にて`マイIP`をチョイス、保存でＯＫ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248679/39ac54a9-3d21-7765-76b4-b70d28816471.png)

これで無事接続できました。
ルータのファイヤウォール設定と要領は同じですね！ただAWS歴100秒未満の雑魚にとっては厳しい！
Rails6での before_render

render メソッドを、run_callbacks で包むだけのモンキーパッチ

```rb
# frozen_string_literal: true

module BeforeRender
  extend ActiveSupport::Concern

  included do
    define_callbacks :render
    prepend RenderPatch
  end

  module RenderPatch
    def render(*options, &block)
      run_callbacks(:render) do
        super(*options, &block)
      end
    end
  end

  class_methods do
    def before_render(*names, &block)
      _insert_callbacks(names, block) do |name, options|
        set_callback(:render, :before, name, options)
      end
    end
  end
end
```
【10行】Vue コンポーネントをコンポーネントに動的に追加


```vue:動的に増やしたい子コンポーネント(MyComponent.vue)
<template>
 <div>{{ msg }}</div>
</template>

<script>
var Comp = Vue.extend({
  props: {
    msg: ""
  }
})
</script>
```

```vue:追加先の親コンポーネント
<template>
 <div>Parent Page</div>
 <div id="parentcomponentdiv"></div>
</template>

<script>
let compo = new MyComponent();
compo.$props.msg = "hoge";
compo.$mount();
document.getElementById("parentcomponentdiv").appendChild(compo.$el);
</script>
```
[Flask] 静的ファイルのキャッシュを無効化する

# はじめに
flaskで開発する際、ブラウザキャッシュが面倒だったので url_for を弄って無効化できるようにしました。
開発中 css や js が更新されずにヤキモキされてる方は、この方法を試してみてください。

# キャッシュ無効化の方法
css や js を無効化する方法の1つとして、url のクエリパラメータを更新する方法があります。
この方法は「CacheBusting」と呼ばれてます（参考：[古い静的ファイルを読み込ませない！Cache Bustingとは](https://tech-blog.rakus.co.jp/entry/20190816/query-parameters/cache)）

今回はこの仕組みをflaskに応用することで、キャッシュを無効化します。


# やってみる
### カスタムurl_for関数を作成
返すurlにクエリパラメータを付与する単純な関数です。

単純ですが、これがキャッシュ無効化の核になってます。

```python:utils.py
import time

from flask import url_for


# 元のurl_forと同じ引数
def my_url_for(endpoint, **values):
    url = url_for(endpoint, **values) 
    return url + '?ts={}'.format(int(time.time()))
```

### jinja_envの属性（url_for）を上書き
template は url_for などの関数を利用する際、jinja_env の属性 を参照しています。


カスタムurl_for関数を実行させるために、jinja_env の url_for属性を上書きします。


```python:application.py
from flask import Flask, render_template

from utils import my_url_for

app = Flask(__name__)

# url_forを上書き!!
app.jinja_env.globals('url_for') = my_url_for

@app.route('/')
def index():
   return render_templatet('index.html')
```

以上で設定は終わりです。

# templateでurl_forを利用
url_forは上書き前と同じように使えます。

```html:templates/index.html
<head>
  <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" type="text/css">
</head>
```


# 参考
* [静的ファイルの更新がブラウザのキャッシュで反映されない問題の対策](https://qiita.com/ymko/items/b03499aefcceec10ef8f)
macbook proでログイン後画面が真っ暗になる

# 概要

ディスプレイの調子が悪かったので、メモ。

# 現象


1. 起動してログイン画面までは普通に表示される
2. パスワード入力後にプログレスバーが表示される
3. 画面が切り替わり真っ暗
4. たまに数分放置していると表示されることがある
5. 真っ暗な画面でキーを叩いたりしているとなぜかバッテリー切れ画面の表示になることがある(実際はバッテリー容量あるにもかかわらず）

## 問題発生したmacbook

- MacBook Pro (15-inch,2018)
- macOS Big Sur (最新バージョン)


# 解決方法

以下で直りました。
（同じような現象が発生している全ての方の解決策となるわけではありません。）

1. macOS復旧画面を起動
2. ディスクユーティリティを使って起動ディスクを修復する

詳細はこちら (https://support.apple.com/ja-jp/HT210905)


以下は解決しませんでした。

- NVRAM(PRAM)クリア
- SMCリセット
- システムアップデート (macのソフトウェア・アップデート）
- セーフモードで起動する
[Java16]instanceofの型指定に追加される制約


## 新しい構文

Java16(2021/3/16 GA予定) から正式導入される「`instanceof`のパターンマッチング」([JEP 394](https://openjdk.java.net/jeps/394))，便利そうですよね！ よく知らない方のために簡単に紹介しますと，

```java
if (a instanceof Point p) {
    // p を Point 型変数として使える
    ...
}
```

のように書けます．他にもスコープ関係など細かい仕様があるのですが，詳しい説明は他の記事に譲ることにします(~~気が向いたら自分で書くかも~~)．

今回は，この記法に関連して気が付いた制約があるので紹介します．

## 型の制約

```java
if("text" instanceof String) {
    System.out.println("ok");
}
```

これは以前からコンパイルできますし，予想通りに実行されます．ところが，

```java
if("text" instanceof String s) {
    System.out.println(s);
}
```

このコードを，Java16[^4]でコンパイルしようとすると

[^4]: Release Candidate(Build 35) で検証

```
Sample.java:5: エラー: パターン・タイプStringは式タイプStringのサブタイプです
        if("text" instanceof String s) {
                  ^
エラー1個
エラー: コンパイルが失敗しました
```

のようにコンパイルエラーになります[^7]．ちなみに，

[^7]: しかもこのメッセージだと一見何が悪いのか分からない…

```java
if("text" instanceof Number n) {
    System.out.println(n);
}
```

の場合は

```
Sample.java:5: エラー: 不適合な型: StringをNumberに変換できません:
        if("text" instanceof Number n) {
           ^
エラー1個
エラー: コンパイルが失敗しました
```

という別のコンパイルエラーになります．

実は，パターンマッチングの場合に限って，`instanceof` の次に指定する型には2種類の制約があります．`instanceof` の左辺のコンパイル時の型を`S`，右辺に指定する変換先の型を`T` とすると

+ `S`型のインスタンスが `T` 型になる可能性がなければならない[^5]
+ `S`が`T`のサブタイプであってはならない[^6]

[^5]: 例えば， `Number` クラスのサブクラスが `BufferedReader` クラスを継承する可能性はありません．しかし，`Number` のサブクラスが `Closeable` インターフェースを実装する可能性はあります．
[^6]: つまり，`T` が `S` と一致するか `S` のスーパークラス/スーパーインターフェースである場合は不可

つまり，「常にマッチしない」ものも「常にマッチする」ものも禁止されているわけです．

ところが，従来の`instanceof`構文には１つ目の制約しかありません．互換性を保つ限り後から制約を追加することは出来ないので，今後はこのままパターンマッチングかどうかで制約度合いが異なる状態が続くのではないかと思います．

では，この制約を加えることでどんなプログラムが規制されるのかという話ですが，筆者が考えた例が１つあるので紹介します．

## 禁止される例

```java
    private void newStyle(List<String> list) {
        if(!list.isEmpty() && list.get(0) instanceof String s && !s.isEmpty()) {
            // s を使う処理
        }
    }
```

実は，Java15 の時点では追加制約が無かったので，このコードは`--enable-preview`フラグを指定すればコンパイルできて，意味的には

```java
    private void oldStyle(List<String> list) {
        if(!list.isEmpty()) {
            String s = list.get(0);
            if(!s.isEmpty()) {
                // s を使う処理
            }
        }
    }
```

と同じになります．つまり，パターンマッチングを本来の目的外に転用した読みづらいコードが書けてしまうわけですね．

余談ですが，どうしてもネストを減らしたければこんな書き方もできます:

```java
    private void anotherStyle(List<String> list) {
        String s;
        if(!list.isEmpty() && !(s = list.get(0)).isEmpty()) {
            // s を使う処理
        }
    }
```

これはこれで…笑



## おわりに

というわけで，`instanceof`の型の制約についての話でした．追加制約の理由や分かりやすい例など，他にあればぜひ教えて下さい．
ASP.NET CoreでJWTがExpireしないのはClockSkewのクセがすごいから？

## JWTがExpireしない

ASP.NET CoreでAPIを作るときにJWT認証を実装したところ、発行したJWTのExpire、すなわちトークンの期限、すなわちと言い直すなら最初からトークンの期限と書けと思いますが、とにかく、JWTのExpirationが思ったとおりに行かなかったのでレポートします。

実装例：クライアントにトークンを発行してあげる側

```C#:トークンの発行
var tokenHandler = new JwtSecurityTokenHandler();

var tokenDescriptor = new SecurityTokenDescriptor
{
    Issuer = _config["Jwt:Issuer"],
    Audience = _config["Jwt:Audience"],
    Expires = DateTime.UtcNow.AddMinutes(double.Parse(_config["Jwt:ExpireMinutes"])),　// たとえば1分を設定
    Subject = new ClaimsIdentity(new[]
    {
        new Claim(ClaimTypes.NameIdentifier, useridとか),
    }),
    SigningCredentials = new SigningCredentials(
        new SymmetricSecurityKey(Encoding.ASCII.GetBytes(_config["Jwt:Secret"])),
        SecurityAlgorithms.HmacSha256Signature)
};

var token = tokenHandler.CreateToken(tokenDescriptor);

return tokenHandler.WriteToken(token);

```

例：リクエストにくっついてきたトークンを検証する側

```C#:トークンを検証
services.AddAuthentication(
        JwtBearerDefaults.AuthenticationScheme
        )
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidateAudience = true,
            ValidateLifetime = true,
            ValidateIssuerSigningKey = true,
            ValidIssuer = config["Jwt:Issuer"],
            ValidAudience = config["Jwt:Audience"],
            IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(config["Jwt:Secret"])),

            ClockSkew = TimeSpan.Zero // ←これがポイント
        };
    });
```

細かい実装アプローチに差はあれど、おおまかにはオーソドックスなASP.NET CoreのJWTサポートを利用したコードかと思います。（この記事を記載してた時点で3.1を利用してます。）

## さて、試してみよう

クライアントがトークンを得ずAPIを実行する
401
クライアントがトークンを得てそのトークンを`Authorization Bearer ey～～` とHttpヘッダにつける
*トークン発行10秒後にAPIを実行する*
200
トークン作戦成功！*嬉しくなってトークン発行20秒後にもっかいAPIを実行する*
200
いいぞ！*勝利の余韻に浸ったため3回目はトークン発行70秒後にAPIを実行する*
200　←　は？
そしてしばらく待ち、もう1回、、
401

う～ん。。

問題発生。発行されたJWTは1分後には期限切れにしてほしいから `SecurityTokenDescriptor.Expire` で 1分 としたのに、これ動いてないじゃないか？いろいろ書き方を変えても結果は変わらず。
しばらく調査していると、トークン検証ロジックのほうで 

```
options.TokenValidationParameters = new TokenValidationParameters
・・・
ClockSkew = TimeSpan.Zero // ←これがポイント

```

この`ClockSkew`プロパティ、JWTのLifeTime検証の際の時間のずれを設定するという謎のプロパティで、デフォルトは 5分 らしい。
な、、なんだってー！！
たぶん **Expireを設定しない場合のJWTは5分で期限切れ** になるということなんでしょうね。

これを適切に設定することで、狙いどおりに期限切れを起こすことができます。
クセがすごい！
ふたたびVirtualBoxをインストールしてみる

# はじめに

前の記事「[VirtualBoxをインストールしてみる](https://qiita.com/marbas666/items/ed1ec60caa517d380bcd)」VirtualBoxをインストールしてみましたが、最後に新しいバージョンがあると表示されました。
気になって調べてみたところ、インストーラーのダウンロードが異なるみたいなので、最新版のある方？からダウンロードして再度インストールしてみました。

備忘録

- VirtualBoxをインストール　←この記事はこれ（２回目）
- Lubuntuをインストール
- Javaをインストール
- VSCodeをインストール
- Springでアプリをつくる

# VirtualBoxをインストール

## ダウンロード

どうやら、以下のURLに最新版があるようです。
https://www.virtualbox.org/

![FireShot Capture 014 - Oracle VM VirtualBox - www.virtualbox.org.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/be9d473f-6553-4869-f661-8d48846f4378.png)

「Download VirtualBox 6.1」を押下します。

![FireShot Capture 017 - Downloads – Oracle VM VirtualBox - www.virtualbox.org.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/fc7dba6b-3662-d485-a6b6-a7670b9f1a4a.png)

「Windows hosts」を押下してインストーラーを取得します。


## インストール

「VirtualBox-6.1.18-142142-Win」というファイルがダウンロードされています。
たしかに、前回のファイルよりもバージョンが上です。
これをクリックしてインストールしていきます。

---

![2021-02-12_14h34_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/5c7362f3-5bed-398a-8e1d-292043ec359a.png)
セットアップが開始されます。
「Next >」を押下します。


---
![2021-02-12_14h34_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/062145e8-d3bb-33cb-2246-dc780999cbcd.png)
インストール場所などを聞かれますが、そのままにします。
「Next >」を押下します。

---
![2021-02-12_14h34_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/2c924dea-9f71-3347-0909-1b99855057a5.png)
オプションを聞かれます。
「Create a shortcut in the Quick Launch Bar」だけチェックを外します。
※：好みの問題なので、どれを選択してもインストールはされます。
「Next >」を押下します。

---
![2021-02-12_14h34_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/b01d6040-5c12-64e9-b057-1115f875ec20.png)

警告がでます。
ネットワークをインストールするから一時的にネットワークがリセットされるらしいです。
「Yes」を押下します。

---
![2021-02-12_14h35_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/10cfa560-f772-03e9-0157-7af00e5b1bc7.png)
準備ができたのでインストールをします。
「Install」を押下します。

---
![2021-02-12_14h35_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/2930ade9-453c-0f02-a579-0750e9007397.png)

インストールが始まります。
なにも操作せずにしばらく待ちます。

![2021-02-12_14h36_15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/22f40760-8b05-82ec-811f-1e9610f0a8ea.png)

しばらくすると、インストールが終了します。
「Finish」を押下します。

# VirtualBox起動

インストールが終わると、自動的にVirtualBoxが立ち上がります。

![2021-02-12_10h53_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1103659/491eedc4-c4d6-2903-ea73-efc3d5efc7f7.png)

こんどは、最新版の通知ダイアログはでませんでした。

# まとめ

インストール自体は前回とほぼ同じでした。
しかし、古いバージョンを置いてあるサイトは最新があるサイトに誘導してくれても良いものなのでは？
と思いました。

教訓：Google検索の順番を信用してはいけない
Laravelであらかじめ共通の値をViewインスタンスに渡しておきたい

# はじめに
こんにちは。先日、実家に眠ってた、`Windows 98`のノートパソコンと`Windows XP`のデスクトップPCを[浜屋](http://www.hamaya-corp.co.jp/)に持って行って、合計1,500円で買い取っていただいた筆者です :yen: 

さて、Webサイトの構築をしているのですが、サイトの**ヘッダー**とか**フッター**に使う値をDBから取得するケースがあります。

その際に親のコントローラーであらかじめViewインスタンスに渡せるので共有します。
こうすることで、子コントローラーのactionまで値を引き回さないで済みます:+1:

# これでいけます:+1:
[share](https://laravel.com/api/8.x/Illuminate/View/Factory.html#method_share)メソッドがあるのでこれに渡せば大丈夫です。

```php
$data = [];
// 1個だけ渡すとき
view()->share('data', $data);

// 複数個渡すとき
$data2 = [];
view()->share(compact('data', 'data2'));
```

# おわりに
これ結構便利なんですよね。同じaction内で別のtemplate表示させたいときとかも、あらかじめセットできるので、変数のスコープが短くなって、コード全体の可読性も上がると思います :smile: 

それでは！
applyとsapplyの挙動の違いについて

# はじめに
Rでデータフレームへいろいろと操作するとき、`apply`と`sapply`の動作の違いでちょっとハマってしまったので、備忘録として記事を残しておく。

# `saplly`,`apply`関数と`is.character`での文字列の判定
文字列と数字の混ざったデータから、数字データのみを取り出したかった。ので、以下のようなデータフレームを準備する。

```R:コード
a <- c(1, 3, 7)
b <- c("test1", "test2", "test3")
c <- c(0.8, 0.6, 0.4)

x <- data.frame(a, b, c)
x
```

```:出力
  a     b   c
1 1 test1 0.8
2 3 test2 0.6
3 7 test3 0.4
```

ここから、b列を文字判定してTRUE, FALSEのベクトルをつくり、再度データフレームを再構築すれば、実装できそう。なので`apply`関数を使い`is.character`を列に適応する。

```R:コード
apply(x, 2, is.character)
```

```:出力
   a    b    c 
TRUE TRUE TRUE 
```
なぜか、数字のみが入っているa, c も文字列判定されてしまった。ここで、ならば`sapply`ではどうなるか疑問が生じたので試してみる。


```R:コード
sapply(x, is.character)
```

```:出力
    a     b     c 
FALSE  TRUE FALSE 
```
こんどは上手くいった！ので、文字列以外の要素でデータフレームを再構成すると、

```R:コード
y <- x[, !sapply(x, is.character)]
y
```

```:出力
  a   c
1 1 0.8
2 3 0.6
3 7 0.4
```

となり、これで文字列を除外した数値のみのデータが作れた。

# `apply`関数が目的の通り動作しなかった理由

ここで`apply`関数のヘルプを見てみると(`?apply`を実行すると)、

> If X is not an array but an object of a class with a non-null dim value (such as a data frame), apply attempts to coerce it to an array via as.matrix if it is two-dimensional (e.g., a data frame) or via as.array.

とある。つまりデータフレームなどは`as.matrix`を通して操作することになる、と。では、`as.matrix`はと言うと、

> The method for data.tables will return a character matrix if there are only atomic columns and any non-(numeric/logical/complex) column, applying as.vector to factors and format to other non-character columns. Otherwise, the usual coercion hierarchy (logical < integer < double < complex) will be used, e.g., all-logical data frames will be coerced to a logical matrix, mixed logical-integer will give an integer matrix, etc.

とある。英語が苦手なのできちんと読み解けているか不安だが、非（数値、論理、複素数）型が含まれていると、「文字列」で値を返す仕様らしい。`as.matrix`の出力を見てみると、

```R:コード
as.matrix(x)
```

```:出力
     a   b       c    
[1,] "1" "test1" "0.8"
[2,] "3" "test2" "0.6"
[3,] "7" "test3" "0.4"
```

となり、確かに全部文字列になってしまっている。もし、b列が無いデータ（整数と少数のみのデータ）の場合は、

```R:コード
tmp <- data.frame(a,c)
tmp
```

```:出力
  a   c
1 1 0.8
2 3 0.6
3 7 0.4
```

```R:コード
as.matrix(tmp)
```

```:出力
     a   c
[1,] 1 0.8
[2,] 3 0.6
[3,] 7 0.4
```

```R:コード
apply(tmp, 2, is.character)
```

```:出力
    a     c 
FALSE FALSE 
```

となり、全て想定通りの挙動を示した。

# おわりに
`sapply`は値をリストとして扱ってくれるのでこの問題が起きない、と思われる。

`sapply`の詳しい説明はヘルプを見てもよく分からなかったので、もし補足等あればコメント頂けますと幸いです。
Migrationでテーブルを作成する

メモです。参考にしないでくださいね。:point_up:

Migrationファイルのひな形を作る
（今回はnewsテーブルを作る）

```
$ php artisan make:migration create_news_table
```

データの保存
Modelのひな形を生成
（今回はnewsモデルを作る）
(Model名は単数系)

```
$ php artisan make:model News
```

##Validationを定義
（Model内に定義します）

```php

namespace App;

use Illuminate\Database\Eloquent\Model;

class News extends Model
{
    protected $guarded = array('id');

    // 以下を追記
    public static $rules = array(
        'title' => 'required',
        'body' => 'required',
    );
}
```
##エラーメッセージを日本語化
config/app.php で `local` を指定している箇所を編集し、**en** から **ja** に変更

```
'locale' => 'ja',
```

resources/lang/en　を右クリックコピー
resources/lang　の下にペースト、ファイル名を　**ja**　に変更

```
$ cp -rp resources/lang/en/* resources/lang/ja
```

resources/lang/ja ディレクトリにある validation.phpの
‘required’ の部分を下記のように書き換える

```
'required'             => ':attribute に入力が必要です。',
```
【おすすめ】SQLBoltで、SQLを学んでます

## はじめに
SQLBoltというWebサイトで、SQLの学習を進めています。

各レッスンに練習問題が用意されていて、お題に沿ったコードを記述、実行しながら学んで行けるので、実務でのSQLの使われ方ってこんな感じなのかなー、とイメージしながら学習できている気がして楽しいです。

今回は、サイトの紹介と、学習を進めていくに当たって自分が調べた用語の説明をしていきます。

## 目次
- [はじめに](#はじめに)
- [目次](#目次)
- [SQLBoltの紹介](#sqlboltの紹介)
  - [特徴](#特徴)
- [SQL 用語の意味を簡単にまとめ](#sql-用語の意味を簡単にまとめ)
- [おわりに](#おわりに)

## SQLBoltの紹介
サイトのURLはこちら↓

[SQLBolt Learn SQL with simple, interactive exercises.](https://sqlbolt.com/lesson/introduction)

### 特徴

- <b>【おすすめ！】ブラウザ上でSQL文の記述と実行ができます。</b>
  - 環境構築したり、データベースの中身を用意したりといったことが必要ないので、初学者でも言語自体の学習に集中することができます。
  - 自分の環境では、文字の入力カーソルが実際に指している文字より右にずれて表示されてしまうのが気になるのですが、まあご愛敬..笑

- <b>全部で18レッスンに分かれており、各レッスンサクサク進められます。</b>
  - 各レッスン、簡単な解説の後に、その解説で取り上げられた内容を用いて練習問題を解いていく、という流れになります。
  - 気合を入れて取り組めば、10時間程度で一周できるのではないかというボリューム感です。

- <b>英語です。</b>
  - 自分は英語の勉強も兼ねて、逐一単語の意味を調べながら解説も含めて読み進めてます（その分時間はかかりますが..）。

![SQLBolt.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1021378/7e46a02a-b63e-ac75-06e1-978fd4d77c72.png)<figcaption>左下のテキストエリアにSQL文を記述していきます</figcaption></figure>

## SQL 用語の意味を簡単にまとめ

学習時、ある程度意味を把握しておかないと技術全体の
理解が進まないと感じた用語について、なるべく一言でふに落ちるようにまとめてみます。

- <b>エンティティ（Entity）</b>
  - DBで扱いたいインスタンスの要素を、抽象化して抽出したもの（カラムの集合体？）
  - ER図におけるテーブルの呼び名

- <b>クエリ（Query）</b>
  - データベースへの「これやってくれ！」な命令文

- <b>文（Statement）</b>
  - ≒クエリ
  - データベースへの命令において、一つの実行単位となる
  - SELECT * FROM table; 　←これで一文

- <b>句（Clause）</b>
  - 文、もしくはクエリを構成する要素一つ一つのこと
  - FROMとかWHEREとか。組み合わせることで一つのクエリになる

## おわりに

用語一つ一つの意味をきちんと理解しながら進めていくことが、技術全体の体系的な理解に不可欠だなと感じます。急がば回れでの精神で、焦らずコツコツと学習を継続していきたいです。

また、SQLBoltは自分で一通りさらってみて、SQL理解の足掛かりとしてとても丁度いい難易度だなあと感じたので、興味のある方は是非トライしてみてください^^
Invalid hook call. Hooks can only be called inside of the body of a function component. This couldでnode_modulesあたりをミスって爆死した話

# 概要
Next.jsで自実装中
今まで普通に立ち上がっていたローカルサーバーが急遽立ち上がらなくなりました、、、
Invalid hook call. Hooks can only be called inside of the body of a function component. This could
こちらエラー内容

どうやらhooksの使い方に問題があるようです

## Reactのドキュメントの解決策
解決策としてはReactのドキュメントに3つあげられています。
You might have mismatching versions of React and React DOM.
You might be breaking the Rules of Hooks.
You might have more than one copy of React in the same app.

React-domのバージョン古くない？笑
そもそもhooksの使い方間違ってるやないかい！！！！
Reactのバージョン複数持っちゃってるんじゃない？
って感じのことが書いてあります笑
https://reactjs.org/warnings/invalid-hook-call-warning.html

## 原因を探っていく
上記の3つの原因のどれに当てはまっているかをまずは切り分けしていくことが重要です。
これはどのエラーにも共通します。

## まずバージョン
これはReactのバージョンが16.0.8以下だとそもそもhooksに対応していないのでエラーになります。
これはReact versionなどでググって解決しましょう！！

## hooksの使い方違くない？
これはそもそもhooksの使い方が違っている場合です。
これはhooksのドキュメントを見直して見ることをおすすめします。
大体の場合だとhooksとclassコンポーネントを同時に使ってしまっている場合が多いようです。

## Reactのバージョン複数持っちゃってるんじゃないい？笑
自分の場合はおそらくこれに該当しました。

なぜこれに辿り着けたかというと、自分の場合は今までは通常に動作していたため、コードに問題があるかというよりかはバージョン管理に問題ががあると切り分けました。
またバージョンも16.0.8以上だったので絶対これだあああと断定しました。

## 結論の解決策
おそらく3つ目のタイプの場合は知らないうちにnode_modulesやpakege.jsonあたりをいじってしまっている可能性が高いです。
Reactのバージョンが2つインストールされているなど、

解決策として結論からいうとnpmを再インストールすることです！
1. 一度ローカルサーバーを停止させます
2. node_modulesを削除(node_modulesが壊れるというのはよくある話みたいでこちらは削除しても特に問題ありません！)
3. yarn.lockとpakege-lock.jsonを削除(こちらはバージョン管理のログのようなものが記載されているのでこれが残っていると再インストールしてもまた同じものがインストールされてしまします)
package-lock.jsonとyarn.lockは、プロジェクトが依存してるパッケージの正確なバージョンを記録してるファイルです。
4. こちら2つのファイルを削除し終わったら

```
npm install
```

以上です。
やってることに関してはlockファイルを削除することで以前の状態のキャッシュを効かせることができます！

つまりlockファイルを削除していないと、キャッシュが効かせられないのでいくら再インストールしても解決できないということですね！
node_modulesが壊れたりバージョン管理でミスった時は一度落ち着いて、元の状態に戻すこともおすすめです！！

お疲れ様でした！！！
超簡単AWS　EC２作成してみた後編！！

・ルートの追加を押して設定していきます。
![スクリーンショット 2021-02-11 16.27.49.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/8d31b29d-6326-7c82-fdfb-d269c6f7ee8a.jpeg)
・インターネットゲートウェイのルートを作成しました。
![スクリーンショット 2021-02-11 16.28.08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/53a4901c-bd5b-970c-84a0-f7ab9001eeae.jpeg)

・次にEC２インスタンスの作成していきます。
検索欄に「EC2」と検索します。
![スクリーンショット 2021-02-11 18.06.14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/2b7e25bb-068c-0739-4e10-09100c9d798b.jpeg)
・「インスタンスを起動」を押したら、Amazon Linux2AMIを選択します。
![スクリーンショット 2021-02-11 16.28.58.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/71e270d9-4d58-87e9-27ce-512c77bc78b7.jpeg)
・tc2.microを選択。
![スクリーンショット 2021-02-11 16.29.19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/9386fd1b-f006-3ed0-daf5-ab2179c0b3ba.jpeg)
・インスタンスの詳細設定で、ネットワークを「test-vpc」を選択し。サブネットを「test-subnet-0」を選択。自動割り当てパブリックIP「有効」を選択。
![スクリーンショット 2021-02-11 16.30.11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/9df14de4-c083-fe16-0c06-6d999a361d1d.jpeg)
・タグの追加てName　test-ec2-1　に指定。「起動」をクリック。
・キーペアの選択。　「新しいキーペアの作成」　キーペア名「test-keypair」　キーペアのダウンロード
パソコンのFinderにダウンロードしてる事を確認。
![スクリーンショット 2021-02-11 16.33.56.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/851e0cb0-0ac7-fdf9-c638-e403b1bb09ae.jpeg)
・インスタンスに戻り。インスタンスが作成と正常にインスタンスの状態が「実行中」ステータスチェックが「２/２のチェックに合格」している事を確認します。

・次にセキュリティーグループを開きます。「セキュリティーグループの作成」をクリックし設定していきます。
「セキュリティーグループの作成」「インバウンドルール」の設定「アウトバンドルール」の送信先を設定。
![スクリーンショット 2021-02-11 16.43.30 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/8e081aae-b2b9-7e94-8bdc-07fb1451f045.jpeg)
・作成したEC2インスタンスのセキュリティーグループを付け替えていきます。（OSやバージョンよってはアクションのカテゴリーが違うことがあります。）
![スクリーンショット 2021-02-11 16.44.46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/16a607c9-fc27-4b81-2682-7383b7cf0b33.jpeg)
・セキュリティーグループの指定をtest-sg-1にします。
![スクリーンショット 2021-02-11 16.45.30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/7cfa9a51-6236-47f5-767e-ee6649121b4c.jpeg)
・EC2インスタンスを接続する前にサブネットのサブネットにアタッチしているネットワークの状態を確認します。
VPCを開きサブネットを選択し、test-subnet-0の選択し「ネットワークACL」を選択。「ALLOW」になっていることを確認します。
![スクリーンショット 2021-02-11 16.48.57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/d97cbc15-f469-31dc-e5e6-36226d8f60b3.jpeg)

これでEC2の作成が完了です。
超簡単AWS　EC２作成してみた前編！！

・まず　https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-using-volumes.html　
からアカウント作成、ログイン完了！
![スクリーンショット 2021-02-11 16.11.47.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/c6598656-63ee-e1fa-908a-fd2e11bbce18.jpeg)



・右上のロケーションを「東京」にします。
・サービスを検索で「VPC」と検索
![スクリーンショット 2021-02-11 16.12.38.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/63d63581-4854-6cb5-d645-9c6596c48c13.jpeg)
・VPCを開きます。
![スクリーンショット 2021-02-11 16.13.01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/5a0ba28e-8996-1d42-a5d3-204d46b0da52.jpeg)
・・VPCを作成します。
![スクリーンショット 2021-02-11 16.14.10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/d732dd15-8849-4fd7-13b2-156b0e1b927e.jpeg)
・サブネットを開き、test-subnet-0を作成します。
![スクリーンショット 2021-02-11 16.16.08.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/2728224b-1b96-3773-5c9d-6742e240e540.jpeg)
・サブネットを以下のように設定します。
![スクリーンショット 2021-02-11 17.18.16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/5ca9a2e5-a542-2ee6-ef5e-95619ce4b598.jpeg)
・test-subnet-2を作成します。
![スクリーンショット 2021-02-11 16.18.46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/63237a6c-2cb7-9ad9-c991-39d796c7a6bb.jpeg)
・サブネットで作成した、test-subnet-0、test-subnet-２があることを確認できます。
![スクリーンショット 2021-02-11 16.23.00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/c9c13243-c320-0ead-2413-e3525e5d3d1a.jpeg)
・次にインターネットゲートウェイをアタッチしていきます。
・まずインターネットゲートウェイを開いて、作成します。
![スクリーンショット 2021-02-11 16.23.22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/60cc0cbf-199c-e83d-a933-b7f7766dc8d3.jpeg)
・名前をtest-internetgatewayにして作成。
![スクリーンショット 2021-02-11 16.24.03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/83a62f12-0f9d-bd6a-e6af-fa7def1fb16f.jpeg)
・Detachedをatatachedにするのに、アクションから「VPCにアタッチ」をクリックし「test-vpc」にattachedにします。
![スクリーンショット 2021-02-11 16.25.27.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/6ea6f6bd-de1a-a050-3755-2172604bf5d0.jpeg)
・次にサブネットを選択し、ルートテーブルの編集でルートを追加します。
![スクリーンショット 2021-02-11 16.27.18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589963/6bd76be8-fa0f-414f-02c9-f9b0e1080ccb.jpeg)


終わりに。
AWSを１から学ぶなら下のURLからご加入オススメです！！！
https://aws-cloud-tech.com/
javascriptでcssの@keyframesを操作する

内容は、■の大きさと色を変化させる、というものです。

１．pタグを生成して\<body>内に配置する
２．@keyframesを記述して、\<style>内に配置する
３. pタグに■を記述し、@keyframesと関連づける
<br><br>

```javascript:
<script>
	window.onload=function(){

        // <body>要素を取得し、<p>タグを生成し、<body>内に配置する
		let body=document.getElementById('body');
		let ptag=document.createElement('p');
		    body.insertBefore(ptag,null);
		
        // @keyframesでアニメーションを記述
		let scale='@keyframes scale{ 0%  {font-size:1px  ;color:rgba(255,255,  0,0.5)}'+
		                            '50% {font-size:30px ;color:rgba(255,100,255,0.5)}'+
                                    '100%{font-size:1px  ;color:rgba(255,255,  0,0.5)}';

        // <style>タグを取得し、<style>内に@keyframesを配置
        // <p>タグに■を設置し、<p>の style でアニメーションを関連づける
		let css =document.getElementById('css');
		    css.insertAdjacentHTML('afterbegin',scale);
		    ptag.textContent='■';
		    ptag.setAttribute('style','animation:scale 5s infinite ease-in-out');
	}
</script>

<style id='css' ></style>
<body  id='body'></body>
```

javascript も css も殆ど使わないので、コードの出来は分かりません。
VBAでヘッダーのフォントを変更する方法

# はじめに
VBAのヘッダーのフォントの指定方法が複雑で、変数化するときにちょっと悩んだので備忘録としてメモ

# やること
中央のヘッダーのフォントを変更します。
指定フォント : 游明朝
サイズ : 24


# ヘッダーの変更方法

```VBA
Option Explicit

Const FONT_SIZE = "&24"
Const FONT_NAME = "&""游明朝"""

Sub main()
    Call ChangeCenterHeader(ActiveSheet, "けものフレンズ1400万再生おめでとう")
End Sub

Function ChangeCenterHeader(Worksheet As Worksheet, Text As String)
    Worksheet.PageSetup.CenterHeader = FONT_NAME & FONT_SIZE & Text
End Function

```
# 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154799/fbb06221-2ede-efb5-56f3-95e5be39d814.png)

# 余談
太字とか他のフォントを設定したいときは、[公式リファレンス](https://docs.microsoft.com/ja-jp/office/vba/excel/concepts/workbooks-and-worksheets/formatting-and-vba-codes-for-headers-and-footers?redirectedfrom=MSDN)を参考にするとよい

```VBA
Const BOLD = "&B"

Function ChangeCenterHeader(Worksheet As Worksheet, Text As String)
    Worksheet.PageSetup.CenterHeader = FONT_NAME & FONT_SIZE & BOLD & Text
End Function
```

以上

# 参考
[ヘッダーとフッターに指定できる書式コードと VBA コード - Office VBA リファレンス](https://docs.microsoft.com/ja-jp/office/vba/excel/concepts/workbooks-and-worksheets/formatting-and-vba-codes-for-headers-and-footers?redirectedfrom=MSDN)
[Excel VBAでヘッダーのフォント種別・文字サイズを設定する](https://www.relief.jp/docs/excel-vba-header-font.html)
AppStoreで効率化アプリであっても金融系だとリリースは非常に厳しいことがわかった件

## 要約
* レンディングを効率化するアプリを作ってリリースしようとした時の記録
* 以後、同じようなNGをくらわないように、備忘として残す
    * 今後金融関連は手を出さないというのが一番だが・・・

## 結論
* ちょっとしたアプリで20往復以上やりとりしたが、通らなかった

## アプリ概要
* Bitfinexのレンディングを自動化するアプリ

## 提出後の経緯

(AppStore) 
　・どんなサービスですか
　・だれがターゲットですか
　・有料ですか
　・どのように支払いますか

(自分)
　・完全に無料で、レンディングを自動で行いたい人が対象です

(AppStore)
　・ログインしなくても使える機能はログインしないで使えるようにしてください

(自分)
　・必ずログインしてもらうのでログインなしの機能はありません

(AppStore)
　・動かない部分があります

(自分)
　・APIを設定しないと動かないです

(AppStore)
　・APIはだれが払い出しますか
　・APIはどのように取得しますか

(自分)
　・エンドユーザがBitfinexから取得します

～ 5往復経過 ～

<この辺で最初の頃の質問が繰り返し(多分レビュアーが変わった)>

～ 10往復経過 ～


(AppStore)
　・Bitfinexの委託であること、もしくはBitfinexを開発者に加えてください

(自分)
　・公開APIを叩くだけで世界中に自動化ツールがありますがダメでしょうか。
　・AppleStoreにも同種のアプリはたくさんありますがダメでしょうか。

(AppStore)
　・このアプリでレンディングはできますか

～ 15往復経過 ～

(自分)
　・エンドユーザが設定したものを有効/無効にするので、直接的にはNO.間接的にはYesです。
　・処理はアプリではなくバックエンドサーバで行われます

＜ここでガイドライン改定＞ :exclamation: 
(viii) Apps used for financial trading, investing, or money management should come from the financial institution performing such services.

(AppStore)
　・上記のガイドラインに違反しています

(自分)
　・確認します。以前の回答をもらっていない確認に回答をお願いします。

(AppStore)
　・電話しますので、電話番号を教えて下さい

(自分)
　・電話番号を通知

※ここから電話(多分レビュアーとは別の方・・・)

(AppStore)
　・資料によると〇〇なのでNGです。
　・レビュー結果によると△△はNGです。

(自分)
　・〇〇は・・・。△△は・・・と説明をしていく

(AppStore)
　・XXはレンディングに関わりがあるのでNGです。

（自分）
　・設定の切り替えをするだけでもだめですか

(AppStore)
　・ダメです

(自分)
　・●●アプリでも同じことをしますが

(AppStore)
　・あなたのアプリのレビューなので、他は関係ありません

(自分)
　・金融だけが厳しいのですか？他のアプリでもAPIを使って有効/無効の切り替えはすると思いますが

(AppStore)
　・金融と医療は厳しくチェックします

＜いろいろ確認するが、あげ足ばかりで、通す気無いのがバリバリ伝わる・・・＞

（AppStore)
　・ご理解いただけたようで幸いです

(自分)
　・・・


## 所感

* まぁ、全てはApple様のさじ加減だけなのですが、1年かけたアプリがこうなるとつらいなぁ。。。

* 完成しないとレビューしてもらえないけど、最後の最後にNGになると、レビューリスクってどうやって軽減するんだろう。。。

* レビューアーにムラがあって、すごくやりづらい。同じ内容なのに前回は引っかからなかったのに、アップデートで今更のコメントもあるし、、、

* 自分の気のせいかもしれないけど、電話がすごく高圧的なんですよね。。。聞きたいことも聞けないし、ただ落とすだけのための電話という感じ、、、
    * 途中から面倒くさくなってとにかくダメだから諦めろよみたいなニュアンスになってくるし
        * ダメなところを直そうと思っていたのですが、心が折れましたので、アプリを消しました
    * 途中で電話切れるし、音声がすごく聞き取りづらいのも、コミュニケーションがうまくとれない原因に
    * 電話になったらとにかくNGということなんでしょうね :pensive:
Alibaba Cloudプロダクト一覧をPythonとBeautifulSoupでスクレイピングする

## この記事の目的
Google colaboratoryを使って、Alibaba Cloudサイトからプロダクト一覧を取得してみます。
Google colaboratoryはGoogleが提供しているJupyterNotebook環境で、Googleアカウントさえあれば誰でも利用することが可能です。また、一時的ですがGPUリソースを利用することもできます。

無料かつ環境構築のハードルもなくすぐに使えて性能も良いので、使っておいて損はないです！

https://colab.research.google.com/notebooks/intro.ipynb?hl=ja#recent=true

## 対象のサイト（Alibaba Cloud国際サイト）
https://www.alibabacloud.com/ja/product
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/c9d7f6ba-4e93-eb52-d72c-fa0e21589a28.png)

> WEBサイトによってはスクレイピングを禁止しています。
事前に利用規約を読み問題ないかを確認してみましょう。

## htmlからプロダクト名称とプロダクト詳細を見つける
chromeのデベロッパーツールからhtmlを解析します。

#### プロダクトの名称
`h6`、`class="product-tit text-base"`が判別できました。
したがって、pythonのコードでは以下の通りにタグを指定します。
`product_name = soup.find_all("h6", class_="product-tit text-base")`

#### プロダクトの詳細

`p`、`class="product-desc text-sm"`が判別できました。
したがって、pythonのコードでは以下の通りにタグを指定します。
`product_detail = soup.find_all("p", class_="product-desc text-sm")`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/32f097bb-0122-4e2d-a9e1-85ea4a863ad0.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/cbf84a8d-4e9f-fb72-b210-0c4cb8e4ece3.png)


## 実行コード
```python

# モジュールのインポート
import re
import csv
import requests
import time
import pandas as pd
import numpy as np
from bs4 import BeautifulSoup

# 関数
def albb():
    # スクレイピング対象の URLに リクエストを贈り HTML を取得する
    res = requests.get("https://www.alibabacloud.com/ja/product")
    time.sleep(1)
    # レスポンスの HTML から BeautifulSoup オブジェクトを作る
    soup = BeautifulSoup(res.text, "html.parser")              
    # プロダクト名称 
    product_name = soup.find_all("h6", class_="product-tit text-base")
    # プロダクト詳細
    product_detail = soup.find_all("p", class_="product-desc text-sm")

    # 辞書とリストの空箱を用意                                      
    result = []
    result_2 = []

    # find_allで取得したものはリストオブジェクトなのでループ文で1つずつリスト内にappendする
    for i in product_name:
        result.append(i.text)
    for x in product_detail:
        result_2.append(x.text)
    # pandasのデータフレームに格納する
    df_result = pd.DataFrame({'product':result, 'detail':result_2})
    # nullセルをdrop
    df_notnull = df_result.dropna(how='any')
    # csvに出力
    df_notnull.to_csv('output.csv',index=False)
    return df_notnull
```

```python
# 関数の呼び出し
albb()
```

## 結果
データフレームに格納されたものを、csvに出力することができました。
csvは、googleのcolaboratory内に保存されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/8fd09a88-b47e-4c59-1cd5-c59b8b37168b.png)

## CSVファイルを見てみる

プロダクト以外の余計なサービスを除くと、164種類のプロダクトがありました。
めっちゃ増えてる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274358/cc40d2cb-00cf-504a-9983-e67cf003a81f.png)
【初学者】プログラミングスクールで獲得できる経験・能力はなんなのか。

##自己紹介
某プログラミングスクールを2020年8月に入学し、2021年2月に卒業しました。
看護師からエンジニアとして転職を目指す30代です。
プログラミング学習の時間を確保したかったため、派遣社員に切り替えてスクールへ入校しました。


##獲得できたと感じる点
大きく３つあったと思います。

```
      １）企画力
      ２）質問力
      ３）利益を追求する視点
```

##理由
### １）企画力
スクールではカリキュラム以外にも、たくさんのイベントがありました。
それを模範にし、スクールのチームメンバー対象に転職活動準備会を開きました。
IT企業の社長様や社員様、スクールの卒業生であるエンジニア1年目の方を招いて、IT市場や転職の現状をリアルな声として聞かせていただきました。
30代未経験というハードルの高い転職活動において、なにを重視して行動したらよいか有力な情報が収集でき、不安の軽減になりました。
私は前職でこのような機会がほとんどなく、出演していただく方へのアポイトメントやリハーサルを通して、対人関係スキルや提案力が向上したと感じています。

### ２）質問力
スクールの卒業達成要件である最終課題では、「自分で決めた期限を厳守」し実装しました。
これは現場に出たことを意識して設定しました。
納期が必ず存在しますが、それを守るためには「質問力」が重要であると感じています。
自力実装が難しい場合には、質問することで、先に進むアクションをとることができます。
質問した先輩も自分と同じ様に業務に携わっていることから、簡潔明瞭に言語化して伝えることは、
現場に出て良好な対人関係を作るためにも、納期を守るためにも、軽視できないことだと感じました。


### ３）利益を追求する視点
オリジナルアプリでは、ユーザーを意識した設計をすることについて学びが深かったと思います。
オリジナルアプリは、看護師の業務負担を軽減するアプリを作成しました。推定30分以上の時間を節約できます。
厚労省は看護師の残業時間は月平均16時間と発表しています。
これを1500人規模の看護師が在中する医療機関で換算すると、年間3060万円の残業代を削減することができます。
「道徳なくして経済なし」「経済なくして道徳なし」
よりよいサービスは結果として利益を出すというごく当たり前なことですが、
これまで「利益」を追求する視点では、業務を行ってこなかった私は、弱い部分だと感じていました。
しかし、このオリジナルアプリを機に、利益を追求する視点の準備ができました。


##結果
以上挙げた獲得できた経験・能力は自身で積極的に掴んだ結果だと考えています。
プログラミングスクールに限らずですが、目的意識を持ち、自身で獲得しようという姿勢がなければ、何も得るものもないです。
ただ、プログラミングというスキルだけを学ぶのか、それを通して業界を学ぶのかは、
同じコストと時間をかけても大きな差になるかと思います。
目的意識は、楽しくしようとした結果、獲得できた経験だったので、そこを軸に考えたのもよかったのかなと思います。

##まとめ
```
　　　楽しく学習しようという目的意識から、プログラミング以外にも、オリジナルな経験が経験できる。
　　　社会人でもあるが、「スクール生」という学生(?)の立場に戻り、アクションを起こしやすいというポジションでもある。
　　　プログラミングスクールは、そこを武器にして積極的に活動できるよい機会である。
```

##最後に
これからプログラミングスクールやプログラミング学習を始める方、検討されている方に伝えたいことがあります。

```
　　　可能であれば、学習時間を絶対に確保できる状態にしてから、始めた方がよいかもです。
```
自身のスクールでは、同期が約20名程度。そのうち卒業できたのは、半分です。
卒業条件は最終課題であるフリマアプリでLGTMをもらうという達成条件があります。
全員の卒業条件が達成できなかった理由はわかりませんが、少なくとも自身の所属するチームメンバーでは、
明らかに、下記の理由だったと思います。

```
　　　学習時間が確保できなかった
```

みんなどんぐりの背比べのような技術力の差です。違うのは時間の確保だけだと感じています。
エンジニアは考える仕事です。
カリキュラム学習中は、読み進めるだけでもよいのですが、卒業達成要件である最終課題は自身の自走力を高める学習になります。
カリキュラムを振り返りながら、自分で考えなければなりません。
その時間を確保できるかできないかは、学習において非常に重要なことになり、それが卒業出来た人数として現れたのだと思います。
熱意だけではできません。
社会人の貴重な時間とコストをかけるので、途中で挫折がない様に時間の確保は重要だと感じました。

自己紹介でPRした自身の仕事への切り替えもよかったと感じていますが、
出来ない方はその辺りを調整されて受講されることを心からお勧め致します。
そして、これからの自身の成長に大きく関わる素敵なスクールライフを送って、自分だけの経験を得られてください！！
応援しています！！
UIActivityViewControllerでテキストを共有するメソッドを作る

#作り方
```swift
public func shareText(view:UIViewController,text:String){
    let size = view.view.bounds.size
    let activityVC = UIActivityViewController(activityItems:[text],applicationActivities: nil)
    activityVC.popoverPresentationController?.sourceView = view.view
    activityVC.popoverPresentationController?.sourceRect =
    CGRect(x:size.width/2,y:size.height/2,width:1,height:1)
    view.present(activityVC,animated:true,completion:nil)
}
```
#使い方
```swift
let text = "共有するテキスト"
shareText(view:self,text:text)
```
多次元配列で2回ソートしたいとき

items.sort {($0.a,$0.b) < ($1.a. , $1.b)}

上記は一番初めにaがソートされ次にbでソートされます。

同時にやりたい場合は

($0.a < $1.a $$ $0.b < $b.1)

とかでやればいいけど、あまり期待の値は取れないので使う機会は少ないかも
faker ダミーデータ生成ライブラリ Go

人名や住所などのダミーデータをランダムに生成するGoライブラリ。英語ですが。

[faker](https://github.com/jaswdr/faker)

```golang
package main

import (
	"fmt"

	"github.com/jaswdr/faker"
)

func main() {
	faker := faker.New()

	fmt.Println(faker.Person().Name())

	fmt.Println(faker.Address().Address())

	fmt.Println(faker.Lorem().Text(100))
}
```

ループで使用する場合。

```
	p := faker.Person()

	for i := 0; i < 10; i++ {
		fmt.Println(p.Name())
	}
```

実行結果

```
Ms. Kaitlin Johnston II
7 Balistreri Crossing Apt. 728
Loychester, DE 29058
aliasconsequaturautperferendissitvoluptatemaccusantiumdoloremqueaperiameaqueipsaquaeabilloinventore
Mr. Merlin Donnelly
Ilene Douglas
Dedric Kautzer
Waldo Schinner
Mr. Milan Kling Jr.
Emie Kling
Craig Kulas
Alivia Strosin
Ms. Fannie Raynor III
Ms. Macie Sanford Jr.
```
devise_token_authで「Unpermitted parameters: :format, :registration」が出た時の対処法

# はじめに
Rails6+vue.jsでSPAを作成しており、ログイン周りでdevise_token_authを使うことにした。

色々な記事を参考にdevise_token_authを追加し、各種設定をして新規登録のテストをしたら下記のエラーを吐いた。

```
web_1  | Unpermitted parameters: :format, :registration
web_1  | Unpermitted parameters: :format, :registration
web_1  | Unpermitted parameters: :format, :registration
```

このエラーが出ても処理自体は行えるので実装上は問題ないけど、エラーがあるのは良くないので解決することに。そしたらめっちゃくちゃハマったので備忘録として残しておく。

# 解決策
devise_token_auth用に作成したcontrollerのストロングパラメータの記述を修正することで解決した。

・エラー吐いてたもともとのやつ

```api/auth/registrations_controller.rb
class Api::Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController
  private

  def sign_up_params
    params.permit(:name, :email, :password, :password_confirmation)
  end

  def account_update_params
    params).permit(:name, :email)
  end
end
```

・修正してエラーを吐かなくなったやつ

```api/auth/registrations_controller.rb
class Api::Auth::RegistrationsController < DeviseTokenAuth::RegistrationsController
  private

  def sign_up_params
    # require(:registration)を追加
    params.require(:registration).permit(:name, :email, :password, :password_confirmation)
  end

  def account_update_params
    params.permit(:name, :email)
  end
end
```

ストロングパラメータ関連のエラーだと分かってたけど、参考にしたサイトはどれも`require(:registration)`を省いて書いてたから、この記述でも問題ないと思って他のところを調べてて解決するまでめちゃくちゃ時間かかった。

ちなみに継承元のdevise_token_authでも同じようにストロングパラメータが定義されてたし何でエラーが発生してたかは分からない。

``` devise_token_auth/app/controllers/devise_token_auth/registrations_controller.rb 
def sign_up_params
    params.permit(*params_for_resource(:sign_up))
end
```
【超シンプル備忘録】Linux bash起動時に実行されるファイル

ユーザーがログインに成功した後、bashは「ログインシェル」として一般的に以下のような流れでファイルを順次検索し、ファイルが存在していれば実行し起動します。

```
1. /etc/profileを実行
2. /etc/profileによって、/etc/profile.dディレクトリ配下のすべてのファイルを実行
3. ログインユーザーのホームディレクトリにある̃ /.bash_profileを実行*
4. ̃/.bash_profileによって、̃ /.bashrcを実行
5. ̃/.bashrcによって、/etc/bashrcを実行
```


　例えば、コマンドラインからのbashの起動、suコマンドで別のユーザーになった場合など、
ログインシェルとしての起動ではない場合は、5のみが実行されます。

https://www.itmedia.co.jp/enterprise/articles/0803/10/news012.html
Task.AsyncStateの使い方

#AsyncState

あまり使い道が思い浮かばなかったが、一応メモ
AsyncStateを使うとTaskの中に埋め込まれたオブジェクトを取得することが出来る。
Taskの値を取得したいならTask.Resultを使う場合がほとんどだと思うけど、いつ使うんだコレ

```c#
using System;
using System.Threading;
using System.Threading.Tasks;

class Program {
    static void Main(string[] args) {
        Task task = Task.Factory.StartNew(  x => Calc(  (Data)x),   new Data(){init = 123});

        task.Wait();    
        Data data = task.AsyncState as Data;
        Console.WriteLine(  "init:{0}   id:{1}  rand:{2}",  data.init,  data.id,    data.rand); 
    } 
    public static void Calc(    Data data){
        data.id = Thread.CurrentThread.ManagedThreadId;
        data.rand = new Random().Next(1000);
    }
}
class Data{
    public int init;
    public int id;
    public int rand;
}
```
Nest.js と Nginx の連携

こちらのプログラムを Nginx 経由でアクセスするようにしました。
[Nest.js と TypeORM で MariaDB に接続](https://qiita.com/ekzemplaro/items/91ce87d281a3387f33c6)
>リバースプロキシーの設定をしました。
>Ubuntu 20.10 で確認しました。

次の設定を加えます

```text:/etc/nginx/sites-available/default
server {
（省略）
       location  ^~ /users {
                proxy_pass   http://127.0.0.1:3000/users;
        }
}
```

設定ファイルが正しいか確認

```text
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
```

Nginx の再起動

```bash
sudo systemctl restart nginx
```

クライアントからアクセス

```bash
curl http://localhost/users
```

データの挿入

```bash
curl -X POST http://localhost/users -d firstName='左千夫' -d lastName='伊藤'
```

データの削除

```bash
curl -X DELETE http://localhost/users/2
```
Docker-compose.yml の volumes を勉強する

#はじめに
いつものようにDocker-compose.ymlを書いて(コピペして)`docker-compose build`したら、下記のエラーが出ました。

```
ERROR: Named volume "mysql-data:/var/lib/mysql:rw" 
is used in service "db" but no declaration was found in the volumes section.
```

google翻訳「名前付きボリューム「mysql-data：/ var / lib / mysql：rw」がサービス「db」で使用されていますが、ボリュームセクションに宣言が見つかりませんでした。」

なんのこっちゃ。
という訳でありまして、調べてみました。

#そもそもvolumeとは
コンテナが破棄されてもvolumeは残る。
つまり、データベースの中身を永続的に残すための領域を定義することらしい。
そしてその領域は他のコンテナからもアクセスできて、ホストのディレクトリをマウント出来るとのこと。

#実際に見てみる

下記は実際に動いているRailsのdocker-compose.ymlファイルの内容の一部です。

```
services:
  db:
    volumes:
      - mysql-data:/var/lib/mysql

volumes:
  mysql-data:
    driver: local
```

servicesの中にdbとvolumesの2つがあり、ややこしいです。
1番左側でservicesと同じ高さにあるvolumesは`Named volume（名前付きボリューム）`を定義するためのもので、今回は`mysql-data:`が名前付きボリュームとなっています。
その下の`driver: local`はlocalという名前のドライバー（プラグイン）を名前付きボリュームに設定するという意味です。

db:の中のvolumes:は名前付きボリュームである`mysql-data:`をコンテナ内のディレクトリである`/var/lib/mysql`にマウントするという意味になります。

##python3やappのservice（コンテナ）にもvolumesがある
例えば

```
services:
  python3:
    volumes:
      - ./tmp:/root/tmp
```

これはホスト側のディレクトリの`./tmp`を自コンテナ専用のvolumeとして、コンテナ内のディレクトリである`/root/tmp`にマウントしているという意味。
これでアプリケーションの実行に必要なファイル達がpython3というコンテナで使えるのです。

#エラーを解消する
今回は「ボリュームセクションに宣言が見つかりませんでした」とのことだったので、1番左側に来る名前付きボリュームを定義するvolumesが抜けていたのだと推測します。
`docker-compose.yml`の1番下の1番左側に以下の内容を書き足します。

```
volumes:
    mysql-data:
```

書き足したら、いつものように下記の手順でdocker-composeを立ち上げます。

```
$ docker-compose build
$ docker-compose up
```

#おわりに
docker-compose.ymlの書き方について１つ賢くなれました。
ファイルの中身はまだまだ全てを把握しきれていませんが、エラーを乗り越えていく中で少しずつ学習していきたいです。
第七章シェルスクリプト

####7.1シェル環境のカスタマイズ
エイリアス機能＊超使える！
これは自分がカスタマイズするオリジナルコマンドが作れる
例えば削除を表すrmコマンドに-iオプションを使って
毎回削除する前に確認して欲しい
alias ='rm -i'コマンドを実行すると
次回からrmコマンドを使うだけで、勝手にrm -iと同じ処理をしてくれる
コマンドの解除がunalies
エイリアスを一時的に使わないで実行する時は
\コマンドを実行しましょう。

上記はコマンドをカスタマイズする処理だったが、
今度はコマンドを組み合わせた処理をまとめてみましょう。

いうならばエイリアスAボタンを押すと、かめはめ波が出る処理ですが、今度はBボタンを押すとかめはめ波を打った後に元気玉を打つまとめたコマンドを１ポチでできる技であります。
[function]関数名(){　コマンド　}

[function]chrm名(){ ls -l |rm -i　}
ちなみに上記のエイリアスを使うと
alias chrm ='ls -l | less'}

多分呼び出す時は
function(引数)

リスト表示するにはdeclear -f　setコマンド
削除する時はunset 関数名

7.1.5 bashの設定ファイル
ところで、今まで習った環境変数やエイリアス、関数っていつ定義（中身を入れる）されてるんだろ
例えばbashの時には、いついつにこのファイルをみてねというのが書いてある場所があります。

/etc/profile ログイン時に実行されて、全ユーザーから参照される
/etc/.bash.bashrc bash起動時に実行され、全ユーザーから参照される
~/.bash_profileファイル
①ログイン起動
②対話起動
コンピューターから人間様へ質問していくことによって物事を完了させること
CP　ユーザー名は
俺　ゆうと
CP　パスワードは
俺　＊＊＊
設定が完了しました。みたいな

####7.2シェルスクリプト
スクリプト言語を用いることで、コマンド作業を自動化（ワンポチ）できる。
例えばプログラミングっていうとSwiftだとIOSアプリを動かすためにある。rubyだとwebサーバーを動かすためにある。
シェルスクリプトは、このLinuxコマンドを動かすために、.sdファイルにプログランミングファイルを実行する。
↑スクリプトファイルを実行するにはどうするの？
＊bash　スクリプト名　コマンド（実行権はなくてもいい）
＊source スクリプト名　コマンド
＊.lsld　スクリプト名コマンド（要実行権）
大事
bashコマンドを使って実行した場合→子プロセスが起動する
sourceコマンドを使った時→親プロセスのまま実行される
これの何か問題かって、
親プロセスで使っていたシェル変数は、子プロセスでは使えない！（使えない変数が出てくると考える）

ウィンドウマネージャーを起動させる必要もない

exec　シェル名　コマンドを使うと、同じプロセスでシェルwp起動できる

引数のところわからない

実行結果の戻り値　実行した結果の成否を数字や文字で表すことです。
0がでたら正常終了
0以外　何らかの不具合
使い方としては
例）ls-l　fail　1,000
→そんなファイルないよ
echo $? をすると直前で問題があったか判断
1(問題あり　と出る)

ある条件を満たされた時に真偽判定をするのがtestコマンドです
このある条件って、例えば、、
このファイルがあったら真にしてね
このディレクトリがあったら真にしてね
数字１と数字２が同じだったら、、真にしてね！とか

プログラミングやっている人はわかると思うけど、IF分と似ている。でも、結果が真かどうかでしか表せないので
真だったり、そうでなかった場合の処理まで表示したい時は、if分を使う

testコマンド
150km投げれるの？
はい
いいね！

if分（大体シェルスクリプトの中に描かれる）
150kmなげれるの
はい
じゃぁピッチャーやって（その後に何をするかが書かれている）

if 条件(ここはtestコマンドだったり、そうでなくても良い)
then
 処理
else
fi

case分(大体シェルスクリプトの中に描かれる）
case $引数 in
条件
esac

例）
script中
case $1 in(コマンドプロンプト内の１番目の引数を読み取ってね)
echo "jan"
echo "feb"

コマンド内
./スクリプト　2→１番目の引数

結果は
febになる

for文
for　変数　in 変数に代入するリスト
 do
  echo $var Linux
 done

for　変数　in 変数に代入するリスト
 do
  echo $var Linux
 done

例えば
　　スクリプト内
　for var in 1番目　２番目　３番目
　do
  echo $var Linux
 done

　結果は
　1番目　linux
  2番目　linux
  3番目　linuxとなる

while文
i=1
while[$i -le 10]（１回目から１０回目まで）
do echo $i
let i = i +1(iが１づつ代入されていく　１＋１　２＋１　3＋１)
done

readコマンド
スクリプト上に記入しておくと
コマンド→ユーザにしつもんが作れる
例）スクリプト内
#!/bin/bush
echo -n "who are you:"（人間様への質問内容を考える）
read username（人間様の答えを入れる変数を作る）
echo"Hello,$username!"変数を使ってしたい処理をかく、さっきの変数に人間様の答えが入る

シェルスクリプトの実行環境
上記の通りスクリプト内で
#!/bin/bushのようにシェルを指定すると
子シェルとして新しく実行される。
SFSafariViewControllerを表示するメソッドを作る

#作り方
```swift
import SafariServices    
public func openSafariVC(view:UIViewController,url:String){
    let safariVC = SFSafariViewController(url:NSURL(string:url)! as URL)
    view.present(safariVC,animated:true,completion:nil)
}
```
#使い方
```swift
let url = "https://apple.com/"
openSafariVC(view:self,url:url)
```
Python 入れ直しになる原因（yumの場合の解決策）

# 背景

pyenv を使って Python を入れて使っているのですが、いざ始めようとすると警告やエラーが出て Python の入れ直しになるケースが多発しているので、対応策をまとめておきます。

試した環境は CentOS7 です。

# コマンド

```console
# pandas で Could not import the lzma module という警告が出る
$ sudo yum install -y xz-devel

# pip install で No module named '_ctypes' というエラーが出る
$ sudo yum install -y libffi-devel
```


```console
# Python の入れ直しも
# 3.9.1 の場合
$ pyenv uninstall 3.9.1
$ pyenv install 3.9.1
```

# その他

適宜追加していきます。
データベースに関する知識

RDB　リレーショナルデータベース　自分たちが使っているような列と行を持っているもの

RDBMS　RDBを使う時に用いるマネジメントシステムのこと　MySQL

単一責任の原則 　オリジナルアプリのクラスを決める際に重要

オブジェクト指向　役割ごとにそれぞれ分けることをさす　例えばmodelもオブジェクトであり、その中のそれぞれのモデルもオブジェクトである。

ORM  RDBのデータをオブジェクト指向プログラミング言語でオブジェクトに変換すること
Railsで言うとActiveRecordのこと

SQL　RDBの操作を行うための言語　 ActiveRcordのようなORMメソッドはSQLに変換されるためテーブルの操作ができるようになる

SQLはどのような種類のRDMに対しても用いることができる国際規定されているから