OmniAICreator/Qiita-1.07M huggingface dataset:
ブラウザに表示させるための事前処理（コンパイラ）

複数の静的ファイルがブラウザに適用されるまでの仕組みをまとめました。
大まかに言うと、
ブラウザでは認識できる言語が決まっており、どんな言語も認識できる言語に翻訳する必要があります。
この翻訳作業をコンパイルといい、コンパイルできないものは事前に処理をする必要があります。この事前処理はプリコンパイルと呼ばれ、細かい機能1つ1つをモジュールという処理のまとまりにし、コンパイルしてブラウザに返すといった流れです。

```
前提
プログラミング初学者(2ヶ月)が学んだ内容をまとめたものです。
実際の現場では通用しないことや間違った情報がある可能性があります。
お気づきの方はコメントにてご指摘いただければ幸いです。
```

#ブラウザは認識できる言語が決まっている
ブラウザはHTML,CSS,JavaScript,WebAssemblyという言語のみを認識することができます。
サーバーサイドでどんな記述をしていたとしても、最終的にはこの4つでブラウザに返されています。
これ以外の言語ではブラウザはページを描画することができません。
##開発を便利にする言語
ブラウザでは、上記4つだけを認識してくれますが、開発ではより書きやすく読みやすいように設計されたプログラミング言語があります。
このプログラミング言語を**高級言語**といいます。
###高級言語
機械よりも人間が理解しやすいように設計されたプログラミング言語
機械が認識しやすい言語は**低級言語**と呼ばれます。
高級言語の例
CSS:SCSS、SASS
JavaScript:TypeScript、CoffeeScript
##ブラウザが認識できる言語に変換する仕組み
開発に便利な言語をブラウザが認識できるように翻訳する作業をコンパイルといいます。

**コンパイル**
プログラミング言語を動作する機械が理解できるように翻訳する作業
コンパイルはコンパイラというプログラムによって行われる。
コンパイラで認識できない言語がある場合は予めプリコンパイルしておく必要があります。

**プリコンパイル**
コンパイラが翻訳できない言語を翻訳できるようにする事前コンパイルのこと
メインとなる処理に対して行う前処理のこと
このプリコンパイルを行うための手法として、アセットパイプラインという仕組みがある。

**アセットパイプライン**
JavaScriptやCSSなどのアセットと呼ばれる静的ファイルを小さくまとめてくれる機能
アセットパイプラインの処理は、プリコンパイル→連結→圧縮→配置の流れで行われます。
複数の静的ファイルをプリコンパイルして連結したのち、圧縮して軽量化したものをpublicディレクトリに配置して、ブラウザへ渡せるようにします。
プリコンパイルはモジュールバンドラを使って行われます。

**モジュールバンドラ**
モジュールバンドラはJavaScriptのモジュールの依存関係を考慮しながら管理するツール
モジュールは機能を1つずつ分けて他のファイルから読み込めるようにした処理のまとまりのこと
機能のまとまりをモジュール、この1つ1つの機能が依存関係にある場合にモジュールバンドラはこれらを考慮しながら管理してくれます。
モジュールで管理せず、機能をファイルごとに分割してしまうと、最終的に1つのファイルにまとめるときに不具合が生じるためモジュールパンドラが使われています。

**webpack**
モジュールバンドラの中で主流なツール
webpackが行うことは大きく４つ
・Entry
依存関係を解決するためにどのファイルを基準（エントリーポイント）とするかを決める。
・Output
エントリーポイントにされ、webpackによってまとめられたファイルをどこへどのような名前で出力（アウトプット）するのか指定する。
・Loaders
JavaScript以外のCSSやHTMLなどのファイルをモジュールに変換する方法を読み込み（ロード）、指定した処理を行う。
・Plugins
圧縮などのファイルをまとめる以外でローダーが実行できないタスクを導入し、拡張（プラグイン）する。
Rについての個人的まとめ

#####※注意
本記事はpublicにしておりますが、あくまで自己の学習備忘録になりますので、あしからず。
最終的には皆さんが読めるようにしたいのですが、今はそんな余裕がございません。

```
#算術演算
3 + 2       #和
3 - 2       #差
3 * 2       #積
3 / 2       #商
3 ^ 2       #累乗
```

```
#文字列
fr1 <- "apple"		        #文字列
fr2 <- c("orange", "lemon") 	#文字列を要素とするベクトル
fruites <- c(fr1, fr2, fr1)     #要素を結合
fruites	                        #fruitesを表示		
```
Azure Static WebApps で react URL 直打ち


# routes.jsonの配置
static webapps 用のルーティング設定ファイル『routes.json』をpublicに配置して、デプロイすればOK
![2020-09-08 215916.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439179/4c4b51d6-ac79-86c9-fd97-009f3b36dc4a.png)

```　json
{
    "routes": [
        {
            "route": "/*",
            "serve": "/index.html",
            "statusCode": 200
        }
    ]
}
```

MSの[サイト]

[サイト]:https://docs.microsoft.com/ja-jp/azure/static-web-apps/routes

開発環境なら別にいいけど、サイトにのっけると CSR なので、index.html に来てもらわないと、href でサイトの相対パス設定しても 404 なります
【Java】参照型である文字列におけるequalsと==の違い

###参照場所の比較と値の比較
|比較方法|内容|
|:--|:--|
|equals|メモリ領域の比較|
|==|値の比較|

###プログラム例

```java
public class MyApp {
		
	public static void main(String[] args) {

		String s1 = "ab"; // メモリ領域を格納
		String s2 = "ab"; // メモリ領域を格納（上と同じ領域）

		if(s1.equals(s2)) { // 内容が同じか比較
			System.out.println("same1 equals");
		}

		if(s1 == s2) { // 基本データ型の比較
			System.out.println("same2 ==");
		}
		// 文字列オブジェクトの生成（equalsメソッドを持つ）
		String ss1 = new String("ab"); // メモリ領域の格納
		String ss2 = new String("ab"); // メモリ領域の格納（上とは別の領域を作る）

		// 基本データ型の比較
		if(ss1 == ss2) { // メモリ領域の比較をしているのでfalseになるので実行されない
			System.out.println("same3 == オブジェクト");
		}
		// データの内容のの比較
		if(ss1.equals(ss2)) {
			System.out.println("same4 equals オブジェクト"); // メモリ領域は違うが値は同じなので実行される
		}
	}
}
```

###実行例

```
same1 equals
same2 ==
same4 equals オブジェクト
```

###文字列はクセがある

本来参照型である文字列には、変数には参照先のメモリ領域の場所が格納される。

そして、例では`ab`という同じ文字列をs1とs2に代入しているが、なんとs1にはメモリ領域の場所が入って、同じ文字列をs2に代入していると言うことで同じメモリ領域の場所が入ってしまうらしい。つまり

```java
String s1 = "ab";
String s2 = s1;
```

と同じ意味？になる。

試しに実行してみると

```java
same1 equals
same2 ==
same4 equals オブジェクト
```


###参照場所は同じということはどちらかで参照先の値を帰るとどうなる？s1の値だけ変えても両方変わる？

```java
String s1 = "ab";
String s2 = s1;
s2 = "cd";
```
にするとどうなるのか...わかりやすく

```java
		System.out.println("s1: " + s1);
		System.out.println("s2: " + s2);
```
を追加して実行。


```：実行結果
s1: ab
s2: cd
same4 equals オブジェクト

```

s2のみ変更され、s1には反映されていない。

そういえば、文字列は基本データ型と同じような振る舞いをするということもあり、int型と同じ挙動をするという。。。

値が同じうちは同じ参照先で、値の更新があった場合は新しいメモリ領域を作ると言うことですかね？



ややこしいですが、実行してみて改めて理解しました。

配列なら両方の値が更新されるんでしたね。復習復習！
rails + vue.js でテンプレートインジェクション対策をする　

## テンプレートインジェクションって?
テンプレートエンジンやjsのフレームワークを使用しているアプリケーションに対して、文字列展開される記法を利用して、santizeの漏れをつき任意のプログラムを実行させる攻撃方法の一つです。

広義のxssに近いような攻撃ですね。

例えばサーバーサイドをrails、フロントエンドをvue.jsという構成でアプリケーションが作成され、
一般ユーザーから入力を受け付けて表示する機能があるとします。

ここで悪意のあるユーザーが、攻撃対象のwebサイトが使用しているフロントエンドフレームワークをvue.jsだと仮定して攻撃します。
文字列の展開に使われる{{を使用して以下の文字列を入力してきました。

```text
{{constructor.constructor('alert(1111111111)')()}}
```
現状のrailsの仕様だと、
部分的に文字列表示をrailsで行っている箇所で {{ マスタッシュがエスケープの対象になっていません。
なので、vue.jsのテンプレートと解釈されて中の文字列がjsとして実行されてしまいます。

## なぜ、これが怖いのか?
という説明を今さらしてもあれなのですが、この中で任意のjsを実行できると訪問したユーザーの情報を他サーバーに送信するなどなんでもできちゃいますよね。

## 対応
でどうやって対応したの?
まあセキュリティ対策の基本で入力で弾く&出力で置き換えるをやっていきます。

### 入力部分での対応
入力時にマスタッシュ文字がある場合弾いてあげます。
controllerがパラメーターを受け取る前後で対応するか、modelの保存直前で対応するか迷ったのですが、
railsのstrong parameterをいじるのが難しかったので、modelで対応しています。

```ruby
class BaseModel < ApplicationRecord
  self.abstract_class = true

  def delete_vue_template
    string_value_keys = self.attributes.map do |key, value|
      key if value.class == String
    end
    string_value_keys.compact!.each do key
      self[key].replace('{{', '{ {').replace('}}', '} }')
    end
  end
end
```

該当のmodelに

```ruby 
before_validation :delete_vue_template
```
を記載してあげています。

### 出力部分での対応
大体のrailsアプリケーションで[sanitize](https://apidock.com/rails/ActionView/Helpers/SanitizeHelper/sanitize)が使われていたり、simple_formatで内部的に呼ばれているかなと思いますので、そこに手を入れて行こうとと思います。

ApplicationHelperにsanitizeメソッドを作成して、オーバーライドしてあげます。
simple_formatを使っている方も多いと思いますのでそちらでも自動で適用されるよう工夫しています

```ruby
  def simple_format(string, options = {})
    super(sanitize(string, tags: %w[p br strong]), options)
  end

  def sanitize(html, options = {})
    html.replace('{{', '{ {') if html.class == String
    super(html, options)
  end
```

## 感想&追記
セキュリティ検査を会社で行い、対応しようと思った際にあまり資料がなかったのでrails&vue.jsのアプリケーション向けに資料に致しました。
もっとこうやった方いいとか、記載に誤りや視点に抜け漏れがあった際にはコメント等頂けると嬉しいです。
編集リクエストでも助かります。

## 他の対応方法
angular.jsのドキュメントには一部記載があります。
https://angular.jp/guide/security#offline-template-compiler


> オフライン・テンプレート・コンパイラはテンプレートインジェクションと呼ばれる脆弱性を確実に防止し アプリケーションのパフォーマンスを大幅に向上させます。プロダクション環境ではオフラインテンプレートコンパイラを使い、 動的にテンプレートを生成しないようにしましょう。Angularはテンプレートコードを信頼するので、 テンプレート、特にユーザーデータを含むテンプレートを生成すると、Angularの組み込みの保護が回避されます。 Angularはテンプレート文字列を全面的に信頼するため、動的なテンプレート生成は常にXSSの危険性を有します。フォームを安全に動的に構築する方法については Dynamic Forms のガイドを参照してください。


既にリリースしていてこの機能を使っているなら変更する手間がかなり大きいですが、動的テンプレートを生成しないようにしておくのもいいかなと思います。
rails + mysql5.7で"Mysql2::Error: Expression #1 of ORDER BY clause is not in SELECT list, references column 'テーブル名.カラム名' which is not in SELECT list "

#環境
ruby 2.5.1
rails 5.2.4
mysql 5.7

#背景
railsのDBをmysqlに変えて、rspecを実行したら、見慣れぬエラーが発生

```
ActionView::Template::Error:
   Mysql2::Error: Expression #1 of ORDER BY clause is not in SELECT list, references column
   'portfolio1_test.users.name' which is not in SELECT list; this is incompatible with DISTINCT:
    SELECT  DISTINCT `communities`.* FROM `communities` LEFT OUTER JOIN `community_users` ON
   `community_users`.`community_id` = `communities`.`id` LEFT OUTER JOIN `users` ON `users`.`id` = 
   `community_users`.`user_id` ORDER BY `users`.`name` DESC, created_at DESC LIMIT 15 OFFSET 0
```

#原因
Mysqlから以下の設定が追加されたために問題が発生していたらしい
sql_mode,'ONLY_FULL_GROUP_BY

##解決策１
上記の設定が影響するSQL文を変える
[MySQL5.7にアップデートしたらonly_full_group_byでエラーになった](https://www.p-nt.com/technicblog/archives/204 #)

##解決策2
Mysqlの設定を変える
[Ransack の sort_link が MySQL で動作しない（ incompatible with DISTINCT）](https://qiita.com/hnyssh/items/632e8ff999e5025b958d #)


#今回はMysqlの設定を変えることにした
変更する箇所が多すぎるので、Mysql の設定を変えることにした。
ローカルでは設定を変えることで、問題が解決するが、Docker 環境でもこの設定変更を実行させたい。

docker-compose.yml にて command を使って、設定を変更できるはず。

# コンテナを構築する際に、Mysqlの設定を反映させたい
[MySQL 5.7 のONLY_FULL_GROUP_BY が出た時にDockerでやった対処](https://qiita.com/masayuki14/items/3aa199035eb4fdcfa446 #)

```docker-compose.yml
version: '3'
services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    tty: true
    stdin_open: true
    depends_on:
      - db
    ports:
      - "3000:3000"
    volumes:
      - .:/myapp:delegated
  db:
    image: mysql:5.7
    command:
      - --sql-mode=NO_ENGINE_SUBSTITUTION   #追加!!
    environment:
      MYSQL_USER: root
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3316:3306'
    volumes:
      - ./db/mysql/volumes:/var/lib/mysql
```
【GAS】LINE文字起こしbotを作ってみた



ぜひ使ってみて
---

タイトル通りですが、
**"LINEで画像を送信すると、画像の文字部分を抽出して返信してくれるチャットbot"**を作りました。
下のQRコードから追加できます。よかったら追加して使ってみてください。
![screenshot.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703207/38d652f4-c016-47d6-56d9-be5cd2fbe93b.png)


作った経緯
---
GASについて学べる本をフリマアプリで探していたところ、
著者：河合大さんの「[独学プログラマーのためのAIアプリ開発がわかる本][link-1]」に出会いました。
![ダウンロード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703207/ffa02ef2-efc7-3a13-5724-95dba34290e1.jpeg)



さっそく購入し本の順序通りに進めていたら、チャットボットが勝手にできたという感じです。（結構苦戦しましたが、、）

余談ですが本の感想を言うと、
**GAS(Google Apps Script)を体系的に学べる本ではありません。
LINE Chat botを作ることに特化しています。APIを取得したりするので、コード自体は初心者より少し中級者向けなのかなと。**
公開できる制作物を一つ流れで作成できる点は、非常に達成感があってよかったと思います。モチベーションに繋がるのでお勧めです。




[link-1]:https://www.amazon.co.jp/%E7%8B%AC%E5%AD%A6%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AEAI%E3%82%A2%E3%83%97%E3%83%AA%E9%96%8B%E7%99%BA%E3%81%8C%E3%82%8F%E3%81%8B%E3%82%8B%E6%9C%AC-%E6%B2%B3%E5%90%88-%E5%A4%A7/dp/4046040076
TestFlight「"app name"をインストールできません あとでやり直してください」が起きて原因がキレそうだった件

## はじめに

タイトル通り、TestFlightにて急に昨日まで問題なかったインストールができなくなり、原因が謎過ぎて、今日7時間ぐらい使ってしまったのでキレそうになり、そのノリで書いてます。


## 原因

**接続しているノード（WiFi）が問題でした、、**
自宅のものでは問題なかったのですが、良くあるセキュアなWiFiではTestFlightからのインストールが出来ませんでした。
4Gに変えた瞬間解決しました（キレそう）

ただ、恐らくWiFiが問題と言うより、MacBook Proの方で先にWiFiにつないで認証した後だと、同じapple idを使っているiPhoneでは認証を求められなかった為だと思われます。

原因が分からなすぎて、冗談抜きで証明書50回ぐらい作り直して、試したので証明書周りはもう脳死で出来る様になりました😇

後、試せる人が他にいればその人に試してもらうのが一番早いです！
その人が問題無ければ環境に違いって事に目付けれるので

ちなみにこの状態になって考えられる原因は
- 証明書が開発用
- 本件（wi-fi問題）

## owari

何が言いたいかって、こんなものに時間を割いてるは本当にもったいないです、非効率的過ぎます。
と言う事でこう言うヤバ目の記事はなかったので誰かの為に置いておきます。
supervisord.confのpathが上手く通っていない際に通す方法

`echo_supervisord_conf > /etc/supervisord.conf` 使ってsupervisord.conf作ったのに、pathが通っていない…。
以下のコマンドで通すことが出来たのでメモっておきます。

```
supervisord -c /etc/supervisord.conf
```
matplotlibを使ってみる

matplotlibはLinux環境で手軽に使えるデータビジュアライゼーションのライブラリです。[公式のチュートリアル](https://matplotlib.org/tutorials/introductory/usage.html#sphx-glr-tutorials-introductory-usage-py)に紹介されている最もシンプルなパターンのグラフは例えば以下のようなコードで記述することができます。

```python

import matplotlib.pyplot as plt

fig, ax = plt.subplots()  # Create a figure containing a single axes.
ax.plot([1, 2, 3, 4], [1, 4, 2, 3])  # Plot some data on the axes.

plt.show()
```

モジュールが見つからないなどのエラーが出る場合は、以下のような手順(pipなど)を使ってインストールします。

```python

sudo pip3 install matplotlib
```

numpyやpandasも一緒に使うことが多いので入れておくと便利かもしれません。

```python

import numpy as np
import pandas as pd
```
emacsのshell-modeでパスワードが表示されてしまう問題

# 現象
emacsのshell-modeからパスワードを入力すると普通は、画面下に専用の入力ボックスが開きそこに伏せ文字で入力できます。しかし、日本語版Ubuntuで`sudo`をするとそれが機能せずパスワードが直に表示されてしまいます。

```sh
$ sudo ls
[sudo] ユーザーホゲホゲのパスワード:ここにパスワードが表示されてしまう
```

# 伏せ字機能の仕組み
コマンドラインで表示される文字列が`comint-password-prompt-regexp`の正規表現とマッチする場合は伏せ字機能が有効になります。つまり本件の場合は`[sudo] ユーザーホゲホゲのパスワード:`が正規表現にマッチしていない事が原因です。`export LANG=C`で英語表記にするとsudoは`[sudo] password for user_hogehoge:`になるため、正規表現とマッチして伏せ字機能が有効になります。しかし日本語フィアル名が文字化けするしスマートではないです。

# 解決策
`comint-password-prompt-regexp`に正規表現を追加することで任意の文字列で伏せ字機能を使えるようにします。`"\\|^..."`の`...`の部分に追加したい正規表現を加えます。`[sudo]`で始まり`:`で終わる文字列が来たら有効化したいので追加する正規表現は`"\\|^\\[sudo\\].+:"`となります。以下を設定ファイルに追記します。

```scm
(add-hook 'shell-mode-hook
          #'(lambda ()
              (setq comint-password-prompt-regexp
                    (concat comint-password-prompt-regexp
                            "\\|^\\[sudo\\].+:"))))
```

- `""`で囲んでいるためバックスラッシュは2重にする -> `\\`
- `^`行頭からを評価する

# 参考
https://qiita.com/y2q_actionman/items/5986df9480960c40eb4e

https://emacs.stackexchange.com/questions/21116/how-to-prevent-emacs-from-showing-passphrase-in-m-x-shell
chip8の研究

#概要

chip8を調べてみた。

#chip8 アセンブラ　命令セット


|ニーモニック|意味|コード|
|:--|:--|:--|
|CLS                 |dispクリア|0x00E0|
|scrole              |スクロール|0x00c6|
|DRW Vx, Vy, sprite  |Vx, Vy <- sprite|0xdnnn|
|LD Vx, byte         |Vx <- byte|0x6nnn|
|LD Vx, Vy           |Vx <- Vy|0x8nnn| 
|LD Vx, I            |V0:Vx <- memory[I]|0xf065|
|LD Vx, DT           |Vx <- delay timer|0xf007|
|LD Vx, K            |Vx <- Key|0xf00a|
|LD DT, Vx           |delay timer <- Vx|0xf015|
|LD ST, Vx           |sound timer <- Vx|0xf018|
|LD F, Vx            |memory[I] <- sprite|0xf029|
|LD B, Vx            |memory[I] <- BCD(Vx)|0xf033|
|LD I, addr          |I <- addr|0xannn|
|LD I, Vx            |memory[I] <- V0:Vx|0xf055|
|OR Vx, Vy           |Vx <- Vx or Vy|0x8001|
|AND Vx, Vy          |Vx <- Vx and Vy|0x8002|
|XOR Vx, Vy          |Vx <- Vx xor Vy|0x8003|
|SHR Vx, Vy          |Vx <- Vx >> Vy|0x8006|
|SHL Vx, Vy          |Vx <- Vx << Vy|0x800e|
|ADD Vx, byte        |Vx <- Vx + byte|0x7nnn|
|ADD Vx, Vy          |Vx <- Vx + Vy|0x8004|
|ADD I, Vx           |I <- I + Vy|0xf01e|
|SUB Vx, Vy          |Vx <- Vx - Vy|0x8005|
|SUBN Vx, Vy         |Vx <- Vy - Vx|0x8007|
|RND Vx, byte        |Vx <- rnd(byte)|0xcnnn|
|SE Vx, byte         |if (Vx == byte) pc += 2|0x3nnn|
|SE Vx, Vy           |if (Vx == Vy) pc += 2|0x5nnn|
|SNE Vx, byte        |if (Vx != byte) pc += 2|0x4nnn|
|SNE Vx, Vy          |if (Vx != Vy) pc += 2|0x9nnn|
|SKP Vx              |if (key(Vx) == 1) pc += 2|0xe09e|
|SKNP Vx             |if (key(Vx) != 1) pc += 2|0xe0a1|
|SYS addr            |pc <- addr|0x0nnn|
|JP addr             |pc <- addr|0x1nnn|
|JP V0, addr         |pc <- V0 + addr|0xbnnn|
|CALL addr           |stack <- pc, pc <- addr|0x2nnn|
|RET                 |pc <- stack|0x00EE|


#補足

命令長は、2バイト。固定。
データバスは、8bit
アドレスバスは、12bit
レジスタは、V0からVFの16個で、8bit
VFレジスタは、算術演算命令実行時のキャリーフラグ
スタックは、16個。
アドレスレジスタとして、Iレジスタで12ビット
プログラムは、アドレス0200h番地から実行
出力は、64×32ピクセルのグラフィック機能
左上が(0,0)で、右下が(63,31)。
描画はXORで行われる。
4×5ピクセルのフォントパターンを内蔵しています。（'0'-'9','A','B','C','D','E','F'）
入力は、キー、16個あります。
2つの8ビットタイマがあります。
一つはディレイタイマDT、もう一つはサウンドタイマSTです。

以上。
ReactとTSでMaterial Designのアプリのセットアップをする手順

1. アプリを作る `yarn create react-app my-app --template typescript`
1. Material UIを追加する `yarn add @material-ui/core`
1. Robotoをインストールする `yarn add fontsource-roboto`
1. index.tsxに `import 'fontsource-roboto';`を追加
1. Iconsを追加 `yarn add @material-ui/icons`
1. 使いたいアイコンをインポート`import { AccessAlarm, ThreeDRotation } from '@material-ui/icons';`
1. routerをインストール `yarn add react-router-dom && yarn add @types/react-router-dom`
Magento 1をMagento 2に移行する方法

![magento.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705866/d0f26bcc-9158-d169-391a-6a0fceefadc6.png)

移行するか、移行しないか？ Magento 2が登場して以来、この疑問は間違いなくあなたの頭に浮かびました。 Magento 2への移行は魔法のようなワンクリックプロセスではないので、迷うことはありません。
また、Magento 2は市場を征服しており、ビジネスオーナーはより多くの利益を得るために、ストアを新しいバージョンに徐々に移行しています。

それでも疑問がある場合は、[Magento development](https://whidegroup.com/blog/how-to-migrate-magento-1-to-magento-2/)の詳細と、Magento 1をMagento 2に安全に移行する方法をご覧ください。

さらに、ためらっている間、Magento 1のサポートは2020年6月に廃止されることを覚えておいてください（オープンソース1とCommerce 1の両方のエディションを指します）。この日付を過ぎると、Magento 1に新しいアップデートはありません。

Magento 1のオンラインストアにどのような影響がありますか？パフォーマンスが低下したり機能が古くなったりするだけでなく、さらに重要なことに、安全性も失われます。悪意のあるソフトウェアに攻撃される可能性が高まります。

平均的なウェブサイトの移行には最低1か月かかることを忘れないでください。ただし、ウェブサイトが重くて複雑な場合は、最大6か月間使用する必要があります。

新しいMagentoバージョンへの移行は、Magento 1.8と1.9の間の単純なアップグレードではなく、オンラインビジネスとまったく別のCMSシステムへのまったく新しいアプローチです。

Magentoの開発での経験を活かして、Magentoに関する有意義な洞察を共有する準備が整いました。
【jQuery】val(),prev(),on()

jQueryについて学習内容を備忘録としてまとめます。
#val()
html要素にval()を実行することでvalue要素を取得することができます。

```js

//html
<button id="btn" value="a">ボタン</button>

//jQueryの処理
var btn = $('#btn').val();
console.log( btn );

//実行結果
a
```
実行結果にある通り、htmlのvalue要素である`a`を表示しています。

#prev()
対象要素の直前にあるHTML要素を取得することができます。

```js

//html
<div class="test">
	<p>testtest</p>
	<a>リンク</a>
</div>
//jQueryの処理
var result = $('a').prev().text();
console.log(result);

//実行結果
testtest
```
このようにaの直前にあるtesttestが実行結果として表示されます。

#on()
さまざまなイベント処理を記述するためのメソッドになります。
たとえば、マウス操作やフォームから何か送信されることが該当になります。

```js

//html
<button>ボタン</button>
//jQueryの処理
 $('button').on('click', function() {
    
        console.log('クリックされました！');
    
    })
//実行結果
クリックされました！
```
ボタンをクリックするとjQueryが稼働してクリックされました！と表示されます。

#参考URL
https://www.sejuku.net/blog/45297
https://www.sejuku.net/blog/58952
https://www.sejuku.net/blog/38774
seaborn,pairplot日本語で出力する。

結構前にseabornでpairplotを行なった際にラベル名が日本語でなくて文字化けしてしまうことがありました。その解決法について共有できたらと思います。

##解決方法について

```python

import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
```

<strong>真ん中のコードが鍵。</strong>
　　　　　　　　　　　　　
参考させて頂いたサイト
>https://stackoverflow.com/questions/56656777/userwarning-matplotlib-is-currently-using-agg-which-is-a-non-gui-backend-so
【Elixir/Phoenix】(Mix) Could not compile dependency :cowboyでmix ecto.createできない場合

`mix ecto.create`するとこんなエラーが出る。

```
$ mix ecto.create
===> Compiling cowboy
Function: request_process/3
===> Compiling src/cowboy_stream_h.erl failed
src/cowboy_stream_h.erl:none: internal error in sys_core_dsetel;
crash reason: {case_clause,
    {'EXIT',
        {{case_clause,
             #{0 => 1,1 => 1,2 => 1,4 => 1,5 => 1,6 => 1,10 => 0,
               'Reason' => 1}},
         [{sys_core_dsetel,visit,2,[{file,"sys_core_dsetel.erl"},{line,98}]},
          {lists,mapfoldl,3,[{file,"lists.erl"},{line,1354}]},
          {lists,mapfoldl,3,[{file,"lists.erl"},{line,1355}]},
          {sys_core_dsetel,visit,2,[{file,"sys_core_dsetel.erl"},{line,188}]},
          {lists,mapfoldl,3,[{file,"lists.erl"},{line,1354}]},
          {lists,mapfoldl,3,[{file,"lists.erl"},{line,1355}]},
          {sys_core_dsetel,visit,2,[{file,"sys_core_dsetel.erl"},{line,188}]},
          {sys_core_dsetel,visit,2,
              [{file,"sys_core_dsetel.erl"},{line,144}]}]}}}

  in function  compile:'-select_passes/2-anonymous-2-'/3 (compile.erl, line 585)
  in call from compile:'-internal_comp/5-anonymous-1-'/3 (compile.erl, line 349)
  in call from compile:fold_comp/4 (compile.erl, line 376)
  in call from compile:internal_comp/5 (compile.erl, line 360)
  in call from compile:'-do_compile/2-anonymous-0-'/2 (compile.erl, line 177)
  in call from compile:'-do_compile/2-anonymous-1-'/1 (compile.erl, line 190)

** (Mix) Could not compile dependency :cowboy, "/Users/*/.mix/rebar3 bare compile --paths="/Users/*/projects/*/_build/dev/lib/*/ebin"" command failed. You can recompile this dependency with "mix deps.compile cowboy", update it with "mix deps.update cowboy" or clean it with "mix deps.clean cowboy"
```

__対応__
2点やるべきことがある。

1.`mix.exs`に`{:cowboy, "< 2.8.0", override: true}`１行を追記する。

```mix.exs
  defp deps do
    [
      {:phoenix, "~> 1.5.4"},
      {:phoenix_ecto, "~> 4.1"},
      {:ecto_sql, "~> 3.4"},
      {:postgrex, ">= 0.0.0"},
      {:phoenix_html, "~> 2.11"},
      {:phoenix_live_reload, "~> 1.2", only: :dev},
      {:phoenix_live_dashboard, "~> 0.2"},
      {:telemetry_metrics, "~> 0.4"},
      {:telemetry_poller, "~> 0.4"},
      {:gettext, "~> 0.11"},
      {:jason, "~> 1.0"},
      {:plug_cowboy, "~> 2.0"},
      {:cowboy, "< 2.8.0", override: true}
    ]
  end
```

2.OTPを22以降のバージョンにする。

例えば、[OTPを23.0にする。](https://qiita.com/freelance_engineer/items/528f5b884adcbdfa4df2)
GCP:Pub/SubからCloud Functions、Cloud Functions からPub/Sub、を繰り返す

以下今回のアーキテクチャイメージです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503434/b6926124-d536-8f97-cc4a-c5c265de9f19.png)

#用意するモノ
・Pub/SubでTopic2つ
　┗「topic_1」と「topic_2」という名前とする

・Cloud Scheduler
　┗トピックに「topic_1」を設定し、ペイロードは「hello」とする

・Cloud FunctionsでFunctionを2つ
　┗「function_1」と「function_2」という名前とする
　　「function_1」のトリガーはPub/Subの「topic_1」を設定する
　　「function_2」のトリガーはPub/Subの「topic_2」を設定する

# function_1の中身

以下の「event_message」ではtopic_1を経由したCloud Schedulerで設定したペイロード「hello」とかの文字列が格納されている。

N個のCloud Schedulerをペイロードだけ変えてほか同じ設定にすると、function_1 内で event_message を判定させて後続処理をごにょごにょできる

```.py
def main(event, context):
    event_message = base64.b64decode(event['data']).decode('utf-8')
```

次に、function_2にリストを渡すと仮定する
Pub/Subではテキストのみが渡せるのでencodeさせる必要がある

```.py
from google.cloud import pubsub_v1

PROJECT_ID = os.getenv('GCP_PROJECT')
client = pubsub_v1.PublisherClient()

topic_id = "topic_2" # 次にパスするトピックを設定

topic_path = client.topic_path(PROJECT_ID, topic_id)

pub_text = ["りんご", "ゴリラ", "ラッパ"]

data = pub_text.encode() # ここでエンコード
client.publish(topic_path, data=data) # これでtopic_2にpub_textがpushされる
```

上記の最終行でtopic_2へ'["りんご", "ゴリラ", "ラッパ"]'が渡されてfunction_2が発火している。

# function_2の中身

以下 event_message では'["りんご", "ゴリラ", "ラッパ"]'が入っているのでevalしてpythonのリストに戻す。
後続処理はよしなに

```.py
def main(event, context):
    event_message = base64.b64decode(event['data']).decode('utf-8')
    fruit_lst = eval(event_message)
```

# function_2を並列起動させてみる

Cloud Functionsは以下公式ドキュメントの通り、並列起動ができる
https://cloud.google.com/functions/quotas?hl=ja#scalability

そのためfunction_1を以下のようにループさせながらPub/Subへpublishさせると、function_2では3つのフルーツを取得することになる

```function_1.py
from google.cloud import pubsub_v1

PROJECT_ID = os.getenv('GCP_PROJECT')
client = pubsub_v1.PublisherClient()

topic_id = "topic_2"

topic_path = client.topic_path(PROJECT_ID, topic_id)

fruit_lst = ["りんご", "ゴリラ", "ラッパ"]

for fruit in fruit_lst:
    data = fruit.encode()
    client.publish(topic_path, data=data)
```

# 参考文献
https://cloud.google.com/solutions/streaming-data-from-cloud-storage-into-bigquery-using-cloud-functions?hl=ja
https://cloud.google.com/functions/quotas?hl=ja#scalability

## 余談

list や dict も encode() して Pub/Sub へ渡して受け取った側で eval すれば元通りなので、複数の軽い処理を定期的に実行する、という場合に便利でした。
pythonのルールに関して学ぶ、python学習歴８ヶ月目の私。~PART.1~

pythonの学習を初めて８ヶ月目、最初からwebスクレイピングの学習をメインにし、インデックス値の指定方法や基本的な変数、辞書、リストの型など最低限の勉強してこなかった私。機械学習や初歩的な問題に遭遇することが多くなっていると感じたため、順序がオカシイですが基礎的な部分に戻っていきます。

##pythonのルールについて

関数・変数に関して
・<strong>小文字を採用する</strong>
・<strong>予約語と衝突する場合は”_”で区切って名前を設定</strong>

##モジュールに関して
？モジュールとは
他のpythonファイルにて実行され、他のコードの場でも参照する場合それをモジュールという。
（自分で作ったpythonファイルを利用するため）
・<strong>_を指定しても良い。（これだけでも）</strong>
・よくモジュールのコードの中で

```python

if __name__ == '__main__':
```

が出現しますが、これはモジュールの実行によって誤作動が起こらないようにするためだそうです。
これに関しては、発生問題に関しても確認しながらもう一度勉強します。

>・https://gammasoft.jp/python/python-script-pattern/#sample
>・インポートされた際にプログラムが動かないようにするために、以下のように if __name__ == "__main__": というif文を書きます。
>・ですので、 if __name__ == "__main__" という if文を使うことで、「この hello.py は python hello.py のように実行された（== importされたことで動作したのではない）」と判定できます。

##パッケージに関して
・_は非推奨
・小文字の短い名前を設定する
・パッケージとはモジュールを組み合わせたもののことを言う。

>add関数が他のファイルにあってもお互いの名前空間が守られるため安全そうです！

##クラス名に関して
・頭文字は大文字で指定する。（CapWords方式を使う）

##例外に関して
・エラーの文言に対して最後に"Errorとつける"(CapWords方式を使う)

##関数やメソッドに対しての処理
>・https://djangobrothers.com/blogs/class_instance_staticmethod_classmethod_difference/

これに関しても今度考え直してまとめます。


##最後に学習してみて
大半に関しては、どうにか勉強しなくてもまかなえた部分であると感じましたが
初めて知る事も多く勉強してよかったです。
一回では理解できない部分についても考え直そうと思いました。
なぜ僕がここまで学習せずにこれたのかと言うとwebスクレイピングonlyの学習を続けてきたためです。

参考にさせて頂いたサイトに関しまして、
>https://www.sejuku.net/blog/106044
>https://blog.pyq.jp/entry/Python_kaiketsu_180207
>https://gammasoft.jp/python/python-script-pattern/#sample
>http://www.tohoho-web.com/python/module.html
【CircleCI】裏で動き続けるSSH用ジョブを終了する

## SSH接続用ジョブ
Saas型のCI/CDサービスである[CircleCI](https://circleci.com/ja/)には
実行に失敗したジョブ（コンテナ）をSSH接続可能にして再実行する便利な機能があります。
<img width="300" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191981/2f2045c4-60a3-de47-c6b2-95cd55edee07.png">

ただ、SSH接続すると2時間経つまでこのジョブは裏で動き続けるという罠があり
同時起動数の限られたプランだと他のジョブがしばらく実行されなくなります。
しかもSSH接続用ジョブはPipeLinesに表示されないため、不具合で起動しないのだと勘違いしがちです。

本記事ではこの「Rerun Job with SSH」で起動したSSH接続用のジョブを確認・終了させる方法について書きます。

### SSH用ジョブの確認
UIのバージョンアップに伴い、2020/09/01時点では通常の[PipeLines](https://circleci.com/docs/ja/2.0/pipelines/)にはSSH接続用ジョブが表示されません。
下のURLを直打ちして[Legacy Jobs View](https://support.circleci.com/hc/en-us/articles/360047731771-How-to-view-all-jobs-for-a-project)から確認してください。

- https://app.circleci.com/pipelines/{vcs}/{org}/{project}/jobs
- 例: https://app.circleci.com/pipelines/github/foo-com/bar-pj/jobs

<img width="800" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191981/9d89b171-52ca-0436-e09b-d6ec55f5a728.png">

### SSH用ジョブの手動終了
下の三つのどれかです。ここでは三番目の手順を説明します（[2020/08/13の公式記事](https://support.circleci.com/hc/en-us/articles/360047125652-How-to-see-running-SSH-jobs)）。

- SSH接続しなければ10分で自動終了
- SSH接続してしまうと2時間後で自動終了
- ひと手間かけて手動終了

1. Legacy Jobs Viewにてジョブ番号を調べる（ジョブ先頭の#のついた数字）
2. 下のURLを直打ちした先で、右上のRerunのプルダウンから「Cancel Job」を選択する

- https://app.circleci.com/pipelines/{vcs}/{org}/{project}/x/workflows/x/jobs/{job_id}
- 例：https://app.circleci.com/pipelines/github/foo-com/bar-pj/x/workflows/x/jobs/1780

<img width="800" alt="ファイル名" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191981/bbf7d532-273a-fa7d-1a30-bd07dc6a5ad7.png">
仮想ルータでネットワークを構築する

## はじめに
よくA拠点とB拠点のActiveDirectoryやOracleのデータのレプリケーションを検証する際に、複数ネットワークが欲しいシーンがあったりします。
そういうときはWindowsやLinuxで仮想ルータを作成して対応しています。

## 1. 環境
今回はRHEL7です。OSが動けばリソースはしょぼくてOKです。

## 2. 手順
まず、OSをセットアップします。ここではセットアップ時に192.168.10.254と192.168.20.254をNICに設定し、それらを各ネットワークのゲートウェイにする前提とします。

```
[root@router ~]#  ip address show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:2d:69:6c brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.254/24 brd 192.168.10.255 scope global ens192
       valid_lft forever preferred_lft forever
    inet6 fe80::b347:e70a:2921:964d/64 scope link 
       valid_lft forever preferred_lft forever
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:2d:69:76 brd ff:ff:ff:ff:ff:ff
    inet 192.168.20.254/24 brd 192.168.20.255 scope global ens224
       valid_lft forever preferred_lft forever
    inet6 fe80::9d1d:dec7:15ba:aa2/64 scope link 
       valid_lft forever preferred_lft forever
```

ルーティングの設定を有効にするため、sysctl.confに設定を追加します。

```php:sysctl.conf
[root@router ~]# cat /etc/sysctl.conf
# sysctl settings are defined through files in
# /usr/lib/sysctl.d/, /run/sysctl.d/, and /etc/sysctl.d/.
#
# Vendors settings live in /usr/lib/sysctl.d/.
# To override a whole file, create a new file with the same in
# /etc/sysctl.d/ and put new settings there. To override
# only specific settings, add a file with a lexically later
# name in /etc/sysctl.d/ and put new settings there.
#
# For more information, see sysctl.conf(5) and sysctl.d(5).
net.ipv4.ip_forward = 1 ←★追加
```

次に、firewalldの設定変更を行います。ここでは検証環境ということでサービスを停止させます。

```
[root@router ~]# systemctl status network
● network.service - LSB: Bring up/down networking
   Loaded: loaded (/etc/rc.d/init.d/network; bad; vendor preset: disabled)
   Active: active (exited) since 金 2020-07-31 14:10:46 JST; 1 months 7 days ago
     Docs: man:systemd-sysv-generator(8)
  Process: 847 ExecStart=/etc/rc.d/init.d/network start (code=exited, status=0/SUCCESS)

 7月 31 14:10:46 router systemd[1]: Starting LSB: Bring up/down networking...
 7月 31 14:10:46 router network[847]: ループバックインターフェイスを呼び込…K  ]
 7月 31 14:10:46 router network[847]: インターフェース ens192 を活性化中: …K  ]
 7月 31 14:10:46 router network[847]: インターフェース ens224 を活性化中: …K  ]
 7月 31 14:10:46 router systemd[1]: Started LSB: Bring up/down networking.
Hint: Some lines were ellipsized, use -l to show in full.

[root@router ~]# systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)
```

これで検証したいサーバのデフォルトゲートウェイに192.168.10.254や192.168.20.254を設定してあげれば通信可能になります！
keyof typeofの使い方 [TypeScript]

#やりたいこと
object等の呼び出しで `Object[key]` のようにするとき、`key` に動的な変数を入れたい。
上記をより美しく。

#問題・エラー
今回の記事では、こちらのコードを修正します。
関数`receivedStringValue()`は、ランダムでStringの値を返す関数とします。

```js

const object = {
    aaa: 'aaa',
    bbb: 'bbb',
    ccc: 'ccc',
};
// keyには動的に生成された値
const key: string = receivedStringValue();
const value = object[key];
```
こちらのコードでは、下記のエラーが出ます。

```
Element implicitly has an 'any' type because expression of type 'string' can't be used to
```
#解決策
`object` に対して型を定義する

#結論
`key` の型がわかるような `object` の型を定義する

```js
interface StringKeyObject {
    // 今回はstring
    [key: string]: any;
}
const object: StringKeyObject = {
    aaa: 'aaa',
    bbb: 'bbb',
    ccc: 'ccc',
};

// keyには動的に生成された値
const key: keyof typeof object = receivedStringValue();
const value = object[key];
```
keyの型がstringだとあいまいなので、 `keyof typeof object` でしっかりと制限をかけることがポイントです。

最後まで読んでくださって、ありがとうございます。

###参考記事

https://qiita.com/tktcorporation/items/051bb03bb4d72930d8e9
ERROR: In file ./.env: environment variable name 'THOR_SILENCE_DEPRECATION ' may not contain whitespace. への対処法

タイトルの通りですが、今回は

```ruby:.env
ERROR: In file ./.env: environment variable name 'THOR_SILENCE_DEPRECATION ' may not contain whitespace.
```

というエラーが出た際の対処法について、私の環境下でのソリューションを共有したいと思います。

私はRuby on Railsでプログラミング学習を開始して1ヶ月ほどの初学者ですので、至らない点や説明不足の点等もあるかと思います。
お気づきの点等ございましたらご指摘いただけると幸いです。

※できるだけ初学者の方にも分かりやすく説明する事を心がけているため、やや冗長に感じる部分もあるかもしれませんがご了承くださいませ。

#環境

・Ruby 2.6.5
・Rails 5.2.3
・MySQL 5.7
・Docker
・Dokcer-compose version: '3'

#まずは解決した方法から
早速ですが解決方法から述べたいと思います。

私の環境下では、ルートディレクトリ
(DockerfileやGemfile等のファイルと同じ階層)
に存在する.envファイルの記述が間違っていた事が原因でした。


```ruby:.env
#こちらがエラーが出てしまう記述
THOR_SILENCE_DEPRECATION = true


#以下の記述に修正すればエラーは解消される
THOR_SILENCE_DEPRECATION=true
```

エラーが出てしまう記述では、余計な空白が入ってしまっていますね。
空白を除去する事で、上記エラーは解消されます。

#エラーの深掘り


エラーの内容を再度見てみましょう。

```ruby:.env
ERROR: In file ./.env: environment variable name 'THOR_SILENCE_DEPRECATION ' may not contain whitespace.
```

こちらの文章をGoogle翻訳で日本語に修正してみると、


 >*エラー：ファイル./.env：環境変数名 'THOR_SILENCE_DEPRECATION'に空白が含まれていない可能性があります。*

と変換されます。

日本語としては若干分かりづらいのですが、なんとなく

「空白の関係でエラーが出ているのだな」

とアタリをつける事ができます。

エラー文本文でググってみると、完全に同じエラー文が出てきた方はいらっしゃいませんでしたが、解決にあたっては以下のブログを参考にさせていただきました。

>**Composerで.env内のスペースはクォートで囲む必要があるエラーが発生**
>https://awesome-linus.com/2019/04/07/composer-install-error-need-quotes/


エラー文でググったところ情報が少なかったため、おそらくそう頻繁に出るエラーではないのだと予測できますが、初学者の方がエラーに遭遇した際の一つのソリューションとして参考になれば幸いです。


#エラーが起きた背景を詳しく

エラーが起きた背景について、もう少し詳しく記述していきます。

このエラーは「.envファイル」の記述が間違えているのが原因なのですが、そもそも.envファイルを触った事がないという方もいらっしゃるかも知れません。

私も約1ヶ月ほどRailsを勉強してきた中で、.envファイルを触る機会というのは一度もなかったのですが、ログイン機能を実装するGem「sorcery」を導入する過程で、以下のエラーを解決するために.envファイルを触る必要が出てきました。


```
Deprecation warning: Expected string default value for '--test-framework'; got false (boolean).
This will be rejected in the future unless you explicitly pass the options `check_default_type: false` or call `allow_incompatible_default_type!` in your code
You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.
```

こちらのエラーは、

・Gemfileにsorceryを追加
・bundle install
・sorceryを使用するためのコマンド「rails g sorcery:install」を実行

という過程の中で発生したものです。


エラーの詳細については私もよく分かってはいないのですが、どうやらシェルスクリプトを生成するためのGemからエラーが出ているらしいとのこと。

このエラーを解決するための方法として、.envファイルに

```ruby:.env
#正しい記述
THOR_SILENCE_DEPRECATION=true
```

の記述を追加する必要があり、
誤って以下のコードを記述。

```ruby:.env
#不要な空白があるためエラーが出る記述
THOR_SILENCE_DEPRECATION = true
```

そして、rails g controller ~~
を実行しようとしたところ、タイトルのエラーが発生したという経緯です。

ちなみに、「Deprecation warning〜〜〜」のエラーに関しては、以下の記事


>**[Ruby on Rails]環境変数の設定方法(.bash_profile、Dotenv-rails)**
>https://qiita.com/yuichir43705457/items/7cfcae6546876086b849

>**RSpecを導入する**
>https://qiita.com/d0ne1s/items/1ecd114b33e80058215f

を参考に解決する事ができました。
ありがとうございました。

#おしまい

以上が、今回のエラーの解決方法と周辺情報です。
あまり情報が多くないエラーでしたので、もし遭遇して困っている方は参考にしていただけると幸いです。
また、説明が分かりづらい点等があれば、ご指摘いただければと思います。

それでは、最後までお付き合いいただきありがとうございました。
TypeScriptでMapクラスやSetクラスを型拡張してfreeze()できるようにする

TypeScriptで、JavaScript組み込みのMapクラスやSetクラスのインスタンスの要素を後から変更できないようにし、意図しないバグを仕込んでしまうのを防ぎたい人のためのハックです。

[Immutable.js](https://github.com/immutable-js/immutable-js)を使ってもよいのですが、名前が被っていたり、大げさだったりするので、カジュアルに`set()`, `delete()`, `clear()`が呼び出された時に例外が飛ぶようにします。

prototypeの汚染しますが、節度を持って利用することで、コードの質を高められると信じています。

```Map.extension.ts
export {};

declare global {
  interface Map<K, V> {
    freeze(): Map<K, V>;
  }
}

const disabledOperation = (): never => {
  throw new Error('disabled operation');
};

Map.prototype.freeze = function <K, V>(this: Map<K, V>): Map<K, V> {
  this.set = disabledOperation;
  this.delete = disabledOperation;
  this.clear = disabledOperation;
  return this;
};
```

このようなコードを用意して、使うとこんな感じになります。

```ts
const fruits = new Map<string, string>();
fruits.set('apple', '林檎');
fruits.set('orange', 'オレンジ');
fruits.freeze();

fruits.set('banana', 'バナナ'); // 例外が飛ぶ
```
エイリアス (alias)でEmacsのパス通す

自分用メモです。
なのであまり参考になりません。
#やりたいこと

ターミナルzshからEmacsを起動したい。
#手順

1. 起動したいファイルのパスを探す
1. zshrcにエイリアスを記載する
1. zprofileで読み込み設定



#１.起動したいファイルのパスを探す

パスとは、ファイルやフォルダの場所を示す
**/usr/local/bin**
こんなやつ

finderで探す、
**/Applications/Emacs.app/Contents/MacOS/Emacs**
ターミナルでこれをだけ記載して起動したらそれで合ってる。

#2.zshrcにエイリアスを記載する。
エイリアスとは、
Linuxコマンドを組み合わせて自分で作れるやつ。

  ```zsh
  $ alias 登録名='登録するコマンド'
  ```
で作れる。
ターミナルにそのまま打ち込んでも使えるようになるけど、一回消したら消えて忘れるから。
.zshrcに書き込む。

```zsh
$vim ~/.zshrc
``` 
で開いて

```
alias em='/Applications/Emacs.app/Contents/MacOS/Emacs
'
```
を記載

```zsh

$source ~/.zshrc 
```

でなんかようわからんけどファイル変更したから反映させるコマンド

#3.zprofileで読み込み設定

エイリアスは.zshrcに書いただけでは設定が反映されません。

なので設定を反映させるために、.zprofileに.zshrcを読んでもらう必要があります。

.zprofileは ターミナルが起動すると読み込まれる ものなので、そのタイミングで.zshrcも読んでもらう。


```
$vim ~/.zprofile
```
で開き

```
source ~/.zshrc 
```
をファイルに記載

#まとめ
エイリアスは自分の好きなコマンドを登録して呼び出せる機能、
それを設定するのがzshrcファイルで、それをターミナル起動時に読み込んでくれるように設定するのがzprofile。


パクった記事
https://qiita.com/yutat93/items/b5bb9c0366f21bcbea62

https://qiita.com/tewi_r/items/04215f7d7835a74d3d43
Prism コードサンプル学習：02-Regions

# Prism コードサンプル学習：02-Regions

## はじめに

以下の記事の続きです。
<https://qiita.com/mngreen/items/49767e120292896d3937>

## 02-Regions

本サンプルではRegionManagerクラスを用いて、領域に名称を与えるサンプルのようです。

```xml
<Window x:Class="Regions.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:prism="http://prismlibrary.com/"
        Title="Shell" Height="350" Width="525">
    <Grid>
        <ContentControl prism:RegionManager.RegionName="ContentRegion" />
    </Grid>
</Window>
```

```csharp
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : PrismApplication
    {
        protected override Window CreateShell()
        {
            return Container.Resolve<MainWindow>();
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
        }
    }
```

ポイントとしては以下でしょうか。

- 前回はBootstrappprを利用していたが、そのBootstrapperを隠蔽するPrismApplicationクラスが利用されている
  - PrismApplicationの基底クラスは[こちら](https://github.com/PrismLibrary/Prism/blob/master/src/Wpf/Prism.Wpf/PrismApplicationBase.cs)
- MainWindowでは、ContentControlコントロールに添付プロパティであるRegionManager.RegionNameプロパティに"ContentRegion"がセットされている
  - RegionManagerは[こちら](https://github.com/PrismLibrary/Prism/blob/master/src/Wpf/Prism.Wpf/Regions/RegionManager.cs)
- 名前が設定されると、その領域を指定して画面遷移させられることができる
  - 一番シンプルに使える[RequestNavigate()メソッド](https://github.com/PrismLibrary/Prism/blob/master/src/Wpf/Prism.Wpf/Regions/RegionManager.cs#L365)
  - 引数で指定したregionNameにURIで指定したコンテンツが表示されるよう
  - [Qiitaの記事](https://qiita.com/tera1707/items/86901d7c6bba5d6d3c7d)も参照

## おわりに

今回はRegionManagerクラスのソースコードを読み、領域に名前を付ける方法が分かりました。
所感ですが、領域にRegionManagerを経由させて名前を定義し、コンテンツを色々登録しておけば後からビューをどんどん追加することもできそうです。
次回、03-CustomRegionsについて見ていこうと思います。
Tableauで利用できるフィルタの適用順序とその役割

# TL;DR
![filtering.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/566f3fb6-a392-14e6-7dbb-9c0562966a62.jpeg)
※矢印は実行される優先順位です


# 背景
Tableau Desktop Associate Certificated の勉強を進めていくうちに、Tableauには6種類のフィルタがあることがわかりました。

しかし、これらのフィルタがどのような目的をもって利用されるかわからなかったので、自分なりに簡易的にまとめてみました。

# 6つのフィルタについて

Tableauには以下の6つのフィルタが存在します。

1. データ抽出フィルタ
2. データソースフィルタ
3. コンテキストフィルタ
4. ディメンションフィルタ
5. メジャーフィルタ
6. 表計算フィルタ

## 1. データ抽出フィルタについて

![スクリーンショット 2020-09-08 17.45.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/d7a75c7b-fc43-7119-c914-5a077298a5d4.png)


優先度が一番高いこのフィルタは、主にデータソース(csvファイルやデータベースのデータ)をTableauに取り込んだ後に処理を行うフィルタになります。

データ抽出フィルタでかけたデータは、その後のグラフ作成時のフィールド全体に影響するため、**シートにデータを読み込む前にフィルタをしておくことでパフォーマンスを向上させる**ことができます。

またここで前処理したデータは、Tableau Serverに抽出データ(.hyper形式)として保存することもできます。

## 2. データソースフィルタ

![スクリーンショット 2020-09-08 17.46.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/f43fe648-37b8-6a42-ce65-24747fd84a6c.png)

データ抽出フィルタとの違いは、フィルタをかけてしまう前の**実験用途**として利用ができるということです。なので、Tableau上で利用するデータには影響がありません。

役割としてはデータ抽出フィルタ前の試行錯誤的な意味合いがあるわけです。

## 3. コンテキストフィルタ
![contextfilter_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/d27f755a-bb7d-78b3-f805-4536d7e562b9.gif)
(公式ヘルプより引用: [コンテキスト フィルターでビューのパフォーマンスを改善する](https://help.tableau.com/current/pro/desktop/ja-jp/filtering_context.htm))

コンテキストフィルタとは、グラフを作成する際に、利用するデータを該当するフィルタに通るものだけに制限するためのフィルタになります。

主にワークシート上で利用するデータのサイズを小さくするために利用されます。

## 4. 5. ディメンション & メジャー フィルタ

![filtering-drag.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/c19851dc-edb0-0338-8f69-d18999898453.gif)
(公式ヘルプより引用: [ビューからのデータのフィルター](https://help.tableau.com/current/pro/desktop/ja-jp/filtering.htm))

これはTableau上におけるフィールドそれぞれに対するフィルタになります。このフィルタを操作する際にはフィルターシェルフへフィールドをドラッグすることで適用できます。

## 6. 表計算フィルタ

![table_calc_filter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/1d63ad48-01ee-3cfc-4fe9-08d62f3ef285.png)

作成したグラフに対して、インタラクティブにフィルタかけることができます。
値の表示・非表示、グラフ範囲の制限などに用いられます。

# まとめ

![filtering.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/566f3fb6-a392-14e6-7dbb-9c0562966a62.jpeg)

#### データ抽出フィルタ
データをグラフで可視化する前にデータ量を削減するためのフィルタ
#### データソースフィルタ
データ抽出フィルタの前に安全に試行錯誤をするためのフィルタ
#### コンテキストフィルタ
利用することが予め決まっている場合に、利用するデータを該当するフィルタに通るものだけに制限するためのフィルタ
#### ディメンションフィルタ
ディメンションフィールドに対してかけることができるフィルタ
#### メジャーフィルタ
メジャーフィールドに対してかけることができるフィルタ
#### 表計算フィルタ
作成したグラフに対して値やグラフを調整するためにかけることができるフィルタ

# 参考リンク
- [データ ソースからデータをフィルターする](https://help.tableau.com/current/pro/desktop/ja-jp/filtering_datasource.htm)
- [コンテキスト フィルターでビューのパフォーマンスを改善する](https://help.tableau.com/current/pro/desktop/ja-jp/filtering_context.htm)
- [ビューからのデータフィルター](https://help.tableau.com/current/pro/desktop/ja-jp/filtering.htm)
- [データを慎重にフィルターする](https://help.tableau.com/current/pro/desktop/ja-jp/perf_filter.htm)
vagrant環境でvsftpdを使ってテスト用FTP/FTPSサーバーを構築する

現場でFTP関連の開発を行った際に、ローカル環境(vagrant)でFTPのアップロード・ダウンロードのテストを行いたかったため、テスト用のFTPサーバーを構築しました。

ftp専用のユーザーを作成しログインできるようにしたかったが、ftpのログイン時のパスワードで530エラーになってしまい、原因がわからず、仕方なくvagrantユーザーをそのまま使うことに（ローカル環境でテストできればいいので今回は良しとする。。）

## FTPサーバーの構築

### vsftpdのインストール

```bash
$ vagrant ssh

$ sudo yum -y install vsftpd
```

### vsftpd.confの設定

```bash
# 下記に設定ファイルがある
$ ls /etc/vsftpd

$ cd /etc/vsftpd
$ cp vsftpd.conf vsftpd.conf.bk #念の為バックアップを取っておく

$ sudo vi /etc/vsftpd/vsftpd.conf
```

下記で設定。

```bash:/etc/vsftpd/vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
connect_from_port_20=YES
xferlog_std_format=YES
ascii_upload_enable=YES
ascii_download_enable=YES
listen=YES

pam_service_name=vsftpd
tcp_wrappers=YES

# passiveモードで使いたいので
pasv_enable=YES
pasv_min_port=10000
pasv_max_port=10100

# 特定のユーザーだけログインできるように
user_config_dir=/etc/vsftpd/vsftpd_user_conf
userlist_enable=YES
userlist_deny=NO

# 特定のユーザーにchrootを設定する
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_list
```

**vsftpd_user_confの設定**

```bash
$ cd /etc/vsftpd
$ sudo mkdir vsftpd_user_conf

$ sudo vi vsftpd_user_conf/vagrant
```

```bash:/etc/vsftpd/vsftpd_user_conf/vagrant
local_root=/home/vagrant #追加
```

**user_listの設定**

```bash
$ cd /etc/vsftpd

$ sudo vi user_list
```

```bash:/etc/vsftpd/user_list
vagrant #追加
```

**chroot_listの設定**

```bash
$ cd /etc/vsftpd

$ sudo vi chroot_list
```

```bash:/etc/vsftpd/chroot_list
vagrant #追加
```


### vsftpdの起動

```bash
$ sudo service start vsftpd  #起動
```

停止、再起動する場合は下記。

```bash
$ service stop vsftpd  #停止
$ service restart vsftpd  #再起動
```

### FTPで接続できるかテスト

FTPコマンドが入ってなかったのでインストール。

```bash
$ sudo yum -y install ftp
```

接続できるか確認してみる。

```bash
$ ftp localhost
Trying ::1...
ftp: connect to address ::1Connection refused
Trying 127.0.0.1...
Connected to localhost (127.0.0.1).
220 (vsFTPd 2.2.2)
Name (localhost:vagrant): vagrant
331 Please specify the password.
Password:
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp>
```
接続できました。

## FTPSサーバーの構築

FTPSのテストを行いたい場合。

こちらの解説がわかりやすかったです。
http://ossfan.net/setup/vsftpd-02.html

### vsftpdの再起動

```
$ sudo service vsftpd restart
```

### FTPSで接続できるかテスト

再起動後、先ほどのFTPコマンドでログインしようとすると、`530 Non-anonymous sessions must use encryption.`でエラーになるはずです。FTPSで接続するためにlftpコマンドを使います。

**lftpコマンドのインストール**

```
$ sudo yum -y install lftp
```
接続のテスト。

```
$ lftp vagrant@localhost
Password:
lftp vagrant@localhost:~>
```
接続できました。
[競プロ] nCrの(mod 素数)を計算したい

競プロをしていたらよく、<b>nCrを1000000007で割った余り</b>を求めたいことがあると思う。
これの求め方を自分の復習がてら説明する。
以下、一般に M で割った余り、すなわちmod M について書く。
<h2>前提知識</h2>
この記事でも軽く説明するが、高校数学で習う nCrの意味とmodについての知識があると良い。

まず、nCrは<b>「n個の中からr個選ぶ時の選び方の総数」</b>である。

数式にすると,

```math
{}_nC_r=\frac{n!}{r!(n−r)!}
```
である。
これをコードで表すために軽く式変形すると

```math
{}_nC_r=\frac{n!}{r!(n−r)!}=\frac{n(n-1)(n-2) …(n-r-1)}{1・2・3・…(r-1)r}
```
のようになる。

ここまでをC++で書くと、分母をy,分子をxとして

```cpp
for (int i = 0; i < r; i++) {
	x = x * (n - i)  ;
	y = y * (i + 1);
}
```
```math
{}_nC_r=\frac{x}{y}
```
の用になる。
これをMODで取ってやりたいのだが、MODの性質として足し算、引き算、掛け算は同じMOD同士のもので演算して良いのだが、割り算はとある条件の時以外してはいけないという物がある。

つまり,

```cpp
for (int i = 0; i < r; i++) {
	x = x * (n - i)%M;
	y = y * (i + 1)%M;
}
```
のように分母分子をmod Mで取った後に x/yを計算してはだめなのだ。

ここで

一般に、yで割るというのは 1/yをかける　と言い換えられるのはいいだろうか。
ここでy * (1/y)=1である。
これをmodの世界でも適用してあげると yで割るという演算の代わりに、

y * y'=1 (mod M)

となるような y'を見つけてあげてかければよいのである。

ここで、<b>†フェルマーの小定理†</b>という小難しい名前の定理がある。
定理の主張自体は全く難しいものではなく、


pを素数、aを pの倍数でない任意の整数としたとき、

```math
a^{p−1} ≡ 1 \  (mod\ p)
```
が成立するというものだ。

ここでpをMに、aをyに置き換えて、少しだけ式変形をすると

```math
y*y^{M−2} ≡ 1 \  (mod\ M)
```

となり、上記のy'が y^(M-2)に相当することがわかる。

ゆえに求めたいものは

```cpp
for (int i = 0; i < r; i++) {
	x = x * (n - i)%M;
	y = y * (i + 1)%M;
}

// ans=( x * pow(y,M-2) )% M
```

となる。なお、 pow(a,b)はa^bを表す
以上が本質部分であり、今回の主題であったが、実装に置いては細かいことが残っている。
それはC++の標準のpow()だと遅い上に、計算過程でオーバーフローしてしまうことである。
ゆえに逐次modを取りながらべき乗の計算をしなければならない。
ここでは詳しく語らないが、pow()高速化をするのに繰り返し二乗法というアルゴリズムがある。
n乗の計算を、標準のアルゴリズムでは o(n) かかるのに対し、 o(log n)　で計算するものである。

以上のものを使って書いたコードが以下だ。

```cpp
//繰り返し二乗法
long long pow_mod(long long x, long long n) {
	long long ret = 1;
	while (n > 0) {
		if (n & 1) ret = ret * x % MOD;  // n の最下位bitが1ならば(nが奇数ならば) x^(2^i) をかける
		x = x * x % MOD;
		n >>= 1;  // n を1bit 左にずらす
	}
	return ret;
}


long long nCr_mod(long long n, long long r) {
	long long x = 1, y = 1;

	for (int i = 0; i < r; i++) {
		x = x * (n - i) % MOD ;
		y = y * (i + 1) % MOD;
	}

	return x * pow_mod(y, MOD - 2) % MOD;
}
```
css animationでいい感じに重力を再現する

```sass
// PC
.pop-float-button{
    animation: pop-animation 1.4s;
    animation-delay: 1s;
    animation-timing-function: ease-in;
}
@keyframes pop-animation {
    0%,100% {bottom: 100px;}
    30% {bottom: 115px; }
    50% {bottom: 100px; }
    80% {bottom: 108px; }
}

// SP
.float-button-sp{
    animation: pop-animation-sp 1.4s;
}
@keyframes pop-animation-sp {
    0%,100% {bottom: 30px;}
    30% {bottom: 40px; }
    50% {bottom: 30px; }
    78% {bottom: 35px; }
}
```
Spring Securityで独自の認証項目を追加する

## 概要
Spring Bootで認証を実装しようとする際に、Spring Securityを使うこともあると思います。
Spring Securityではログイン時に項目を設定すれば自動で認証する仕組みがあるのですが、基本的にはユーザ名とパスワードのセットで認証を行います。それ以外に認証用の項目を追加したい場合はどうすればいいのか、書いてみます。

## 前提など
* 実装する際のベースとなる設定等は[Spring Security with Spring Boot 2.0で簡単なRest APIを実装する](https://qiita.com/rubytomato@github/items/6c6318c948398fa62275)の内容を前提とします。SpringSecurityの設定全般について、分かりやすく解説されている記事です。
* 上記の記事ではユーザの取得に`UserDetailsService`を使用しているので、これを活かして追加で実装する形にします。今回は`DaoAuthenticationProvider`を使用する方法で実装します。[Check extra parameters with Spring Security](https://stackoverflow.com/questions/27658030/check-extra-parameters-with-spring-security)の記事を参考にしています。

## 実装サンプル
SecurityConfigに、authenticationProviderを追加します。authenticationProviderは後述の独自に実装した`AuthenticationProviderImpl`を設定します。
また、configureGlobalにてauthenticationProviderを設定します。

```SecurityConfig.java
  @Autowired
  private AuthenticationProviderImpl authenticationProvider;
  
  @Autowired
  public void configureGlobal(
    AuthenticationManagerBuilder auth,
    @Qualifier("userService") UserDetailsService userDetailsService,
    PasswordEncoder passwordEncoder) throws Exception {

    authenticationProvider.setUserDetailsService(userDetailsService);
    authenticationProvider.setPasswordEncoder(passwordEncoder);
    auth.eraseCredentials(true)
      .authenticationProvider(authenticationProvider);
  }

```

独自で実装するauthenticationProvider。テーブルにstatus列を追加して、`active`ではないユーザは認証NGとしています。

```AuthenticationProviderImpl.java
@Component
public class AuthenticationProviderImpl extends DaoAuthenticationProvider {
  @Override
  protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    super.additionalAuthenticationChecks(userDetails, authentication);
    User user = (User) userDetails;

    // 追加の条件
    if (!user.getStatus().equals("active")) {
      throw new AccountStatusNotActiveException("Status is not active");
    }
  }

  public static class AccountStatusNotActiveException extends AuthenticationException {
    public AccountStatusNotActiveException(String message) {
      super(message);
    }
  }

  @Override
  protected void doAfterPropertiesSet() {}
}
```

## その他参考
* [Spring Security認証周りについて](https://qiita.com/nannou/items/2363b37516f6228a4b9d)
* [Spring Security:データベース支援UserDetailsS​​erviceによる認証](https://www.codeflow.site/ja/article/spring-security-authentication-with-a-database)
* [Spring Bootで独自の認証を組み込む](https://m-shige1979.hatenablog.com/entry/2017/01/18/080000)
* [Spring Securityで独自の認証を実装する](https://fueiseix.hatenablog.com/entry/2018/03/11/191200)
Git ブランチ名を間違えた

##ブランチ名を間違えた##
**ローカルブランチ名の変更**

```
・ git branch -m {正しいブランチ名}
```
**リモートブランチの削除**

```
・ git push origin :{削除するブランチ名}
```
**リモートへブランチを送る**

```

・ git puah origin {変更したローカルブランチ名}
```
JSON でdiff をとった

# JSON matcher を使って rspec を書いてたけど JSON の要素が多くてどこが違うかわからなかった

```ruby:a.rb
#!/usr/bin/env ruby

def main
  ARGF.each do |line|
    line.match(/expected (.*) to be JSON matching (.*)/) do |m|
      e, r = m[1, 2]
      r.gsub!(/(At=>)([^"](?:[^,]+|,[^ ]|, [^:])+)(, :)/) do
        "#{$1}\"#{$2}\"#{$3}"
      end
      r.gsub!(/(\(an instance of String\))/, "\"\\1\"")
      r = eval(r)
      puts e
      puts r.to_json
    end
  end
end

main
```

```shell-session
$ rspec aaa_spec.rb:xxx >! out
$ ./a.rb out | jq -s '.[0]' >! b
$ ./a.rb out | jq -s '.[1]' >! c
$ vimdiff b c
```

みたいに書いてみたけど，結局見つけたのは部分部分ケズってみて原因を特定したりした．

記事を書いて供養しておこう．

## 追記

結局こうなった

```shell-session
$ perl -lne 'm/^\s+[+-]/ and do { s/^\s+-/e = {/; s/^\s+\+/r = {/; s/,$/}/; s/(At=>)([^"][^,]+)(, :)/\1"\2"\3/g; s/(=>)(\([^)]+\))(,)/\1"\2"\3/g; s/\(contain exactly /[/g and do { s/([}\]"\d])\)/\1]/g; s/ and /, /g;}; print};BEGIN{print"#!/usr/bin/env ruby\nrequire '"'"'json'"'"'\n"}END{print "puts e.to_json\nputs r.to_json"}'
```
Git コミットメッセージを間違えた

## commitメッセージ間違えた
※間違えたローカルブランチにいること

***「直前の場合」***

```
・git commit --amend -m "正しいメッセージ"
```

***「昔の場合」***

```
・git log --oneline
```

**上のコマンドで最新のコミットを１として修正したいコミットの番号を知る**

```
・git rebase -i HEAD~{x} //{x}は修正したいコミットの番号
・修正したいコミットの先頭{pick}を{edit}に変更して:wq
・git commit --amend -m "正しいメッセージ"
・git rebase --continue
・git push -f origin {リモートブランチ名}
```
git リモートから作成済のブランチをローカルに持ってくる

## リモートから作成済のブランチをローカルに持ってくる
※マスターブランチにいること

```
・git fetch
・git checkout -b {リモートから持ってきたいブランチ名} origin/{リモートから持ってきたいブランチ名}
```
git プルリクしたあと不要なコミットを削除したい

## プルリクしたあと、不要なコミットを削除したい
※必ず実行したいブランチにいることを確認する
***「方法１」履歴が残らない***

```
・git reset --hard HEAD^
・コードを修正する
・git add　と　git commit をする
・git push -f origin {リモートブランチ名}
```

***「方法２」履歴が残る***

```
・git revert {コミットID}
・コードを修正する
・git add　と　git commit をする
・git push -f origin {リモートブランチ名}
```