OmniAICreator/Qiita-1.07M huggingface dataset:
Goの開発環境構築（mac）

最近PCを入替えたので備忘を兼ねてメモ

# やりたいこと
1. Go が動かせるようになること
2. バージョンの切替が簡単にできること

# 環境情報
```
% sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H1323

% zsh --version
zsh 5.7.1 (x86_64-apple-darwin19.0)
```


# やったこと
1. homebrew のインストール
2. homebrew で goenv をインストール
3. goenv で go をインストール

---
## 1. homebrew のインストール
公式サイトからインストール用のコマンドを取得してきます。

https://brew.sh/index_ja

取得してきたコマンド

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

実行します


```
% brew -v
Homebrew 3.2.10
Homebrew/homebrew-core (git revision bb44918281; last commit 2021-09-03
```
無事、インストールできました

## 2. goenv のインストール
homebrew を使ってインストールします

```
% brew install goenv

% goenv -v
goenv 1.23.3

```

無事インストールできました

goenv, go を使うのに必要な環境変数を設定しておきます
`% vi ~/.zshrc` で編集

```rb:~/.zshrc
export GOPATH=$HOME/go
export GOENV_ROOT=$HOME/.goenv
export PATH="$GOENV_ROOT/bin:$PATH"
eval "$(goenv init -)"
export PATH="$GOROOT/bin:$PATH"
export PATH="$PATH:$GOPATH/bin"
```

以下のコマンドで設定を読み込んでおきます

```
% source ~/.zshrc  
```


## 3. go のインストール
まずは goenv でインストール可能なバージョンを確認します

```
% goenv install -l
 Available versions:
 ...
 ...
 1.11.2
 1.11.3
 1.11.4
 1.12beta1
```

あれ、古いバージョンしかないぞ？？
brew でインストールできる `goenv` 自体のバージョンが古いらしい。。。
なので、github から直接とってきます。

その前に、お片付けで `brew install goenv`をアンイストールします

```
% brew uninstall goenv 
brew uninstall goenv 
brew uninstall goenv 
Uninstalling /usr/local/Cellar/goenv/1.23.3... (158 files, 265KB)

```

では、気を取り直して、
公式から最新版を取得してきます

https://github.com/syndbg/goenv

```
% git clone https://github.com/syndbg/goenv ~/.goenv
 ...
 ...
# インストールできたのでバージョンを確認
% goenv -v
goenv 2.0.0beta11
``` 
無事にインストールできました
バージョンも変わってますね。（1.23.3 -> 2.0.0beta11）
同じようにインストールできる go のバージョンを確認していきます

```
% goenv install -l
 Available versions:
 ...
 ...
 1.16.0
 1.16beta1
 1.16.1
 1.16.2
 1.16.3
 1.16.4
 1.16.5
 1.16.6
 1.16.7
 1.17.0
 1.17beta1
 1.17rc1
 1.17rc2
```

最新のものまで表示されるようになりました。
今回は、 `1.17.0`を指定してインストールします

```
% goenv install 1.17.0
...
...
Installing Go Darwin 64bit 1.17.0...
Installed Go Darwin 64bit 1.17.0 to /Users/.goenv/versions/1.17.0
```
インストールできました
インストールできたバージョンを golobal で有効化します

```
% goenv global 1.17.0

# 設定されているバージョンを確認
% go version         

go version go1.17 darwin/amd64
```
これで無事に設定できました。

バージョンを変更したい場合は、

```
# 1. 使いたいバージョンをインストール
% goenv install x.xx.x

# 2. global で使用するバージョンを指定
% goenv global x.xx.x

```
とするだけ。
また、特定のリポジトリでのみ特定のバージョンを指定したい場合は

```
% cd /hoge/repository
% goenv local x.xx.xxx
```
としてあげればOKです。
便利ですね
Railsのlink_toでdeleteメソッドが動作しなくなった

Railsアプリ開発中に発生して、色々調べて解決したのでまとめました（今回は初歩的なスペルミスでした）。

問題：bootstrapを導入したらlink_toのdeleteメソッドが機能しなくなった
原因：application.jsファイルに記述するコードのスペルミス

学んだこと：サーバーを起動してデベロッパーツールでエラーが生じていないか確認すること

## 環境
ruby 2.7.3
rails 6.1.4.1
bootstrap 5.1

## 背景

1. デザインを整える前にCRUD処理を実装済み
1. 新規登録、編集、詳細表示、削除が機能することは確認済み
1. デザインを整えるためにbootstrap5.1, popper.js, FontAwesomeをインストール
1. 動作を確認すると削除が機能しない（具体的には一覧画面や編集画面で`削除`を押すと詳細画面に飛んでしまう）
1. ここまでにやったことは`bootstrapを使用できるようにimportへの記述`・stylesheetsのapplication.cssをscssに変更したぐらい

## 現象の確認
bootstrap導入のブランチを切る前、元のdevelopブランチでCRUDが機能することは再確認した。ここはやはり問題ない。

そしてbootstrapを導入したことで機能しなくなった問題のコードは下記。


```ruby:○○.html.erb
<%= link_to "削除", word, method: :delete, data: { confirm: "削除しますか？"} %>
```

ターミナルのログを確認すると`削除`ボタンを押した時に、`GET`メソッドが動作していた。しかし、`delete`メソッドが正常に動作している時も呼び出されているのは`GET`メソッドであるため、これは本質ではないと考える。

詳細画面に飛ぶということは、`link_to`で`path(ここではword)`が呼び出された後の`method: :delete`以降が認識されていないと考える。

色々調べた結果、`link_to`を`button_to`に変更すると動作した。しかしこの場合、`confirm`が作動せず「削除しますか？」の問いかけなしに削除されてしまった。

## 問題の解決
サーバーを起動してデベロッパーツールで確認したところ、コンソールで下記のエラーが発生していた。

```
Uncaught Error: Cannot find module 'bootsstrap/dist/js/bootstrap'
    at webpackMissingModule (application.js:1)
    at Module../app/javascript/packs/application.js (application.js:1)
    at __webpack_require__ (bootstrap:19)
    at bootstrap:83
    at bootstrap:83
```

スペルミスしてる・・・

```ruby:application.js
import 'bootsstrap/dist/js/bootstrap'
import '@fontawesome/fontawesome-free/js/all'
```

一行目の部分で`bootstrap`とするべき部分を`bootsstrap`とスペルミスしていた。ここを修正したら、問題なく動作した。
ちなみにFontAwesomeもスペルミスをしていて、`@fortawesome`とするべき部分を`@fontawesome`としていた。

## 学んだこと

普段Railsのルーティングやメソッドでエラーがある場合は、それに対応したエラー画面が出力されるため気付くが、今回のエラーはRailsの問題ではなくJavaScriptの問題であるため、エラー画面が出力されずすぐに気付けなかった。

これからはサーバーを起動してデベロッパーツールでもエラーが発生していないか確認しようと思う。

ちなみに上記のような単純なスペルミスではない場合、下記に記載した記事が参考になるかもしれません。





参考
[【Ruby on rails】data-confirm で動かないdeleteメソッドが動作しない](https://nabelog.org/695/)
[Railsでlink_to deleteメソッドが動かない](https://qiita.com/mami3sansan/items/6a9710b3ffdc937aa5f3)
[Rails学習者にrails-ujsの動作説明したら感動された話](https://www.inodev.jp/entry/2019/12/03/234210)

[【Rails】 button_toの使い方をどこよりもわかりやすく解説！](https://pikawaka.com/rails/button_to)
[アウトプット用]　初心者が押さえるべきReact用語集

# オリジナルのWEB用語集

作成経緯として、プログラミングを学習して専門用語と衝突し何となくの理解や知識が浅はかである知識の理解を深めるのが狙い:writing_hand_tone2:

この発信の期待効果として、

* __人に教えるスキルを習得__
* __記憶力の定着__
* __頭の中が言語化され理解度UPを図る__



# WEB用語集　説明書
* 作者の躓き・理解の浅い分野のアウトプットリスト（初心者に教えるように心掛ける）
* アルファベット・５０音順
* 随時更新とする

過去のアウトプット集


https://qiita.com/kinoshitaken123/items/f724d2f0c484b1f3d0db

https://qiita.com/kinoshitaken123/items/f986717a1852e94bf481

# 更新履歴

#コンポーネント
ソフトウェアやシステムを構成する部品のことです。ソフトウェア開発では、機能を部品化して開発することがよくあります。

この部品化した「プログラム部品」のことを コンポーネントと呼びます。

# Material UI
Reactで簡単にコンポーネントベースでマテリアルデザインを実現できるライブラリ。

# UIライブラリ
ユーザーインタフェースを実現するための集合体

# webpack
webpackとは、モジュールバンドラ。モジュールバンドラとは、複数のファイルを１つにまとめて出力してくれるツールのこと。

__開発効率アップ__

>機能ごとにファイルを分けて開発をすることによって、
コードが整理されて開発効率、保守性向上。

__システムの性能アップ____
１つのファイルにまとめることで、リクエストも１回にし、性能を高めることができる。
>リクエスト回数を減らせるため、通信回数を減らすことができます。そのため、サーバーの負担が少なくなることもメリットです。
SwiftでAPI通信する際はAlamofireを使うと便利

**(2021年9月)**
swiftでhttp通信を行ってapi叩きたいときにAlamofireライブラリを使いました。
取り敢えずAlamofireインポートして下記のコード叩けば通信成功のprint出力できます。



```ViewController.swift
import UIKit
import Alamofire

class ViewController: UIViewController {

    @IBOutlet weak var a:UITextField!
    override func viewDidLoad() {
        super.viewDidLoad()
        let url = "https://dog.ceo/api/breed/shiba/images/random/12"
        getadress(url: url)
     }
    
    func getadress(url:String){
       
        AF.request(url).responseJSON { response in

            switch response.result {
                case .success:
                    do {
                        print(response)
                    } catch {
                        print("デコードに失敗しました")
                    }
                case .failure(let error):
                    print("error", error)
            }

        }

    }
}
```
**実行後の画面**
![スクリーンショット 2021-09-04 23.49.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803173/fd4c549c-edfd-d7a6-ec33-ad26c149b2c5.png)

postとかget投げたい場合とかリクエストする際にパラメーター送りたい際は
getaddress関数のAF.requestを修正する。
(例)**postver.**

```ViewController.swift
AF.request(url, method: .post, parameters: parameters)
```

**リクエストする際のパラメーターに使う引数**

```ViewController.swift
let parameters:[String: Any] = ["username": "アイウエオ"]
```


昔の記事とかはAlamofire.requestになってるから注意。
Adafruit_DHTがError accessing GPIOで失敗する場合の対処

RaspberryPiでAdafruit_DHTを利用して温湿度センサを動かそうとした際に以下のエラーで失敗した
エラーでググったが解決策にたどり着くまで時間がかかったので書き残しておく

```
RuntimeError: Error accessing GPIO. Make sure program is run as root with sudo!
```
#結論
Adafruitのフォーラムにあった
https://forums.adafruit.com/viewtopic.php?f=24&t=168118
この通りやれば解決した
https://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/python-setup

#経緯
これまでRaspberryPi 4B（64bit）で温湿度センサAM2302（DHT22）を制御していたが、画像撮影する`raspistill`が64bitのRaspberry Pi OSでは使えないことに気づき、32bitでOSを再インストールして再び同じように温湿度センサの環境を[こことか](https://codezine.jp/article/detail/10562)見ながら構築していた際に上記エラーが出た
俺はなにも悪いことをしていない

#対処方法
エラーに書いてる通りGPIOピンの状況確認や`sudo`付けて実行など一通りやってダメだったのでググったが同様の報告があまりなく、最終的にはAdafruitのフォーラムにて案内されていたやり方にて対処した
https://forums.adafruit.com/viewtopic.php?f=24&t=168118

フォーラムによると
>Our Adafruit_DHT library is deprecated. We are now using the CircuitPython_DHT Library which will correctly identify your board as Pi4 based (BCM2835) instead of confusing it for a BeagleBone Black as the error indicates.

Adafruit_DHTは非推奨で今はCircuitPython_DHTとかいうのがあるよ、らしい

な、なにー！！！　今まで俺が使っていたAdafruit_DHTは…！？

なんでこのエラーが出たのかは最後まで分からなかったので知ってたら教えてください

##CircuitPython_DHTインストール
言われた通りに`adafruit-circuitpython-dht`と`libgpiod2`をインストール

```
pip3 install adafruit-circuitpython-dht
sudo apt-get install libgpiod2
```

##温度・湿度取得コード
https://learn.adafruit.com/dht-humidity-sensing-on-raspberry-pi-with-gdocs-logging/python-setup
CircuitPython_DHT用のサンプルコードがあったので自分用に編集

```Python:dht_simpletest.py
import time
import board
import adafruit_dht

def get_temp_humidity():
    dhtDevice = adafruit_dht.DHT22(board.D20)

    try:
        temperature_c = dhtDevice.temperature
        humidity = dhtDevice.humidity
        print('{:.1f},{}'.format(temperature_c, humidity))
        
    except RuntimeError as error:
        print(error.args[0])
        
    except Exception as error:
        dhtDevice.exit()
```
例外処理はテキトーなので適宜変更してほしい
これでとりあえず`python3 dht_simpletest.py`で温度湿度が`26.8,58.9`のような感じで出力できるようになった

これまでAdafruit_DHTがpython2でしか動かなかったので地味にうれしい

#おわり
ラズパイで熱帯魚水槽にめちゃくちゃなことをやっている
https://scrapbox.io/asyley-aqua/
[#あしゅりーアクアリウム](https://twitter.com/search?q=%23%E3%81%82%E3%81%97%E3%82%85%E3%82%8A%E3%83%BC%E3%82%A2%E3%82%AF%E3%82%A2%E3%83%AA%E3%82%A6%E3%83%A0&src=hashtag_click)
[gigalixir]** (Postgrex.Error) ERROR 42P01 (undefined_table) relation "hoge" does not exist の対処

# 結論

```
gigalixir run mix ecto.migrate
```
を実行すればok


### 背景

gigalixirにアプリをデプロイしたばかりの段階でurlにアクセスしたら、

```
** (Postgrex.Error) ERROR 42P01 (undefined_table) relation "hoge" does not exist
```
というエラーがログに出ていて、ブラウザには

```
internal server error 
```

と表示されていた。
ドキュメントを確認して上記のように対応。
 
### 参考
https://gigalixir.readthedocs.io/en/latest/getting-started-guide.html
https://elixirforum.com/t/debugging-deployment-assets/24117
[CSS]画像を縦横比を変えず表示

# はじめに
本記事では、CSSで画像を縦横比を変更させないようにする方法を記述しました。
本日私が行ったことになりますので、一部他の方と異なる可能性がありますので、
ご容赦ください。

# コード
ビュー
ここは個人の自由です。

```erb
<div class="ranks-food-post">
  <div>
    <%= link_to user_path(food.user_id) do %>
      <% if food.user.icon.present? %>
        <%= image_tag food.user.icon, class: "icon-img" %>
      <% else %>
        <i class="fas fa-user-circle"></i>
      <% end %>
    <% end %>
  </div>
  <div>
    <%= link_to user_path(food.user_id),class: "ranks-food-post-user" do %>
      <%= food.user.nickname %>
    <% end %>
  </div>
</div>
```

```css
.ranks-food-img {
  width: 25vw;
  height: 25vw;
  margin: 1vw;
  object-fit: cover;　　←ここ！！
  background: #ffc29050;
  border: 2px solid #2c161c46;
  border-radius: 5vh;
```

# 結論
`width`と`height`の大きさは合わせておくことで
正方形になるので綺麗に見えるのではないでしょうか。

`object-fit: cover;`を使用することで、
画像が縦に長くなったり、横に伸びたりすることはなくなり、
指定された範囲内で画像をそのままの比率で表示してくれます。

以上です。

# 終わりに
調べた結果、
このようにすることで、画像を綺麗に見せることができました。
これをすることで、投稿した画像やアイコンをうまく見せることができると思います。

以下参考サイトです。
[CSSをつかって円をつくるよ！ | border-radius](https://bgt-48.blogspot.com/2018/09/css-border-radius.html)
[CSSだけで縦横比固定のトリミングされたサムネイルをつくる【内接・外接リサイズ】](https://www.esz.co.jp/blog/2778.html)
[画像の縦横比を維持したままリサイズ(拡大/縮小)するCSS ](https://www.nishishi.com/css/resize-image-keep-aspect-ratio.html)
↓この方の記事たちはおすすめです。
[【図解】CSSだけで画像の縦横比を維持したサムネイルを表示する](https://qiita.com/suin/items/8de26866a8ab6ca65ba4)

今日はスローペースでしたが、
明日の用事はありませんのでバリバリ頑張ります！！
【Oracle】GROUP BYの結果をカンマなどで連結して取得する

# はじめに

MySQLには`group_concat()`という関数があり、GROUP BYの結果セットをカンマなどで連結して取得することができます。
Oracleに同じような機能がないかと調べてみた所、`LISTAGG()`という関数があることが分かったので、試しに使ってみました。

# 使用した環境

* Oracle社が提供している[Oracle Live SQL](https://livesql.oracle.com/)でOracle19cを利用しました。


# 作成したSQL

* テストデータを投入するのが面倒だったので、今回はサンプルスキーマ（SCOTT）のDEPTテーブルとEMPテーブルを使いました。
* DEPTテーブルには紐づく社員の居ない部署（OPERATIONS）があるため、`LEFT OUTER JOIN`でEMPテーブルと結合させています。

## サンプルコード1

* [Oracle19cのLISTAGG関数のリファレンス](https://docs.oracle.com/cd/F19136_01/sqlrf/LISTAGG.html)などを参考にして、`LISTAGG()`を使ってみました。
 * MySQLの`group_concat()`に比べると、少々構文が長い印象です。
* [LISTAGG\(\)のリファレンス](https://docs.oracle.com/cd/F19136_01/sqlrf/LISTAGG.html)には、以下の注意書きがありました。
 * 列のデータ型がRAW型の時は戻り値がRAW型、それ以外の時は戻り値がVARCHAR2型となる。
 * 戻り値がVARCHAR2型の場合、MAX_STRING_SIZEの設定値によって戻り値のデータの最大長が変わる。

```sql:
SELECT
  T1.DNAME AS DEPT_NAME,
  LISTAGG(T2.ENAME, ',') WITHIN GROUP (ORDER BY T2.ENAME ASC) AS DEPT_MEMBERS
FROM
  SCOTT.DEPT T1
  LEFT OUTER JOIN SCOTT.EMP T2
  ON T1.DEPTNO = T2.DEPTNO
GROUP BY
  T1.DNAME;
```

## サンプルコード1の実行結果

* 部署に所属するメンバーが、`DEPT_MEMBERS`列にカンマ区切りで出力されています。

|DEPT_NAME|DEPT_MEMBERS|
|---|---|
|ACCOUNTING|CLARK,KING,MILLER|
|OPERATIONS| - |
|RESEARCH|ADAMS,FORD,JONES,SCOTT,SMITH|
|SALES|ALLEN,BLAKE,JAMES,MARTIN,TURNER,WARD|

## サンプルコード2

* Oracle19cからは、`LISTAGG()`に渡す結果セットの重複を除去できる`DISTINCT`というキーワードが追加されたそうなので、それを踏まえたSQLを作ってみました。
 * [Oracle18cのリファレンス](https://docs.oracle.com/cd/E96517_01/sqlrf/LISTAGG.html)だと`DISTINCT`というキーワードが見当たらないので、おそらく19cから追加されたものと思われます。

```sql
SELECT
  T1.DNAME AS DEPT_NAME,
  LISTAGG(DISTINCT T2.JOB, ',') WITHIN GROUP (ORDER BY T2.JOB ASC) AS JOBS
FROM
  SCOTT.DEPT T1
  LEFT OUTER JOIN SCOTT.EMP T2
  ON T1.DEPTNO = T2.DEPTNO
GROUP BY
  T1.DNAME;
```

## サンプルコード2の実行結果

* 部署に所属するメンバーの役職が、`JOBS`列にカンマ区切りで出力されています。
* 実際のデータにはRESEARCH部にはANALYSTが2名、SALES部にはSALESMANが4名在籍していますが、`DISTINCT`キーワードで結果の重複が除去されています。

|DEPT_NAME|JOBS|
|---|---|
|ACCOUNTING|CLERK,MANAGER,PRESIDENT|
|OPERATIONS| - |
|RESEARCH|ANALYST,CLERK,MANAGER|
|SALES|CLERK,MANAGER,SALESMAN|




# 参考URL

* [LISTAGG関数 - Oracle19c](https://docs.oracle.com/cd/F19136_01/sqlrf/LISTAGG.html)
* [LISTAGG関数 - Oracle18c](https://docs.oracle.com/cd/E96517_01/sqlrf/LISTAGG.html)
* [グループ内の結果セットを単一列に連結する](https://www.shift-the-oracle.com/sql/aggregate-functions/listagg.html)
緯度経度から住所などに変換

#今回の内容

* 緯度経度から住所などに変換

#コードと簡単解説

* ` func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {}`内で`locations`から緯度と経度を取得します。
* 取得してきた緯度と経度から`reverseGeocodeLocation`により住所などに変換して利用することができる。

```Swift:
    //使用者の現在地の緯度と経度を取得して、住所か建物の名前などに変換
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        
        CLGeocoder().reverseGeocodeLocation(CLLocation(latitude: (locations.first?.coordinate.latitude)!, longitude: (locations.first?.coordinate.longitude)!)) { placeMark, error in
            
            if error != nil{
                
                return
            }
            
            if let resultPlaceMark = placeMark?.first{
                
                if resultPlaceMark.administrativeArea != nil || resultPlaceMark.locality != nil{
                    
                    self.currentLocationLabel.text = resultPlaceMark.name! + resultPlaceMark.administrativeArea!
                    
                }else{
                    
                    self.currentLocationLabel.text = resultPlaceMark.name!
                }
            }
        }
    }
```

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
Reduxメモ

React+Reduxでクイズアプリを作った。
[クイズメーカー](https://react-practice-meu29.vercel.app/)

##Redux
グローバルステートを管理するためのライブラリ。
グローバルステートは複数のページで同じ状態を共有するのに用いる。
逆に1つのページだけで用いる状態をローカルステートという。

##Action
グローバルステートの更新内容をまとめたオブジェクト。typeとpayloadのプロパティを持つ。
アクションを返す関数をアクションクリエータという。

```actions/message.ts
const setMessage = (message: string) => {
    return {
        type: "SET_MESSAGE",
        payload: {
            message: message
        }
    }
}
```

##Reducer
グローバルステートとアクションを受け取り、アクションをもとにを更新したグローバルステートを返す関数のこと。
受け取ったグローバルステート自体を書き換えてはいけない。
リデューサーを複数使う場合はcombineReducersメソッドでまとめる。

```reducers/index.ts
import { combineReducers } from "redux";
import { messageReducer } from "./message";

export const rootReducer = combineReducers({messageReducer: messageReducer});
export type RootState = ReturnType<typeof rootReducer>;
```
```reducers/message.ts
import { AnyAction } from "redux";

type State = {
    message: string
}

const messageReducer = (state: State = {message: ""}, action: AnyAction) => {
    switch (action.type) {
        case "SET_MESSAGE":
            return {...state, message: action.payload.message}
        default:
            return state;
    }
}
```

##Store
グローバルステートを保持するオブジェクト。
1つのアプリはストアは1つだけ持つ。

```store/index.ts
import { createStore } from "redux";
import { rootReducer } from "../reducers";

export const store = createStore(rootReducer);
```

##Provider
各コンポーネントがグローバルステートを参照できるようにする。

```App.tsx

import { Provider } from "react-redux";
import { BrowserRouter as Router, Route } from "react-router-dom";
import Header from "./components/commons/Header";
import IndexPage from "./components/pages/Index";
import { store } from "./store";

const App: React.FC = () => {
    return (
        <Provider store={store}>
            <Router>
                <Header />
                <Route exact path="/" component={IndexPage} />
            </Router>
        </Provider>
    );
}

export default App;
```

##グローバルステートの取得・更新
useSelectorメソッドでグローバルステートを取得。
アクションを引数としてdispatchメソッドを実行することでグローバルステートが更新される。

```pages/Index.tsx
import { useSelector, useDispatch } from "react-redux";
import { RootState } from "./../../reducers";

const message = useSelector((state: RootState) => state.messageReducer.message);
const dispatch = useDispatch()

/* この場合はアクションクリエイターの返り値がアクション */
const onClick = () => dispatch(setMessage("Hello"));

/* connect()・mapStateToProps()を使わないのでprops不要 */
const IndexPage: React.FC = () => {}

export default IndexPage;
```
Vue2からVue3への移行

#初めてに
プロジェクトを修正している途中、Vue3が発表されたのを知りました。
この機会に新バージョンを使ってみたいと思いました。
だがこれが4時間にかかる苦労になるとは…

#実施したVue3への移行手順
ほとんどの手順はVue公式の[マイグレーションガイド](https://v3.vuejs.org/guide/migration/migration-build.html#installation)に載っているのを参考しました。

1. vue upgrade
vue-cliのアップグレード。ここは問題なし。

2. パッケージの修正
package.jsonを修正します。

dependenciesのvueを３書き換えるようです。


```
"dependencies": {
    "vue": "^3.1.0-0", // 追加
    "@vue/compat": "^3.1.0-0" //　これも追加
    "vue": "^2.6.11", // 削除
    ...
},
"devDependencies": {
    "@vue/compiler-sfc": "^3.1.0-0" // 追加
    "vue-template-compiler": "^2.6.11" // 削除
    ...
}

```
その後``npm install``でvue3をインストールしますが、エラー発生。
コンソールには``peerDependencies``エラーなっちゃらが出ました。

これで何時間むだにし,やっと検索で得た解決策は、``--legacy-peer-deps``でインストールすること。

3. 漏れたモジュールの補修

後は``npm run serve``で起動できるか確認！
しかし、起動は成功したものの、ページが見えない問題が。
調べてみると、Vueのエントリーページのレンダリング方法が変わったみたいです。

```javascript:main.js
import Vue, { createApp }  from 'vue'
import App from './App.vue'
import router from './router'

// Vue2の起動メソッド
// new Vue({
//   components: {
//     VuePureLightbox
//   },
//   router,
//   render: h => h(App)
// }).$mount('#app')

// Vue3の起動メソッド 
createApp(App).use(router).mount('#app')
```
たぶんこんな感じかな。起動方法を修正したら直りました。
私が記憶しているのはこれが全てです。

#結果
1時間やってもマイグレーションできなくてVue3の空プロジェクトからファイルを移るか、またはVueを諦めてReactにするかなどなど悩みましたがなんとか既存のコードを活かしながらマイグレーションできました。
Default Servlet filter loaded by Spring Boot

# What is servlet filter

You can get the answer from [here](https://docs.oracle.com/cd/B14504_01/dl/web/B10321_01/filters.htm).

# How Spring Boot creates and loads filter

First creates bean which implements *javax.servlet.Filter* interface (Normally filter bean is extended from *org.springframework.web.filter.GenericFilterBean* class). Below is an example

```java
public class HttpEncodingAutoConfiguration {
	//...

	@Bean
	@ConditionalOnMissingBean
	public CharacterEncodingFilter characterEncodingFilter() {
		CharacterEncodingFilter filter = new OrderedCharacterEncodingFilter();
		filter.setEncoding(this.properties.getCharset().name());
		filter.setForceRequestEncoding(this.properties.shouldForce(Type.REQUEST));
		filter.setForceResponseEncoding(this.properties.shouldForce(Type.RESPONSE));
		return filter;
	}

	// ...
}
```  

Then during Servlet registrate to servlet container (Servlet class is *org.springframework.web.servlet.DispatcherServlet*), beans created above will be collected and registered at

```Java
public class ServletContextInitializerBeans extends AbstractCollection<ServletContextInitializer> {
	// ...

	@SuppressWarnings("unchecked")
	protected void addAdaptableBeans(ListableBeanFactory beanFactory) {
		MultipartConfigElement multipartConfig = getMultipartConfig(beanFactory);
		addAsRegistrationBean(beanFactory, Servlet.class, new ServletRegistrationBeanAdapter(multipartConfig));
		// *** HERE ***
		addAsRegistrationBean(beanFactory, Filter.class, new FilterRegistrationBeanAdapter());
		for (Class<?> listenerType : ServletListenerRegistrationBean.getSupportedTypes()) {
			addAsRegistrationBean(beanFactory, EventListener.class, (Class<EventListener>) listenerType,
					new ServletListenerRegistrationBeanAdapter());
		}
	}

	// ...
}
```

# Filter registered by default

| Filter | Function |
| --- | --- |
| org.springframework.security.web.FilterChainProxy | Used by Spring Security. It holds many sub-filter for performing security policy |
| org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter | Exposes the request object to the current thread|
| org.springframework.boot.web.servlet.filter.OrderedHiddenHttpMethodFilter | Converts posted method parameters into HTTP methods |
| org.springframework.boot.web.servlet.filter.OrderedFormContentFilter | Parses form data for HTTP PUT, PATCH, and DELETE requests and exposes it as Servlet request parameters. By default the Servlet spec only requires this for HTTP POST |
| org.springframework.boot.web.servlet.filter.OrderedCharacterEncodingFilter | apply default character encoding for request if not specify in request |
ソースコードをhtmlに変換

#変換アプリ
htmlではスペースやタブなどが表示されないので、pythonなどで記述したソースコードをhtmlに貼り付けるときは

[srctohtml](http://marginalsoft.com/tools/srctohtml/)などの変換アプリを使うと便利。

#使い方
使い方はソースコードを貼り付けて、言語は特に選択する必要はないので、[HTMLに変換]というボタンを押せば、下にhtmlのコードが表示されるので、それをコピーしてhtmlファイルに貼り付ければOK
Vuetify/v-data-tableで無眼スクロールしてみた!

# Vuetify/v-data-tableで無眼スクロールを実装する際に困ったことのメモと実装例


### v-data-tableに指定しないとスタイル補正される


* disable-pagination
* hide-default-footer

#### tableのDOMで無限scrollする場合
* スクロールバーを出すため、heightを指定する！
* DOMをscriptで取得するためのrefかidを付ける！

```  
     <v-data-table
            ref="tables"
            :headers="headers"
            :items="desserts"
            :loading="isLoaging"
            disable-pagination
            hide-default-footer
            fixed-header
            height="500"
            class="elevation-1"
          ></v-data-table>
```

# 無限ローディングの実装例

![scroll.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457942/edb74de0-5826-8503-6dcf-07edd120dc14.gif)


### 実装に必要なdataを用意する!

*data.headersはVuetifyのサンプルから引用*

```
  data() {
    return {
      isLoaging: false,
      headers: [
        {
          text: "Dessert (100g serving)",
          align: "start",
          sortable: false,
          value: "name",
        },
        { text: "Calories", value: "calories" },
        { text: "Fat (g)", value: "fat" },
        { text: "Carbs (g)", value: "carbs" },
        { text: "Protein (g)", value: "protein" },
        { text: "Iron (%)", value: "iron" },
      ],
      desserts: []
    };
  }
```
### Vueのライフサイクルフックでスクロールを検知する！

* tableで無限scrollする場合、DOMを指定してスクロールを検知する！
* windowのスクロール幅で無限scrollする場合、window.scrollY などを使う！

```
  mounted() {
    const instance = this.$refs.tables.$el.childNodes[0];
    instance.addEventListener("scroll", this.onScroll);
  }
```

###  最下部までスクロールされた際の処理を追記する！

* スクロール幅などの条件を付けて、さらに読み込み処理を書く。
* ローディングアニメーションの為、用意したフラグを利用する！


*今回はローカルで用意したものを追加、アニメーションの為にsetTimeOutしています* 

```
  methods: {
    onScroll() {
      const instance = this.$refs.tables.$el.childNodes[0];
      if (
        instance.scrollTop + instance.clientHeight >= instance.scrollHeight &&
        !this.isLoaging
      ) {
        this.isLoaging = true;
        const add = () => {
	     // 読み込んだ差分を追加
          const toAddDessert = [
            {
              name: "Frozen Yogurt",
              calories: 159,
              fat: 6.0,
              carbs: 24,
              protein: 4.0,
              iron: "1%",
            },
	    ...
          ];
          const mergedItems = [...this.desserts, ...toAddDessert];
          this.desserts = mergedItems;
          this.isLoaging = false;
        };
        setTimeout(add, 700);
      }
    }
  }
```

#注意点

*  eventListnerを適切に解除する！
*  DOM関連でのエラーハンドリングをする！
*  v-data-tableのkeyについても考える! keyについてはこちらが参考になるでしょう。

https://qiita.com/uucchhiiee/items/93ebd4af8f68e3686940

### あとがき

Vuetifyを利用することで簡単に実装できました！
windowのスクロール幅を利用したものはまた追記するかもです！
gem install mailcactherで起きたエラーを解決する

## mailcactherをインストールしたい

## やったこと

```gem install mailcacther```
を実行してmailcactherをインストールしようとする

（ちなみに、mailcactherは```bundle```を使ってインストールすると不具合が生じるらしい）


エラー発生

```
1 warning and 2 errors generated.
make: *** [parser.o] Error 1
```

以下のコマンドを打つ

```
gem install thin -v '1.5.1' -- --with-cflags="-Wno-error=implicit-function-declaration"
```
 

またエラー発生


```
Permission denied @ rb_sysopen - /Users/nagaoka/.rbenv/versions/2.7.3/lib/ruby/gems/2.7.0/gems/thin-1.5.1/CHANGELOG 
```
権限を許可しないといけないらしい。
sudoをつけて権限を許可させよう

```
sudo gem install thin -v '1.5.1' -- --with-cflags="-Wno-error=implicit-function-declaration"
```
↓
成功！！！

だけどsudoをむやみに使うのはよくないみたいだから今度はその理由についてまとめたい

## 参照
・ [現場で使える Ruby on Rails実践ガイド p302](https://www.amazon.co.jp/%E7%8F%BE%E5%A0%B4%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B-Ruby-Rails-5%E9%80%9F%E7%BF%92%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-%E5%A4%A7%E5%A0%B4%E5%AF%A7%E5%AD%90/dp/4839962227)
・https://qiita.com/tokimari/items/feda1ed61f2d8b5b317c
レジスタ

## 64ビットの16本の汎用レジスタ（GPR）
|64 ビット|32 ビット|16 ビット|8 ビット|備考|
|:-|:-|:-|:-|:-|
|RAX|EAX|AX|AH, AL||
|RBX|EBX|BX|BH, BL||
|RCX|ECX|CX|CH, CL||
|RDX|EDX|DX|DH, DL||
|RSI|ESI|SI||ソースインデックス|
|RDI|EDI|DI||デスティネーションインデックス|
|RBP|EBP|BP||ベースポインタ|
|RSP|ESP|SP||スタックポインタ|
|R8|R8D|R8W|R8B|
|R9|R9D|R9W|R9B|
|R10|R10D|R10W|R10B|
|R11|R11D|R11W|R11B|
|R12|R12D|R12W|R12B|
|R13|R13D|R13W|R13B|
|R14|R14D|R14W|R14B|
|R15|R15D|R15W|R15B|
※以下のレジスタは専用
RIP（インストラクションポインタ）
RFLAGS（フラグレジスタ）
M5StickC PlusでGrove LED Socket Kit (Lチカ)を試す

#1. 外観

1秒点灯、1秒消灯を繰り返すLEDチカチカを作ります。

![DSC_0235_2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68547/ce967bba-427b-b2a8-70dd-9c8b2b78f01d.jpeg)

#2. 環境

* [M5StickC Plus](https://www.switch-science.com/catalog/6470/)
* [Grove LED Socket Kit](https://www.seeedstudio.com/Grove-Blue-LED.html)
* Arduino IDE 1.8.15

#3. 接続

Groveの4ピンケーブルで接続するだけなのですが、表にしておきます。

| M5StickC Plus | Grove LED Socket Kit | Memo |
|:-:|:-:|:-:|
| G (GND) | GND | - |
| V OUT (5V) | VCC | + |
| G32 | NC | 接続なし  |
| G33 | SIG | 信号 |

#4. スケッチ

```cpp:Grove_LED_Socket_Kit.ino
#include <M5StickCPlus.h>

#define SIG_PIN 33          // G33 --> SIG

void setup() {
  M5.begin();
  M5.Axp.ScreenBreath(8);   // 画面の明るさ
  M5.Lcd.setRotation(1);    // 画面の向き
  M5.Lcd.setTextSize(2);    // 文字の大きさ

  pinMode(SIG_PIN, OUTPUT);
  delay(1000);
}

void loop() {
  digitalWrite(SIG_PIN, HIGH);  // 点灯
  M5.Lcd.fillScreen(BLACK);     // 画面塗りつぶし
  M5.Lcd.setCursor(10, 10);     // カーソル座標指定
  M5.Lcd.print("HIGH");
  delay(1000);

  digitalWrite(SIG_PIN, LOW);   // 消灯
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(10, 10);
  M5.Lcd.print("LOW");
  delay(1000);
}
```

以上です。
ダヴィンチ1.0AにRepetier(CFW)をインスコしたときにハマった話

:::note alert
CFWのインストールにより、本体が文鎮化（＝使用不能になる）の可能性があります
この記事を参考にしてインストールし、文鎮化しても一切の責任を負いません。自己責任で。
:::

#背景
ひょんなことでダヴィンチ1.0A（以後、1.0A）を格安で入手しました。


元々、オープンタイプ？の3Dプリンターは持っていましたが、ABS印刷時に安定しない（印刷物の周辺温度が安定せず、変形が発生する）ことから、クローズドタイプ？の3Dプリンターを使ったら楽かなあと思って探していたところだったので、渡りに船でした。


調べると、1.0Aの前身である1.0は2014年ごろ？に発売されたようなので、おそらく1.0Aも同時期、もしくはその後少ししてから発売されたと思われます。

クローズドタイプということについては満足ですが、個人的に1.0Aの仕様で、以下の点が気になってしまいました。

- スライサーにCuraは使えず、純正ソフトを使用して印刷する仕様（1.0A以降の機種は可能）
- 内部基板にmicroSDカードが刺さっているが、純正ファームウェアではスタンドアローンで印刷ができない（microSDを延長するキットは売っているので対応可能）
- 今まで使ってた3Dプリンターに比べて調整範囲が少ない（ように感じる。その分、印刷出来るようになるまでは簡単）

このような状況を解決するため、CFW（カスタムファームウェア）であるRepetier-Firmware-4-Davinci（以後、Repetier）をインストールして、ちょっと使いやすくしようとしました。


#インストールの準備
- 1.0A本体
- USBケーブル
- Arduino 1.8.0（→PCにインストールする）
- Repetier-Firmware-4-Davinci（→githubからzipでダウンロード）

基本的には以下のサイトを参考に作業します。
http://naguu.blogspot.com/2016/01/da-vinci-10-repetier-firmware-092.html

#ハマったところ
CFWであるRepetierを1.0Aにインストールする方法として、1.0Aは制御用にArduino DUE互換ボードが使用しているため、搭載されたボード上のAruduinoを書き込み可能な状態にしたうえで、CFWを書き込む形です。
しかし、Arduinoの1.5.8以降？から、Arduino DUEは標準ボードとしてプリセットされていないらしく、自分でインストールしなければいけません。

そのプリセットのインストールは
ツール　＞　ボード　＞　ボードマネージャー　で検索窓から「DUE」を検索し、右下のインストールを押すとインストールできます
![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569778/f85680fe-c88b-1e71-84db-a2300dbe464a.png)

ここでインストールが完了させれば、あとは設定ファイルを修正し、CFWを書き込み可能にした1.0Aを接続してビルドすることで、書き込みができます。

###### ですが、画面上は正常に書き込みが完了したように見えますが、3Dプリンターを再起動しても液晶画面に「■」が並んだまま起動しません。
→直すには、再度ファームウェア書き換えが出来る状態にしないと、再書き込み自体も出来なくなります

#ここでハマった
githubのTutorialに、[FAQとして記載があります](https://github.com/luc-github/Repetier-Firmware-4-Davinci/discussions/114)が、このパッケージをインストールした後に、指定フォルダ内のファイルを差し替える必要があります。自分の環境だと

> C:\Users\（ユーザー名）\AppData\Local\Arduino15\packages\arduino\hardware\sam\1.6.12

にcores と variantsというフォルダがありますが、このフォルダ内のファイルを差し替えるために、githubからダウンロードしたzipファイル内を開いて、

> src\ArduinoDUE\AdditionalArduinoFiles\Arduino - 1.8.0 -Due 1.6.8\Arduino15\packages\arduino\hardware\sam\1.6.8

内にあるcores と variantsの2フォルダを先ほどのフォルダ（自分の環境だと1.6.12）内にコピーします。
※最新版をインストールしたため、1.6.8と1.6.12でVerが合ってませんが、プリセットのインストール時に1.6.8を選択してもいいかもしれません

念のため、Arduinoを再起動し、再度ビルドとファームウェアの書き込みを行えば、CFWが書き込まれた状態で起動するはずです。

##### 2021/0/9/13追記：必ずArduino DUE互換ボードのインストールが終わった後に、ファイルのコピーをすること。そうしないとせっかくコピーしてもインストールで上書きされます。

#まとめ
ちゃんと公式のFAQを読んで対処しましょう
AWS Certified Data Analytics - Specialty (DAS-C01) 試験に合格しました

2021/9/4 に DAS 試験を受験してギリギリ合格しました。対策したことと、感想を書いておきます。
![score.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/780549/33f7ac31-4535-e3c2-741e-1e0b0840358b.png)

## 経験
php とか python を使って開発しているサーバーサイドよりの開発者です。DAS 試験で問われるほとんどのサービスの使用経験はないです（使ったことがあるのは S3 くらい）。

## 対策

問題集を解きまくりました。間違えた問題について、解説を読んでも分からない問題は公式ドキュメントを読んで理解するようにしました。Black Belt よりも公式ドキュメントの方が情報量が多いので、最初は読むのが大変でしたが、圧倒的に役に立ちました。

### 問題集

[こちら](https://aws.koiwaclub.com/)を使用しました。問題集を何周もして、全体として9割くらいの正答率になるまで解きました。

### 参考書

「[AWSではじめるデータレイク](https://www.amazon.co.jp/AWS%E3%81%A7%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%83%AC%E3%82%A4%E3%82%AF-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%81%AB%E3%82%88%E3%82%8B%E7%B5%B1%E5%90%88%E5%9E%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%83%AA%E3%83%9D%E3%82%B8%E3%83%88%E3%83%AA%E6%A7%8B%E7%AF%89%E5%85%A5%E9%96%80-%E4%B8%8A%E5%8E%9F-%E8%AA%A0/dp/491031301X/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=aws+%E3%83%87%E3%83%BC%E3%82%BF%E3%83%AC%E3%82%A4%E3%82%AF&qid=1630757657&sr=8-1)」と「[ビッグデータを支える技術](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82-%E3%83%93%E3%83%83%E3%82%B0%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93-%E2%80%94%E2%80%94%E3%83%A9%E3%83%83%E3%83%97%E3%83%88%E3%83%83%E3%83%971%E5%8F%B0%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%83%BC%E3%82%BF%E5%9F%BA%E7%9B%A4%E3%81%AE%E3%81%97%E3%81%8F%E3%81%BF-PRESS-plus/dp/4297119528/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=10M38VGKGRY4&dchild=1&keywords=%E3%83%93%E3%83%83%E3%82%B0%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E6%94%AF%E3%81%88%E3%82%8B%E6%8A%80%E8%A1%93&qid=1630757715&sprefix=%E3%83%93%E3%83%83%E3%82%B0%E3%83%87%E3%83%BC%E3%82%BF%2Caps%2C283&sr=8-1)」を読みました。「AWSではじめるデータレイク」の方で、aws の分析系のサービスを使用してどのようにデータレイクを構築するのかを理解するのに使用し（実際に構築することはしませんでした）、「ビッグデータを支える技術」で Hadoop を構成しているサービスについて理解するようにしました。実際に試験に役立ったので時間のある人は読んでおくことをおススメします。

## 押さえておくべきポイント

各サービスのベストプラクティスについては押さえておいたほうがいいです。試験でよく問われます。
**Redshift**
https://aws.amazon.com/jp/blogs/news/top-8-best-practices-for-high-performance-etl-processing-using-amazon-redshift/
**Athena**
https://aws.amazon.com/jp/blogs/news/top-10-performance-tuning-tips-for-amazon-athena/
**EMR**
https://media.amazonwebservices.com/jp/wp/AWS_Amazon_EMR_Best_Practices.pdf

## 感想

Glue について結構問われた印象です。あと、問題文と選択肢が長いものがあったり、サービスの細かい部分を問われる問題がありましたが、（試験解く上での鉄則だと思いますが）簡単な問題を確実に正答しておくことが重要だと思います。難しい問題や知らない問題も出てきますが、簡単な問題も出題されますので、簡単な問題を確実に解いて点を稼ぐことで合格にグッと近づきます。
英語のテキストファイルをいい感じに改行するスクリプト

# はじめに
既存の英文を編集する際に一定以上の桁数以上の文字が存在していると、UIからはみ出ることがあったので、いい感じに改行するツールを探しましたが、やりたいことができるツールが見つからなかったのでPythonで作ってみました。

# アプリ仕様
* Python3系で動作
* 引数1：変更元のファイルパス
* 引数2：1行あたりの最大文字数
* OUT:変更元ファイルのディレクトリに生成、名前が重複した場合は連番の数値を付与して生成する。
* 改行位置が単語の途中だと改行せず、一つ前のスペースの位置で改行する。

# 実行例

```text:スクリプト実行前
#Introduction
When editing an existing English sentence, if there are characters with more than a certain number of digits, it may protrude from the UI, so I searched for a tool that breaks lines nicely, but I did not have it, so I made it with Python I did.

#App specifications
* Works with Python 3 series
* Argument 1: Change source file path
* Argument 2: Maximum number of characters per line
* OUT: Generated in the directory of the change source file, and if the name is duplicated, it is generated by adding a serial number.
* If the line break position is in the middle of a word, the line break does not occur, but the line break occurs at the position of the previous space.
```


```text:スクリプト実行後(引数2：20に指定)
#Introduction
When editing an
existing English
sentence, if there
are characters with
more than a certain
number of digits, it
may protrude from
the UI, so I
searched for a tool
that breaks lines
nicely, but I did
not have it, so I
made it with Python
I did.

#App specifications
* Works with Python
3 series
* Argument 1: Change
source file path
* Argument 2:
Maximum number of
characters per line
* OUT: Generated in
the directory of the
change source file,
and if the name is
duplicated, it is
generated by adding
a serial number.
* If the line break
position is in the
middle of a word,
the line break does
not occur, but the
line break occurs at
the position of the
previous space.
```


# リポジトリ
公開してますので、同じようなことをしてみたい方は使ってみてください。

https://github.com/KazukiKuriyama/AddFeedEng
【備忘録】JavaのOptionalについて

#はじめに
Optionalについて自分なりの理解を備忘録として執筆します。

#Optionalとは
値をラップしてその値がnullである可能性を表現するクラス。
NullPointerExceptionを防ぐことができる。

#Optionalを使う理由
nullである可能性のあるメソッドを呼ぶ場合、事前にnullかどうかのチェックを実装する必要がある。
しかし、実装を忘れてしまう可能性がある。
実装を忘れることを防止するためにOptionalが利用される。

#ソースコードで確認
ofNullableメソッドを利用して、Optionalが型のオブジェクトを作成する。
If文の中でisPresent関数を利用して、値が存在しているときのみlengthメソッドを実行している。
この時、変数strの中身はnullであるため実行してもコンソール上にはなにも表示されない。

```java:java
		String str=null;
		Optional<String>strOpt=Optional.ofNullable(str);

		if(strOpt.isPresent()) {
			String message=strOpt.get();
			System.out.println(message.length());
		}
```
if文を利用しないでnullチェックする方法はラムダ式を用いて下記のように記載することもできる。

```java:java		
		strOpt.ifPresent(v->System.out.println(v.length()));
```

#値として受け取る場合
map関数を利用する。
mapメソッドの戻り値は、ラムダ式の戻り値をラップしたOptionalとなる。（この場合はInteger型のOptionalが返ってくる）
strOptの値が存在しない場合、値を持たないOptionalオブジェクトが返ってくる。

```java:java
Optional<String>strOpt=Optional.ofNullable(str);
Optional<Integer>lengthOpt=strOpt.map(v->v.length());
```

#参考
https://qiita.com/shindooo/items/815d651a72f568112910
[Ruby] Float#ceilメソッド

##はじめに
競プロ問題を解いているときに見つけたメソッド「Float#ceil」メソッドを紹介します・

##Float#ceil

簡単に言えば小数を繰り上げるメソッドです。（引数に負の整数を渡せば0より大きい桁も繰り上げの指定ができます。）

```ruby
1.1.ceil
=> 2

1.3.ceil
=> 2

2.0.ceil
=> 2
```

通常の使い方といえば上記のような使い方でしょうか。

もし小数第二まで繰り上げとかなら引数で指定できます。

```ruby
1.2345.ceil(2)
=> 1.24
```

こんな感じです。
小数点の「.」を軸に正の整数を渡せば右に数字を指定できるイメージ。
逆に負の整数を渡せば0よりも大きい数の桁を繰り上げることができるといえます。
注意が必要なのは負の整数の場合は引数のn番目を繰り上げ、正の整数を渡したときは小数のn番目までになることです。

```ruby
1234.56.ceil(-2)
=> 1300
```
外出先から家のLANにVPNを使ってアクセスする Part.1 ~構成解説編~ 

どうも、こんちゃす。

Yozakura_Shionです。

初投稿なんで文章が拙いかもしれませんけど、よろしくお願いします...

つーわけで、今回やっていくのはタイトルにも書いてある通り外出先から家のLANにVPNにアクセスして、外から家のメイン機にRDPとかできるようにしようという話です。

まずは、構成からですね。

鯖は、VMwareのvSphereを使った仮想鯖です。今回は、2台用意します。
1つ目が仮想ルーターの役割をしてくれる「ルーター」

2つ目が外からアクセスするためのVPNを構築する「VPN」

以上の2台を使っていきます。

今回使用するOSは、CentOS 8.4(ルーター構築用)とWindows 7(VPN構築用)です。

なぜ、この2つのOSを使うのかは次回説明します。

次に家のLANについてです。

まず、うちの家ではLANには家族のいろんなデバイスがつながっているので、万が一を考えて別ネットワークを作ります。後で、どっちのLANか分かるように家族のデバイス達がつながってる方をLAN(A)とし、別ネットワークの方をLAN(B)とします。今後は、上記の言い方で統一します。

今回はここら辺で失礼します。ありがとうございました。
キャッシュとクッキーの違いを超超超簡単にまとめてみた

キャッシュとクッキーは別物らしい。
エンジニアになったばかりの人は、先輩エンジニアがキャッシュがどうとかクッキーがどうとか言っているのを聞いたことがあるのではないでしょうか。
僕もエンジニアになったばかりのころはなんとなくわかっている状態だった。

## キャッシュとは？ クッキーとは？
|  |キャッシュ  |クッキー  |
|---|---|---|
|保存される情報  |WEBサイトの情報(html,css,jsとか)  |WEBサイトのユーザー情報(ID,pwとか)  |
|削除するべきタイミング  |WEBサイトが重い時とか  |みんなで共通のPCを使用する時とか  |

キャッシュとクッキーの違いは上の表のような感じ。

キャッシュは、WEBサイトの情報を保存される貯蔵庫とよく表現される。
このキャッシュには、ブラウザキャッシュとサーバーキャッシュなるものがある。
さらに詳しく知りたい人はググってください。

クッキーは、WEBサイトのユーザー情報を保存しておくところ。
例えば、ログイン画面でまたすぐにログインしたいときにこのクッキーにIDとかパスワードといった認証情報が保存される。
これによって、次にログインしたいときに再入力が不要だったりする。

おわり
[.NET] IHostBuilder.ConfigureWebHost と IHostBuilder.ConfigureWebHostDefaults の違い

# はじめに

`IHostBuilder`には、`ConfigureWebHost`と`ConfigureWebHostDefaults`の2つの拡張メソッドがあります。

違いを探ってみます。

バージョンは .NET 6.0.0 preview 7 です。

# ConfigureWebHost

[ソース](https://github.com/dotnet/aspnetcore/blob/330c2397160929d6d3275ade03cee436265258e8/src/Hosting/Hosting/src/GenericHostWebHostBuilderExtensions.cs#L31) です。

主たるところを引用します。

```cs
public static IHostBuilder ConfigureWebHost(
    this IHostBuilder builder,
    Action<IWebHostBuilder> configure,
    Action<WebHostBuilderOptions> configureWebHostBuilder)
{
    var webHostBuilderOptions = new WebHostBuilderOptions();
    configureWebHostBuilder(webHostBuilderOptions);
    var webhostBuilder = new GenericWebHostBuilder(builder, webHostBuilderOptions);
    configure(webhostBuilder);
    builder.ConfigureServices((context, services) =>
        services.AddHostedService<GenericWebHostService>());
    return builder;
}
```

`GenericWebHostBuilder`のインスタンスを生成して、引数となっているラムダ関数を呼んでいます。


# ConfigureWebHostDefaults

[ソース](https://github.com/dotnet/aspnetcore/blob/330c2397160929d6d3275ade03cee436265258e8/src/DefaultBuilder/src/GenericHostBuilderExtensions.cs#L33)です。

主たるところを引用します。

```cs
public static IHostBuilder ConfigureWebHostDefaults(this IHostBuilder builder, Action<IWebHostBuilder> configure)
{
    return builder.ConfigureWebHost(webHostBuilder =>
    {
        WebHost.ConfigureWebDefaults(webHostBuilder);
        configure(webHostBuilder);
    });
}
```

`ConfigureWebHost`を呼び出したあと、`WebHost#ConfigureWebDefatuls`を追加で呼んでいます。

## WebHost#ConfigureWebDefatuls

[ソース](https://github.com/dotnet/aspnetcore/blob/330c2397160929d6d3275ade03cee436265258e8/src/DefaultBuilder/src/WebHost.cs#L215) です。

ちょっと長いです。

こんなメソッドたちを呼んでいます。

```cs
builder.ConfigureAppConfiguration(/* snip */);
builder.UseKestrel(/* snip */);
builder.ConfigureServices(/* snip */);
builder.UseIIS();
builder.UseIISIntegration();
```

使うかどうかわからないですが、いろいろ使えるようにしてくれています。

### ConfigureServicesの中でやっていること

さらにConfigureServicesの中でやっていることも見てみます。

```cs
services.PostConfigure<HostFilteringOptions>(/* snip */);
services.AddSingleton<IOptionsChangeTokenSource<HostFilteringOptions>>(/* snip */);
services.AddTransient<IStartupFilter, HostFilteringStartupFilter>();
services.Configure<ForwardedHeadersOptions>(/* snip */);
services.AddTransient<IStartupFilter, ForwardedHeadersStartupFilter>();
services.AddRouting();
```

何かいろいろ必要そうなものを足しています。

# わかったこと

IHostBuilder.ConfigureWebHostDefaults は、IHostBuilder.ConfigureWebHost +α ということがわかりました。

だいたい ConfigureWebHostDefaults で大丈夫そうですが、自前でやりたいときは ConfigureWebHost を使えばよさそうです。
spacemacsのorg-modeで見出しの文字サイズを本文と合わせる

spacemacsのデフォルトの設定では、見出しの文字が本文より大きい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25428/d1002cd0-7d11-3a53-ac24-d7ee9466246e.png)
単純な見出しであれば問題ないのだが、TODO機能を使う際にTODO状態だと文字サイズが大きく、DONE状態になると本文と同じ文字サイズになるような挙動を防ぐため、見出しであっても本文と同じ文字サイズにすることとした。


## 方法1
`M-x customize`を実行後、検索バーに `spacemacs-theme-org-height` を入力し、設定をoff(nil)の状態にする。
https://github.com/nashamri/spacemacs-theme#customizations

## 方法2
`~/.spacemacs` の `dotspacemacs/user-init` に

```
(setq spacemacs-theme-org-height nil)
```
を追加
https://develop.spacemacs.org/doc/DOCUMENTATION.html#default-theme

## 補足
文字サイズは `spacemacs-theme` パッケージの下記の箇所で設定を行っている。
https://github.com/nashamri/spacemacs-theme/blob/dfe06629f8211ccd9933fc0d457019401ecbe594/spacemacs-common.el#L765-L767

全てのレベルで見出しのサイズ変更を打ち消したい場合は`M-x customize-face` で `org-level-1`, `org-level-2` などを個別に設定するよりも、`spacemacs-theme-org-height`の変数を設定した方が効率がいい。
【JavaScript】thisについて

#はじめに
こんにちは。
JavaScriptのthisについてアウトプットしていきます！

##thisとは
> thisとは、特別な変数のこと！
ちなみに何が特別かというと呼び出した場所、使い方によって用途が変わってくる点です。

>参照：https://breezegroup.co.jp/202005/js-this/

<br>

コードを記述しながら説明していきます。

```javascript:JavaScript
console.log(this);  //windowオブジェクト
```

何にも囲まれていない状態でthisを出力してみると、windowオブジェクトを参照しています。

<br>

```javascript:JavaScript
const obj = {
  name: 'Sato',
  age: 20,
  sample: function(){
    console.log(this.name);   //Sato
    window.setTimeout(function(){
      console.log(this);      //windowオブジェクト
    });
  }
}

obj.sample();
```

上記の記述では、objの関数sampleの処理を実行しており、「this.name」のthisはobjを参照しているので、「Sato」が出力される。また、「window.setTimeout」はobjではなく、windowオブジェクトを参照している。

<br>

上記のように、thisは直近で囲まれているオブジェクトを参照しており、状態によって取れる値が変わっていきます。


#最後に
ここまでthisについてまとめました。
なかなか理解できるまで時間がかかりましたが、今後のアプリ開発をしていくためにも基礎をしっかり抑えていきたいと思います！
Djangoを触ってると出てくる {% csrf token %} とは？ざっくり分かりやすく説明します！

Djangoでアプリケーション開発をしていてフォームを設置するときに、 {% csrf token %} というおまじないみたいなものを使いますが、こいつってそもそも何者なんでしょうか？

今回はエンジニア歴が浅い方や、非エンジニアの方向けに、このcsrf tokenが「何者なのか」というのを、ざっくりと分かりやすく書いていきます！

#そもそもCSRFって何？

csrf token を理解する前にまずは「csrf」がそもそも何かを少し説明します！

csrfを訳してみると
「サイト間を横断する(Cross Site)リクエストの偽造(Request Forgery)」
となり、

__悪意のあるサイトが、被害者となるユーザのフリをして、別のサイトにリクエストを飛ばして、そこで悪さをする__といった内容になります。

これだけだと分かりづらいですね汗

なのでまずはcsrfによるトラブル例をご紹介して、
それぞれのステップで何が起きているかを説明していきます！

注：この記事ではcsrfの概念の理解のために厳密な表現を避けております。あくまでcsrfが全く分からない！という方が少しでも理解いただけるように書かせていただきます...！

例）
__1. Twitterにログイン状態のユーザーが、悪意のあるウェブサイトに遷移する
2. 遷移先の悪意のあるウェブサイト内に（ユーザーが思わず押してしまうような）リンクが用意されていて、ユーザーが実際にクリックしてしまう
3. そのリンクはTwitter内のツイート投稿処理のURLと紐づいており、ユーザーに覚えのないツイートが勝手に投稿されてしまう__

### 1. Twitterにログイン状態のユーザーが、悪意のあるウェブサイトに遷移する。

csrfが行われる際には、「ユーザー」「ユーザーがログイン中のサイト（この例ではTwitter）」「悪意のあるウェブサイト」の3つの登場人物が出てきます。

この「1」のプロセスで大事なポイントは、__ユーザーが何かしらのサイトにログイン中である__という点です。

サイトにログインすると、ユーザーが使用しているブラウザのセッションには「今Twitterにこのアカウントでログイン中だよ～」というような情報が保存されます。

そしてこの「セッションに保存されたログイン情報」というのは、別のタブで別の作業をし始めようとも、ログアウトしない限りはずっとブラウザに保存されます。

ここが味噌となります。

### 2.遷移先の悪意のあるウェブサイト内に（ユーザーが思わず押してしまうような）リンクが用意されていて、ユーザーが実際にクリックしてしまう

そして、その後「悪意のあるウェブサイト」に、何かしらのサイトにログイン状態のユーザーが遷移してくると、悪意のあるウェブサイトによる攻撃が始まります。

ここで今更ですが、悪意のあるウェブサイトの目的を、今回の例では「誰かのTwitterアカウントから[公共の場に爆弾を仕掛けた]という旨のデマ情報を流したい」とかにしておきましょう。

また、この悪意のあるウェブサイトは、遷移してきたユーザーに対して
「あなたのスマホがウイルスに感染しているかもしれません！下記のリンクをクリックしてスキャンしてください！」
と脅してくるサイトだとしましょうか。

ネットになれていないユーザーだと不安を煽られて思わず押してしまいそうですが、
この「下記のリンク」にはある細工が仕掛けられていて...

### 3. そのリンクはTwitter内のツイート投稿処理のURLと紐づいており、ユーザーに覚えのないツイートが勝手に投稿されてしまう

既にWebアプリケーションの開発経験がある方からすると理解しやすい部分かと思いますが、

ネット上でツイートを投稿したり、そのツイートを編集したり、投稿した過去のツイートを削除したり...という処理を行う際には、画面だけ見ていると分かりませんが、それぞれにURLが割り振られているんです。

つまり何が言いたいかというと、__処理のためのURLと、必要な情報（ツイートに書きたいことなど）を用意すれば、Twitter以外の外部のサイトからでもツイートが可能である__ということなのです。

そしてこの悪意のあるウェブサイトは、ツイート投稿を行うために割り振られたURLと、投稿内容（[公共の場に爆弾を仕掛けた]という旨）を用意しておいて、
「下記のリンクをクリックしてスキャンしてください！」という文言で示されたリンクに埋め込むことで、
__ユーザーがそのリンクをクリックした時に、リンクをクリックしたユーザー自身のアカウントからそのツイートを作成させることが可能となる__のです。

これが「csrfとは何か」に対しての説明になります！

#本題！「csrf token」とは何者？

それでは本題に入っていきます！
csrf tokenがあることで、このcsrfを防げるのですが、いったいどうやって機能しているのでしょうか？

まず、csrf tokenがフォームに設置されることで、
ログインしたタイミングで、「このユーザーはログインしてるよ！」という情報と共に、__ユーザーのブラウザのセッションに対csrf用の特別な鍵が渡されます__。

ここで注目すべきポイントは、__ユーザーのブラウザにはその特別な鍵が存在する__ものの、__悪意のあるウェブサイトはその鍵を持っていない__という点です。

これを利用して、csrf tokenを設置しているサイト側では、
__ツイートを送信しようとしている人物がその鍵を持っていない場合はツイートを許可しないということが可能となる__のです。

なので、前述のような方法で悪意のあるウェブサイトが偽造ツイートを作成しようとしても、
__悪意のあるウェブサイト自体はログインしていない（ログインしたのはユーザー自身だから）ために鍵を持っておらず、偽造ツイートが作成できない__ようになっています。

（つまり直接ツイートを投稿する人物がその鍵を持っていないと投稿できない、という意味になります。）

以上が「csrf token」の説明となります！

#まとめ

一言でまとめるとcsrfとは、「被害者ユーザーがログイン中のサイトで、好き勝手いろいろやる(語彙力...)」ような攻撃方法のことで、
csrf tokenはそれを防いでくれる仕組みとなっています。

既に記載したように、csrf tokenの概念理解のために厳密な表現とは違う部分もあったかとは思いますが、
この記事をきっかけに「なんとなくcsrfってそういうことなのね！ちょっと自分でも調べてみよう！」と思ってくださった方がいたら嬉しいです！

また、この記事への感想や内容への指摘など、お気軽にコメントを頂けますと幸いです！

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

## 追記

こちらの記事を書いた後に見つけたのですが、
CSRFについてさらに詳しく知りたい方がいましたら、こちらのサイトがかなり参考になると思います！

ハンズオン形式で実際にCSRFを再現することで理解を深められる内容になっております。

https://www.hypertextcandy.com/csrf-hands-on-tutorial
CASE式でNULLを用いる際の注意点

## はじめに

前の2記事の知識をベースとして、本記事は具体例を述べています。

気になった方、前提知識がない方は下記の記事をご覧ください。

https://qiita.com/ryosuketter/items/e9c906cfdf8fbc33f32a

https://qiita.com/ryosuketter/items/e9eadaeb48540e94d88b

実行結果はこちらで確認できます。

https://www.db-fiddle.com/

## CASE式でNULLを用いる際の注意点

スキーマの定義は以下とします。

Schema (MySQL v5.7)

```sql
CREATE TABLE companies (
  id INT NOT NULL PRIMARY KEY auto_increment,
  company_name TEXT,
  company_group_id INT,
  address TEXT
);
    
INSERT INTO companies VALUES
	(1, 'ACE', 1, 'Japan Tokyo chiyoda 1-1'),
	(2, 'ACE_1', 1, 'Japan Tokyo chiyoda 1-1'),
	(3, 'ACE_2', NULL, 'Japan Tokyo chiyoda 1-2'),
	(4, 'RAINBOW_MEAL', 2, 'Japan Tokyo koukyogaien 1-1'),
	(5, 'STEP_INDUSTRY', 3, 'Japan Osaka fuchu midorigaoka 1-1');
```

クエリにて、company_group_id から グループ名を命名したいとき CASE式を用いる際の注意点です。

Query

```sql
SELECT
	company_name,
	CASE
		WHEN company_group_id = 1 THEN ' ACE_group'
		WHEN company_group_id = NULL THEN 'unknown'
		ELSE 'other'
	END AS group_name
FROM companies
```

| company_name  | group_name |
| ------------- | ---------- |
| ACE           |  ACE_group |
| ACE_1         |  ACE_group |
| ACE_2         | other      |
| RAINBOW_MEAL  | other      |
| STEP_INDUSTRY | other      |

`ACE_2`は NULLなので、`unknown`となって欲しいところですが、`other`となりました。

なぜおかしいかは、こちらの記事に詳細書いてます。

https://qiita.com/ryosuketter/items/e9c906cfdf8fbc33f32a

`ACE_2`は NULLなので、`unknown`となってくれるクエリは

```sql
SELECT
	company_name,
	CASE
		WHEN company_group_id = 1 THEN ' ACE_group'
		WHEN company_group_id IS NULL THEN 'unknown'
		ELSE 'other'
	END AS group_name
FROM companies
```

ですね。

| company_name  | group_name |
| ------------- | ---------- |
| ACE           |  ACE_group |
| ACE_1         |  ACE_group |
| ACE_2         | unknown    |
| RAINBOW_MEAL  | other      |
| STEP_INDUSTRY | other      |

`ACE_2`の`group_name`が`unknown`となってくれました。

大事なのは、**NULLは値ではない**ということを理解しているかです。

今回は以上です！

## 参照

https://www.amazon.co.jp/dp/4798157821/

68p

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
ストロングパラメータ覚えづらい

掲題の通りでヒィヒィ言ってる。
以下備忘録。

#1. ストロングパラメータって何だっけ
意図しないDBの読み書きを防ぐのがストロングパラメータ。createアクションを元にフォームなどから送られてきたパラメータをレコードに保存するときに、受け取るパラメータを制限するもの。

```ruby
params.require(:モデル名).permit(:キー名, :キー名.....)
```
このように指定していく。例えば、modelというモデルでやりとりできるデータベースに{sample1:"hogehoge",sample2:"fugafuga"}というレコードがあるとして

```ruby
params.require(:model)
 #=> {sample1:"hogehoge",sample2:"fugafuga"}
params.require(:model).permit(:sample2)
 #=> {sample2:"fugafuga"}
```
上記のようなことが起こる。params.requireの内容からキーを指定すると、指定したもの以外のキーは一切受け付けなくなる。

#2.　なんで必要か
要するに、書き換えられたくないカラムを書き換えられないようにしなければならないために設定するもの。
Mass assignment 脆弱性がキーワードとなる。

<a href="https://www.infoq.com/jp/news/2012/03/GitHub-Compromised/">関連記事</a>
ダミーデータ生成【VBA】【初心者向け】

## はじめに
ExcelVBAを使って顧客のダミーデータを
指定した数だけ出力するマクロを作ります
## 今回作るもの
```php:イメージ
氏名
佐藤 翔太
鈴木 拓也
高橋 健太
...
...
...
```
↑このようなものを再現するために
###
```php:実行例
氏名
wbv liji
kdg ksgf
nik gshv
...
...
...
```
↑このような【a～z 3文字】【半角スペース】【a～z 4文字】を指定した数だけ出力するVBAを作ります
## ステップ1
拡張子【xlsm】のファイルをデスクトップ上に作ります
ファイル名をダミーデータに変更します
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664939/289dcc49-ee4b-7cb0-34cc-8d72dbfd6688.png)
## ステップ2
下記のように入力します
※開発タブ→挿入→ボタンをクリックでボタン生成
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664939/dab6bc6e-2029-0544-6c37-739365c73f29.png)
## ステップ3
開発タブ→Visual Basicを押しVBA画面を開きます
MicroSoftExcelObjects(右クリック)→挿入→標準モジュール→Module1を開き、VBAを記述します
###
```vb:Module1
Sub make_dummy_name()
    Dim num
    num = Cells(2, 4)
    Dim i
    For i = 2 To 1 + num
        Cells(i, 1) = 1
    Next 
End Sub
```
## ステップ4
Excel画面に戻ります
マクロ実行ボタンを右クリック→マクロの登録→make_dummy_nameをOKを選択しマクロ実行ボタンを押します
↓のように人数があっていることを確認します
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664939/c5827aa9-ab5e-8292-a43e-275d7c20b784.png)
## ステップ5
VBA画面を開きます
VBAを追記します
###
```vb:Module1
Sub make_dummy_name()
    Dim num
    num = Cells(2, 4)
    Dim dummy_name As String 'ダミーネーム宣言
    Dim i
    Dim j 
    For i = 2 To 1 + num
        For j = 1 To 8
            If j <> 4 Then
                '4文字目以外はアルファベット小文字を結合
                dummy_name = dummy_name + CStr(chr(make_lowercase_ascii_number))
            Else
                '4文字目は半角スペースを結合
                dummy_name = dummy_name + " "
            End If
        Next   
    Cells(i, 1) = dummy_name
    dummy_name = "" 'ダミーネーム初期化  
    Next 
End Sub

Function make_lowercase_ascii_number()
    Randomize   '乱数系列初期化
    make_lowercase_ascii_number = Int(Rnd * 25 + 97) '97～122の範囲で乱数を生成
End Function
```
### ※Tips
ASCIIコード【10進数 97～122】はアルファベットa～z
chr(数値)でASCIIコード【10進数】に対応する文字をChar型として取得できる
CStr(【Char型】)でChar型→String型に型変換できる
## ステップ6
Excel画面に戻りマクロ実行ボタンを押します
ダミーデータが取得できました
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664939/1f45c203-42e9-7a42-3137-b5b72730143d.png)
## おわりに
ASCIIコードの【10進数】→【文字】の変換を覚えると便利です