OmniAICreator/Qiita-1.07M huggingface dataset:
Laravelで主キー名を変更する際の注意点

## 目的

LaravelでDBテーブルの作成を行う中で、有名な「SQLアンチパターン」の中の１つ"IDリクワイアド"を避けるために、テーブルの主キー名をidから変更します。
IDリクワイアドについては[こちら](https://qiita.com/ayayo/items/ba38853bca0c2cc2acb7)

## 実装

例えば、新たに作るClientテーブルの主キーを `client_id` にするとします。
`php artisan make:migration create_clients_table` で生成したマイグレーションファイルを書き換えます。

``` 2019_06_14_150035_create_clients_table.php
    public function up()
    {
        Schema::create('clients', function (Blueprint $table) {
            $table->bigIncrements('client_id'); // デフォルトの'id'から変更
            $table->string('client_name');
            $table->string('tel', 11);
            $table->string('email')->nullable();
            $table->timestamps();
        });
    }
```

こんな感じにして、`php artisan migrate` を実行すると、主キーが `company_id` となったclientsテーブルが作られます。
あとは登録機能実装して登録するだけ！
<br>
...
<br>
<br>



```
SQLSTATE[42703]: Undefined column: 7 ERROR: 列"id"は存在しません LINE 1: ..._at") values ($1, $2, $3) returning "id" ^ (SQL: insert into “clients" (“client_name”, "updated_at", "created_at") values (hoge, 2019-06-14 15:30:38, 2019-06-14 15:30:38) returning "id")
```

あれ...（´・ω・｀）
migrationファイルの書き換えだけでは足りないようです。

## 解決

内部で主キーのカラム名がid以外許されていないのだろうか…などと思いながら調べていった結果、公式にちゃんと答えがありました。
[Laravel5.8 Eloquent：利用の開始]
(https://readouble.com/laravel/5.8/ja/eloquent.html)
>主キー
Eloquentは更にテーブルの主キーがidというカラム名であると想定しています。この規約をオーバーライドする場合は、protectedのprimaryKeyプロパティを定義してください。

予想通り。しかもちゃんとオーバーライドも用意されてた（当たり前か）

というわけでEloquentモデルのClientクラスに以下の１行を追加します。

``` Client.php
protected $primaryKey = 'client_id';
```

これで問題なく保存できるようになりました。


## 余談
今回取り上げたIDリクワイアドですが、SQLアンチパターンの中では賛否両論あるパターンのようです。
[SQLアンチパターン「IDリクワイアド」の再検討](https://tgk.hatenadiary.org/entry/20130305/1362485154)

自分は単純にReadableなプログラムを目指す中で取り入れてみましたが、もう少し勉強して検討した方がよさそうですね。
DataBindingでバインドした変数を、includeタグで読み込んでいる他のレイアウトで利用したい

# 実現したいこと
 
![DataBindingイメージ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306161/cabf189f-b2bd-561f-e107-5419a27fdd05.png)

登場ファイル

- MainActivity.kt
- MainViewModel.kt
- activity_main.xml
- contents_main.xml

Activity(`MainActivity.kt`)のレイアウトファイル(`activity_main.xml`)に、`include`タグで他のレイアウトファイル(`contents_main.xml`)を読み込んでいる場合に、`DataBinding`を用いて`MainActivity.kt <=> MainViewModel.kt`間でバインドしたデータを`contents_main.xml`で利用したい。

#解決法
###`contents_main.xml`で定義した変数を`activity_main.xml`の`include`タグ内で渡す

```contents_main.xml
<layout>
    <data>
        <variable
            name="foo"
            type="String"/>  
    </data>

    …
</layout>
```
上記のように、`contents_main.xml`に変数(`foo`)を定義する。

```activity_main.xml
<layout>
    …
    <data>
        <variable
            name="vm"
            type="com.example.MainViewModel" />
    </data>

    <FrameLayout>
        …
        <include
            android:id="@+id/contents"
            layout="@layout/contents_main"
            app:foo="@{vm.hoge}" /> /* ←ココ */ 

    </FrameLayout>
</layout>
```
上記のように、`contents_main.xml`で定義した変数(`foo`)に、`MainActivity.kt <=> MainViewModel.kt間`でバインドしたクラスを利用して値を`include`タグの属性にセット（言い方合ってるかわかりません）する。


```contents_main.xml
<layout>
    <data>
        <variable
            name="foo"
            type="String"/>  
    </data>

　　<TextView
        …
        android:text="@{foo}" />
    …
</layout>
```

これで上記のように`contents_main.xml`で使えるようになりました！


#参考
[Data Binding Library](https://developer.android.com/topic/libraries/data-binding?hl=ja)
[DataBindingのあれこれ](https://qiita.com/ushi3_jp/items/9478ff18c496746519d2)
インターフェースを派生したクラスを取得する

抽象クラスの派生先は以下でとれる

```c#:code.cs
//Tは抽象クラス
var types = Assembly.GetAssembly(typeof(T))
                   .GetTypes()
                   .Where(type =>
               {
                   return type.IsSubclassOf(typeof(T))
                    && !type.IsInterface
                    && !type.IsAbstract;
               });
```

が、インターフェースの派生先はこれでは取れないので　↓

```c#:code.cs
//Tはインターフェース
var types = Assembly.GetAssembly(typeof(T))
                    .GetTypes()
                    .Where(type =>
                {
                    return typeof(T).IsAssignableFrom(type)
                     && !type.IsInterface
                     && !type.IsAbstract;
                });
```

抽象クラスとインターフェースは除外している
所有権が適切に設定されているのにシンボリックリンクが開けないといわれた件について

## TL;DR
chroot の影響を受けるユーザーは、chroot で設定されているディレクトリよりもシンボリックリンクの参照先が上位にある場合、適切な所有権を有していても、シンボリックリンクの参照先の操作はできない。
シンボリックリンクの参照先のファイルを操作したい場合は、`mount` コマンドで設定すれば、操作することができる。

## シンボリックリンクの参照先のファイルを操作する場合の対応

前提として

```shell-session
$ whoami
qiita
$ pwd
/home/qiita
$ ls -l ~/
drwxr-xr-x 10 qiita qiita    6144 Jun 14 09:59 public_html -> /mnt/efs/qiita/www/public_html
```

となっているとする。

### mount コマンドの場合

一時的な対応であれば、mount コマンドで実行してしまう。

```shell-session
$ mount --bind /mnt/efs/qiita/www/public_html /home/qiita/public_html
```

### 継続的に設定を反映する場合

`/etc/fstab` に記述する。

```shell-session
$ sudo vim /etc/fstab
/mnt/efs/qiita/www/public_html  /home/qiita/public_html  none  bind
$ sudo mount -a
$ ls -l ~/
drwxr-xr-x 10 qiita qiita    6144 Jun 14 09:59 public_html
$ ls ~/public_html/
index.html
```

## 教訓

FTP や SFTP でログインするユーザーがいる場合、セキュリティ上の理由から chroot で参照できるディレクトリに制限をかけられている場合がある。

chroot をかけられているユーザーがいるかどうかを確認する場合

### SSH ならば

```shell_session
$ cat /etc/ssh/sshd_config | grep ChrootDirectory
```

として、制限が設けられているユーザーの有無を確認する。

### ftp ならば、

FTP サーバーが動いていることを確認して、

```shell-session
$ sudo netstat -natp | grep ":21 "
tcp        0      0 0.0.0.0:21                  0.0.0.0:*                   LISTEN      2046/vsftpd
```

FTP サーバーの設定ファイルを確認する。vsftpd の場合は、

```shell-session
# chroot_local_user: ユーザのログインディレクトリを、そのユーザのルートディレクトリに変更 (chroot) する
chroot_local_user=YES
chroot_list_enable=YES
chroot_list_file=/etc/vsftpd/chroot_users
```

で、chroot が有効になっているかを確認して、対象ユーザーのルートディレクトリを確認する。
運用業務で役に立つ「ファイル名を指定して実行」コマンド

「ファイル名を指定して実行」からWindowsアプリケーションを起動するコマンドの内、運用業務で役に立つものの覚書です。

すでに覚書を書かれている方がいらっしゃいますが、自分が運用業務で使用しているコマンドとは、差異があったので覚書を残しました。

- [「ファイル名を指定して実行」を極める](https://qiita.com/sta/items/4b70e6b130a1033dc2c5)
- [「ファイル名を指定して実行」で、よく使うやつ](https://qiita.com/usop4/items/389ee355625641486d98)
- [windows ファイル名を指定して実行覚書](https://qiita.com/suvene@github/items/454e4f9fb9e426a5c40f)


##起動方法
「ファイル名を指定して実行」からWindowsアプリケーションを起動する方法です。

1. Win + r キー
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298692/ff476292-3a6c-b2cc-3ad2-5599a9ced141.png)

2. コマンド入力
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298692/ae3c8bae-2609-5b66-ba96-cb01e292866b.png)


3. Enter キー（Ctrl + Shiftと一緒にEnterキーで管理者実行）

アプリケーションが起動する。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298692/21bbcf66-1a83-8a8c-3512-e07e78a26697.png)


##「ファイル名を指定して実行」を使うメリット

- Windows OSバージョンごとの起動手順の違いがない。
※特にWindows Server 2008と2012の、GUIでの起動手順は大きく違います。

- GUIよりも、アプリ起動までの手数が少ない。

- デスクトップにショートカットを作る手間が省ける。


##よく使うコマンド

| コマンド          | アプリケーション |
|:-----------------|:------------------|
| mstsc             | リモートデスクトップ |
| notepad          | メモ帳 |
| cmd              | コマンドプロンプト |
| services.msc      | サービス |
| taskschd.msc      | タスクスケジューラ |
| appwiz.cpl        | アプリケーションの追加と削除 |
| perfmon           | パフォーマンスモニタ |
| eventvwr          | イベントビューア |
| taskmgr            | タスクマネージャ|
| mspaint          | ペイント |
| excel            | エクセル |
| calc             | 電卓 |
| winver            | OSのバージョン確認 |

※エクスプローラは「explorer」ではなく「Win + e」で起動します。
※cmdはCtrl + Shiftと一緒にEnterキーで管理者実行になります。

##たまに使うコマンド

| コマンド          | アプリケーション |
|:-----------------|:------------------|
| inetcpl.cpl       | インターネットオプション |
| ncpa.cpl          | ネットワーク接続 |
| lusrmgr.msc       | ユーザの管理 |
| firewall.cpl      | Windowsファイアウォール |
| diskmgmt.msc      | ディスクの管理 |
| regedit           | レジストリエディタ |
| powercfg.cpl      | 電源 |
| sysdm.cpl         | システムのプロパティ |
| gpedit.msc        | ローカルグループポリシーエディタ |
| iexplore         | インターネットエクスプローラ |
| chrome           | クローム |
| outlook          | アウトルック |
| powerpnt         | パワーポイント |
| winword          | ワード |


##コントロールパネル、管理ツール

上記以外のアプリケーションを起動するためや、コマンドを忘れてしまった時に使用します。

| コマンド          | アプリケーション |
|:-----------------|:------------------|
| control          |コントロールパネル |
| control admintools| 管理ツール|
エクセルでJAVAアプリを超簡単生成！「ワンダーロボ」ビューのオプション(コード、比較、条件、条件間、order by)の使い方

###ステップ1.ビューを作成する
###ステップ2.ビューのオプションを設定する
###ステップ3.ビューの確認
---
###ステップ1.ビューを作成する

この「入庫出庫情報一覧」ビューは、「在庫」テーブルと「会社」テーブルを結合しています。
※結合関係の書き方は、文字列の折り返しが不可になります。

そして、各項目は参照フィールドに設定されています。
※下の図を参照
<img width="1126" alt="21.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/1c8341c1-fcdf-e5d1-24ce-5e57a1f8cd66.png">



・在庫テーブル
「入庫出庫情報一覧」ビューは「在庫」テーブルの赤線に囲まれている下記項目を参照フィールドに指定しています。
参照フィールド：「注文書NO」「出入庫時間」「出入庫状態」「商品名称」「単位」「数量」「単価」「合計」
<img width="1128" alt="16.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/d55d5d4e-53d9-bc51-92b2-7c022a44c98a.png">

・会社テーブル
「入庫出庫情報一覧」ビューは、「会社」テーブルの赤線に囲まれている下記項目を参照フィールドに指定しています。
参照フィールド：「会社名」
<img width="1128" alt="17.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/ed85badb-8867-25ba-5099-97c332c1759f.png">
---
###2.ビューのオプションを設定する
次にビューのオプションを設定します。
「コード」「比較」「条件」「条件間」「ORDER BY」を自由に設定します。
<img width="1128" alt="061305.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/2a78b790-a850-f46e-b2df-69dae598b9c1.png">

**コード**：項目に候補値リストを設定する場合、○をつけると自動的にSQL文「case when else end」を設定します。（例：0：日本；1：アメリカ）
**比較**：抽出条件の演算子（例：より大きい）
**条件**：比較用の条件値。（例：concat,date_format）
**条件間**：抽出条件間の結合条件※2つの条件間には空白不可
**ORDER BY**：ビューの検索結果の表示順

---
###ステップ3.ビューの確認
SaaSForceの開発環境にログインし、設計書ファイルをインポートします。そして、利用画面で反映されているか確認して完了です。
SaaSForceシステム===>「システム」===> 「開発設定」===> 「システム自動構築」

そして、SaaSForceシステム===>「テーブル」===> 「ビュー定義・作成」からインポートしたビューを確認します。
<img width="593" alt="061307.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/368b010b-1c3b-a15e-1cff-e56c0a2a6d08.png">
エクセルでJAVAアプリを超簡単生成！「ワンダーロボ」ビューID、ビュー名と結合関係の設定方法

ステップ1、2、3でビューIDとビュー名、結合関係の設定方法を説明します。

###ステップ1.ビューID、ビュー名の入力
###ステップ2.ビューの結合関係
###ステップ3.ビューの確認
---
###ステップ1.ビューID、ビュー名の入力
ビューを設計した時に、ビューIDとビュー名を入力します。
下記図の「会社仕入れ先検索」ビューは、「会社」テーブルを参照しています。
赤色の項目は、必須入力になります。この時に「ビューID」「ビュー名」「メインテーブル」「参照テーブル」「区分」を設定していきます。
<img width="1128" alt="20.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/a7949b69-cdaf-02cb-2042-6d2ad2c2c367.png">
---
###ステップ2.ビューの結合関係

図1の「入庫出庫情報一覧」ビューは、図2「在庫」テーブルと図3「会社」テーブルを結合して設定されていきます。
そして、テーブルの各項目は、「参照フィールド」にて設定していきます。

※「結合関係」の記述では、各「テーブル指定」「条件指定」の途中で、改行による文字列の折り返しをしない。
※図1
<img width="1128" alt="061303.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/35f6de4f-e75d-f6ef-858f-bec3239fd300.png">



・在庫テーブル
「入庫出庫情報一覧」ビューで、「在庫」テーブルの赤線に囲まれている各項目は、「参照フィールド」にて設定しています。
#####参照フィールド：
①「注文書NO」
②「出入庫時間」
③「出入庫状態」
④「商品名称」
⑤「単位」
⑥「数量」
⑦「単価」
⑧「合計」
※図2
<img width="1128" alt="061302.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/60495898-896f-95a0-e04e-2135abb5d10b.png">


・会社テーブル
「入庫出庫情報一覧」ビューは、「会社」テーブルの赤線に囲まれている下記項目を参照フィールドに指定しています。
#####参照フィールド：
⑨「会社名」
※図3
<img width="1128" alt="061304.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/df358a79-d7f5-d5b5-275d-7c76567e3aa2.png">
---
###ステップ3.ビューの確認
SaaSForceの開発環境にログインし、設計書ファイルをインポートします。
SaaSForceシステム===>「システム」===> 「開発設定」===> 「システム自動構築」

そして、SaaSForceシステム===>「テーブル」===> 「ビュー定義・作成」からインポートしたビューを確認します。
<img width="592" alt="061308.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184885/868127a6-cb8b-9cd4-ab6a-2b98f0335f15.png">
Quantopianで使えるデータまとめ（2019年6月現在）

Smart Trade社インターン生として、トレードアルゴリズム開発の自社プラットフォームQuantXとアメリカのQuantopianとの違いをリサーチしています。今回は開発者がトレードの指標として使えるデータについてです。

# QuantXで利用できるデータ（2019年6月10日現在）

### 1.日本の日次株式取引データ
株式分割調整前と後それぞれの始値、終値、安値、高値と出来高、売買代金が3年分使用できます。

### 2.中国の日次株式取引データ
内容は日本のデータと同様です。

### 3.（エンジン換装後利用可能になる予定）bitflyer.jpの取引所データ
取引価格、bid価格、ask価格それぞれの始値、終値、安値、高値およびbid、askの板の厚さ、出来高の数値が利用できます。


# Quantopianで利用できるデータ（2019年6月10日現在）
公式一覧：　https://www.quantopian.com/data?type=free

### [1.Daily Pricing（テクニカル）](https://www.quantopian.com/docs/data-reference/daily_pricing)

金融商品の日次取引データです。世界26ヶ国に対応しており、日本については東証、JASDAQ、大阪取引所、名古屋証券取引所、福岡証券取引所、札幌証券取引所のデータが利用できます。その他対応している国一覧はこちら： https://www.quantopian.com/docs/data-reference/overview#supported-countries-data-reference 

中身は（株価調整後の）始値、終値、安値、高値、出来高です。QuantXとは異なり、株価調整前のデータを持ってくることはできません。2004年1月1日以降のデータが使えます。

### [2.FactSet Fundamentals（ファンダメンタルズ）](https://www.quantopian.com/docs/data-reference/factset_fundamentals)

FactSet Research System社提供のファンダメンタルデータです。決算書データ、ビジネス区分、地理的区分などのデータが含まれます。
同じく世界26ヶ国に対応していて、2004年1月1日以降のデータを使えます。

### [3.Morningstar Fundamentals（ファンダメンタルズ）](https://www.quantopian.com/docs/data-reference/morningstar_fundamentals)

同じくファンダメンタルズのデータですが、こっちはアメリカの金融商品に特化しています。アメリカの企業の経済的パフォーマンスを評価する600以上の指標が含まれています。2002年1月1日以降のデータが使えます。

### [4.FactSet Estimates - Consensus（ファンダメンタルズ）](https://www.quantopian.com/docs/data-reference/estimates_consensus)

FactSet Research System社提供のマーケットコンセンサスデータ、つまり企業の発行する決算書に基づいてアナリストが作成したパフォーマンス予想の平均（中庸？）です。世界26ヶ国に対応していて、2004年以降のデータが使えます。

### [5.FactSet Estimates - Actuals（ファンダメンタルズ）](https://www.quantopian.com/docs/data-reference/estimates_actuals)

FactSet Research System社提供の、企業の「実際の」パフォーマンスを示すデータです。企業の分析をする際に使用します。基本的には各企業のプレスリリースから計算されますが、プレスリリースが存在しない場合は前のイベントに対するコンセンサスから計算されます。

### [6.FactSet RBICS Focus](https://www.quantopian.com/docs/data-reference/rbics_focus)

FactSet Research System社提供の企業分類データです。世界26ヶ国の上場企業のIR情報を用いてその企業が営業するセクターを判別しています。北アメリカの企業に関しては2004年以降のデータが、アジアの企業に関しては2011年以降のデータが使えます。その他の地域に関してはこちら： https://open.factset.com/products/factset-rbics/en-us

### [7.Equity Metadata](https://www.quantopian.com/docs/data-reference/equity_metadata)

FactSet Research System社提供の金融商品の種類に関するデータです。証券のタイプや証券が発行されている通貨などの情報が得られます。世界26ヶ国の企業に対応しており、北米のものに関しては2004年以降、アジアに関しては2011年以降のデータが使えます。（他の地域に関しては上記リンク参照）

### [8.PsychSignal Trader Mood（センチメント）](https://www.quantopian.com/docs/data-reference/psychsignal)

PsychSignalという、自然言語処理技術を用いてSNSを解析しトレーダーの気分を数値化する企業が提供するセンチメントデータです。2009年6月以降のアメリカのデータのみが使えます。
解析対象となっているSNSはTwitterとStocktwitsです。

### [9.Sentdex News Sentiment（センチメント）](https://www.quantopian.com/docs/data-reference/sentdex)

Sentdexという、ある出来事に対する人々の感情をコンピュータ言語化する企業が提供しているセンチメントデータです。QuantopianではウォールストリートジャーナルやCNBC、フォーブスなど20以上のニュースソースから得た金融イベント情報に対するネット上の人々の反応を数値化したデータが利用できます。2013年6月以降のアメリカのデータのみが使えます。

### [10.Quandlのデータ](https://www.quandl.com/)
Quandl社の提供データいろいろ

# 終わりに
利用可能なデータは変更になる可能性があります。本記事は2019年6月時点での情報です。
Aura コンポーネントで Google Fonts を使ってみる

Google Fonts のフォントを Aura コンポーネントから読み込めるか試してみました。

# CSP 信頼済みサイトに登録
Google Fonts を使う場合、 font-face が大量に記述されたスタイルシートを読み込む必要があります。これは、https://fonts.googleapis.com 上で提供されており、Aura コンポーネントから読み込むには `設定 > セキュリティ > CSP 信頼済みサイト` で事前に登録しておく必要があります。

<img width="640" alt="スクリーンショット 2019-06-14 15.33.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26378/b539e0fe-560f-dbbc-79f7-3860dcdff91d.png">


# @ import で読み込む
フォントを読み込む時は、.css ファイル内で Google Fonts が指定する通りに記述すればすぐに使えるようになります。
今回は [Great Vibes](https://fonts.google.com/specimen/Great+Vibes) というフォントを読み込んでみました。


```html:GoogleFonts.cmp
<aura:component implements="flexipage:availableForAllPageTypes" access="global" >
    <div>
        <p >A red flare silhouetted the jagged edge of a wing.</p>
        <p class="GreatVibes">A red flare silhouetted the jagged edge of a wing.</p>
    </div>
</aura:component>
```

```css:GoogleFonts.css
@import url('https://fonts.googleapis.com/css?family=Great+Vibes&display=swap');
.THIS .GreatVibes {
    font-family: 'Great Vibes', cursive;
}
```

以下が表示結果です。
フォントを指定した \<p> タグ内のテキストのみフォントが適用されているのがわかります。

<img width="640" alt="スクリーンショット 2019-06-14 15.39.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26378/5a6419f5-616e-e8c5-f594-5e5202c5a7ec.png">
sqlplusの場所

# sqlplusの配置場所がわからない
コマンドプロンプトでsqlplusを打つと起動するけど、exeの場所どこだっけ。

#結論
winキー押下
↓
（Windowsメニューが出た状態で）
sqlplusと入力
↓
検索結果に
sqlplus コマンドの実行
が出るのでクリック
↓
sqlplus.exeが起動する
タイトルバーにexeのフルパスが表示されている
BitbucketでSSH接続

# 既に公開鍵が作成されているか確認
```
$ cat ~/.ssh/id_rsa.pub

cat: /home/vagrant/.ssh/id_rsa.pub: そのようなファイルやディレクトリはありません
```
と、返ってきたら鍵を作る必要があります。

# SSH認証の公開鍵と秘密鍵の作成
```
    $ cd ~/.ssh
    $ ssh-keygen -t rsa -C mail@mail   <----自分のメールアドレス
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/vagrant/.ssh/id_rsa):　　　<-----Enterを押す
    Enter passphrase (empty for no passphrase): 　　　　　　　　　　　　　　<-----Enterを押す
    Enter same passphrase again: 　　　　　　　　　　　　　　　　　　　　　　<-----Enterを押す
    Your identification has been saved in /home/vagrant/.ssh/id_rsa.
    Your public key has been saved in /home/vagrant/.ssh/id_rsa.pub.
    The key fingerprint is:
    0f:19:40:a4:36:b4:89:42:b0:e2:f4:b2:5b:ce:85:39 mail@mail
    The key's randomart image is:
    +--[ RSA 2048]----+
    |o.  .o+          |
    |.. o + .         |
    |+.. *   .        |
    |+... .   o       |
    | o .    S        |
    |  o o    o       |
    | . E .    .      |
    |  = o            |
    | . o             |
    +-----------------+
```

これで公開鍵と秘密鍵が作成されました。

```
id_rsa: 秘密鍵
id_rsa.pub: 公開鍵、 Bitbucketに登録する
```

# ~/.ssh/configにSSHキーの設定
configに設定を書いていきます。なければ以下のコマンドで作ることもできます。

```
$ vi ~/.ssh/config
```

configに以下を書き込みます。

```
Host bitbucket.org
  HostName bitbucket.org
  IdentityFile ~/.ssh/id_rsa
  User git
```

設定は以上です！

#  Bitbucketに公開鍵を登録する
- Bitbucketにアクセス後、左下のユーザーアイコンを選択すると「Bitbucket settings」が表示されるので選択します。
<img width="1346" alt="スクリーンショット 2019-06-14 12.29.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364469/33ccc7b9-c88d-f145-4bf1-99f7e035e7f7.png">


- セキュリティのSSH鍵を選択します。
<img width="1346" alt="スクリーンショット 2019-06-14 12.29.38.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364469/d159fcf4-58c9-b4de-1678-c38c5df83a73.png">

- 鍵を追加を選択します。
<img width="1360" alt="スクリーンショット 2019-06-14 12.30.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364469/13b28fcd-db0e-06e9-6c32-295b5d2f3282.png">


- SSH鍵登録
以下のコマンドで公開鍵を表示し、「ssh-rsa〜自分のメールアドレス」をコピーします。

```
$ cat ~/.ssh/id_rsa.pub
ssh-rsa
**************************************************************************
**************************************************************************
mail@mail
```

コピーした公開鍵を key に貼り付けます。
Label はなんでもいです。

<img width="1360" alt="スクリーンショット 2019-06-14 12.30.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364469/0a97bb38-ec27-0381-5e2d-656b029af1eb.png">

鍵の追加を選択し、完了です。

# 接続の確認
以下のように表示されれば正常に接続できています。

```
$ ssh -T git@bitbucket.org
logged in as アカウント名.
You can use git or hg to connect to Bitbucket. Shell access is disabled.
```

# エラーが出る場合

```
Bad owner or permissions on /home/hoge/.ssh/config
```

上のエラーが出る場合、パーミッションや所有者を確認する必要があるようですが、
ほとんどの場合、以下で解決できるそうです。権限を変えてあげましょう。

```
$ chmod 600 ~/.ssh/config
```

# 参考記事
https://bokunonikki.net/post/2018/0301_bitbucket_ssh/
https://qiita.com/colorrabbit/items/837810ef6176b3b6f4cc
ストアド(PLSQL)でバッチを作る時の色々

最近引越しが終わった人です。

ここ数週間は業務用のバッチをストアドで書くことが多かったのでその時の注意メモ
特に夜間バッチ系で動くやつは速度やエラーハンドリング間違えると
監視の都合で検知はされると思いますが、まあ中々致命的な問題も引き起こすケースありますからね。

今から話す内容は[この本](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AEOracle-SQL%E5%85%A5%E9%96%80-Oracle-12c%E3%80%8111g%E3%80%8110g%E5%AF%BE%E5%BF%9C-Oracle%E7%8F%BE%E5%A0%B4%E4%B8%BB%E7%BE%A9/dp/4797377070/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=pl%2Fsql&qid=1560490585&s=gateway&sr=8-1)を購入して読めばこの記事で書いてあること大体できると思うので
ぜひ読んでみてください。

(SQLが書けること前提ですです)




# 速度編

## バルク処理
自分はoracle12c環境でゴリゴリ書いているわけですが、
実はSQLの記載とPL/SQLの記載って実行エンジンが違うそう。
なのでエンジンが細かく切り替わる記載方法はコストがかかるので良くないそう

```sql:SQLエンジン
SELECT 1
  FROM DUAL;
```

```sql:PL/SQLエンジン
WK_NUM := 1 + 1;
```

簡単に言うとこういう記述を同じSQL内で書けますが、
内部的に解析するエンジンが違うぽいですね。

よくある例で__FOR～LOOP__と__FORALL__では
FORALLのほうが早いと言われていますが、これはFORALLの記載がPLSQLエンジンのみ処理するからです

詳しくは[ここ](https://www.oracle.com/technetwork/jp/database/articles/plsql101/o52plsql-1709862-ja.html)に書いてますね。

EMP表にNUMという数字を入れるカラムを作成して10000行入れると言う単純な処理を書いたときに2つを比べると処理に差が出てくるので試してみてください。

```sql:ダメな例
DECLARE
BEGIN
    --FOR記載のPLSQLエンジンと
    --INSERT分のSQLエンジンの切替にコストが掛かる
    FOR I IN 1..10000 LOOP
        
        INSERT INTO EMP
        VALUES(I);
        
    END LOOP;
    COMMIT;
END;
```
```sql:良い例
DECLARE
    --タイプ作成
    TYPE HOGE_T IS TABLE OF EMP.NUM%TYPE INDEX BY PLS_INTEGER; 
    --リスト作成
    L_HOGE   HOGE_T;
BEGIN
    
    FOR I IN 1..10000 LOOP
        --リストに要素を拡張
         L_HOGE(L_HOGE.COUNT + 1) := I;
    END LOOP;
    
    --PLSQLエンジンのみで一括格納
    FORALL I IN 1 .. L_HOGE.COUNT
    INSERT INTO EMP
    VALUES(L_HOGE(I));
    
    
    COMMIT;
END;
```

## ストアドファンクションのコールについて
たまに「共通化や！！！」みたいなことを言ってカプセル化をする人多いのですが、
ビジネスロジックが99%のこの言語では、可読性も大事ですが、速度は維持したい所。
ですがなんでもカプセル化して共通化して頭を殺して使用するとブーメランが帰ってきます。

### ファンクション内でSQLエンジンを動かすリスク
例えばとある管理マスタの項目の数字を引数の数字と掛け算して返すというモジュール作ります。
(先程のEMP表を使います1レコードしか帰ってこない前提で)

```sql:ファンクション
CREATE OR REPLACE FUNCTION FN_MULTI_MASTER
(
    IN_NUM     IN NUMBER
) RETURN NUMBER
IS
    WK_RTN NUMBER;
BEGIN
    SELECT EMP.NUM * IN_NUM
      INTO WK_RTN
      FROM EMP
    ;
    RETURN WK_RTN;
END FN_MULTI_MASTER;
```

これに対してSELECT文で下記の様な使い方をすると…

```sql:ダメ
SELECT FN_MULTI_MASTER(10) AS NUM
  FROM DUAL
```

計算結果が帰ってきますがこれはダメなやつです。
なぜかと言うと
1. 実行計画のコストが正確に出てこない。
2. レコードの件数だけFUNCTION内部でSELECT文を実行してしまっている。
上記2点に引っかかります。
__DUAL__文ではなく、複数行あるテーブルに対して上記関数をしかけると
各レコードに対してファンクション内部のSQL文を実行するのでパフォーマンスが悪くなります。

なのでこういうときは外部結合,内部結合等を使って取得するか。
マスタの値を返すファンクションに変更してバインド変数で固めた後使用しましょう。



思いついたら追記していきます。
ReButtonまとめ

ReButton関連のソフト、ハードを作成上で参考にできるところをまとめました。
I2C、UART for debugが無いので今後充実させたいです。

#イベント
ALGYAN(あるじゃん)主催 公式イベント！
ReButton+IoT Central体験
[ALGYAN](https://algyan.connpass.com/event/)

#Qiita
[ReButtonをArduinoで開発]
(https://qiita.com/sera_ramon/items/691726bbde61e02ebbf1)
[ReButton を MicroPush Bot を押すリモートボタンにする]
(https://qiita.com/ma2shita/items/6c82aea07e9e612d1078)

#GitHub
[Rebutton - ReButtonの全ての情報収集可能]
(https://seeedjp.github.io/ReButton/README-ja)
[ReButtonApp - ReButtonのファームを作成するならここから]
(https://github.com/SeeedJP/ReButtonApp)
[タッチアンドトライ ~ ReButton ~@ALGYAN](https://github.com/algyan/touch_and_try-ReButton/blob/master/readme.md)

#SlideShare
[ReButton Internal - ReButtonの歴史が解る]
(https://www.slideshare.net/TakashiMatsuoka2/rebutton-internal)

#blog
[Seeed ReButtonを動かしてみる]
(http://matsujirushi.hatenablog.jp/entry/2019/01/23/171257)
[Seeed ReButtonでメール送信]
(http://matsujirushi.hatenablog.jp/entry/2019/01/28/214300)
[Seeed社のReButtonの紹介@オモシロインク](http://omoshiroinc.com/2018/12/04/rebutton001/)

#UART for debug

#I2C Groveコネクタ 3.3V IO

#SWDデバッグ

#購入
[ReButton@Seeed](https://www.seeedstudio.com/ReButton-p-2930.html)
Golang テスト実行時の循環参照でハマった話

GodeAPIを作り始めたのはいいのですが、コントローラーのテストを行なった際に循環参照が発生してハマりました。フレームワークはginを使用しています


# 循環参照が発生するソース

```go:/controller/user_controller_test.go
package controller

import (
>..."github.com/ashiato/config"
>..."github.com/ashiato/db"
>..."github.com/stretchr/testify/assert"
>..."net/http"
>..."net/http/httptest"
>..."testing"
)

//func TestLoginSuccess(t *testing.T) {
func TestIndexSuccess(t *testing.T) {

>...//DB接続
>...db.Init()

>...//ルーティング設定
>...router := config.Router{}
>...ro := router.LoadRoute()

>...w := httptest.NewRecorder()
>...req, _ := http.NewRequest("GET", "/user", nil)
>...ro.ServeHTTP(w, req)

>...assert.Equal(t, 200, w.Code)
}
```

```go:/config/router.go
package config

import (
>..."github.com/ashiato/controller"
>..."github.com/gin-gonic/gin"
)

type Router struct{}

// Init is initialize server
func (ro Router) Init() {
>...r := ro.LoadRoute()
>...r.Run()
}

func (ro Router) LoadRoute() *gin.Engine {
>...r := gin.Default()

>...u := r.Group("/user")
>...{
>...>...ctrl := controller.UserController{}
>...>...u.GET("", ctrl.Index)
>...}

>...return r
}

```

テストはhttps://gin-gonic.com/ja/docs/testing/ に習ってrouter.goのLoadRouteを呼び出しています。そのためgithub.com/ashiato/configパッケージを読み込んでいるのですが、
router.goはコントローラーのメソッドを呼び出しているためgithub.com/ashiato/controllerが必要です、この時循環参照が発生します。

configに入っているrouterをcontrollerに持っていくとソースの見通しが悪くなり、逆もまた然り、
かと行ってテストでルーターを作成するのは2重管理になってしまい嫌です。

そんな時こちらの記事をでこんな記載がありました

https://budougumi0617.github.io/2018/08/19/go-testing2018/

抜粋

>Goは同じディレクトリ以下に複数のpackage名を許さないが、例外的にxxxパッケージとxxx_testパッケージは同じディレクトリに共存できる。
当然異なるパッケージになるので、非公開メソッドなどは参照できなくなるが、循環参照を回避できる。
また、非公開な機能をexport_test.goを介してアクセスすることもできる。

なるほど、そういうことでしたか！

ということで修正します

```go:/controller/user_controller_test.go
package controller_test    // 変更

import (
>..."github.com/ashiato/config"
>..."github.com/ashiato/db"
>..."github.com/stretchr/testify/assert"
>..."net/http"
>..."net/http/httptest"
>..."testing"
)

//func TestLoginSuccess(t *testing.T) {
func TestIndexSuccess(t *testing.T) {

>...//DB接続
>...db.Init()

>...//ルーティング設定
>...router := config.Router{}
>...ro := router.LoadRoute()

>...w := httptest.NewRecorder()
>...req, _ := http.NewRequest("GET", "/user", nil)
>...ro.ServeHTTP(w, req)

>...assert.Equal(t, 200, w.Code)
}
```

これでうまくいきました、まだまだGolangと仲良くなれません。
Windows10でIME入力切替時に画面中央に出る表示を消す方法

#はじめに
Windows10でIME入力切替の時に表示される「A」とか「あ」とかを消す方法です

##現象
**コイツです**
![ime-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/e71c08bc-72df-a76a-fc25-f1496aa04417.png)　　　　　　![ime-02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/72353d7f-2816-b77d-a7ac-3fc5852abfc3.png)

さあ、消していきましょう

##対処方法
１・タスクバーのIMEを右クリック、[プロパティ]を選択
![ime-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/a26a9409-43b7-d90c-c223-fdffd0deb37c.png)
２．[IMEモード切替の通知]-[画面中央に表示する]のチェックを外す
![ime-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437338/024c2f7b-c1b9-bdc4-de96-b903ec12d652.png)
３．OKをOKする

##結果
消えます

#おわりに
Microsoft社はなんでこんなに大きくしたんでしょうか

【Windows10 Senior】みたいな高齢者向けなら分かりますけどね

それではまた
Rails Dockerでpostgresが起動しなくなった時の対処メモ

# 概要
dockerでpostgresが今まで起動してたのに急に起動しなくなった。

# エラー
`docker-compose up` すると下記エラーが出て失敗する。  

```コマンド
db_1   | 2019-06-14 05:53:38.017 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
db_1   | 2019-06-14 05:53:38.017 UTC [1] LOG:  listening on IPv6 address "::", port 5432
db_1   | 2019-06-14 05:53:38.023 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
db_1   | 2019-06-14 05:53:38.152 UTC [22] LOG:  database system was shut down at 2019-06-14 04:25:59 UTC
db_1   | 2019-06-14 05:53:38.158 UTC [22] LOG:  invalid primary checkpoint record
db_1   | 2019-06-14 05:53:38.158 UTC [22] PANIC:  could not locate a valid checkpoint record
db_1   | 2019-06-14 05:53:38.159 UTC [1] LOG:  startup process (PID 22) was terminated by signal 6: Aborted
db_1   | 2019-06-14 05:53:38.159 UTC [1] LOG:  aborting startup due to startup process failure
db_1   | 2019-06-14 05:53:38.162 UTC [1] LOG:  database system is shut down
docker-rails-db_1 exited with code 1
```

# 原因
`PANIC:  could not locate a valid checkpoint record`のエラーでWALログ(pg_xlog) が壊れたらしい。  

# 対処法
データベースのデータを全削除しました。  その後`docker-compose build`し直しました。
例：`docker-compose.ym`のdb >  volumesのパスのファイルを全削除
excelでハイパーリンクがついてしまう設定を変更する

[情報]-[オプション]-[文書校正]-[オートコレクトのオプション]-[オートコレクトのオプション]-[オートコレクト]-[入力フォーマット]-[インターネットとネットワークのアドレスをハイパーリンクに変更する]（深い）から☑をはずす。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277081/59b410c4-fe83-82bd-278a-1131a1fd43b3.png)
HTTPプロトコルとAjax 

最近JavaScript周辺の勉強を始めたので、ノート代わりにまとめていきます。
主に自分の学習の流れを振り返りで残す形なので色々、省いてます。
Webエンジニアの諸先輩方からアドバイスやご指摘を頂けたらありがたいです！

#HTTPプロトコルとは
HTTP(Hyper Text Transfer Protocol)は、クライアント（例えばChromeなど)とWebサーバーの間で、HTMLで記述されたWebページや画像、音声ファイルなどを転送しウェブ(World Wide Web)の世界を通信するためんのプロトコル（通信規約）です。
>メッセージやリソースに特殊文字、日本語などの複数バイトの文字バイトが含まれている場合はURLエンコードをしてから送信する。

#HTTPによる通信
HTTPでは、クライアントがサーバーにリクエストメッセージを送信しサーバーがこれに対してレスポンスを返します。通常の場合はHTTPリクエストを返すとブラウザを更新してしまい、ページ遷移する場合などにブラウザの状態をリセットしてしまいます。
>レスポンスを返した時点でサーバーは初期状態に戻り、この際サーバーはクライアントの状態を保存しません。また通常のHTTP通信では同期通信なのでレスポンスが返ってくるまでロックされて何もできない状態になります。

<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394657/eaef128d-d315-7b56-7689-2f65da5758ed.png">

#Ajaxとは
従来の同期通信を改善する為にできたのがAjaxです。
Ajax(Asynchronus JavaScript and XML)はサーバーと通信を行う為の技術です。
XMLHttpRequestというJavaScriptのオブジェクトを利用してWebサーバーと非同期通信をおこないます。
DOM操作を利用してダイナミックにWebページを書き換えるプログラミングの手法です。
>非同期通信とはサーバーからレスポンスが返ってくるのを待つことなく、他の作業を進める事ができます。この間、ユーザーは他の処理をする事ができます。逆に同期通信とはレスポンスが返ってくるまで他の作業をする事ができません。


Ajaxの重要な機能は、ページを遷移する事なくサーバーと通信を行うことです。

#Ajaxを利用した通信
Ajaxを用いたサービスで有名なものはGoogle mapです。
この場合、ユーザーによって見たい場所が変更されると、クライアント側のJavaScriptプログラムが現在のページで足りない部分を見つけて、その部分を送ってもらうようにリクエストを送信します。サーバーは、このリクエストを受信し、足りないデータの部分だけを送信します。クライアントはこれを受信し、DOMを使って必要部分を変更し表示します。
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394657/d312d644-15a2-f3f4-867c-f77cf58ed603.png">

>- Ajaxの特徴
    - 最小限のデータ通信でけで済む為、処理が高速でサーバーへの負荷が少なく、通信トラフィックへの負荷も小さい
    - 非同期通信を行うユーザーの操作をロックしない
    - Webページの更新はクライアント側で行い、ページ遷移を伴わない部分変更を行う為、高速に描画できる。
S3の署名バージョン2 廃止(2019/06/24)になるのでAWS CLIをバージョンアップした時のメモ

## 概要

[【超重要】対応しないと使えなくなるかも？！今、全S3ユーザがチェックすべき署名バージョン２の廃止について](https://dev.classmethod.jp/cloud/aws/s3-sigv2-abolition/)
を受けて社内でSigV2が使われていたものがあったのでAWS CLIをバージョンアップしました。


## 手順
### アップグレードするバージョンを確認

[公式のドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/UsingAWSSDK.html#w168aac66c21c17b9)にも書いてある通り以下のバージョンより低ければバージョンアップする必要があります。

|利用中のSDK|SDKのアップグレード要否|
|:--:|:--:|
|AWS CLI|1.11.108 にアップグレード。|


### 現在のバージョン確認

```bash
$ ./aws --version
aws-cli/1.11.24 Python/2.7.10 Darwin/17.7.0 botocore/1.4.81
```

上記の通り`1.11.108`よりもバージョンが低かったのでアップデートする

### アップグレードコマンド

```bash
$ pip install awscli==1.11.108 -t ./
```


### 確認

```bash
$ ./aws --version
aws-cli/1.11.24 Python/2.7.10 Darwin/17.7.0 botocore/1.4.81
```

あれ.....変わってない

### <font color="red">要注意!!</font>

まぁコマンド実行した時のログをちゃんと確認してればすぐ気づくこと(あとコマンドの意味的にアップグレードコマンドじゃないな..;)なんですが,既にawscliを導入しててアップグレードする場合は↓のようなのが出てると思います。

```bash
Target directory xxxxx/pyasn1 already exists. Specify --upgrade to force replacement.
Target directory xxxxx/s3transfer already exists. Specify --upgrade to force replacement.
Target directory xxxxx/docutils already exists. Specify --upgrade to force replacement.
Target directory xxxxx/colorama already exists. Specify --upgrade to force replacement.
Target directory xxxxx/six.pyc already exists. Specify --upgrade to force replacement.
Target directory xxxxx/rsa already exists. Specify --upgrade to force replacement.
Target directory xxxxx/awscli already exists. Specify --upgrade to force replacement.
Target directory xxxxx/botocore already exists. Specify --upgrade to force replacement.
Target directory xxxxx/colorama-0.3.7.dist-info already exists. Specify --upgrade to force replacement.
Target directory xxxxx/concurrent already exists. Specify --upgrade to force replacement.
Target directory xxxxx/six.py already exists. Specify --upgrade to force replacement.
Target directory xxxxx/jmespath already exists. Specify --upgrade to force replacement.
Target directory xxxxx/dateutil already exists. Specify --upgrade to force replacement.
Target directory xxxxx/rsa-3.4.2.dist-info already exists. Specify --upgrade to force replacement.
Target directory xxxxx/yaml already exists. Specify --upgrade to force replacement.
Target directory xxxxx/bin already exists. Specify --upgrade to force replacement.
```

既に存在しているファイルがあり上書きされなかったみたいです。
なのでログに書いてある通り `--upgrade` というオプションをつけてアップグレードしましょう


### 再度アップグレード

```bash
$ pip install --upgrade awscli==1.11.108 -t ./
```

### 確認

```bash
$ ./aws --version
aws-cli/1.11.108 Python/2.7.10 Darwin/17.7.0 botocore/1.5.71
```

これでようやくアップグレード完了
SigV2もSigV4に変わっていました

### 署名のバージョンの確認
以下の記事を参考にしてみると良いと思います

[廃止予定のS3署名バージョン2API利用をCloudWatchEventで検出してみた](https://dev.classmethod.jp/cloud/aws/check-s3-sig2-usage-cloudwatch/)

#### <font color="red">残り1週間ちょっとなので対応はお早めに</font>

### おわり
Ubuntu18.04LTS に Milkode をインストールする

## やりたいこと
ソース全文検索ツール [Milkode](https://milkode.ongaeshi.me/milk.html) をサーバに入れて、git/subversionのリポジトリにコミットされているソースを、Web上から全文検索したい.

## サーバ環境とファイル構成

OS: Ubuntu18.04LTS
Database: $HOME/.milkode/ (デフォルト)
Port: 9292 (デフォルト)

## サーバに実行環境を構築する

```shell
# install package
sudo apt install ruby
sudo apt install ruby-dev
sudo gem install milkode

# check version
ruby --version
## ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux-gnu]
milk --version
## milk 1.8.9.1

# init milkode's DB
milk init --default

# add packages to DB
#  @see https://milkode.ongaeshi.me/milk.html
milk add -p svn http://ABC.co.jp/svn/MYPROJ/trunk          -n my-project
milk add -p svn http://XYZ.com/svn/OTHERPROJ/branches/test -n other-test-project
milk add -p git https://github.com/myname/myproj.git
milk add ~/Documents/myreports/

# update DB by crontab
crontab -e
mkdir $HOME/log
sudo vim /etc/logrotate.d/homelog

# test milk web
milk web

# make milk web service
sudo vim /etc/systemd/system/milkweb.service
sudo systemctl enable milkweb
sudo systemctl start milkweb
```

* milk web にてブラウザが起動し、http://localhost:9292 にて milk add で登録したパッケージが表示されたら成功です.
* 成功を確認してから、milk web をサービス化する.

### crontab への登録内容
```shell:crontab
$ crontab -l
## Ubuntu18.04LTS default ENV:
# HOME=/home/maintainer
# LOGNAME=maintainer
# PATH=/usr/bin:/bin
# LANG=ja_JP.UTF-8
# SHELL=/bin/sh
# PWD=/home/maintainer
#
## commands
#m h D M W      commands
@daily  (date && /usr/local/bin/milk update --all)  >> $HOME/log/milk-update.log 2>&1
```

* milk add で登録したパッケージ(検索対象)を ```@daily``` のタイミングで更新する.

### logrotateの設定
* とりあえず毎日回転し10個保持する. 頻度と個数はお好みで調整する.
* milk update は root ではなく maintainer ユーザ権限で動かし、そのログファイルも $HOME/log/ にあるので、su で権限を合わせる.

```conf:/etc/logrotate.d/homelog
/home/maintainer/log/*.log {
#       size 100k
#       monthly
#       weekly
        daily
        rotate 10

        compress
        delaycompress

        su maintainer maintainer
        nocreate
        missingok
        notifempty
}
```
### service設定

```conf:/etc/systemd/system/milkweb.service
[Unit]
Description = milk web

[Service]
## milk needs enviroment $HOME.
# Environment='HOME=/home/maintainer'
# ExecStart = /usr/local/bin/milk web -n --host 0.0.0.0 --db=/home/maintainer/.milkode
User=maintainer
ExecStart = /usr/local/bin/milk web -n --host 0.0.0.0
Restart = always
Type = simple
## default output to syslog.
#StandardOutput=null
StandardOutput=file:/home/maintainer/log/milkweb.log
#StandardError=file:/var/log/milkweb.log

[Install]
WantedBy = multi-user.target
```

* 参考資料では /opt/milkweb.sh に環境変数HOMEの設定とmilkweb起動を記入しているが、serviceに直接記入してみた。
* --db= 指定があれば環境変数HOMEは不要に思えるが、それがないとmilkodeがエラーを吐く。

```log:syslog
Jun 25 13:25:12 C196 milk[25792]: /var/lib/gems/2.5.0/gems/milkode-1.8.9.1/lib/milkode/common/dbdir.rb:14:in `expand_path': couldn't find login name -- expanding `~' (ArgumentError)
```
* User=maintainer を記載すれば、HOME の設定は不要である.

## 参考資料
- [milkodeのmilk webをサービス化](https://qiita.com/shin-exer/items/b744c511141cb58b49b7)
- [Milkodeでソースコード検索](https://qiita.com/yoshihito_souma/items/9a1c50f26b238507c28f)

## END
シェルのif文でハマった話

# 作成したコード

ターミナルから意地でも離れないマンなので、ターミナル上からbitbucketを一発で開きたい…！
という思いで作成したコマンド。

```
bit [リポジトリ名] //指定したリポジトリのページを開く (e.g.)bit hoge 
```

# まず成功例

```zsh:.zshrc
alias bit="open_bitbucket"

function open_bitbucket() {
    sh open_bitbucket.sh $1
}
```

```zsh:open_bitbucket.sh
#!/bin/bash

if [ "$1" = "hoge-repository" ]; then
    open "hoge-repositoryへのURL"
elif [ "$1" = "fuga-repository" ]; then
    open "fuga-repositoryへのURL"
fi
```

# 【失敗例１】 [hoge: command not found

これはシェルを全く知らない僕がまず初めに詰んだポイントです。
↓のように書くとこのエラーが発生します。

```zsh:open_bitbucket.sh
#!/bin/bash

if ["$1" = "hoge-repository"]; then
    open "hoge-repositoryへのURL"
elif ["$1" = "fuga-repository"]; then
    open "fuga-repositoryへのURL"
fi
```

原因は**カッコ[]の中にスペースが含まれていないこと**でした。
シェルでの`[]`は条件を判定するtestコマンドの別の書き方で、if文に限らず条件式を`[]`で書くときはカッコ内の前後にスペースを入れる必要があります。

```zsh:open_bitbucket.sh
#!/bin/bash

if ["$1" = "hoge-repository"]; then #こうじゃなく
if [ "$1" = "hoge-repository" ]; then #こう
```

# 【失敗例２】 [: hoge: integer expression expected

これは、失敗例１で悩みながら色々調べてコードを変更した末にたどり着いた第２のハマりポイントでした。
コードは以下の通りです。


```zsh:open_bitbucket.sh
#!/bin/bash

if [ "$1" -eq "hoge-repository" ]; then
    open "hoge-repositoryへのURL"
elif [ "$1" -eq "fuga-repository" ]; then
    open "fuga-repositoryへのURL"
fi
```

`-eq`という演算子を使っていることが原因っぽかったです。
ど初心者なのでこんなことも知らなくて恥ずかしいのですが、`-eq`は数値の比較にしか使えないみたいですね…
[参考]http://itdoc.hitachi.co.jp/manuals/3020/30203S3530/JPAS0134.HTM
ということで、下記のように修正します。

```zsh:open_bitbucket.sh
#!/bin/bash

if [ "$1" -eq "hoge-repository" ]; then #こうじゃなく
if [ "$1" = "hoge-repository" ]; then #こう
```

# まとめ

シェルの文法は独特で慣れるまで大変そうですが、Vimmerの私としてはぜひとも慣れておきたいなと思いました。
頑張って勉強します。
FIELD関数でソートする時の記法忘れるのでメモっておく

Rails でレコード取ってくるとき普段は ActiveRecord を使うと思うんですけど、たまに Arel を使う場面あると思います。「このレコードだけ前に出したい」とか「このタイプのレコードは後ろに持ってきたい」みたいな場合とかに MySQL の FIELD 関数使ったり。

んですけど、いつも記法忘れちゃうのでここでメモっておきます。多分将来のオレは今のオレに感謝すると思う。



Article モデルのレコードが 100 件ある場合。

```ruby
Article.order([Arel.sql('field(articles.id, ?) DESC'), [10, 11, 12]]).pluck(:id)
# => [12, 11, 10, 1, 2, 3, 4, 5, ...]
Article.order([Arel.sql('field(articles.id, ?) ASC'), [10, 11, 12]]).pluck(:id)
# => [1, 2, 3, 4, 5, ..., 98, 99, 100, 10, 11, 12]
```

参考文献

- https://dev.mysql.com/doc/refman/5.6/ja/string-functions.html#function_field
- https://github.com/rails/arel
Webアプリケーションを簡単に作る仕組み

Webアプリケーションの見た目の部分はHTMLとCSSを利用、データベースとのやりとりの部分はRubyを利用して作成することがわかりました。それらを連動させ、Webアプリケーションとして機能させてくれるのがRuby on Railsなどのフレームワークです。

Ruby on Rails
Ruby on Railsは、Rubyによって構成されたWebアプリケーションにおけるフレームワーク(枠組み)です。フレームワークとは、Webアプリケーションを機能させるために必要な共通部分を予め用意するものです。アプリケーションの開発者は独自に必要なHTML/CSSやRubyの記述に時間を割くことができ、開発効率が向上します。
stm32f4-discoveryの作法 その13

#概要

stm32f4-discoveryの作法、調べてみた。
俺言語を移植してみた。

#写真

![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/11ce229a-5fb2-c21f-f417-43d3c3e774f0.png)

#サンプルコード

arduino用を移植。以下、変更点。

```
uint8_t rx_buffer[20];
void putchr(char c)
{
	char * p = "a";
	p = &c;
	uart_2_send(p, 1);
}
char getch()
{
	if (uart_2_is_interupt()) 
	{
		uart_2_clear_interupt();
		int length = uart_2_get(rx_buffer);
		return rx_buffer[0];
	}
	return;
}
void putint(uint8_t c)
{
	char s;
	char t;
	char * p = "a";
	p = &t;
	uart_2_send(p, 1);
	s = c / 100;
	if (s > 0)
	{
		t = s + 48;
		uart_2_send(p, 1);
		c = c - s * 100;
	}
	s = c / 10;
	if (s > 0)
	{
		t = s + 48;
		uart_2_send(p, 1);
		c = c - s * 10;
	}
	t = c + 48;
	uart_2_send(p, 1);
}
void setup()
{
	for (i = 0; i < MEMSIZE; i++)
	{
		WR(i, '\0');
	}
	WR(Bnd, Obj);
	putstr("\r\nore stm32f4\r\n");
}
int main(void)
{
	driver_init();
	setup();
	while(1)
	{
		char c = getch();
		if (c != NULL) onKey(c);
	}
	return 0;
}
```

#配線

```
TX  PA2
RX  PA3
```


以上。
SmartGit > featureブランチきり忘れ時の処理 > 変更内容のブランチ移動

```txt:動作環境
Windows 10 Pro (64bit) バージョン 1903
SmartGit 18.2.3 Git for Windows (git version 2.19.1.windows.1) 
```

### 参考

- [gitで「あっやべっ！」ってときに使うコマンド[随時更新]](https://qiita.com/ihcamonoihS/items/38e196651212c591dfe0)
    - by @ihcamonoihS さん
    - > [ブランチを切り忘れた！](https://qiita.com/ihcamonoihS/items/38e196651212c591dfe0#%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%82%92%E5%88%87%E3%82%8A%E5%BF%98%E3%82%8C%E3%81%9F)

情報感謝です。

## SmartGitでの操作

### 1. Save Stashする

- 1-1. [Save Stash]をクリック
- 1-2. Messageを記載して[Stash All]する

![2019-06-14_14h29_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/1dde5ad4-a09d-bcd8-c9ee-df13cf21238f.png)

![2019-06-14_14h30_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/ebd84d3e-1677-65fc-9e48-a66307c4ea44.png)

### 2. featureブランチをきる

### 3. Apply Stashする

- 3-1. [Apply Stash]をクリック
- 3-2. [Apply]をクリック


![2019-06-14_14h30_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/99064ef3-8cab-a169-267d-c85a54eef66e.png)

![2019-06-14_14h31_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/d08025d9-85de-dce0-0d30-a3e1c7a9d36c.png)


これで移動できました。

@ihcamonoihS さん
どうもありがとうございます。
「通信」と「サーバー」について勉強

　

インターネットを使ったサービスは、**サーバー**と通信しています。


PC,スマホからサーバーに情報を要求することを**リクエスト**と呼びます。
その反対サーバーから答える方を**レスポンス**と呼びます。

PC→リクエスト→サーバー
PC←レスポンス→サーバー


 私の方を**クライアントサイド**、サーバーの呼び方を、**サーバーサイド**と呼ばれます。情報を手紙のように往復でやり取りをするので、住所に当たるものが必要になります。それを**IPアドレス**と言います。例「32.34.32.1」IPアドレスを人間が分かりやすいように作られた別名が、よく見る、「○○○.com」など。この変換のことを、名前解決と呼ぶ。


自分の機会をサーバーにすることができる
IPアドレスを固定することでできる。それにはプロバイダーと別途契約が必要となる。サーバ用のOSはLinuxがよく使われています。
昔のPCは、文字を打つことしかできませんでした。これはUCIと呼ばれます。これを普及させようと推し進めたのは故スティーブ・ジョブズ氏だったりします。


リクエストされたサーバーはレスポンスを返すまでにどのような動きをしているのでしょうか。例えばサービスを作るには
  ①データを保存する仕組み
  ②サービスの仕様を反映したロジックが必要です。
ロジックは、サーバーサイドスクリプト（ruby/java/PHP）そしてデータの保存はデーターベースが担当します。データーベースが情報を保存する場所（SQLはデータベースを操作するための言語）。

ブラウザが理解できるのは、HTML/CSSだけです。データーベースやサーバーサイドスクリプトはブラウザとは全く関係ありません。
timedeltaの変換

# timestampの差を取る
データセットとしてtimestampをもらったときにその工程間の差を特徴量に使いたい。

しかしながらtimestamp同士の差をとるとtimedelta型になってしまいその後の正規化などが面倒なので秒数に変換したい。

# total_seconds()
timedelta型のメソッドtotal_seconds()を使えば解決する。

```python
diff_time = '7 days 00:56:49.317000'
# Timedelta
diff_time.total_seconds()
# 60829.317
```

# DataFrameでtotal_seconds()を適応したい
dtを使う

```python
diff_time
'''
0    6 days 23:10:44.847000
1    7 days 00:56:49.317000
2    5 days 03:00:34.800000
dtype: timedleta64[ns]
'''

diff_time.dt.total_seconds()
'''
0    601844.847
1    608209.317
2    442834.800
dtype: float64
'''
```
【小中学生向け】OSのデュアルブートについて、お話しします

[初心者編集動画]https://www.nicovideo.jp/watch/sm35247895?ref=search_tag_video&playlist=eyJpZCI6InZpZGVvX3dhdGNoX3BsYXlsaXN0X3NlYXJjaCIsInNlYXJjaFF1ZXJ5Ijp7InR5cGUiOiJ0YWciLCJxdWVyeSI6IumCqua3qyIsInBhZ2UiOjEsInBlclBhZ2UiOjMyLCJzb3J0IjoiK2YifX0&ss_pos=2&ss_id=009d3ba4-4dcc-44ad-9955-20779c918651

**OSのデュアルブートについて、お話します。**


みんな、OSの**デュアルブート**って、
知ってるかな？

デュアルブートというのはね、

例えば

**windowsが入っているストレージに、
Linuxのパーティションをつうづるっこんでやる**と、
気持ちがいい、とか

あるいは、
**Linuxを使い終わったあと、
windowsを使うと、
ハードウェアクロックが９時間前にずれていて**気持ちがいい、
といったことを、

OSのデュアルブートと言うんだ。

Linuxと、Windowsの
**デュアルブートの難しさは、
各OSのハードウェアクロックに対する解釈の差**から、
来ているんだよ。

そして、
**デュアルブート環境と、
仮想化環境の利便性は、
どちらが上かな？**
もちろん、
**仮想化環境**のほうが、
**2つのOSを同時に使えて便利**だから、
上だよね？

同じストレージに
異なるOSを共存させることに、
心が集中するとね、
いつの間にかHDDの中がパーティションだらけの
**カオス状態**になって、
その子は下の世界に生まれ変わるんだって。
嫌だねぇ。

今、デュアルブートをしていない良い子は、
**パーティションをいじらずに、
Virtualboxなどの、
OS仮想化ソフト**を使おうね。

今、デュアルブートをしている子は、**windowsログイン時常に
ローカル時間を取得できるように
タスクスケジューラから設定**を変えようね！
(↓詳しくは下記のリンクからご覧ください)
https://www.lifehacker.jp/2011/08/110810windowsclockupdate.html

また、デュアルブート環境の構築中に、
**間違えてWindowsの回復用パーティションを
消してしまわないように**、
気をつけようね！（震え声）

**自分のしたい作業の効率と
利便性を大切にして、
生きようね！**
Golangで二分探索木の生成・探索をする

この記事は、[筆者ブログ](https://krgpi.github.io/)を出典としています。

## 二分探索木とは

**左の子の値 ≤ 親の値 ≤ 右の子の値** という制約がある二分木である。

### 二分探索木にデータを格納するメリット

線形リスト(配列に格納されたデータ)を0番目から順番に検索するよりも、早く目的のデータを見つけ出せる可能性がある。

ここで、要素数を $N$ とする。

木の高さ $H$ は

- 最良の場合: 平衡状態で $H = log_{2}N$ 
- 最悪の場合: 全てのノードで左(または右)だけに子が続くとき $H = N$ (線形リストと同じ)

深さ優先探索を行う場合、時間計算量は $O(log_{2}N)≤E≤O(N)$であり、線形リストの時間計算量$O(N)$に対し、削減される。

## Goでの実装
### ノードの定義

```go
type node struct {
	key   int
	value int
	left  *node
	right *node
}
```
ノードには、ノードを識別するkeyと、値(データ)を格納するvalueをまず格納する。また、左右の葉にぶら下がる子ノードへのポインタも含める。

### 木の定義
```go
type tree struct {
	root *node
}
```

### 二分探索木の生成
着目ノードの葉（左右は着目ノードの値との比較で決める）に子ノードがなければ、新たなノードを作成し値を格納する。

```go
func maketree(parentNode *node, newKey int, newValue int) {
	var childNode node
	childNode.key = newKey
	childNode.value = newValue
	if newValue >= parentNode.value {
		if parentNode.right == nil {
			parentNode.right = &childNode
		} else {
			maketree(parentNode.right, newKey, newValue)
		}
	} else {
		if parentNode.left == nil {
			parentNode.left = &childNode
		} else {
			maketree(parentNode.left, newKey, newValue)
		}
	}
}
```

### 深さ優先探索
targetNumberを右側ノードから深さ優先探索する。

```go
func findNumber(targetNode *node, targetNumber int) {
	if targetNode.value == targetNumber {
		fmt.Printf("target number[%v] found at key[%v]\n", targetNumber, targetNode.key)
	} else if targetNumber > targetNode.value {
		if targetNode.right != nil {
			findNumber(targetNode.right, targetNumber)
		} else {
			fmt.Printf("target number[%v] not found.\n", targetNumber)
		}
	} else {
		if targetNode.left != nil {
			findNumber(targetNode.left, targetNumber)
		} else {
			fmt.Printf("target number[%v] not found.\n", targetNumber)
		}
	}
}
```

### データの生成、木への格納、探索を行うメイン関数

```go
func main() {
    //格納するデータを生成
        maxValue := 1000
	var valueArray = []int{maxValue/2}
	rand.Seed(time.Now().UnixNano())
	for index := 0; index < maxValue; index = index + 1 {
		valueArray = append(valueArray, rand.Intn(maxValue))
	}

	//木と根ノードのインスタンス化
	var myTree tree
	var firstNode node
	myTree.root = &firstNode

	//二分探索木の生成
	for index := 0; index < len(valueArray); index = index + 1 {
		maketree(myTree.root, index, valueArray[index])
	}

	//探索
	findNumber(myTree.root, 100)
}
```

ここでは、平衡状態に近づけるため、根ノードを$maxValue/2$とした。実運用上では、データが新たに追加または削除されたりした場合、平衡状態に近づける(=木の高さを減らす)為に、回転(Tree Rebalancing)などの変換を行う
Ruby空配列卒業

Railsで開発していて、冗長なコードがあったので( ..)φメモメモ

#シチュエーション
例えば、UserモデルとExtraworkモデルがあり、1対多の関係で存在しているとする。
ローカル変数extraworksには、下記レコード(オブジェクト)が複数入っているとする。

ex) **Extraworkモデル**

|id|残業申請日|user_id|
|:-:|:--:|:-----:|
|1|2019.6.1|2|
|2|2019.6.2|2|
|3|2019.6.2|3|
|4|2019.6.4|3|
|…|…|…|
|29|2019.6.15|2|
|30|2019.6.15|3|
|31|2019.6.16|4|

#冗長なコード
ローカル変数extraworksから、一意のUserオブジェクトを配列として取得したい場合、
以前まで下記のように書いていた。
※Rubyでfor文はあまり使用しないと思いますが、使ったことないので使ってみました。

```ruby:
users = []

for i in extraworks do
users << i.user
end

@extrawork_applying_users = users.uniq

#.userで紐付いているUserオブジェクトにアクセス
#.uniqでUserオブジェクトの重複を取り除き、一意にする

```

#mapメソッドを使おう！

空の配列を定義するようなコードはたいていの場合、mapメソッドでシンプルにできる。
※mapメソッドの詳細については、ググればすぐに出てきますので、割愛します。
※&:も少し高度な書き方みたいですが、ググればすぐに出てきますので、割愛します。

```ruby:
@extrawork_applying_users = extraworks.map(&:user).uniq
```

#最後に
プログラミング学習のためには、ググりながら何か作ってみることが
一番効果的な方法と思っていたので、技術書には手を付けていませんでした。
ただ最近は、技術書を読んでいるとこんなことができるのかと学び・気づきの点が
多々発見でき、良い勉強になっています。

今回は[「プロを目指す人のためのRuby入門」](http://gihyo.jp/book/2017/978-4-7741-9397-7)を読んで気づきを得ました。
Windows の traceroute の注意点

# Windows の traceroute(tracert.exe) の注意点

「<b>tracert</b>」と入力したら「<b> -d</b>」と続けるように<b>体に覚えさせましょう。</b>

>C:\>tracert -?
>
>使用法: tracert [-d] [-h maximum_hops] [-j host-list]  [-w timeout]
>               [-w timeout] [-R] [-S srcaddr] [-4] [-6] target_name
>
>オプション:
>    <b>-d                 アドレスをホスト名に解決しません。</b>
>    -h maximum_hops    ターゲットを検索するときの最大ホップ数です。
>    -j host-list       host-list で指定された緩やかなソース ルートを使用します
>                       (IPv4 のみ)。
>    -w     timeout     timeout ミリ秒間、応答を待ちます。
>    -R                 往復のパスをトレースします (IPv6 のみ)。
>    -S srcaddr         使用するソース アドレスです (IPv6 のみ)。
>    -4                 IPv4 の使用を強制します。
>    -6                 IPv6 の使用を強制します。

「Windows の Traceroute は遅い」と文句言う人は大抵「-d」オプション付けていない。

# 自作した Windows 上の Tracerouteコマンドの記事

[sTcpTraceRoute Manual](https://qiita.com/tomoki0sanaki/items/b0e918787cc7cbae2865)

# 以上
dockerでとにかくGPGPU環境が欲しいときのワンライナー（Tensorflow, Pytorch, Keras諸々対応）

# はじめに
この記事はdocker、NVIDIAの環境がそろった（`nvidia-docker` `nvidia-smi` などのコマンドが通る）環境を想定して、はじめます。

# ワンライナー

```
nvidia-docker run -it  --name your_env_name -v /home/your_home_dir:/home/your_home_dir --env CUDA_​VISIBLE_​DEVICES=0 nvcr.io/nvidia/tensorflow:19.05-py3 bash
```
## 説明

- your_env_name: つくるdockerの仮想環境名
- your_home_dir: ホストOS上でのあなたのホームディレクトリ。-vオプションで仮想環境と共有することができる。ホームを共有すると便利
- CUDA_VISIBLE_DEVICES: 仮想環境で使うGPUのIDを指定する。上では0のみを使用する。通常、0~(GPU個数-1)までのGPUが指定可能。複数個指定する場合は`,`で区切る。
- nvcr.io/nvidia/tensorflow:19.05-py3: tensorflowを使用する場合の2019/6/14現在の最新版参照環境。以下のURL先を参照し適宜変更
    - 参照環境用URL
        -  https://ngc.nvidia.com/catalog/containers
        -  https://hub.docker.com/

これでとりあえず上のワンライナーで`tensorflow`環境のBASHに入ることができる。
Githubでプルリクエストを送るのが面倒

# CLIとGithubの画面の操作を行き来するのが面倒だったので


## 簡単なシェルスクリプトで自動化して
```bash
#!/usr/bin/env bash
if [ $# -eq 0 ]; then
  echo "Usage:"
  echo "git wip (branch-name) (issue-number)"
  exit 2
fi
issue_number=''
issue_title=''
branch_name=$1
if [ $# -eq 2 ]; then
  branch_name="$2/$1"
  issue_number="#$2"
  issue_title=$(hub issue | hub issue | grep $2 | xargs)
fi

git pull origin develop
git checkout -b $branch_name
git commit --allow-empty -m "[ci skip][init] $issue_number"
git push origin $branch_name
pull_request_title="[WIP] $issue_number $issue_title"
open $(echo "$pull_request_title\n\n$issue_number" | hub pull-request -F -)
```

## とりあえず package.json を書いて
```json
{
  "name": "@aileron/git-wip",
  "version": "1.2.0",
  "main": "git-wip",
  "repository": "https://github.com/aileron-inc/git-wip",
  "author": "Masahiko ashizawa <masa@aileron.cc> (http://aileron.cc/)",
  "license": "MIT",
  "bin": "git-wip",
  "files": [
    "git-wip"
  ]
}
```

( README 書いたりとか、こまごまして

## npm として登録!

```
yarn global add @aileron/git-wip
```

これで、どっからで簡単なスクリプトが入れられて便利
npm で、nodejs以外のファイルを上げてみる方法は簡単だし便利