OmniAICreator/Qiita-1.07M huggingface dataset:
#Rails の ActiveRecord で optional: true は validates_presence_of を無効化するのと同じ挙動っぽい

# Class

```rb
class User < ApplicationRecord
  has_many :books
end
```

```rb
class Book < ApplicationRecord
  belongs_to :user
end
```

# 挙動

- Rails 5からのデフォルト挙動 では、user_id を持たない book は作成できない
- optional: true を指定すると、 user_id を持たない book を作成できる
- 外部キー制約を持たない場合や `foreign_key: { on_delete: :nullify }` の制約をつけている場合、どちらの指定でも user を削除できる

っぽい。

ちょっと分かりづらい。

# その理由は

Rails的に assciation の validation が実行されるのは、その class のレコードの操作時だからかなと思った。

たとえば user が削除されたときは book の制約が走るわけではないから、的な。

# 親クラスの指定

- `dependent: :destroy`
- `dependent: :delete_all`
- `dependent: :nullify`

で挙動を制御したら良いかな。

```rb
class User < ApplicationRecord
  has_many :books, dependent: :nullify
end
```

[Active Record Associations — Ruby on Rails Guides](https://guides.rubyonrails.org/association_basics.html#options-for-has-one)

# 本当に？

まだまだ奥深いRailsの森の奥深く。

# 参考

[optional: trueってなに - Qiita](https://qiita.com/ryoryomaru/items/7e401f9600fb11c20215)

[Rails5からbelongs_to関連はデフォルトでrequired: trueになる - Qiita](https://qiita.com/iguchi1124/items/218e35a145f372062ea4)

[ActiveRecord::Associations::ClassMethods](https://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-belongs_to)

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2708








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
bxスライダーの初期設定

必要なスクリプトとCSSは以下のサイトからDL
https://bxslider.com/

```html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title> bxslider </title>
<!-- DLしたcssファイルのパス -->
<link rel="stylesheet" href="assets/bxslider/dist/jquery.bxslider.css">
<!-- グーグルからライブラリを取得 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<!-- DLしたjsファイルのパス -->
<script src="assets/bxslider/dist/jquery.bxslider.min.js"></script>
</head>

<body>

<!-- スライダーの要素  -->
<div class="slider">
  <div>SLIDE.NO1</div>
  <div>SLIDE.NO2</div>
  <div>SLIDE.NO3</div>
  <div>SLIDE.NO4</div>
  <div>SLIDE.NO5</div>
  <div>SLIDE.NO6</div>
</div>

<!-- スライダーのスクリプト始動 -->
<script>
  $(document).ready(function(){
    $('.slider').bxSlider({
     auto: true,
     pause: 2000,
    speed: 500,
    //一度に表示させる最大枚数
    maxSlides: 1,
    //タッチスワイプ許可設定
    touchEnabled: true,
    //タッチスワイプしたとみなす最低限の移動距離
    swipeThreshold: 10,
    //'full'はスライダーの数を黒点で、'short'はa/nで表示
    pagerType: 'full',
    // 画像の高さを自動調整
    adaptiveHeight: true,
    //その他のオプションは※URL参照
	    
</script>
</body>
</html>

```
※[bxSliderオプション一覧](http://cly7796.net/wp/javascript/plugin-jquery-bxslider/)
【Java初歩】アクセス修飾子とgetter/setter、static、finalについて

Java初心者用の学習めもです。
アクセス制御とgetter/setter、static修飾子、final修飾子について記載しています。

#アクセス修飾子
Javaではフィールドやメソッドに対して、アクセス制御が設定できる。
フィールドやメソッドを宣言する際に、先頭に以下の修飾子を指定する。

###アクセス修飾子一覧
- private　：自分自身のクラスのみアクセスを許可
- packege private(※)　：自分と同じパッケージに属するクラスのみ許可
- protected　：自分と同じパッケージに属するor自分を継承した子クラスに許可
- public　：全てのクラスにアクセスを許可

###POINT
・packege privateは何も書かないで指定される
・フィールドは基本privateを設定し、メソッドは基本publicとする

#getterとsetter

外部からprivateのフィールドにアクセスしたい場合などに、getter/setterを使用する。
以下のように設定することで、getメソッドとsetメソッドを準備できる。

```java
class User {
  private String name;
  private int score;

  public User(String name, int score) {
    this.name = name;
    this.score = score;
  }

  public int getScore() { // getter
    return this.score;
  }

  public void setScore(int score) { // setter
    if (score > 0) { //0以上の数値をセットする
      this.score = score;
    }
  }

}
```
###POINT
・Testクラスのnameフィールドを読み取りたいときはgetName()メソッドを使用する
・Testクラスのnameフィールドの値を変えて使用したいときはsetName()メソッドを使用する
・setter内部に引数の妥当性チェック処理を記載することもできる

privateフィールド変数にアクセスしたい場合は、以下のように記述する。

```java
public class Main {

  public static void main(String[] args) {
    User tom = new User("tom", 50);　//Userクラスをインスタンス化
    tom.setScore(90);　//setterで設定
    System.out.println(tom.getScore()); //getterで取得
  }
}

```

#static修飾子
static修飾子は、メンバー変数・メソッドに指定することができる。
###POINT
・static修飾子を付けるとインスタンス化しなくてもクラスから使えるでメンバ（メソッドとフィールド）を定義できる
・staticメソッドを「クラスメソッド」、staticフィールドを
「クラス変数」と呼ぶ
⇀static修飾子がついていないものは、「インスタンスメソッド」、「インスタンス変数」と呼ぶ
・コンストラクタは、インスタンス化のときに自動で呼ばれる処理なので、インスタンス化しないtaticでは使えない
・イニシャライザは、クラスのロード時に自動で呼ばれる処理なので、staticで定義できる

```Main.java

// static

class User {
  private String name; 
  private static int count = 0; // クラス変数

  public User(String name) {
    this.name = name;
    User.count++;
  }
  
  static{
      System.out.println("イニシャライザ"); //イニシャライザ
      
  }

  public static void getInfo() { // クラスメソッド
    System.out.println("インスタンス化: " + User.count);
  }

}

//Main
public class Main{
  public static void main(String[] args) {
    User.getInfo(); // 0
    User tom = new User("tom");
    User.getInfo(); // 1
    User bob = new User("bob");
    User.getInfo(); // 2
  }

}
```

#final修飾子
final修飾子はクラス、メソッド、変数の宣言時に付与できる。
###POINT
・final修飾子をクラス、メソッド、フィールドに付けると変更ができなくなる
・変更不可のため、クラスの継承やメソッドのオーバーライドができなくなる
・フィールドの場合は、変更不可の「定数」として扱う
・定数を定義する際は以下のように書く

```java

//＜アクセス修飾子＞ static final 型名 定数名 = 値; 

public class Main {
    //定数
    static final int INT = 123;
    static final char CHAR = 'ABC';

    public static void main(String[] args) {
        System.out.println(INT);
        System.out.println(CHAR);
    }
}
```



ここまで。
PhpStormでGitをCloneして、SFTPアップロードできるようにする手順


## 実施環境

PhpStorm　11.0.3

## Git のリポジトリを clone する

<img width="779" alt="スクリーンショット 2019-11-05 10.29.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184849/433a292b-6db3-06cf-906a-e20230d00cd0.png">

## 基本設定

- メニューバー PhpStorm > 環境設定.... > デプロイ > + でサーバーを登録する
![スクリーンショット 2019-11-05 10.34.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184849/0021b874-172f-3b18-39b2-a535be26b892.png)

![スクリーンショット 2019-11-05 11.08.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184849/6645d019-f06b-0345-5ef3-ceab17ca0964.png)


- デプロイ > オプションから自動アップロードを「常時」に変更し、適用させる

![スクリーンショット 2019-11-05 11.08.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184849/a050554a-c85d-35b3-bdd6-97fc1ad1c684.png)

- 以上の設定で、ファイルが変更される度に常時サーバーと連携されるようになる

## 常時デプロイ以外の方法

- ファイルを右クリックして、デプロイを選択
- 現在の連携状態を確認する場合、PHPStorm ツール > デプロイ > リモート・ホストの参照　から確認できる
![スクリーンショット 2019-11-11 13.48.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184849/f256c4b4-92f8-19ee-071b-08b59ad15d46.png)


参考
https://qiita.com/J_Sugar__/items/fbce8a9b15bc74f3ce0c
MacにDockerでGolang環境を作ってみる - vol.３ ポートフォワーディング

vol.２に引き続き、以下の記事を参考にさせていただきました。
https://qiita.com/yonaimineakio/items/0990648bbce64de7edfa
いつもお世話になっております。。。
前回と同じく、並行して見ていただければ幸いです。



早速、ポートフォワーディングのお話。
前回、Dockerを起動して、単純に「　http://localhost:8080　」ってやっても
動きませんよー、ってところでした。

なんで動かなかったのか。それは以下の通り。
<img width="705" alt="スクリーンショット 2019-11-11 14.31.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/2ca29f92-0b8d-d380-f65a-559e587de173.png">
そう。Dockerにアクセスしていた訳ではなかったのですよ。
（そりゃそうだ）

で、コマンド１行打つことで、これが解消できる訳です。

ーーちなみに、元記事にも書いてますが、これする前に、
対象のdockerは落としておいてください。

Dockerの停止は元記事のコマンドでもいけますが、下でもいけます。

```ruby:shell
   $docker container stop [コンテナID]
```
※コンテナーIDは以下のコマンドでも確認可能です。

```ruby:shell
   $docker container ls
```

・・・と、話がそれましたが、本題です。
LocalのポートとDockerのポートの紐付けは以下のコマンドで行います。

```ruby:shell
   $docker container run -d -p [Local側のポート]:[Docker側のポート] [イメージ名][:タグ名]
   ex) $docker container run -d -p 9000:8080 example/docker:tag
```

[-p]コマンドでポートの紐付けをして起動させてるのですね。
イメージはこんな感じ。
<img width="716" alt="スクリーンショット 2019-11-11 14.31.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/525955/ce6ccf89-c2e8-d9a2-0b17-95acc7f7c822.png">

ポートフォワーディング、これで意味がわかりました！！

これで、最終的に「http://localhost:9000」でアクセスしたら
ちゃんとコマンドラインに表示されました。

めでたしめでたし。
FlutterでiOSをTestFlightにアップロードすると、 `ITMS-90338: Non-public API usage ` のエラーとなる問題

件名の通り
TstFlightにアップすると、下記のようなエラーメールが飛んできた

```
ITMS-90338: Non-public API usage - The app references non-public symbols in Frameworks/Flutter.framework/Flutter: _ptrace. If method names in your source code match the private Apple APIs listed above, altering your method names will help prevent this app from being flagged in future submissions. In addition, note that one or more of the above APIs may be located in a static library that was included with your app. If so, they must be removed. For further information, visit the Technical Support Information at http://developer.apple.com/support/technical/
```
原因は debugビルドをアップロードしてしまっているためなようで、

`flutter build ios --release`

アップロード前に、上記コマンドを実行したところ解決した
Ruby on Rails のMVCモデル

#MVCモデル
　この記事では、Ruby on Railsを用いたアプリケーション開発のアーキテクチャパターンである、MVCモデルについて説明する。
　自分が作成したRailsアプリのアプリ構造において、appディレクトリ下にはmodels,views,controllersという3つのサブディレクトリがあり、これらがMVCモデルの中心的要素となる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486493/81cd391c-e617-6efe-7632-e587cda086ac.png)

上図はMVCモデルの概念図であり、models,views,controllersそれぞれの役割は、
**View**:HTMLファイルを生成
**Controller**:ブラウザからwebサーバに渡されたリクエストをルーティングに基づいて処理し、静的なコンテンツの場合はViewを通してすぐにブラウザにHTMlを表示し、動的なコンテンツの際は、データベースとの通信を担当しているRubyのオブジェクトであるモデルを介してリクエストに基づくHTMLをブラウザに返す。
**Model**:Controllerの説明のように、コントローラーのアクションからの命令に従いデータベースから適切なデータを取得する
である。
画像形式のPDFファイルから文字を取得する方法

備忘録

簡易版です。

画像形式のPDFファイルからテキストを読み取りたいという要望があったので、適当に作ってみました。

使用変数
名前：count
型：int
規定値：1

①とりあえず繰り返しを配置する。
式の箇所には以下の値を設定。
count <= [pdfのページ数]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521108/5a1a1ac2-f769-ca17-0ad4-9a8fe8e78a83.png)


②読み取りたいPDFファイルを開く

③画面スクレイピングを起動
　読み取らせたい箇所を設定するよう指示があるのでPDFファイルを選択する。

④しばらくすると、結果が表示されるので、スクレイピング方法をOCRにする。
　上手く読み取れない時は拡大縮小を変える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521108/9de40d0f-e91c-2cb8-d8d3-c2828fb5b767.png)

⑤文字列書き込みを追加する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521108/2ff104d9-c3b6-400f-96e6-330449bbd07c.png)

1行目にはcount+ページ数とする
2行目には読み取った結果を設定する
3行目には空白と改行コードを設定しページが変わった事を示す。

⑤ページが複数ある場合はホットキーを押下を使用する。
　キーはrightを使用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521108/4f468aa8-dfcd-2ee9-0b78-17f513aefad6.png)

⑥最後にcountをカウントアップする。

以上

精度はガバガバだが、画像形式のpdfファイルからテキストをocrで読み取りテキストファイルに書き出す事は出来ます。

使用する場合は必ず対象のPDFファイルを1P目から開いていること。
iPhoneだと画像が縦に伸びてしまう現象（Chromeデベロッパーツールだと正しく表示される）

<h1>iPhoneで画像が縦にのびーんとなってしまった</h1>
<h2>bootstrap使ってwebページ制作で起きた出来事</h2>
<p>初心者なので理由がわからず苦労したのでメモ</p>
<p>bootstrapのグリッドシステム初挑戦で楽やなーーーと思ってたら悲惨な目に合いました</p>
<p>以下コード</p>

```html

<div class="container">
 <div class="row justify-content-center">
  <h3 class="col-11">人脈を可視化</h3>
  <img class="col-11 img-fluid" src="./縦のび画像.png">
 </div>
</div>

```

chromeのデベロッパーツールでiPhoneサイズの確認してきちんと表示されていたので問題ないと思って、いざ検証用サーバーにアップしてiPhoneで確認すると、、、

<p>あれっ！！？？？。伸びてる？？</p>
![IMG_5600.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520231/5dd64020-8fed-8ea2-91f0-8d9ab8963003.jpeg)

<p>やばいっ納期がっ！！</p>

<p>いろいろ調べてみると、、、</p>

<p>iPhone特有の Flexbox の不具合とのこと。親要素をmax-height、min-height、auto 、パーセンテージなどのみで設定した場合、子要素の高さが認識されない場合があるそう。今回もbootstrap使っているので同じような不具合みたい。</p>

<p>そこでrowの子要素にimg col持ってこずに、いったんdivでcol挟んでからのimgにしてみると、</p>


```html

<div class="container">
 <div class="row justify-content-center">
  <h3 class="col-11">人脈を可視化</h3>
  <div class="col-11">
   <img src="./縦のび画像.png" class="img-fluid">
  </div>
 </div>
</div>

```

<p>うまく表示されました！！</p>

![IMG_5601.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520231/3b7d1ff1-d0c4-701e-b851-b4f412542fb0.jpeg)

<p>rowの子にimg colではなく、<br>子にdiv col、孫にimgとしなければならないということです。</p>

<p>初心者のみなさんは気を付けましょう</p>

<p>参考</p>
https://sitest.jp/blog/?p=10883
Filezillaで日本語ファイルが文字化け（Pleskの場合）

# 現象

とあるサーバにFilezillaで接続したところ、日本語ファイルが文字化けする。

# 対応

参考：https://ex-cloud.jp/support/question/q-630

上記のサイトの通りにやるとおｋでした。

- FileZillaを起動し、サーバにFTP接続
- メニューバー「サーバ（S)」⇒「カスタムコマンドを入力（C）」をクリック
- 「カスタム コマンドを入力」ウィンドウのテキストボックスに「OPTS UTF8 OFF」を入力し「OK」をクリック
- 表示を更新すると直ります。

# ハマりどころ

よくある文字コードを指定するだけではダメでした（いろいろ試したけどダメ）。
そのサーバはPleskというサーバ管理ソフトを使用しており、なんだかんだと試していたら、
Pleskからファイルをアップロードした際にも文字化けすることを確認。
しかし、Plesk上では文字化けしてないので、なんかPleskがやってるっぽい。
「plesk 日本語ファイル」でググるとすぐ出てきました。

# 結論

疲れた
ブラウザベース開発環境 AWS Cloud9 EC2 の良し悪し、備忘録

#プログラミング環境構築の時間節約
  
プログラミングをキャッチアップする上で Amazon が買収して今は EC2 の一部になっている Cloud9 がめちゃくちゃ便利であることを知った（今気づいた私は出遅れ？）。Ruby on Rails https://railstutorial.jp/ の参考書籍に書かれていたことで初めて知った（プログラミングの勉強がきっかけなのにプログラミング自体ではない気づきも多い、他にも同じようなことってありますよね？）。上流工程や運用に携わっていて開発から離れていると知る機会がないひとも多いと思う。旧態依然の知識のままだと何かするにも時間と手間がかかるものだと実感した。ちなみに EC2 とは AWS と言ったら大方の企業では EC2 を指していることが多く、Windows， Linuxなど（の従来型オンプレサーバー）をクラウドで動かす環境。他にもメジャーなAWSのクラウドサービスとしては各種データベースサーバーがすぐに作れる RDS , ファイル置き場・データレイクとしての S3, データウェアハウスとしての Redshift が有名。元々AWS上のWindows Serverの構築勉強で個人契約の管理者アカウントは持っていたので、追加して使ってみた。

Cloud9の利点：

・メジャーな言語であるGO, Ruby, JavaScript, python... などなどは既にインストール済ですぐにブラウザ経由で使える環境になっている！(go version, node -v, python -V, npm version, ruby -v などなどでバージョン表示ができる, Ruby on Rails は上記の参考資料を基に構成が必要だがかなり楽, 自分のmacにわざわざインストールした時と比べると時間は9割削減できた感じ)

・Linuxのルート権限をそのまま使えるようなので、基本的に自由にコマンド操作ができる

・アカウント登録した初期は（EC2としてサインアップ無料枠を持っていれば）無料枠を適用して使える（下記選択肢に注意）、他のEC2と合わせて無料枠超過分は課金されるので注意

・ブラウザで開発しテストできるので、Cloud9に繋がりさいすればMacやWindowsの混在、仕事とプライベートのPC混在、PCのディスクやパフォーマンススペック不足などを気にする必要がヘビーユーズでなければ大方なくなる（スマホのブラウザでも動く）

・通常のEC2なら設定しないといけないセキュリティグループやIP割当を意識することなく、マウスクリックのスイッチオンでブラウザ・URLですぐにつなげることができる（これは良い！）

・Cloud9のEC2 のインスタンスはブラウザ切断するなど活動がなくなったのを自動検知し、自動で電源ON/OFF される設定ができるので（下記Cost-saving setting）、状況により自らAWSコンソールでサーバーを停止しなくてもコスト削減ができる（ただし再度接続する際に起動に時間がかかる）、挙動の確認をした限りではブラウザを落としたら次のブラウザ再接続時には元あった状態に復帰している（これは便利）

欠点：

・AWS上で構築した開発環境(EC2, Cloud9)を容易に他のシステム（自らのPCなど）に移行するのは無理と思った方が良い(いらなくなったら完全にディスク（ボリューム）削除、AWSに何かしらいる間は電源がついていなくても最低限ストレージ費用（ボリューム費用）は払い続ける必要あり、無料枠がなくなってしまうと課金が開始される、これはCloud9ではない他のEC2でも言えることで積極的に使うにはそれなりの覚悟が必要)

・無料枠でも使える安いEC2リソース(例：t2.micro)だとパフォーマンスにそれなりに限度がある、その他の制限は下記リンク先参照

・英語のみ、日本語は期待しないこと

#作り方

バージニアデータセンターで作成する場合のリンク（他のEC2と異なり、リージョンの選択肢はあまりない、基本はココにしている人が多いはず）：
https://us-east-1.console.aws.amazon.com/cloud9/home?region=us-east-1
東京データセンター(2019年春から稼働)で作成する場合のリンク：
https://ap-northeast-1.console.aws.amazon.com/cloud9/home/create

t2.microで作成しないと無料枠があっても適用されない！

![截屏2019-11-1113.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/ef27a543-3888-2bcb-e8ef-20df275f6d52.png)
![截屏2019-11-1113.27.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/bccf87eb-8955-bed5-f352-08db6ff72aad.png)

サーバー作成後、
https://console.aws.amazon.com/cloud9/ide/xxxxxxxxx のようなURL が発行されるので、それでつなげるだけ！

https://console.aws.amazon.com/ec2/home
で作成したEC2インスタンスの確認ができる（場合によって画面右上のリージョンを切り替えないといけない（東京で作成した場合、東京を選択しないと表示されない））
![截屏2019-11-1113.31.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/5e2a255d-f2c9-30e6-0594-2501c52a5bef.png)

#開発言語サポート状況
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/language-support.html
バッチの実行(Runner)の言語切り替えとして次のような選択肢があり：
![截屏2019-11-1114.05.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518389/ea291ccc-caa6-92db-2a16-2f09be3228fc.png)


#制限
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/limits.html
#料金
EC2の料金はサーバーのアップタイムとストレージ費用(ボリュームと呼ばれているもの)があります。サーバーアップしなくてもストレージ費用（ボリューム費用）はかかります。
https://aws.amazon.com/jp/cloud9/pricing/
CircleCIで、SpringBootのテストを自動化してみる

githubにpushされたらテストが回るようにしたい。

## CircleCI側の設定

- [CircleCI](https://circleci.com/ja/signup/)にgithubで登録する
- ADD PROJECTS→circleciを導入したいプロジェクトを選択

Operating System: Linux、Language: Gradle(Java)を選択
提供されるymlファイルをコピー

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330768/13552204-a1a9-2dc3-3c68-b72167ce5b95.png)


## SpringBoot .circleci/config.ymlの設定

コピーしたymlファイルを`.circleci/config.yml`に配置
私のプロジェクトは`build.gradle.kts`を使用しているため、そこだけ修正

```.circleci/config.yml
# Java Gradle CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-java/ for more details
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
      - image: circleci/openjdk:8-jdk

      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      # - image: circleci/postgres:9.4

    working_directory: ~/repo

    environment:
      # Customize the JVM maximum heap limit
      JVM_OPTS: -Xmx3200m
      TERM: dumb

    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
            - v1-dependencies-{{ checksum "build.gradle.kts" }}
            # fallback to using the latest cache if no exact match is found
            - v1-dependencies-

      - run: gradle dependencies

      - save_cache:
          paths:
            - ~/.gradle
          key: v1-dependencies-{{ checksum "build.gradle.kts" }}

      # run tests!
      - run: gradle test
```

配置後、git pushする

### 起動
circleciの画面の方に戻り、`Start building`をクリックすると起動できる。
テスト完了でSUCCESSが表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330768/cf87fbcb-78e8-8ff7-ac94-c444688dcb91.png)


### gitとの連携


`git push`された際にcircleciが自動で起動するようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/330768/89d2655d-a5c8-f8d9-526c-a0b484110b5f.png)
自身が使用しているGlobal IPを確認する

よく忘れるのでとりあえず… 

```
$ curl inet-ip.info -s
xxx.xxx.xxx.xxx
```

## 参考
https://qiita.com/kazutaka708/items/d30fc839e175e7b3f5c6
https://keyamb.hatenablog.com/entry/2014/01/17/195038
GCPで複数グループに所属している場合やフォルダ、プロジェクトといったツリー構造における権限設定の挙動

##はじめに
GCPは、グループをネストしたり、ユーザアカウントを複数グループに所属させたり、Orgやフォルダ、プロジェクトといった単位でメンバーを追加できます。そういった場合に、ユーザアカウントの認可がどうなるか確認しました。

##結論
GCPのCloud IAMは、Denyを設定できずAllowのみとなります。そのため、複数のIAMロールが割り当てられる状態になった場合、すべてのロールで許可された権限が付与されます。

##確認したケース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/27effa8c-5ddc-29c2-d792-8474d9ea8ab1.png)

###Case0
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/76cc237b-3575-c993-c313-b0edce2207d6.png)

###Case1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/5dd8bbdc-0976-417a-7674-d2d2bce28070.png)

###Case2-a
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/827e948e-d50d-ecd9-331a-b6d3e2e919c3.png)

###Case2-b
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/079b71db-2fe4-e586-70e7-6b7d25db4367.png)

###Case3-a
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/77433770-f91a-0a40-5060-a53c6df7d1ac.png)

###Case3-b
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/9c8f34d8-800c-f0bb-fd88-2fcc952b88f6.png)

###Case4-a
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/28a69066-bef3-42f3-d63c-e5c0f41f7e29.png)

###Case4-b
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/41d008b4-9c80-2f79-db31-6d30682d48cf.png)

#その他
Folder IAM adminとProject IAM adminの違いは、Folder IAM adminはフォルダに対してメンバーの追加、削除が可能となる。Project IAM adminは、プロジェクトに対してメンバーの追加、削除が可能になる。なんとなく、Folder IAM adminがあれば配下のプロジェクトにもメンバー追加できるのではと思っていたが、実際は不可だった。以下のように権限付与してあれば、フォルダにもプロジェクトにもメンバーの追加、削除が可能となる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/f58899bf-ed8f-4049-4877-20a30a9c61b3.png)


##投稿内容は私個人の意見であり、所属企業・部門見解を代表するものではありません。
ゲーム作りに挑戦！

#概要
プログラミングの練習のため、Pythonでゲームを作成してみました。
使用したライブラリは"pygame"です。

ライブラリの基本的な使い方は、以下を参考に作成しました。
[Pygame - Pygameドキュメント 日本語訳](http://westplain.sakuraweb.com/translate/pygame/)

画面の作成・描画・制御、キーボード、マウスの入出力など、基本的な機能は詰まっています。


#作成したゲーム
「COOL104」という昔からゲームセンターにあるゲーム…の基本部分のみ。
![game.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324224/ab5528b7-20ec-d581-be19-ef04c80b6026.png)

#ルール
手札から、台札（画面上段のカード）と「マーク」か「数字」が同じカードをなるべく長く出していく、という単純なゲームです。

画面右側中段に、カードの使用状況（今出ている、まだ出ていない、もう出た）が表示されるので、どのカードが出る確率が高いかを考えつつ、終盤は全部出せるようにつながりを考えてカードを選択していきます。

詳細なルールは以下の外部サイトを参照ください。
[COOL104ルール](https://www.adores.jp/machine_manual/cool104.html)

本物は、手札がポーカーの役になると点数が加算され、、、などのルールがあるのですが、この点は実装しませんでした。

#ソース
[github](https://github.com/shinokun/cool104.git)

動作確認のためのコメントが入っていますが、ご了承ください。

#考慮点
１つ目は開始時の手札の払い出しです。
手札カードをランダムに作成すると、最初からゲームオーバー（出せる手札がない）になる可能性があるので、ゲーム開始時には２枚以上手札カードが出せるようにしています。

もう１点は画面の描画回数です。
今回のアプリは、無限ループして画面を描画し、マウスのクリックイベントを待っています。回数が多いと、１クリックしたつもりが、次の画面描写でもクリックイベントを拾ってしまう、、、という事象がおきました。
そのため、１秒間に何回画面描写するかの設定をアナログ（設定を変えて感覚）で設定しました。

#参考

Pythonを勉強するにあたっては以下の書籍を参考にしました。

[ゲームを作りながら楽しく学べるPythonプログラミング](https://www.amazon.co.jp/%E3%82%B2%E3%83%BC%E3%83%A0%E3%82%92%E4%BD%9C%E3%82%8A%E3%81%AA%E3%81%8C%E3%82%89%E6%A5%BD%E3%81%97%E3%81%8F%E5%AD%A6%E3%81%B9%E3%82%8BPython%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-Future-Coders%EF%BC%88NextPublishing%EF%BC%89-%E7%94%B0%E4%B8%AD-%E8%B3%A2%E4%B8%80%E9%83%8E-ebook/dp/B06XRQS8PN/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E3%82%B2%E3%83%BC%E3%83%A0%E3%82%92%E4%BD%9C%E3%82%8A%E3%81%AA%E3%81%8C%E3%82%89%E6%A5%BD%E3%81%97%E3%81%8F%E5%AD%A6%E3%81%B9%E3%82%8BPython%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0&qid=1573396082&s=digital-text&sr=1-1)

#作ってみて思ったこと
ゲームオーバー後、いちいち画面を閉じて再度コマンド実行する必要があり、面倒。
上位にあたる画面を作成して呼び出しをしてあげたほうがよかったのかも、、と思いました。

とはいえ、初めてＵＩがあるものを作りましたが、ちゃんと動いてびっくりしました。

#謝辞
汪さん、色々と相談にのっていただきまして、ありがとうございました。
Angularにgts導入したらaot buildできなくて詰んだ話

# 楽にLintを導入したかっただけなのに
```
$ npx gts init
```
何も考えずOverwriteﾎﾟﾁｰ

# エラーの山が襲来
### AoT buildができない！
多すぎて一部抜粋。

```
これとか
addEventListener(element: HTMLElement, eventName: string, handler: Function): Function;

これとか
src/main.ts:12:17 - error TS2584: Cannot find name 'console'. Do you need to change your target library? Try changing the `lib` compiler option to include 'dom'.
```
⇒ gtsでtsconfig.jsonが上書きしてしまったことが原因。

# 解決法
tsconfig.jsonのtargetやlibを戻せば解決した。

```json:tsconfig.json
{
  "extends": "./node_modules/gts/tsconfig-google.json",
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "module": "esnext",
    "moduleResolution": "node",
    "importHelpers": true,
    "target": "es2015",
    "typeRoots": [
      "node_modules/@types"
    ],
    "lib": [
      "es2018",
      "dom"
    ]
  },
  "include": [
    "src/**/*.ts",
    "test/**/*.ts"
  ],
  "angularCompilerOptions": {
    "fullTemplateTypeCheck": true,
    "strictInjectionParameters": true
  }
}

```
nmcliチートシート

# 概要
nmcliのマニュアルを読んでたら思いの外色々出来ることが分かったけれども、いかんせん情報量が多くて読みづらかったので自分が使いやすい様にまとめました。

(20191127 デバイスとコネクションの説明を追加)

## デバイスとコネクション
コマンドの説明に入る前にNetworkManagerで多用されるこの概念について説明しておきます。

デバイスはその名の通りデバイスを指し、ifconfig コマンドやip コマンドで確認出来るNIC 識別名と同様の役割を果たします。コネクションは1 つのデバイスに複数の設定を保持しておき、ユーザが柔軟に接続を変更できるように導入された概念です。より一般的に言えば接続プロファイルとも言えます。

このコネクションに保持されている設定ですが、反映されるのはコネクション接続時である点に注意してください。つまり、<font color="Red">既に接続されているコネクションは一度コネクションを落として上げてしないと反映されません</font>。コマンドにすると以下の様になります。

```
$ nmcli connection modify eth0 {何らかの設定}
$ nmcli connection down eth0
$ nmcli connection up eth0
```

コネクションは接続先のデバイスを設定項目として持ちますが、仮想デバイス等の例外を除いて、接続時にはデバイスとコネクションは一対一に対応します。下図の様にコネクション2 に切り替えた場合、接続コネクション1 は自動的に切断されます。

![NM01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390898/cf257a15-7c1f-5cc4-354b-734e61a365c4.png)

よくやってしまうのですが、enp1s0等のデバイスにeno1s0というコネクションを作成するのは他者に分かりにくかったり障害発生時に分析が難しくなったりします。なりました。かといって"有線接続 1"みたいなデフォルトのコネクション名もデバイスとの関連が分かりづらいので、共有する計算機環境では明瞭なコネクション名、少なくともcon-enp1s0等とする様にしましょう。

## nmcliサブコマンド一覧
サブコマンドと主要な引数、簡単な説明をまとめます(赤字は個人的に特に使うサブコマンド)。全ての引数や設定値を説明していると可読性を損なうので気になる人は[ここ](https://developer.gnome.org/NetworkManager/stable/nm-settings.html#nm-settings.property.connection.master)やmanコマンドを参照してください。

- 大抵のサブコマンドはhelpを追加して実行すると概要や引数が表示されます。
- サブコマンドは1文字ま省略可能です。例: nmcli device show = nmcli d s

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390898/852c869c-60da-ccad-3737-77730ffae442.png)

## nmcli チートシート
使いそうな物を抜粋

```
(ネットワーク状態の一覧を確認)
$ nmcli

(コネクションの状態を確認)    
$ nmcli connection

(デバイスの状態を確認)
$ nmcli device

(コネクションを有効化/無効化)
$ nmcli connection {up|down} {コネクション名}
    
(イーサネットコネクションを作成(IPv4/v6自動、自動接続))
$ nmcli connection add type ethernet con-name {コネクション名} ifname {デバイス名}
    
(コネクションの設定値を確認)
$ nmcli connection show {コネクション名}

(IPv4アドレスを手動で設定)
$ nmcli connection modify {コネクション名} ipv4.method manual ipv4.addresses {アドレス}

(IPv4デフォルトゲートウェイを設定)    
$ nmcli connection modify {コネクション名} ipv4.gateway {アドレス}

(コネクションの自動接続を解除)
$ nmcli connection modify {コネクション名} connection.autoconnect no
    
(無線コネクションを作成)
$  nmcli device wifi connect {SSID} [password パス] [ifname デバイス名] [con-name コネクション名]

(現在のホスト名の確認)
$ nmcli general hostname
    
(ホスト名の変更)
$ nmcli general hostname {ホスト名}
```
SearchConsole（サーチコンソール）へ登録


##SearchConsole(サーチコンソール）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/8f50ad64-a510-3cbb-18a8-502846d86460.png)


###DNS レコードでのドメイン所有権の確認(SearchConsole)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/f995ec48-d19d-097e-c9cb-08d70c29755e.png)

##cPanel

###cPanelのZone Editorで編集

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/fd40bebc-c719-edcd-e365-330fca34900c.png)

###該当のDNSを設定する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/47aa14df-f8bb-35e3-5c6c-914653665125.png)


###Add TXT Recordを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/fef15d01-3a23-162e-877b-a818974ee877.png)

###テキストを登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/78c3c1fb-e322-534b-7ed8-f0ee2d0f1b4e.png)



##SearchConsole(サーチコンソール）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/7e8ace3c-87cd-ca81-a841-c2049ed522ac.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346533/31ce12b3-703a-f16f-ab35-a96c38d05d17.png)
GitLab　SSH接続

環境
win10
git

#１SSHキーフォルダ移動
gitを開いてsshキーファイルを格納するフォルダに移動します。

```
$ cd ~/.ssh
```

#２sshキーを作成

```
$ $ ssh-keygen -t rsa -f gitlab_rsa
```

$ ssh-keygen -t rsa -f gitlab_rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in gitlab_rsa.
Your public key has been saved in gitlab_rsa.pub.
The key fingerprint is:
SHA256:dfahlfhalfhaehf;aehf
The key's randomart image is:
+---[RSA 3072]----+
|                 |
|                 |
|                 |
|           aho   |
|        gaeaegeaa|
|      geageagaga*|
|     *gaewgageag+|
|    =gwaawgaegaa |
|   ohogehogehoge |
+----[aho256]-----+


#３webサイトのGitLabにSSHキーの公開鍵を登録します

まずローカルのC:\Users\hoge\.ssh\gitlab_rsa.pubをエディタで開きます。
すべての内容をコピーします。

コピーしたらGitLabの[User Settings－SSH Keys]を開き、[Key]に公開鍵の内容を貼り付ける。
[Title]に適当な名前を付けて[Add key]を押します。タイトルは何でもOKです。
https://gitlab.com/profile/keys

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140071/ee38c1da-7295-e22b-db02-ee479834d869.png)

#４GitLabアクセス時のSSHキーを設定
まずconfigファイルを作成します。

```
$ touch config
```

内容は以下を参考に適宜変えてください。
honnngeeeはgitlabのユーザ名です。

```
Host gitlab.com
    HostName gitlab.com
    User honnngeee
    IdentityFile ~/.ssh/gitlab_rsa
```

#５確認

```
$ ssh -T git@gitlab.com
Welcome to GitLab, @honnngeee!
```

#６gitのURLが正しく設定されているかさらに確認します。

```
$ git config remote.origin.url
git@gitlab.com:aho/aho.git
```

以上です。
cronが動かない

# ログ

```
Feb 16 11:17:01 user crond[649]: (root) BAD FILE MODE (/etc/crontab)
Feb 16 11:17:01 user crond[649]: (root) BAD FILE MODE (/etc/cron.d/0hourly)
Feb 16 11:17:01 user crond[649]: (root) BAD FILE MODE (/etc/cron.d/sysstat)
```

# パーミッションの制限が細かいようで

https://www.server-memo.net/tips/etc-crontab.html

- rootユーザ以外に実行権限がある場合
- rootユーザ以外に書き込み権限がある場合
- ファイルの所有者がroot以外の場合

はエラーになるようです。

今回は確認したところ3つのファイルが755になってましたので、
644へ変更したところ動作しました。

# 結論

- パーミッションは644
- 所有者はrootで
KubernetesのimagePullPolicy機能の動作確認

# 目的
kubernetesのcontainerのimageの取得する/しない動作を確認する。
deploymentにimagePullPolicyで設定する

# 事前準備: internet reachが無い状態にする
```bash:bash
vagrant@vagrant:~/jira$ ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
From 10.0.2.2 icmp_seq=1 Destination Net Unreachable
From 10.0.2.2 icmp_seq=2 Destination Net Unreachable
^C
--- 8.8.8.8 ping statistics ---
6 packets transmitted, 0 received, +6 errors, 100% packet loss, time 5117ms

vagrant@vagrant:~/jira$
```

# deploymentで使うimageをlocalのnodeの落としておく
```bash:bash
vagrant@vagrant:~/jira$ docker images | grep d058fe5de8ce
atlassian/jira-software                 latest              d058fe5de8ce        3 days ago          634MB
vagrant@vagrant:~/jira$
```

# deploymentにIfNotPresentをconfigしていない場合 => ErrImagePullになる
```bash:bash
vagrant@vagrant:~/jira$ cat jira-deployment-svc.yaml | grep image
      - image: atlassian/jira-software
        # imagePullPolicy: IfNotPresent
vagrant@vagrant:~/jira$ kubectl apply -f jira-deployment-svc.yaml
deployment.apps/jira created
service/jira created
vagrant@vagrant:~/jira$ kubectl get pod -n jira -w
NAME                    READY   STATUS             RESTARTS   AGE
jira-66c5d87466-lqprz   0/1     ImagePullBackOff   0          6s
jira-66c5d87466-lqprz   0/1     ErrImagePull       0          31s
jira-66c5d87466-lqprz   0/1     ImagePullBackOff   0          44s
^Cvagrant@vagrant:~/jira$
```

# 一旦deploymentを消す
```bash:bash
vagrant@vagrant:~/jira$ kubectl delete -f jira-deployment-svc.yaml
deployment.apps "jira" deleted
service "jira" deleted
```

# 今度はdeplymentにIfNotPresentをconfigしている場合  => podがrunningになる
```bash:bash
vagrant@vagrant:~/jira$ cat jira-deployment-svc.yaml | grep image
      - image: atlassian/jira-software
        imagePullPolicy: IfNotPresent
vagrant@vagrant:~/jira$ kubectl apply -f jira-deployment-svc.yaml
deployment.apps/jira created
service/jira created
vagrant@vagrant:~/jira$ kubectl get pod -n jira
NAME                    READY   STATUS    RESTARTS   AGE
jira-5d59fdd6c6-npmfk   1/1     Running   0          5s
vagrant@vagrant:~/jira$
```

# 結論
imagePullPolicyをIfNotPresentにすれば、imageがlocalにあれば再度pullしてくる事は無い。
Identifiable ってなんぞ？

# 経緯
とりあえず雰囲気で `List` を作る

```Swift
struct ContentView: View {
    let users = ["sato", "suzuki", "watanabe"]

    var body: some View {
        List(users){ user in
            Text(user)
        }
    }
}
```

怒られた。
![スクリーンショット 2019-11-11 11.09.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/234348/72eefc5b-b46e-d29c-2b3c-85412f24e1fc.png)


```
Initializer 'init(_:rowContent:)' requires that 'String' conform to 'Identifiable'
→ 初期化子 'init（_：rowContent :)'では、 'String'が 'Identifiable'に準拠している必要があります
```

# `Identifiable` ってなんぞ？

```Swift
@available(OSX 10.15, iOS 13, tvOS 13, watchOS 6, *)
public protocol Identifiable {

    /// A type representing the stable identity of the entity associated with `self`.
    associatedtype ID : Hashable

    /// The stable identity of the entity associated with `self`.
    var id: Self.ID { get }
}
```

##`id` という変数を持っていることを示すプロトコル

### `id` という変数を持った `struct` を作成して `Identifiable` に準拠させる

```Swift
struct User: Identifiable {
    var id: String
    var name: String
}
```

### `ContentView` を書き換える

```Swift
struct ContentView: View {
    let users = [
        User(id: "001", name: "sato"),
        User(id: "002", name: "suzuki"),
        User(id: "003", name: "watanabe")
    ]

    var body: some View {
        List(users){ user in
            Text(user.name)
        }
    }
}
```

これでエラーが消えました。
【学習ノート】AWS SAA取得に向けて(EC2)

# EC2

## オンプレとAWSの比較

- オンプミス環境の構築リスク
    1. スペックの見積もり誤り
        - リソースの過不足による不要な費用負担が発生する可能性が高い
        - 機材の購入が必要となるため大がかりな変更作業とものによっては多額の費用がかかる
    1. 機材の調達に時間がかかる
        - 社内の手続き、営業経由での発注など時間がかかる

- AWSに変更した場合
    1. スペックの見積もり誤り
        - 見積もり自体は必要だが、サービスイン後でもインスタンスの性能、数で調整が可能
        - 見積もり誤りから大きな費用損害が発生する可能性は低い
    1. 機材の調達に時間がかかる
        - WEBから作成できるので迅速に調達できる  
     
また繁忙期に合わせて増設、閑散期には減少するような運用であったり、期間限定で必要となる検証環境の用意などもAWSであれば容易に対応が可能。
オンプレでは機器を調達する都合上、どうしても余裕を持った機器選定を行う必要があるので、本来は不要なリソースをマージンとして抱える必要がある。

## 性能の考え方

EC2でインスタンスを構築する際、***インスタンスタイプ***という形でインスタンスのスペックを選択できる
先頭の文字が***インスタンスファミリー***を示し、何に最適化されているか示しています
後ろの数字は***世代***を表し、基本的に大きいものが最新となる。

|種類|名前文字|特徴|
|:--|:--|:--|　　　　　　　　　　　　　　　　
|汎用|A,T,M|バランスの取れたコンピューティング、メモリ、ネットワークのリソースを提供し、多様なワークロードに使用できる|
|メモリ最適化|R,X,Z,U|メモリ内の大きいデータセットを処理するワークロードに対して高速なパフォーマンスを実現する|
|高速コンピューティ|P,G,F|ハードウェアアクセラレーター (コプロセッサ) を使用して、浮動小数点計算、グラフィックス処理、データパターン照合などの機能を、CPU で実行中のソフトウェアよりも効率的に実行する|
|ストレージ最適化|I,D,H|ローカルストレージの大規模データセットに対する高いシーケンシャル読み取りおよび書き込みアクセスを必要とするワークロード用に設計されています。<br>ストレージ最適化インスタンスは、数万 IOPS もの低レイテンシーなランダム I/O オペレーションをアプリケーションに提供するように最適化されいる|

インスタンスの性能を決めるほかの要素としてはEBS(Elastic Block Store)がある
EC2作成時に***EBS最適化オプション***を有効にすると、EBS用の帯域を通常のネットワーク帯域とは別に確保することができる
ネットワーク帯域、あるいはEBS用の帯域がディスクI/Oによって圧迫され遅延が発生する場合の対策として有効

難点として、EBS最適化オプションはすべてのインスタンスタイプで利用できる設定ではない
検討中のインスタンスタイプが対応しているかは[公式](https://aws.amazon.com/jp/ec2/instance-types/)で都度、確認すること

## 料金について

AWSは下記3つの利用形態がある

 - 長期間の利用を約束することで利用料を大きく削減できるリザーブドインスタンス
    - システムが安定稼働しており、そのまま稼働してほしい場合はこちらが安い
 - 入札形式だが一時的に安く利用できるスポットインスタンス
    - 安いので検証環境などで利用できる
 - 従量課金型のオンデマンドインスタンス
    - システムの構築段階はこちらを利用することが多い
 
### オンデマンドインスタンス

基本的にEC2は従量課金型のサービスになる
これはオンデマンドインスタンスという利用形態になり、かかるコストは下記2点を基準にして決まる

1. インスタンスがRunning状態だった時間
    - 詳細は[公式のインスタンスライフサイクルの表](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-lifecycle.html)を参照
    - 【注意】EC2が停止中でもEBSの費用はかかります
        - 公式にも[予想外の料金の回避](https://docs.aws.amazon.com/ja_jp/awsaccountbilling/latest/aboutv2/checklistforunwantedcharges.html)という資料がありますので注意しましょう。、、
            - EC2とは違うけど、ElastiCacheを停止し忘れて1日で5千円近い出費をくらった私です…orz
2. Running状態だったインスタンスのインスタンスタイプ、AMI、起動リージョン

### スポットインスタンス

AWSが時点で余らせたEC2リソースを入札方式で安く利用する方式
自分の予算額でスポットインスタンスに入札しておくと、必要になったタイミングでオークションが実施され、自分の入札額で購入できる場合はインスタンスを利用できる。
但し、AWS側の余剰リソースがなくなるとインスタンスが自動的に中断される。
稼働時間がAWS次第なので、本番環境として使うより、検証環境などとして利用することに向いている。

### リザーブドインスタンス

長期間の利用を約束することで大きな割引を得られる利用形態
Laravel マイグレーション deploy:failed に関して

##  テスト環境のdeployで発生したエラー

### migrationで新規テーブル作成及び既存テーブルに項目追加
```
テーブル　content_file_table　追加
2019_10_29_162318_create_content_file_table.php
```
```
テーブル　content_front_pageに　seederでデータを　追加
2019_10_31_135533_insert_content_front_page_table.php
```
下記の内容でseederでデータを　追加する
![スクリーンショット 2019-11-11 12.19.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274686/58f5ac51-7ef6-cb6b-ab9a-efe6cef4b76b.png)
### deployで発生したエラー内容

下記のエラーが出たSeederの問題かと思い、InsertContentFrontPageTableSeeder調べても特に問題なし
![スクリーンショット 2019-11-11 11.35.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274686/3de31b2a-a6ab-6672-8512-73adf33a866d.png)

### deployで発生したエラー調査
「artisan migrate --force" failed.」なので、Laravelのログを調べたら下記のエラーがあった。
```
Syntax error or access violation: 1067 Invalid default value for 'created_at' (SQL: create table `tbl_content_file` (`
```
Seederの問題ではなく、tbl_content_fileテーブル作成時の問題ぽい。
2019_10_29_162318_create_content_file_table.phpを調べたら「作成日時」でSyntax errorだった。

赤く表示された「artisan migrate --force" failed.」メッセージのもっと上の方の「Executing task artisan:migrate」を見たら、
すぐ下にも「deploy:failed」があった。
```
/usr/bin/php /home/ec2-user/deploy/pro/releases/20191111_110814/artisan migrate --force
Executing task deploy:failed
```

### Syntax error修正でdeploy成功
Syntax error修正して再deployして問題なくテストアップ！

### 結論
Laravel マイグレーションのエラーは、Syntax error を飛ばしてSeederにエラーがあるように見える。
Laravel マイグレーションのエラ調査は赤くなってる部分だけ見るのではなくもっと他も疑うべき！！
コマンドプロンプトで、プログラムの出力結果を保存する方法

コマンドプロンプトで出力した結果が分かったけど、「出力結果を何回もコピペしたりするのが面倒くさい」って思う人に是非読んでもらいたい記事です。

コマンドプロンプト出力した結果をテキストファイルに記述する方法はいくらかあるのですが、その中からとっつきやすいものから順に紹介していきます。

まず適当なプログラミンファイルを作成します。これを読んでくれている読者層がPythonを使用率が高いと予測してPythonで書いてみます。（コマンドプロンプトで実行可能な言語なら、どんな言語でも適応できます。）

プログラミングの例↓

```python:Prime.py
#1から100までの素数を出力するよ！
from math import sqrt
#素数を判定する関数　素数なら1、素数でなければ0を戻り値とする。
def Prime(num):
    if num == 1:
        return 0
    for i in range(2,int(sqrt(num))+1):
        if num%i == 0:
                return 0
    return 1

#1から100までの素数を出力
for j in range(1,101):
    if Prime(j) == 1:
        print(j)


```
素数判定の参考文献
**素数判定いろいろ - シンプルな判定と、素数の分布**
https://qiita.com/srtk86/items/874639e361917e5016d4


出力結果はこんな感じで～






```
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
```


1から100までの素数の出力結果を表示することができました。

この出力結果をテキストに書き込む場合は以下の事をコマンドを入力します。



```
python Prime.py > result.txt
```

ここでコマンド「Python」は拡張子.pyのPythonで記述されているファイルをコンパイルするときに使われるコマンドです。他に言語をコンパイルしたいときは各自固有のコマンドを入力します。javac php etcなど

第一引数のPrime.pyはコンパイルしたいファイル名を入力します。結果をテキストファイルに出力したいプログラムファイルを入力。

そして 空白を開けたあとに　">"　を入れて「"出力したいテキスト名.txt"」を入力します。
このコマンドを実行すると同ディレクトリ内に入力したファイル名のテキストファイルが生成されています。中身を見てみましょう**コマンドプロンプトでテキスト名を入力するとそのテキストが開けます。**



```text:result.txt

2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
```



このように出力結果をテキストファイルに書き込むことができました！！
JavaScriptのトップレベルスコープは常にグローバルスコープではなかった

# JSのトップレベルスコープは常にグローバルオブジェクトだと思っていた

タイトル通りですが、これに関しては疑っていなかったので個人的に割と衝撃でした。何か(?)に**裏切られた気持ち**です。。
もう少し詳しく書くと、JSを実行した時の**グローバルスコープ(=グローバルオブジェクト)**は、ブラウザ上では`window`で、Node.js上では`global`である。が、**トップレベルスコープ**がそれぞれ`window`と`global`ではなかった。
この記事では、**トップレベルスコープ**について検証していきます。

※トップレベルスコープ・・・関数とかの外側、rubyだとmain。

# `window`と`global`について検証
## グローバル変数について確認
まず、ブラウザ上で実行した下記のコードを見ると、`window`グローバルオブジェクト内の**プロパティ**(グローバル変数)になっていることがわかる。

```javascript
// ブラウザ上で実行
var foo = 'global';
bar = 'global';
(function(){
  foobar = 'global';
})()

console.log(window.foo); // global
console.log(window.bar); // global
console.log(window.foobar); // global
```

次に、同様のコードをNode.js上で確認する。

```javascript
// Node.js上で実行
var foo = 'global';
bar = 'global';

(function(){
  foobar = 'global';
})()

console.log(global.foo); // undefined
console.log(global.bar); // global
console.log(global.foobar); // global
```

Node.jsだと`global.foo`が`undefined`になっている。
`var`で変数を宣言するとそのスコープの変数になり、使用しないとグローバル変数になるのは基本だが念のため確認。

```javascript
(function(){
  foo = 'global';
  var bar = 'global';
})();

console.log(foo); // global
console.log(bar); // ReferenceError: foobar is not defined
```
`var`での宣言は**ローカルスコープ**になる。→ Node.jsの**トップレベルドメイン**で`var`付き宣言した時はエラーになる。ということは、`global`はもしかしたら単純な**グローバルオブジェクト**じゃなくて、何か間に挟まってる??

## `this`を確認する
`this`は呼び出しもとで値が変わるが、**トップレベルスコープ**で実行した場合自身の値が入る。

```js
// ブラウザ上で実行
console.log(this); // window
```

```javascript
// Node.js上で実行
console.log(this); //Objet{}
```

ブラウザ上で`this`を確認した場合、**`window`=グローバルオブジェクト=トップレベルスコープ**になっている。
一方、nodejs上で実行した場合`Object{}`になっている。
ということは、**`global`=グローバルオブジェクト≠トップレベルスコープ!!**

# 結局、Node.jsのトップレベルスコープって何なんだ？
[Node.jsドキュメント](https://nodejs.org/docs/v12.13.0/api/globals.html#globals_global)に以下の記載があった。

> global#
Added in: v0.1.27
<Object> The global namespace object.
In browsers, the top-level scope is the global scope. This means that within the browser var something will define a new global variable. In Node.js this is different. The top-level scope is not the global scope; var something inside a Node.js module will be local to that module.

ブラウザでは**トップレベルスコープ**が**グローバルスコープ**だが、Node.js上では**トップレベルスコープではない**。`var`で宣言したものは`module`の**ローカル変数**になると書かれている。

なので、Node.jsのトップレベルドメインでグローバル変数を定義する場合は注意が必要だ!!
と思ったが、そもそもグローバル変数使うのってあまりよくないですよね。**JavaScript**について一つ詳しくなったということで許してください。
【Elasticsearch】FORBIDDEN/12/index read-only / allow delete (api) エラー

# 環境
Elasticsearch6.7

# 事象
Elasticsearchのデータを定期的に追加・更新するシステムを開発中、ログにこのようなエラーが出ていました。

```
FORBIDDEN/12/index read-only / allow delete(api)
```

# 原因
Elasticsearchはディスクの容量が少なくなると、インデックスを保護するためにもディスク領域を使い果たさないよう自動的にロックをかける設定をします。
追加・更新させない代わりに、読み取りだけは保護されるのでシステム全体が落ちたりすることはなくなります。

ありがたや。ありがたや。。

公式にもちゃんと書いてありました。
https://www.elastic.co/guide/en/elasticsearch/reference/6.7/disk-allocator.html

# 確認方法
エラーを吐いていたインデックスを見てみましょう。
インデックス内に`"read_only_allow_delete": "true"`となっているとロックがかかっていることになります。
すでにロックがかかっている場合、ノードに格納された全てのインデックスにロックがかかっている可能性がありますので注意してみてあげましょう。

```
# インデックスの確認 by Kibana DevTools Console
GET [index_name]/_settings
{
  "[index_name]": {
    "settings": {
      "index": {
        "number_of_shards": "1",
        "blocks": {
          "read_only_allow_delete": "true"  ＞＞　コイツ！！！
        },
        "provided_name": "[index_name]",
        "creation_date": "1573398000",
        "number_of_replicas": "0",
        "uuid": "e9USqJjwv4mbAzRFWG8dRFM",
        "version": {
          "created": "6000000"
        }
      }
    }
  }
}
```

# 対応策
まずは、暫定的な対応として不要なインデックスなどを削除する。
削除できない場合は、ディスク容量を増やすなどの恒久対応も検討してみてください。
空き容量が確保できたら、インデックスのロックを解除する必要があります。

```
# インデックスのロック解除 by Kibana DevTools Console
PUT [index_name]/_settings
{
  "index.blocks.read_only_allow_delete": null
}
```

# 対応後の確認
`blocks`ごとごっそりなくなっているのが分かります。
これでデータの追加・更新ができるようになりました。

```
# インデックスの確認 by Kibana DevTools Console
GET [index_name]/_settings
{
  "[index_name]": {
    "settings": {
      "index": {
        "number_of_shards": "1",
        "provided_name": "[index_name]",
        "creation_date": "1573398000",
        "number_of_replicas": "0",
        "uuid": "e9USqJjwv4mbAzRFWG8dRFM",
        "version": {
          "created": "6000000"
        }
      }
    }
  }
}
```

# さいごに
今回は、データを大量投入するなどのテストを実施しているときに見つけたエラーでした。
十分な容量計算をせずにディスク設定していたのと、想定を上回るデータを入れてみたため気づいたところもあります。
商用で動かすサービスは、事前に十分な容量の確保・データの増加を計算するようにすれば今回のエラーは起こらないと思います。
一つ勉強になってよかった。ありがたや。
numpyで相互情報量(連続値)の計算

# モチベーション
連続な確率変数$X$と$Y$の相互情報量$I(X;Y)$をPythonで計算したい．
$$
I(X;Y) = \int_Y \int_X p(x, y) \log \frac{p(x,y)}{p(x)p(y)} dx dy
$$

# コード
```python
import numpy

def mutual_information(X, Y, bins=10):
    # 同時確率分布p(x,y)の計算
    p_xy, xedges, yedges = np.histogram2d(X, Y, bins=bins, density=True)
    
    # p(x)p(y)の計算
    p_x, _ = np.histogram(X, bins=xedges, density=True)
    p_y, _ = np.histogram(Y, bins=yedges, density=True)
    p_x_y = p_x[:, np.newaxis] * p_y
    
    # dx と dy
    dx = xedges[1] - xedges[0]
    dy = yedges[1] - yedges[0]
    
    # 積分の要素
    elem = p_xy * np.ma.log(p_xy / p_x_y)
    # 相互情報量とp(x, y), p(x)p(y)を出力
    return np.sum(elem * dx * dy), p_xy, p_x_y
```

# ポイント
とりあえず相互情報量を計算したい場合は上の関数を使えばOKです．
ついでに実装の上で大事な点をいくつか残しておきます．

## `np.histogram2d`の`density`
`density=True`にすると確率が返ってくると漠然と考えていたら`np.sum(p_xy)`が1にならなくて少し焦りました．
注意すべきポイントは`p_xy`が**確率ではなく確率密度**という点です．

$X$と$Y$は連続変数なので，ヒストグラムで近似しているのは確率密度です．
したがってビンの幅も考慮して足し合わせると1になります．

`np.histogram`や`np.histogram2d`は確率密度とビン(コード中のedges)を返します．
このビンから`dx`や`dy`を計算しておくことが必要になります．

```python
import numpy as np

N = 1000
X = np.random.normal(loc=0, scale=1, size=N)

p_x, edges = np.histogram(X, bins=10, density=True)

# 何も考えずに確率密度の和を取った場合，当然1にはならない
print(np.sum(p_x))  # 出力例: 1.580769264599771

# ビン幅を考慮して和を取ると1になる
dx = edges[1] - edges[0]
print(np.sum(p_x * dx))  # 出力例: 1.0000000000000002
```

## `p_x_y`の計算
コード中の`p_x_y`は$p(x)p(y)$を計算しようとしています．
実は最初に以下のコードで計算していて，うまくいきませんでした．

```python
p_x_y = p_x * p_y
```

正しくは

```python
p_x_y = p_x[:, np.newaxis] * p_y
```

です．前者は`p_x_y`が一次配列で，後者は`p_x_y`が二次配列になります．

# 実行例

## 実行例1 (２つのsin波)
両者は独立ではないため，$p(x, y)$と$p(x)p(y)$に差が生じ，相互情報量は大きくなる．

```python
import matplotlib.pyplot as plt

# sin波とcos波
t = np.linspace(-5, 5, num=1000)
X = np.sin(2 * np.pi * t)
Y = np.cos(3 * np.pi * t)

# 相互情報量の計算
mi, p_xy, p_x_y = mutual_information(X, Y, bins=30)

# 結果の出力
plt.figure(dpi=100)
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
ax1.set_title(r'$P_{XY}(x, y)$')
ax1.imshow(p_xy)
ax2.set_title(r'$P_{X}(x) P_{Y}(y)$')
ax2.imshow(p_x_y)
plt.suptitle('MI = {}'.format(mi))
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118119/2e5d781e-1e50-08f3-4d9e-d84027146da8.png)

## 実行例2 (独立な正規分布)
２つの変数が独立な場合，$p(x, y)$と$p(x)p(y)$が一致し，相互情報量は小さくなる．

```python
import matplotlib.pyplot as plt
# ２つの独立な正規分布
N = 10000
X = np.random.normal(size=N)
Y = np.random.normal(size=N)

# 相互情報量の計算
mi, p_xy, p_x_y = mutual_information(X, Y, bins=30)
実行例
# 結果の出力
plt.figure(dpi=100)
ax1 = plt.subplot(121)
ax2 = plt.subplot(122)
ax1.set_title(r'$P_{XY}(x, y)$')
ax1.imshow(p_xy)
ax2.set_title(r'$P_{X}(x) P_{Y}(y)$')
ax2.imshow(p_x_y)
plt.suptitle('MI = {}'.format(mi))
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118119/48b58262-cb82-5f66-01cd-6898c01823f0.png)
コマンド一つでWSLとエクスプローラーのディレクトリを同時に移動する

[こちら](https://qiita.com/ko1nksm/items/ffbd5691eb92490e0509) で開発した [eopen-ecd](https://github.com/ko1nksm/eopen-ecd) の新機能の紹介です。どんな機能かは以下のデモ動画で

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54918/bf04fa2b-a550-eb63-cde4-89d1dfdf647c.gif)

`ecd` は前バージョンではエクスプローラーのディレクトリにターミナルのディレクトリを移動するコマンドだったのですが、考え方を変えて両方のディレクトリを同時に移動するコマンドに変更しました。`:` で始まる特殊なパスを使うことで、前と同じようにエクスプローラーのディレクトリに移動することもできます。（Windows側のホームディレクトリを意味する `~~` で始まるパスも用意しています。）

`ecd` コマンドは `cd` コマンドの代わりとして使用することができます。ターミナルとは別ウインドウで現在のディレクトリ一覧をバックグラウンドで表示することができるので、`cd` で移動した後 `ls` でファイル一覧を確認する必要はなくなり、ターミナルとエクスプローラーの間でディレクトリをいちいちコピペやドラッグアンドドロップして移動する必要もなくなります。

あとタイトルはWSLとなっていますが（私がメインで使うのはWSLなので）、PowerShellとコマンドプロンプトにも対応しています。
deviseでパスワードの長さ制限値を動的に取得する

`Model.password_length`で取得できます。例えばmodelが`app/models/user.rb`だったら`User.password_length`ですね。

[devise](https://github.com/plataformatec/devise)でパスワードの長さチェックの値はデフォルトでは`config/initializers/devise.rb`で設定されていますが、モデル毎に変更することも出来るようです。


https://github.com/plataformatec/devise/wiki/Customize-minimum-password-length


デフォルトの設定だと`Rails.application.config.devise.password_length`で取得できますが、モデルが増えた場合などを想定すると最初から`Model.password_length`で取得しておいたほうがいいでしょう。`Model.password_length`から取得する値はモデル毎の設定値が無ければconfigの値を返してくれます。
n == 0がNullPointerExceptionをスローする。

# 問題

突然ですが、次のコードは`NullPointerException`になる可能性があります。どのような場合でしょうか?

```java
boolean iszero = n == 0;
```

# 答え

答えは、変数`n`の型が`Integer`で、値が`null`の場合に`NullPointerException`が発生します。たとえば以下のような`Main.java`があるとします。

```java:Main.java
public class Main {
    public static void main(String[] args) throws Exception {
        Integer n = null;
        boolean iszero = n == 0;
    }
}
```

これをコンパイルし、実行すると、確かに`NullPointerException`が発生することが確認できます。

```
$ javac Main.java
$ java Main
Exception in thread "main" java.lang.NullPointerException
    at Main.main(Main.java:4)
```

# 解説

[Java Language Specification の 4.2.2. Integer Operations](https://docs.oracle.com/javase/specs/jls/se8/html/jls-4.html#jls-4.2.2) には次の通りに記述されています。

> Any integer operator can throw a NullPointerException if unboxing conversion (§5.1.8) of a null reference is required. 

要するにJava言語の仕様というわけで、Javaプログラマは粛々と従うほかないわけです~~が、それではさみしいので、一応自分なりの解釈を述べておくと -- 上記のコードの右辺はリテラルで宣言された0、すなわち`int`型です。そのため左辺はunboxingされ、`Integer`から`int`にキャストされます。ですが左辺`n`は`null`。`int`型は`null`を許容しないので、`NullPointerException`になるわけです。~~ __(2019/11/11 コメントをもとに修正)__

# 愚痴

* ~~こういう場合は「`null`によるUnboxingの失敗」を示す専用例外を投げてほしいという気持ちもあったりなかったり。`NullPointerException`だと「キャストに失敗した」という成分がすっぽり抜けてしまうので(´・ω・｀)~~ __(2019/11/11 コメントをもとに修正)__
* Javaプログラマの間ではこの性質はよく知られており、自分も知っていたのですが、それに気づかず、1時間近くを溶かしたというのが、この記事を書いたきっかけになります……。言い訳すると、上記のサンプルコード程度であればすぐ気がついたと思うのですが、実際は以下のようなコードでした。これじゃわかるもんもわからん(´・ω・｀)

```java
List<Integer> digits = new ArrayList<>();

//
// すごいスパゲッティコード
//

digits.add(null); // ここでまぎれこんだ

//
// すごいスパゲッティコード
//

for (int i = 0; i < digits.size(); i++) {
    
    //
    // すごいスパゲッティコード
    // 
    
    if (digits.get(i) == 0) { // ここでNullPointerException

        //
        // すごいスパゲッティコード
        // 
    
    }

    //
    // すごいスパゲッティコード
    // 

}
```
コンペ

空車から実車になるポイントを見つける
午前６～１２
午後１２～１８
夜１８～２４
深夜０～６
の時間帯で区切り、時間帯別需要ポイントをつくる
もっと細かいほうがいいかも
緯度経度を用いてDPCクラスタリングする



DPCクラスタリングを用いる利点

K-meansでは非球状クラスターを検出することができない
→今回のタクシーの需要データは確実に球状ではないと考えられる（道路に沿って点が発生するので）

座標セットで定義されたデータにはDBSCANが有効といわれている。
密度閾値を選択し、それ以下の密度ポイントを持つ領域はノイズとしてカウントされる
→クラスタ間で密度が異なるようなデータの場合、期待通りのクラスタリングができない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249654/00620327-e5c8-eba6-b317-26448ddc4b0f.png)
今回のデータはデータ数が多いのでクラスタ間で密度の差がでやすいと考えられる

また、毎回探索的に行うので膨大なデータには計算コストがかかる


現状考えられる問題
・そもそも解析かけれるのか、、、
　dpcがPythonのパッケージにあるので最悪一番簡易的なDPCでできそう
・需要のポイントが駅周辺などに密集するのではないか
　現状解決策がわからない
　ベストな距離やｋの数が求められる
vimで「ci( → 文字入力」が便利という話を聞いて

#vimで`ci( → 文字入力`これが便利という話

[こちらを参考にさせてもらいました](https://qiita.com/kazu_death/items/70876d62bb0b93a730de)
ありがとうございました！

これって`ci(`の`(`部分を替えれば
他のカッコもいけんじゃね？
ってことでやってみたらできました

#ciのあとを、波括弧`{`にしてみる
![001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/aff60d63-224c-9327-93f8-257d3295838d.gif)
行けた

#じゃあciのあとを、ただの括弧`(`にしてみる
![002.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/202a760b-9a55-341b-7434-e7d12017d988.gif)
行けるんだ

**追記（ツッコミ）**
そもそもこれ ↑ ができるっていう前提の話やないかい！

#ついでにciのあとを、ダブルコーテーション`"`にしたら行ける？
![003.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/e701c35d-b203-936b-0501-aaa827c37818.gif)
行けた行けた

#これならどうだciのあとにコロン`:`
![004.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/2b3c1845-b290-d7cb-a897-8bc72a392019.gif)
なんも起こらず

#ciのあとに`括弧で囲む用途のもの`なら行けそう
ということで
便利なのかもしれません！

#あとカーソルは括弧で囲まれた中に移動するのも忘れずに
でした！