OmniAICreator/Qiita-1.07M huggingface dataset:
【Salesforce】apex:commandButtonタグではなくbuttonタグを使用して入力項目にフォーカス時、Enterキーを押下した際にsubmitしないようにしたい

# 実現方法

```HTML:test.page
<!-- 修正前 ※入力項目にフォーカス時、Enterキーを押下でSubmitしてしまう -->
<apex:commandButton value="ボタン" action="{!method}" styleClass="slds-button slds-button_neutral" />

<!-- HTML読み込み時、typeがsubmitになるため -->
<input type="submit" value="ボタン" class="btn slds-button slds-button_neutral">

<!-- 修正後 -->

<!-- buttonなのでEnterキーで起動しない -->
<button type="button" class="slds-button slds-button_neutral" onclick="method();">
    ボタン名
</button>
<!-- onclickからApexを起動 -->
<apex:actionFunction name="method" action="{!method}"/>
```

※apex:commandButtonのtype(html-type)をbuttonに上書きしようとしたら「apex:commandButtonの属性「type」は上書きできません」とエラーになりました。

# 参考リンク

その他の方法
[Enterキーの無効化](http://sfsupport.blog.fc2.com/blog-entry-10.html)
Bootstrap5のお試しと相続税計算

Bootstrap5を試してみました。

* Bootstrap4からの移行は、3⇒4より楽そう？大きくは変わっていないような…
* jQuery依存から脱却したのは良いと思います、そこは自由であるべきと思います
* スターターテンプレートは[こちら](https://v5.getbootstrap.jp/docs/5.0/getting-started/introduction/)
* ナビゲーションバーは[こちら](https://v5.getbootstrap.jp/docs/5.0/components/navbar/) 、他は動かないサンプルもあるような
* バリデーションは[こちら](https://v5.getbootstrap.jp/docs/5.0/forms/validation/)

相続税の理解に苦しんでいるので、
Bootstrap5のお試しと↑↑の理解も兼ねて、[ざっくり相続税計算](https://www.chuo-system.co.jp/inheritancetax/)を作りました。
RaspberryPiでBluetoothのサーチ対象が影分身しちゃった話

#こんなことがあったよって話です
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/711425ce-d3bf-bcd8-6ec7-74deb8b9861d.jpeg">
EWINのbluetoothミニキーボードを買ったので、Raspberry Pi 4 Model Bにペアリング！
しかし上手くいかず…何度か失敗するうちに…
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/837803/50423f0c-9558-8e9c-ded5-cdf2e22cc47a.png">
こんな感じに…本物どれよ！？

仕方ないのでターミナルから`pair`コマンドで直接ペアリングしようと思ったけど…
何故か上手くいかない…
しかもキーボードのBluetoothボタンを押すたびにMACアドレスが変わってる！？

こんな時どうすればいいか？
とりあえず、このたくさん表示されちゃってるK02 BLE Keyboardを削除しないと、本物が分からない。
なので、ターミナルから
`sudo bluetoothctl`
`devices`
で一覧を表示、対象となるK02 BLE KeyboardのDeviceIDをチェックして
`remove xx:xx:xx:xx:xx:xx`
で削除。
すると次にペアリングしようとすると本物だけに戻ってるのでTry！
失敗したらまた削除をしながらチャレンジします。
まあ、最初に失敗しなければこんな事にはならないと思いますが…

ということで、同じようにつまずいた人の参考になればと思います。
Vagrantからlocalhostを経由してdockerコンテナのAPIをコールする

## はじめに
vagrantとdockerを併用して開発を行っています。
（vagrantの中にdockerを立てているとかではなく、それぞれ同じ階層で独立している）

なぜこんな複雑な環境になっているのかはさておき、
同じような問題で悩んでいる方がもしかしたらいるかもしれないので
備忘録として手順を残しておきたいと思います。

## やりたいことのイメージ
vagrant → ローカル → dockerコンテナ（APIサーバー）

vagrantの仮想環境からAPIを呼び出し、
localhostを経由してdockerコンテナのAPIを実行します。

## 環境構築
ここでは概要しか載せません。
具体的な環境構築手順は検索してください。

### vagrant
VirtualBoxを利用して構築します。
一般的な構築で問題ありません。

### docker
**docker-compose.yml**
ローカルホストの8081ポートをdockerコンテナの80ポートに接続します。
（ローカルホストのポート番号は自由に変更してください）

```
version: '3.5'
services:
  nginx:
    build:
      (省略)
    environment:
      TZ: Asia/Tokyo
    ports:
      - "8081:80"
      - "4431:443"
    depends_on:
      - php-fpm

  php-fpm:
    build:
      (省略)
```

## この時点でできていること
### vagrantとlocalhostの繋ぎ込み
実は初期設定でポートフォワーディングができている。
vagrant（ゲストOS）からlocalhost(ホストOS)を参照する際には`10.0.2.2`のIPを利用する。

> VirtualBox仮想マシンのネットワークはデフォルトでNATとなっている。 VirtualBox の場合、NAT ネットワークアダプタには 10.0.2.0/24 の IP アドレスが割り当てられ、ゲスト OS から見える ホスト OS の IP アドレスには 10.0.2.2 が設定される仕様。
したがってホストOS上に建てたサーバーにゲストOSからアクセスしたい場合は、http://10.0.2.2とアクセスすれば普通に見ることができる。
https://garbagetown.hatenablog.com/entry/20100313/1270039659

※ちなみに
localhost(ホストOS)からvagrant（ゲストOS）の繋ぎ込みは`127.0.0.1:2222`のIPを利用。
詳細はlocalhostで`vagrant ssh-config`で確認可能。
Workbenchをvagrant内のmysqlに接続したいときなどに便利。

```
❯ vagrant ssh-config                                                                                                                                                                             [12:45:47]
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2222
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile (省略)
  IdentitiesOnly yes
  LogLevel FATAL
```

### localhostとdockerコンテナの繋ぎ込み
前述のdocker-compose.ymlで設定した通り、
`localhost:8081`にアクセスすればdockerコンテナの`80`ポートに接続できる。


## 結論
vagrant→ローカルホスト→dockerコンテナのAPIを呼び出すには
vagrant から`10.0.2.2`のIPを利用すればOK


## 参考
https://garbagetown.hatenablog.com/entry/20100313/1270039659
【クラスとインスタンスの比喩】




お初にお目にかかります。

ここでは私自身が咀嚼した知識を吐き出してまいります。
青々しく酸っぱいのであまり参考にしないでください。
たで、同じように解釈や比喩について悩んでいる方の一助になれたら幸いです。


2021年1月22日

```
１、クラス
　クラスとは、個々にデータを持たせるための雛形である。具体的な実体を持っておらず、クラスに共通する属性やメソッドを用いてインスタンス(後述)を作成する。
　例えば、街を行き交う人に「紙の上に三角形を書いてください」と注文する。その際に各人が頭に思い描く「三角形」が、いわば設計図であるクラスと呼べるだろう。人々がどのような三角形をイメージしていても、一般的に共通する特徴はある。線が三本である、直線で描かれている、などだ。
　また、紙上へ出力するための手段がある。鉛筆を使う人もいる一方で、絵筆で描いたりする人もいる。
　この場合特徴は「属性」へ、手段は「メソッド」としてプログラミング上で扱われる。



２、インスタンス
　インスタンスとは、クラスを用いて作成され、それぞれが個別のデータを持つものである。クラスによって作成されたインスタンスは、前述の例を用いて表すならば「人々が実際に書いた三角形」であると言えよう。
　概念から生み出された三角形は、個々人によって様々である。鉛筆を用いて細い小さな一本の線で描いた者もいれば、太いマジックペンで豪快な線を描く者もいる。この場合の描かれた三角形は様々な特徴を持ち、姿は異なる。
　こうして描かれた三角形は、概念上の「三角形」、すなわちクラスから生み出され、様々なメソッドや属性を用いることでインスタンスとして表出する。
```


2021年1月27日

```
１、クラス
クラスは、インスタンスを生成するために定義される。それ自体に実体はない。
例えるならば、たいやきというインスタンスを作り出すための「たい焼き器」であると言える。たい焼きの種類はどうあれ、「鯛」の形を成し、熱によって加工される工程は共通のルールとして定義される。


２、インスタンス
インスタンスはクラスから生成され、個々に異なる値を持つものである。
上記の例示を引用するならば、クラスから作り出された「たいやき」である。
素材によってスタンダードなたいやき、白いたいやき、また、中身もあんこやクリームといったように、様々な特徴を持ったインスタンスが作り出される。
この場合の素材は「属性」、見た目や味といった特徴は「値」と言い換えられる
```

ここまで読んでいただけた奇特な貴方に感謝申し上げます。
また、なにか解釈違いや見当違い等ございましたら、ぜひともご教授いただけますと幸いです。


鍵谷
DynamoDBへのテストデータ作成用pythonスクリプト

# はじめに
DynamoDBへ大量のテストデータを作りたいときのPythonスクリプトが欲しいなという時の参考にしていただければと思います。

## 実装

第一引数に、対象となるDynamoDBのテーブル名、第二引数にテストデータ数を整数で渡してあげると、動作します。

```sample.py
import json
from argparse import ArgumentParser, FileType
 
import boto3
from tqdm import tqdm
 
def main():
    p = ArgumentParser(description='jsonをDynamoDBにインポート')
    p.add_argument('table', help='テーブル名')
    p.add_argument('total', type=int, help='テストデータ数')
    args = p.parse_args()
    session = boto3.Session(profile_name="default")
 
    dynamodb = session.resource('dynamodb')
    table = dynamodb.Table(args.table)
    total = args.total
 
    with table.batch_writer() as batch:
        for i in tqdm(range(total)):
            batch.put_item(
                Item={
                "ID": str(i),
                "TEST_DETAIL": "TESTDATA"
               }
            )
 
if __name__ == "__main__":
    main()
```
エクセルの全シートを同じ印刷設定で印刷する方法

複数のシートをまとめて印刷設定するには
1 Ctrlキーを押しながらシートをクリックすると、複数のシートを選択できる
2 Ctrl + Pを押して印刷設定を開く
3 設定を変更し印刷
スプレッドシートの表をアプリで表示させる方法

スプレッドシートの下記のシートを

![2021-01-27_12h39_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/c08f51ae-312f-ba70-40ad-5fa48552796e.png)

Google Apps Scriptのアプリケーションで下記のように表示させるコードです。

![2021-01-27_12h39_51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/a6ddc5fe-9072-997f-6848-fc6ba88d0c94.png)



```javascript:code.gs
function doGet() {
  const html = HtmlService.createTemplateFromFile("index");
  return html.evaluate();
}

function getData() {
  const sht = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');
  return sht.getDataRange().getValues();
}
```

```html:index.html
<!DOCTYPE html>
<html>
  <head>
    <base target="_top">
    <style>
      
      /* ここら辺は適当に */
      table{
        width: 500px;
        border: solid 1px #000000;
        border-collapse: collapse;
        margin: 20px;
      }
      
      th{
        border: solid 1px #ffffff;
        padding: 8px 12px 8px 12px;
        background-color: #000;
        color: #ffffff;
        }
        
      td{
        border: solid 1px #000000;
        padding: 7px 10px 7px 10px;
        }
      
    </style>
  </head>
  <body>
  
    <table>
      <?
        const data = getData();
        const header = data.shift();

        output._ = '<tr>';
        for(const column of header){
          output._ = '<th>'+ column +'</th>';
        }
        output._ = '</tr>';

        for(const record of data){
          output._ = '<tr>';
          for(const cell of record){
            output._ = '<td>'+ cell +'</td>';
          }
          output._ = '</tr>';
        }
      ?>
    </table>
  </body>
</html>



```
便利なterraformコマンド3選 (備忘録) 

# はじめに
* tfstateで管理しているリソースのリストが見たい
* tfstateから特定のリソースを管理外にしたい
* 作成済みのリソースを狙ったtfstateの管理下にしたい

上記のような対応がしたいときにおすすめのコマンドを記載します。


## tfstateで管理しているリソースのリストが見たい

```
terraform state list
```

上記のコマンドで、モジュールを含むすべてのリソースを一覧表示できます。
[参考: 公式ドキュメント](https://www.terraform.io/docs/cli/commands/state/list.html)

## tfstateから特定のリソースを管理外にしたい

```
terraform state rm [リソース名]
```

上記のコマンドで、対象のリソースをterraform管理外に設定できます。
[参考: 公式ドキュメント](https://www.terraform.io/docs/cli/commands/state/rm.html)

## 作成済みのリソースを狙ったtfstateの管理下にしたい

```
terraform import [tfstate上でどんな名前で管理するかを書く] [基本リソース名]
```
上記のコマンドで、他の方法で作成したリソースを取得して、Terraformの管理下に置くことができます。

[参考: 公式ドキュメント](https://www.terraform.io/docs/cli/import/index.html)
pip経由でidbインストール後にidbコマンドが見当たらない

# 問題
[Flipper](https://fbflipper.com/)でiOS実機ビルドのデバッグに[idb](https://fbidb.io/)が必要そうだったのでセットアップドキュメントに書いてある通り進めたが、pip経由でのidbのインストール後にidbコマンドが見当たらない問題が発生。

```zsh
$ idb
zsh: command not found: idb
```

## 環境
macOS Big Sur 11.1

# 解決方法
https://github.com/facebook/idb/issues/604
ここを参考にした。
一度 `pip install fb-idb` でpermission deniedで再度 `sudo pip install fb-idb` でインストールしたが、この場合上記の問題が発生する模様。
コメントに書いてある通り、一度fb-idbをアンインストール後再度インストールで `/usr/local/bin` に入った。

```zsh
$ pip3.9 uninstall fb-idb
$ sudo pip3.9 install fb-idb
$ which idb
/usr/local/bin/idb
```
複数シートを同じ設定で一度に印刷


### 先に複数シートをどう印刷するかプリンタを設定
①Windows＞スタート＞設定＞デバイス＞プリンタとスキャナ を選択
②印刷するプリンタをクリック、管理をクリック、プロパティをクリック
③印刷設定ボタンをクリック
④給紙方法やモノクロ、両面印刷などの項目を設定、OKボタン　<- 注意！　
（変更した設定は後で元に戻すので覚える、もしくはメモに残す）

---
### Excelで印刷を開始
⑤EXCELに戻る
⑥印刷対象の複数のシートを選択
（キーボードのctrlキーを押したままマウスでシート名のタブを複数クリックしていけば複数選択）
⑦ファイル＞印刷をクリックし表示されたプリンタを他のプリンタに替える　<- ここ重要！
（他のプリンタはMicrosoft XPS Document Writerでも大丈夫）
⑧その後、実際に印刷するプリンタに戻し選択
⑨OKボタンを押して印刷開始、設定の通り選択したシートが複数連続で印刷・・・


---
### 考察
たぶんですが、
プリンタを切り替え戻すと詳細設定の内容が再取得されて複数シートの印刷に反映・・・かと
なお④で変更した設定は元に戻すことを忘れなく
そうしないと、今後プリンタは全てこの設定で印刷となるので
Vue Apollo-composableでqueryをシーケンシャルに実行する方法メモ

#1番目のqueryのレスポンスを2番目のqueryのvariablesに渡したかった
##単なる知っているか知らないかだけの問題で、良く読むと<a href="https://v4.apollo.vuejs.org/api/use-query.html#parameters">公式</a>にも書かれていました。

ポイントは一つだけでuseQueryに渡せるオプションの中に
enabledというプロパティが存在していました。
このプロパティはデフォルトではtrueで、そのままだと即時リクエスト発行の挙動となりますが
falseに指定してやる事で、trueに変更するまでリクエストを発行しなくなります。
この仕組みを利用して、シーケンシャルにQueryを発行できるというわけです。

以下の例は1つ目のqueryで文字列uuidを受け取り
その値を2つ目のqueryのvariablesに条件として指定した場合の例示です。

おまけの情報としてuseQueryのレスポンスに含まれるloadingの値を利用した方が良いのではないか？
という意見もあるかと思いますが、
私自身当初はそれを試みたのですが、loadingはその名前が示す通り
現在読み込み中かという意味合いで、読み込みを開始する前はfalseとなっており
今回のような用途には利用できませんでした。

自分自身enabledの存在に気がつけず、少しハマったので備忘として記録を残します。

```javascript
import * as VueApolloComposable from '@vue/apollo-composable'
import * as VueCompositionApi from '@vue/composition-api'
import { FirstQueryDocument, SecondQueryDocument, ThirdQueryDocument } from './graphql/queries.graphql'

const useFirstQueryResponse = () => {
  const isLoaded = ref<boolean>(false)
  const uuid = ref<string>('')
  const { onResult } = VueApolloComposable.useQuery(FirstQueryDocument)

  onResult((result) => {
    isLoaded.value = true,
    uuid = result?.data?.firstQueryResponse?.uuid
  }

  return {
    isLoaded,
    uuid,
  }
}
const useSecondQueryResponse = (
  firstQueryLoaded: Ref<boolean>,
  uuid: Ref<string>,
) => {
  const secondQueryResponse = ref<SecondQueryResponse>([])
  const isLoaded = ref<boolean>(false)

  const conditions = {
    page: ref(1), // 改ページ処理などのページ数の例
    uuid, // 最初のQueryで受け取ったレスポンスの値を2つ目のQueryの条件として渡す
  }

  const variables = computed(() => ({
    per: 20,// 1ページあたりに何件表示するかのパラメータの想定
    page: conditions.page.value,
    uuid: conditions.uuid.value,
  }))

  const options = computed(() => ({enabled: firstQueryLoaded.value }))
  const { onResult } = VueApolloComposable.useQuery(SecondQueryDocument, variables, options)
  onResult((result) => {
    secondQueryResponse.value = result?.data?.secondQueryResponse
    isLoaded.value = true
  })

  return {
    secondQueryResponse,
    isLoaded,
  }
}

const useThirdQueryResponse = (secondQueryLoaded: Ref<boolean>,) => {
  const thridQueryResponse = ref<thridQueryResponse>([])
  const variables = {}
  const options = computed(() => ({enabled: secondQueryLoaded.value }))
  const { onResult } = VueApolloComposable.useQuery(ThirdQueryDocument, variables, options) 
  onResult((result) => {
    thirdQueryResponse.value = result?.data?.thirdQueryResponse
  })

  return {
    thirdQueryResponse.value = result?.data?.thirdQueryResponse
  }
}

export default defineComponent({
  name: `SequentialQueryComp`
  setup(){
    const firstQueryResponse = useFirstQueryResponse()
    const secondQueryResponse = useSecondQueryResponse(
      firstQueryResponse.isLoaded,
      firstQueryResponse.uuid,
    )
    const thirdQueryResponse = useThirdQueryResponse(secondQueryResponse.isLoaded)
  }
})

// 以下FirstQueryDocumentの参考例
import gql from 'graphql-tag'

export const FirstQueryDocument = gql`
  query firstQuery {
    firstQueryResponse {
      uuid
    }
  }
`

```
【Git】Gitチートシート 

[【Git】作業ブランチに最新のmasterを反映させる方法！](https://mizukazu.com/%E3%80%90git%E3%80%91%E4%BD%9C%E6%A5%AD%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AB%E6%9C%80%E6%96%B0%E3%81%AEmaster%E3%82%92%E5%8F%8D%E6%98%A0%E3%81%95%E3%81%9B%E3%82%8B%E6%96%B9%E6%B3%95%EF%BC%81/)

[コンフリクトしたのでrebaseしたい](https://qiita.com/zizynonno/items/fcf066386bcb7a6610b0)
[jquery]いっぱいある要素を並び順・表示ともにランダムに出力する

```html
<ul class="js-feature-ramdom">
  <li><a href="link"><img src="img1.jpg" alt="img1"></a></li>
  <li><a href="link"><img src="img2.jpg" alt="img2"></a></li>
  <li><a href="link"><img src="img3.jpg" alt="img3"></a></li>
  <li><a href="link"><img src="img4.jpg" alt="img4"></a></li>
  <li><a href="link"><img src="img5.jpg" alt="img5"></a></li>
  <li><a href="link"><img src="img6.jpg" alt="img6"></a></li>
</ul>
```

```js

<script>
$(function() {
  let wW = $(window).width();
  let arr = [];

  $(".js-feature-random li").each(function() {
    arr.push($(this).html());
  });

  $(".js-feature-random").empty();

  arr.sort(function() {
    return Math.random() - Math.random();
  });

  if(wW > 640) {//PCの時は3つ
    for(i=0; i < 3; i++) {
        $(".js-feature-random").append('<li>' + arr[i] + '</li>');
    }
  } else {
    for(i=0; i < 4; i++) {//スマホの時は4つ
      $(".js-feature-random").append('<li>' + arr[i] + '</li>');
    }
  }
});
</script>
```
【Nuxt.js】サーバ起動時にAddress already in use と表示されたときの対処

nuxtサーバー起動時ですが
 WARN  Address localhost:3000 is already in use. 
と表示され別のローカルホストの番号が自動で立ち上がってしましました。
そのときに対処したメモです。

![スクリーンショット 2021-01-27 11.27.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/6a8544ce-e13b-aef8-0549-2f06102524f9.png)

表示されたlocalhost番号でも使えるのですが、
localhost:3000と登録しているツールなどがあるので初期に戻したい。

## 原因
ローカルサーバーを切らずにターミナルを消してしまったことらしいです。

## 対処
ターミナルで以下のコマンドを入力

```
lsof -i :3000
```

するとターミナル上に3000番ポートに現在接続しているものの一覧を出してくれます。

```
COMMAND  PID             USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
node    0123 hogehoge   27u  IPv4 0xd0972da5f637596f      0t0  TCP localhost:hbci (LISTEN)
```
※数字や名前は適当なのにしています。

このなかにある`PID`が接続しているIDになるようです。
自分のPID番号をしてしてターミナルで下記のコマンドを入力します。

```
kill -QUIT <PID>
```

再度Nuxtを立ち上げます
![スクリーンショット 2021-01-27 11.34.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163786/bbb1e877-c8eb-30b8-5e27-55f741baa7fb.png)
うまくもどりました。
tqdm - TypeError: 'module' object is not callable

`tqdm`を使おうとしたときに

```Python 
TypeError: 'module' object is not callable
```

と出てしまった時の問題点と対処法。

# 問題点
`tqdm`はモジュールだから関数として呼べない。

# 対処法

```Python
from tqdm import tqdm
```

とするか、

```Python
import tqdm
for _ in tqdm.tqdm(iterator):
```

とすべし！

# 参考
https://stackoverflow.com/questions/39323182/tqdm-module-object-is-not-callable
JavaScriptで追加した要素にクリックイベントが処理されない

http://www.finefinefine.jp/jquery/kiji2117/

いやー素晴らしい記事ですね。やっとAjaxを使って非同期でデータを取得できるようになったと思ったら、追加した要素にクリックイベントが反映されていないという「なんでやねん！」って一人でツッコミを入れてたけど、すぐに記事が出てきましたね。


>イベントで追加された要素やAjaxローディングを使って読み込んだDOM要素に対して処理を実行する場合、意図した通りに動かない場合があります。
例えば、次のような「ボタンをクリックしてdiv要素を追加する」という記述（scriptの2〜4行目）をした場合、最初からあるdiv要素に対しては、「div要素をクリックしたら背景色をredにする」と言った処理（scriptの5〜7行目）は有効ですが、ボタンクリックで追加された要素に対しては反映しません。


これは素晴らしい！

```javascript:
\\ これだと後から追加されたdiv要素には反映されない
$("div").click(function() {
    $(this).css('background', 'red');
});

```

```javascript
// これなら反映される！！
$(document).on('click', 'div', function() {
    $(this).css('background', 'red');
});

```

###テーブルの情報をAjaxでロードした場合に、詳細画面へのリンクをdata-href属性を追加してリンク先へ


```javascript:toDetailPageFromTableTr.js
// もともと
$('tr[data-href]').click( function(){
	window.location = $(this).attr('data-href');
});
// 変更後
$(document).on('click', 'tr', function(){
	window.location = $(this).attr('data-href');
});
```

そもそも

```javascript
$(document).on('click', 'tr', function(){});
```
なんて書き方知らなかったし！まだまだ学ぶことだらけですな。
samba(cifs)をfstabに書いても自動マウントしてくれない件

# 事象

あれあれ？Ansibleからcifsでmoutnedしても、ブート時にマウントしてくれないぞ？
という事象にハマっておりました。

# 解決策

困っている皆様のために、結論から書くのが私の流儀。（どやぁ）
ジャーナルを見るとネットワーク接続する前にmountしようとしていたので、fstabに以下オプションを付けましょう。

```
noauto,x-systemd.automount
```

# 原因

解決策にも少し書きましたが、ジャーナルを見たらWi-Fiの接続を確立する前にマウントしようとして失敗しているようです。
SSHして`mount -a`すると普通にマウントできるので、ネットワーク関連を疑っていたらビンゴでした。

```
Jan 26 09:56:28 raspberrypi dhcpcd-run-hooks[460]: wlan0: starting wpa_supplicant
Jan 26 09:56:28 raspberrypi kernel: [    7.399312] IPv6: ADDRCONF(NETDEV_UP): wlan0: link is not ready
Jan 26 09:56:28 raspberrypi kernel: [    7.399346] brcmfmac: brcmf_cfg80211_set_power_mgmt: power save enabled
Jan 26 09:56:29 raspberrypi kernel: [    7.412947] FS-Cache: Netfs 'cifs' registered for caching
Jan 26 09:56:29 raspberrypi kernel: [    7.413464] Key type cifs.spnego registered
Jan 26 09:56:29 raspberrypi kernel: [    7.413490] Key type cifs.idmap registered
Jan 26 09:56:29 raspberrypi kernel: [    7.418147] No dialect specified on mount. Default has changed to a more secure dialect, SMB2.1 or later (e.g. SMB3), from CIFS (SMB1). To use the less secure SMB1 dialect to access old servers which do not support SMB3 (or SMB2.1) specify vers=1.0 on mount.
Jan 26 09:56:29 raspberrypi mount[454]: mount error(101): Network is unreachable
Jan 26 09:56:29 raspberrypi mount[454]: Refer to the mount.cifs(8) manual page (e.g. man mount.cifs)
Jan 26 09:56:29 raspberrypi kernel: [    7.460238] CIFS VFS: Error connecting to socket. Aborting operation.
Jan 26 09:56:29 raspberrypi kernel: [    7.460254] CIFS VFS: cifs_mount failed w/return code = -101
Jan 26 09:56:29 raspberrypi systemd[1]: mnt-brains.mount: Mount process exited, code=exited, status=32/n/a
Jan 26 09:56:29 raspberrypi systemd[1]: mnt-brains.mount: Failed with result 'exit-code'.
Jan 26 09:56:29 raspberrypi systemd[1]: Failed to mount /mnt/shared.
```

### Ansibleだとこう書く

AnsibleでマウントしようとしていたのでついでにAnsibleのコードも載せておきます。(v2.10)

```yaml
- name: Mount a directory
  become: yes
  ansible.posix.mount:
    path: /mnt/shared
    src: //x.x.x.x/shared
    opts: rw,async,user,uid=1000,gid=1000,password=ENTER_THE_PASSWORD!,noauto,x-systemd.automount
    state: mounted
    fstype: cifs 
```
ランサムウェアについて（仮）

#はじめに
社内でランサムウェアについて講習を開くことになったため、自分用メモとして作成しました。

#ランサムウェアとは
##名前の由来
>　ランサムウェア(Ransomware)とは、「Ransom（身代金）」と「Software（ソフトウェア）」を組み合わせて作られた名称であり、コンピュータウィルスの一種です。
(出典　[警察庁サイバー犯罪プロジェクト] (https://www.npa.go.jp/cyber/ransom/main1.html))
　要するに造語ですね。

##感染するとどうなるのか
　感染するとファイル等が勝手に暗号化され開けなくなります。暗号を解除するには攻撃者にお金を支払って解除パスワードを教えてもらう必要があります。
　要するに、人間の代わりにデータを人質に取り、身代金を要求してくるコンピュータウイルスです。

##感染の流れ
###感染するまで（感染経路）
####標的型メール攻撃
####よくわからんデータをインストールしている

###感染してから（暗号化）
感染先のパソコンのファイル等を暗号化します。解除キーを攻撃者に送付します。この解除キーをキャプチャすれば解除キーがわかるのではと考えましたが、これも暗号化されているので傍受することはできないようです（一枚上手）。

###復旧するには
　復旧するためには二通り考えられます。
1.攻撃者にパスワードを教えてもらう
　一番手っ取り早い気がします。しかし、パスワードを教えてもらうには攻撃者の目的である身代金を支払う必要があります。そもそも支払っても解除できる保証はありません。（個人的にはランサムウェアの作成意図から推察すると、支払いがあれば必ずパスワードを教えなければ、ランサムウェアに感染後支払いをする人がいなくなるので、絶対教えてくれると思いますが。。。）
>一般的なアドバイスとして、身代金を支払わないことをお勧めします。サイバー犯罪者に送金すると、ランサムウェアが機能していると犯罪者に対して証明することになるだけで、必要な復号鍵を入手できる保証はありません。
（出展　[NO MORE RANSOM!](https://www.nomoreransom.org/ja/index.html)）

　上記の通り、支払いをするとマルウェアの有効性を攻撃者に教えてしまうことになります。また、犯罪者の資金源になってしまうため、望ましいことではありません。

　2.二つ目は自力でパスワードを解除する


##対策
被害を最小限に食い止めるためにはどうすべきか
###バックアップを作成しておく

###OSのアップデートをこまめに行う

##まとめ、感染しないことが一番楽
　これまで述べた通り、感染してしまうと莫大な労力がかかります。そうならないためには感染しないことが一番楽です。
【Ruby on Rails】nilチェックは「==」を使わずスマートに

#人間はすぐに忘れるモノ...
はいだから書きます。
レビューで指摘していただいた１０分後に書いています（笑）

いつもの癖ですぐに使ってしまう下記の様なコード。

```ruby
if hoge == nil
  #処理があって
end
```

すぐに「==」演算子を仕様する癖が染み付いていますのでここで矯正。

```ruby
if hoge.nil?
  #処理があって
end
```

以上です。これでもう同じことはしない。
トランザクション中にrescueするとロールバックしないので注意!

# トランザクション中のrescueはロールバックを発生させない
## 動画による説明
[[Ruby on Rails] トランザクション中のrescueには気をつけて
](https://www.youtube.com/watch?v=hfXOC314lJc)

## トランザクション中のrescue
このようにすると、`create!`で発生した例外をキャッチして、`exec_transaction`の返り値としてfalseを返すことができます。

```rb
def exec_transaction
  ApplicationRecord.transaction do
    User.create!(name: 'Duplicate')
    User.create!(name: 'Duplicate')
  rescue ActiveRecord::RecordInvalid
    false
  end
end
```

Userモデルは下記のようにバリデーションが設定してあります。

```rb
class User < ApplicationRecord
  validates :name, uniqueness: true
end
```

このコードを実行すると、二回目のcreate!でエラーが発生しますが、<b>ロールバック処理が実行されません</b>。

## Rollbackが起きる仕組み
transactionメソッドに与えられたブロックは、最終的にwithin_new_transactionメソッドの中で実行されます。
ここで、与えられたブロックで発生したすべての例外をキャッチして、ロールバックを発生させたあと、例外をもう一度送出します。

[activerecord/lib/active_record/connection_adapters/abstract/transaction.rb#L313-L318](https://github.com/rails/rails/blob/291a3d2ef29a3842d1156ada7526f4ee60dd2b59/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb#L313-L318)

この動作によって、transactionで例外が発生すると、ロールバックが暗黙的に実行されて、例外の送出も行われます。

## Exceptionをキャッチするとロールバックしない
上述の通り、発生した例外をトリガーにしてロールバックが発生します。したがって、先に示したコードのようにブロックの中で例外をキャッチしてしまうと、ロールバックが起きません。

# ロールバックしつつ例外をキャッチしたい場合
方法は二通り。明示的にロールバックするか、トランザクションの外側で例外をキャッチする。

## 明示的にロールバック
こちらの動画で紹介されている方法と同じ考え方です。
https://www.youtube.com/watch?v=jFBvEQhApKQ

ActiveRecord::Rollbackを送出してロールバックを行い、全て正常終了したかどうかを返り値とします。

```rb
def exec_transaction
  success = true
  ApplicationRecord.transaction do
    success &= User.new(name: 'Duplicate').save
    success &= User.new(name: 'Duplicate').save
    unless success do
       raise ActiveRecord::Rollback
    end
  end

  success
end
```

## トランザクションの外側で例外をキャッチする
ロールバックが発生したら例外は再度送出される、という性質を利用します。

```rb

def exec_transaction
  ApplicationRecord.transaction do
    User.create!(name: 'Duplicate')
    User.create!(name: 'Duplicate')
  end
rescue ActiveRecord::RecordInvalid
  false
end
```

# そもそもの例外処理の設計
こういう例外処理がある事自体が良くない可能性もあります。もちろん、すべてが悪いということではないです。
エラー処理の設計については、下記の資料で非常に丁寧にまとめられています。

[Railsアプリケーションにおけるエラー処理（例外設計）の考え方](https://qiita.com/jnchito/items/3ef95ea144ed15df3637)
[プロを目指す人のための例外処理（再）入門 / #rubykansai 2018-01-13](https://speakerdeck.com/jnchito/number-rubykansai-2018-01-13)
CentOSの更新情報を公式RSSで取得する


CentOSの更新情報の公式RSSを取得したいと思っていたけど、ネットで探してもあまり日本語情報がなかったので
記事にしました。

## 結論

基本CPUはx86_64（Intel, AMD 64ビット）.
OSインストール時に有効なリポジトリのみかと思いますので、下記RSSを受信します。

### CentOS7

https://feeds.centos.org/centos-7-x86_64-extras.xml
https://feeds.centos.org/centos-7-x86_64-updates.xml
※ centos7はbaseなかった。

### CentOS8

https://feeds.centos.org/centos-8-x86_64-extras.xml
https://feeds.centos.org/centos-8-x86_64-BaseOS.xml
https://feeds.centos.org/centos-8-x86_64-AppStream.xml

## CentOS公式RSSの一覧

https://feeds.centos.org/

ここでRSSの一覧を確認できます。
（最近作られた？以前はなかったような。もし知ってる方がいたら教えてください。）

### 見方

[centos-7-x86_64-updates.xml](https://feeds.centos.org/centos-7-x86_64-updates.xml)

| 項目 | 値 |
|:-- |:-- |
|OS | centos-7 |
|CPU | x86_64  |
|リポジトリ   | updates  |

になります。
OS毎、CPU毎にRSSがわかれてます。

#### CPUの種類

| 種類 | 説明
| :--- | :--
| [x86_64](https://ja.wikipedia.org/wiki/X64)  | Intel, AMD 64ビット
| [ppc64le](https://www.weblio.jp/content/Ppc64le) | PowerPC
| [AArch64](https://en.wikipedia.org/wiki/AArch64) | ARMv8-A

#### リポジトリの種類

CenOSのyumリポジトリを見れば、有効（`enabled=1`）になっているリポジトリがわかるので、
それをもとに、取得したいRSSを選びます。

下記はCenOS7の場合です。

```
$ ll /etc/yum.repos.d
合計 84
-rw-r--r-- 1 root root 1664  4月  8  2020 CentOS-Base.repo
-rw-r--r-- 1 root root 1309  4月  8  2020 CentOS-CR.repo
-rw-r--r-- 1 root root  649  4月  8  2020 CentOS-Debuginfo.repo
-rw-r--r-- 1 root root  630  4月  8  2020 CentOS-Media.repo
-rw-r--r-- 1 root root 1331  4月  8  2020 CentOS-Sources.repo
-rw-r--r-- 1 root root 7577  4月  8  2020 CentOS-Vault.repo
-rw-r--r-- 1 root root  314  4月  8  2020 CentOS-fasttrack.repo
-rw-r--r-- 1 root root  616  4月  8  2020 CentOS-x86_64-kernel.repo
```

ちょっとでも参考になれば嬉しいです。

## 情報源

https://centosfaq.org/centos/centos-linux-updates-released-rss-feeds/
【GAS】Googleカレンダーの予定をSlack通知

# やりたいこと
slackにGoogleカレンダーの予定を通知したい
朝８時に実行して大体１日の予定を通知する


# Slackのメール転送を有効にする
slackのマイプロファイル→環境設定→メッセージ＆メディアからSlackへのメールの転送を有効化
メールアドレスをコピーしておく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184018/2e2f9ba4-b955-bfaf-bb01-e61082d34a6f.png)

# Google Apps Scriptを作る
slackのEmailアドレスに転送先のメールアドレスを埋め込む

``` 
var destination_Email = '[SlackのEmailアドレス]';

function getCalenderEvents() {
  var now = new Date();
  var twoHoursFromNow = new Date(now.getTime() + (10 * 60 * 60 * 1000));
  var events = CalendarApp.getDefaultCalendar().getEvents(now, twoHoursFromNow);
  for (var i = 0; i < events.length; i++) {
    var title = events[i].getTitle();
    var startTime = events[i].getStartTime();
    var endTime = events[i].getEndTime();
    var duration = (endTime - startTime) / (1000*60) / (60);
    var detail = events[i].getDescription();
    var location = events[i].getLocation();

    startTime = formatDate(startTime, 'JST');
    endTime = formatDate(endTime, 'JST');

    sendSlackfromGmail(title, startTime, endTime, duration, detail, location);

  }//for (var i = 0; i < events.length; i++) {
}//function getCalenderEvents() {

function sendSlackfromGmail(title, startTime, endTime,  duration, detail, location) {
  var body = '開始時間：' + startTime + '\n' + '終了時間：' + endTime + '\n' + '会議時間：' + duration + '\n' + '詳細：' + detail + '\n' + '場所：' + location
  GmailApp.sendEmail(destination_Email, title, body);

}//function sendSlackfromGmail() {

function formatDate(date, timeZone, format) {
  if (date === '') {
    return ''
  } else {
    var format = 'yyy/MM/dd HH:mm';
    var retval = Utilities.formatDate(date, timeZone, format);
    return retval;
  }
}//function formatDate(date, timeZone, format) {
```

# 所感
誰かと共有する必要のない情報なら個人宛に転送するのが良いと思いました。
また、アプリ作成が要らないので簡単に導入できます。
【Ruby】even?メソッド

#はじめに

備忘録の記述です。今回は、配列にある値の中から偶数の数をカウントして出力するメソッドを作りました。

出力例：count_evens([2,1,2,3,4]) → 3

偶数かどうかを判断するメソッドとして「even?」を使用します。
[リファレンスマニュアル](https://docs.ruby-lang.org/ja/latest/method/Integer/i/even=3f.html)

#解答

```ruby:practice.rb
def count_evens(nums)
  count = 0
  nums.each do |num|
    if num.even?
      count += 1
    end
  end
  puts count
end

count_evens([2, 1, 2, 3, 4])
```

「count = 0」：配列の中の偶数の値を出力するためにカウントした数を保存するための変数が必要なため、ここで定義をしています。

「nums.each do |num|」：配列に入っている数字をeach文で取り出し、even?メソッドで1つずつ偶数かどうかを確認しています。偶数だった場合は、countに1を足していきます。
Next.js+TypeScriptでマルチプロセス対応カスタムサーバ作成

# Next.js+TypeScriptでマルチプロセス対応カスタムサーバ作成

- リポジトリ  
<https://github.com/SoraKumo001/nextjs-custom>
- 原文リンク  
<https://ttis.croud.jp/?uuid=46c0f2f8-7db3-4ec4-ab86-5054aea70f49>

## カスタムサーバ

　Next.jsはWebServer機能を標準で内蔵していますが、マルチプロセスや特殊なセッション処理などを組み込む場合には、カスタムサーバという形でWebServer部分を自分で実装する必要があります。

　公式にサンプルはある物の、以外に日本語の情報が少ない、それどころかマルチプロセスやfastifyでの実装記事は皆無だったので、書いていきたいと思います。


## マルチプロセス化について

　Next.jsを動かしているNode.jsは基本的にシングルスレッドで動作します。シングルスレッドといってもI/Oアクセスに関しては非同期で行われているため、無駄なブロックは起こらず、実用的な速度で動作することが可能です。

　ところが計算処理などをしている間は当然他の仕事は出来ません。マルチコアCPUなどでハードウエア的に余裕があっても、シングルスレッドである限りはせっかくのリソースが活用できないのです。

　これに対処するにはNext.jsをマルチスレッドではなく、マルチプロセス化するのが有効な手段となります。ありがたいことにNode.jsには、マルチプロセス化を簡単に実装するライブラリが標準提供されているので、カスタムサーバ化のコードを少し書くだけで、その恩恵を受けることが出来ます。

## Fastifyに関して

　Node.jsでWebServer機能を実装するフレームワークとして有名なのはExpressです。しかし古い実装を引きずっているため、応答速度が遅いといわれています。今回はベンチマークで上位に位置するFastifyを使ってカスタムサーバを作ります。


## インストールが必要な最低限のパッケージ

`yarn add cross-env fastify next react react-dom`
`yarn add -D @types/node @types/react @types/react-dom ts-node-dev typescript`

 

## カスタムサーバの実装コード

　以下の二つのファイルを用意します。
　ちなみに環境変数でINDEXというのを子プロセスに渡していますが、workerにIDが振られるので実は無くてもかまいません

```server/index.ts
import next from "next";
import * as os from "os";
import * as cluster from "cluster";
import { parse } from "url";
import fastify from "fastify";

const dev = process.env.NODE_ENV !== "production";
const clusterSize = Math.min(os.cpus().length, 4);
const portNumber = 3000;

if (cluster.isMaster) {
  for (let i = 0; i < clusterSize; i++) cluster.fork({ INDEX: i });
} else {
  const app = next({ dev });
  const handle = app.getRequestHandler();
  const server = fastify();
  app.prepare().then(() => {
    server.all("*", (req, res) => {
      return handle(req.raw, res.raw, parse(req.url, true));
    });
    server.listen(portNumber).then(() => {
      console.log(`[${process.env.INDEX}]:http://localhost:${portNumber}`);
    });
  });
}
```

```server/tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "outDir": "../.next",
    "esModuleInterop": true
  }
} 
```

　tsconfig.jsonを作成しているのは、Next.js管理下のpagesファイルなどとはTypeScriptのビルドの扱いが異なるからです。

## スクリプト関係

　devはカスタムサーバ自体の自動リロードのため、ts-node-devを使っています。ただし.nextの中身はNext.js側が調整するので、無視指定が必要です。

```package.json
{
  "name": "nextjs-custom",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "dev": "ts-node-dev --ignore-watch \\.next -P server/tsconfig.json server/index.ts",
    "build": "tsc -b server && next build",
    "start": "cross-env NODE_ENV=production node .next/index.js",
    "export": "next export"
  },
  "devDependencies": {
    "@types/node": "^14.14.22",
    "@types/react": "^17.0.0",
    "@types/react-dom": "^17.0.0",
    "ts-node-dev": "^1.1.1",
    "typescript": "^4.1.3"
  },
  "dependencies": {
    "cross-env": "^7.0.3",
    "fastify": "^3.11.0",
    "next": "^10.0.5",
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  }
}
```

## まとめ

　大したコード量も必要なくカスタムサーバが実装できました。マルチプロセスとFastifyのパワーによって、きっと快適SSRライフが送れることでしょう。

　ただしベンチマークを取った結果、それなりの負荷をかけても効果が顕著に出るのは2プロセスまでというオチでした。ベンチマークに関しては別記事を書く予定です。
【React Native】stateを用いた変数管理

## 更新した値を画面に即時反映させたい
React Nativeにてインタラクティブなアプリを作る際、基本的な処理の流れとしては


 - ボタン等を押してメソッドを実行
 - メソッド内で計算、計算後の値を算出(場合によっては結果をDBに反映)
 - 画面に反映

が一般的な流れである。
stateを理解してこの一連の流れが出来るようになったらアプリ作りが捗ったので紹介。

### カウンターアプリの例
上記アプリの例として、カウンターアプリが上げられる。
![スクリーンショット 2021-01-27 8.46.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78136/02d4745d-8f2d-8d23-b515-e643c7401970.png)

#### 画面要素
 - 現在のカウント
 - カウントアップボタン
 - カウントダウンボタン

#### 仕様
「カウントダウンボタン」または「カウントアップボタン」を押したら、現在のカウントが増減

#### 実装的な処理詳細
- 「カウントダウンボタン」または「カウントアップボタン」を押した際、現在のカウントをインクリメントする
- インクリメントした後の数字が現在のカウントに反映される

## クラス内の変数を更新しただけでは、画面は再描画されない
class無いに変数を用意して数字を更新したとしても、画面の数字は更新されない。

```javascript

<View style={styles.container}>
      <TouchableOpacity style={styles.button} onPress={() => 
        {
          counter++
          console.log("after count:" + counter)
        }
      }>
        <Text style={styles.buttonText}>+1</Text>
      </TouchableOpacity>
      <TouchableOpacity style={styles.button} onPress={() => 
        {
          counter--
          console.log("after count:" + counter)
        }
      }>
        <Text style={styles.buttonText}>-1</Text>
      </TouchableOpacity>
      <Text style={styles.paragraph}>
       current count:{counter}
      </Text>
    </View>
```

### ブラウザで実際に試してみる
リンクに動く(数字は動かない)React Nativeのサンプルをおいておきました。
https://snack.expo.io/3n9E_BhFU

### 変数を更新するだけは再描画されない
**描画を更新するには、状態変化をReactに通知して、renderを再度呼んでもらう**必要がある。

## stateによる状態管理、変更
stateとは、**値の変更が常時監視され、値が変わったら画面が再描画される変数**である。

### stateの定義
stateは`useState`を用いて初期化し、以下のように宣言できる。
useStateの引数は変数の初期値である。

```javascript

const [counter, setCounter] = useState(0)
```
counterは数を保持する**変数**、setCounterはcounterを更新するための**setter**である。

stateの勘所は、**setterを用いて値を更新**することで**stateの変更を通知し、画面を再描画**してもらうことである。

setter経由で更新した場合、Reactで更新を検知し

## 値の更新
counterを直接更新するのではなく、setCounterを用いて更新を行う。

```javascript
setCounter(counter + 1)
```
引数に更新後の値を渡すことで値が引数の値で更新される。
今の値に対して差分更新する場合は、上記例のように現在の値と差分で計算すれば良い。


### ブラウザで実際に試してみる
リンクにsateを用いて正常に動くReact Nativeのサンプルをおいておきました。
https://snack.expo.io/NdXVNsFnA

#### 参考:学習に用いたUdemyのコース
react nativeの経験が無い中でアプリを作り始めて、こちらのコースで学習しながら進めている。
今回はstateを学んだのでその紹介。

The Complete React Native + Hooks Course [2020 Edition]
https://www.udemy.com/course/the-complete-react-native-and-redux-course/
【Gitの前に知っておかないといけないこと（小学生でも分かる解説）】

#Git とは

「Git」（ギット）という単語を使うだけで、エンジニアっぽくなる。（気がする）

じゃあ、Gitって何？

結論から、

Gitとは、`「作ったプログラムの履歴を残したり、そこに戻ったりするやつ」`

#CLI（＝CUI）、GUI とは

そのGitの前に知っておくべき、いや、知っておかなければ進めないものがある。

 それが、CLI（CUIとも言われる）とGUI。
英語３文字攻撃だけど、たいしたことじゃない。

**・CLI（コマンドラインインターフェイス）：裏
・GUI（グラフィカルユーザインターフェイス）：表**

以上。いや、例くらい出しておく。

**・CLI（コマンドラインインターフェイス）：黒い画面（ターミナル）に呪文を打ち込む
・GUI（グラフィカルユーザインターフェイス）：（たぶん今やってる）マウスやタッチパッドで画面を動かしたり、タッチしたりする**

へー。で？

で、非常に大変残念ながら、
「Git」は「CLI」の方ですよ。という話。

#Gitはどう使う？

それじゃあ、Gitは実際にどうやって使うのか。

上のCLIのとこで出てきた「ターミナル」というやつを使う。（Mac）

ターミナルっていうのは、いわゆる黒い画面💻
これが実物。
![スクリーンショット 2021-01-27 5.52.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679667/e571c479-c580-13b1-180b-5c08850788a7.png)

せめて日本語１文字くらい入れてくれ！と思うよね。。

この画面だけで拒否反応が出そうだけど、大丈夫。
まず、こんな英語をいろいろと入力できない！と勘違いしがち。

実は、自分が入力した部分は、「％」の右部分だけ。
これで見ると、「pwd」と「ls」の合計５文字だけ！
あとは全部、Enter押したら勝手に出てくる。

だいぶハードル下がったんじゃない？

その「％」の右側に自分で入れるのを「コマンド」っていう。
コマンドっていうのは、こうしてくれという命令。
「パンを買ってこい」と命令して、Enter押したら、「はい/いいえ」と返事が返ってくる感じ。

#ディレクトリ と パス

ディレクトリ。なんでわざわざ難しいような名前にするのか。。
結局は、ディレクトリってこれ↓

**ディレクトリ ＝ フォルダ**

ここでは、フォルダを「`カバン👜`」」と考えてみて欲しい。

コンピュータのデータはいろんなカバンの中に入っている。

こんなこともよくある。
カバンを開けたら、またカバンが入っていて、さらにそのカバンの中にもカバンが入っていて。。。

用語の説明をしておく。

**・ルートディレクトリ：一番上のフォルダ（一番大きいカバン）
・カレントディレクトリ：今いる/作業しているフォルダ（今開いているカバン）**

**・絶対パス：ルートディレクトリからの経路（一番大きいカバンからのスタート）
・相対パス：今のフォルダからの経路（今開いているカバンからのスタート）**

パスっていうのは経路、つまり、道。

カバンで言うと、
・どのカバンからスタートするのか
・そこから何個か開くか、何個かしまい直す
みたいな感じ。


、、、分かりづらいので、例↓
###フォルダ１（1番大きいカバン）###
####フォルダ２（その中の２番目のカバン）←これを開いている####
#####フォルダ３（さらにその中の３番目のカバン）#####

この３つのフォルダ（カバン）があったとする。

・ルートディレクトリは、フォルダ１の１番大きいカバン
・カレントディレクトリは、今開いているフォルダ2のカバン

フォルダ３までのパスを考えると、

・絶対パスなら、「/フォルダ２/フォルダ３」（カバン1がスタートで、その中のカバン2の中のカバン３）
・相対パスなら、「/フォルダ３」（カバン2がスタートで、その中のカバン３）

「/」は「その中の」みたいな意味。



なんとなくわかったかな？

#大事なこと

この黒い画面の操作で、最も大切だと感じたのは、
###今、自分がどこにいるのか（どのカバンを開いているのか）を意識すること###

これはまず間違いないので、最後にもう一回言う。

**今、どのカバンを開いているのかを常に意識すること**

【次回】黒い画面（ターミナル）でよく使うコマンド
Rubyのハッシュとシンボル、キーの関係について、わかりやすく解説する

曖昧な理解になってしまいがちな**「ハッシュ」**と**「シンボル」**について、解説していきます。
Rubyを勉強し始めた時は全然わからなかった。。

この記事を通して
・ハッシュとキーの関係がわかる
・シンボルの使い方がわかる
ようになれば幸いです。<br><br>


##ハッシュは、「関連付いた名前をつけて、データを格納したいとき」に使う

数学のテストがあって、データが点数順に並んでいるとします。

```
 score = [56,43,55,78,79,66,73,90,45,65,43,25]
```
ここで、taro君の点数を知ろうとしたとき「score」という**データ**だけではわかりませんよね。「name」という、データに関連付いた**名前**が必要になってきます。<br><br>

ここで、ハッシュの登場です。
**ハッシュとは、「関連付いた名前をつけて、データを格納したいとき」に使うことができます。**

```
{ :name => score }　　　 #今回の例であれば { :taro => 56 }
```
このような形でハッシュを作ることができます。これでtaro君の点数を知ることができるようになりました。<br><br>

#データに関連付いた名前のことを「キー」と呼ぶ

「:taro」の部分を**キー**と呼びます。**キー(データに関連付いた名前)とデータのセットであるハッシュ**を格納するわけですね。

キーは、文字列、時間、数字など、任意のオブジェクトを使うことできますが、**「シンボル」と呼ばれる、コロンではじまる識別子をよく使います。**(例 => :taro)

また**キーとデータの間の区切りにコロンを使うことができます。その場合、シンボル名の頭のコロンを書いてはいけません。**

```
# ①文字列
"taro" => 56
# ②シンボル
:taro => 56
# ③一番良く使う表記
taro: 56

①、②、③は同じ意味になります
```

**シンボルは「何かしらの名前を表す存在だよ」ということを示しています。**

「:taro」になったり、「taro:」になったりして、コロンに惑わされると思うのですが、①、②、③が同じであることがわかれば安心かと思います。<br><br>



##まとめ

以上、ハッシュとシンボル、キーの関係について、解説していきました。

```
・「ハッシュ」・・・「関連付いた名前をつけて、データを格納したいとき」に使う
・「キー」・・・データに関連付いた名前
・「シンボル」・・・コロンではじまる識別子を使ったキー
```

この3点をおさえていきましょう。<br><br><br>

この記事の説明がわかりやすかった！ここ間違ってるよ！次こんな記事を書いて欲しい！などあればコメント、DMよろしくお願いします。LGTMもぜひ。


Twitterもやってますので、フォローしていただけたらうれしいです。
卓球、心理学、哲学、Webサービス、好きな音楽、カメラ、登山、ランニング、読んだ本などなんでもつぶやいてます。

[https://twitter.com/atsushi101011]
未経験なのに1人で全部やれと言われた人に読んで欲しい３つの教訓

#「とりあえずこれやっといて、簡単だから」
教えてくれる人がいない中で私が未経験エンジニアとして奮闘しながら得た生存戦略です。
未経験で視野の狭い中自分の能力よりもはるかに大きい事をやらざるを得なくなった人に届けたいです。
これが出来ずに倒れていく人を一人でも減らせればと思います。

---
目次
1. SOSを出す。
2. 開きなおる。
3. 戦い方を見つける。

---

#１、SOSを出す。
## そもそも無理ゲーだという事を前提に考える。
ここはサバンナです。
できるかどうか迷ってうろうろしている間にライオンに食べられてしまいます。

社内の別の部署の人、勉強会で見つけた経験者など頼れる人は全員頼ってください。
大丈夫、経験者ならあなたの大変さは絶対わかってくれます。
ただ、やってくださいと言うのではなく、やり方の基本を教えてもらうのがお互いにとっての近道です。
エンジニアは教えるのが好きな人が多いです。
また、**断られても１回で諦めては行けません。状況が良くなるまで助けを求め続けましょう。**

## いつでも助けてもらえる準備する。
プロジェクトが軌道に乗ってきたり、リソースに余裕が出てくるとメンバーが増えることがあります。
その新しいメンバーは貴方の仕事を元に追加、修正していく事になります。

## コードは綺麗に保つ。
まだリーダブルコードを読んだことがない人はこんな記事はどうでもいいので早くそちらを読んでください。
https://www.amazon.co.jp/dp/4873115655/ref=cm_sw_r_tw_dp_JV0dGbG0XJR88

## 追加メンバーを受け入れられるように準備する。
誰かが助けに来てくれても準備ができていなければ
新しいものを作るのではなく、過去の製品を作り直す事に時間を使う事になってしまいます。
コードだけでなくGitのコミットメッセージ、Issueなどいつでもチーム開発できるように準備しましょう。

## こまめに報告、連絡、相談する。
あなたの仕事の結果に対して責任を負っている上司に対して頻繁に現状を報告しましょう。
もしかしたら助けてくれるかも知れませんし、メンバーを増やしてくれるかも知れません。
こまめに報告していればもし、失敗したとしても自分の身を守る事になります。


# ２、開きなおる。
もちろんSOSを出してもすぐ問題が解決するわけではありません。
そうであればそもそも未経験なのに無茶振りしてくることも無いでしょう。
こうなってくるととりあえずは頑張るか諦めるかしかありません。

ここで諦めても誰も責めることはできないと思いますが頑張りたいのであれば腹を決めましょう。

## できなくて当然、できたらすごい
この状況では結果の保証なんてできるはずがありません。
明らかに能力不足ですから。
**しかし、結果のコントロールはできなくても
自分が全力で頑張ることはできます。**

もし成功すれば圧倒的に評価され、能力も上がっていることでしょう。
また、自分に自身がつき挑戦を続けるモチベーションが湧き上がってきます。
社内での評価も上がり、待遇も良くなり、職務経歴書を鮮やかに飾ることができます。

全力で頑張って失敗したらそれはアサインした人の責任です。
あなたは失敗の反省、悔しさをプラスに変えていきましょう。
**そもそも無茶な事をしています。
挑戦した自分を誇ってください。**


# ３、戦い方を見つける
**まずは何をしたら良いかを理解する事に全力を尽くしましょう。**
そもそも理解しなければならないことが抜けている可能性が高いです。
今は書籍、Qiita、note、YouTubeなどで情報は溢れ返っているので基礎を理解する時間を作りましょう。

基礎を知らないでもアプリくらい作れるという主張もありますが、
作りながら学ぶのが最短です。
作る時間と学ぶ時間の配分を常に見直しましょう。

## 検索の精度を上げる。
**Googleでヒットするのは自分が知ってるキーワードに近いものだけです。
そもそも知らない概念は見つからないことがあります。**

本当に最初は何を調べたら良いかわからないことが多いのでひたすらググって
検索結果TOP15までは見ましょう。
**そこから知らない言葉を見つけて、
くり返し意味を調べているうちに
必要だった概念にたどり着けます。**
とりあえずこの段階は量の勝負です。

## 英語で検索する。
できれば検索は英語ですると良いです。
**情報の量と質が圧倒的に高いです。**
検索結果の数も100倍近く変わります。
特に最新の情報は英語のものしかない事が多いです。

![Screen Shot 2021-01-27 at 7.59.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181998/5c7810ba-991c-79df-9c8f-b95656b886b3.png)

![Screen Shot 2021-01-27 at 7.58.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181998/af22a40d-afe2-aa73-2d7b-f7e681eeb403.png)

---

以上いかがだったでしょうか。
この手のプロジェクトで何人も心が折れてしまって病んでしまう人を見てきました。
少しでもそういった人を減らす事ができれば嬉しいです。
elm-test を実行したらReceived invalid JSON from test interface search: SyntaxError: Unexpected end of JSON inputが発生した、そのときの解決方法

いつもどおりに`npx elm-test`を実行したところ

```
Received invalid JSON from test interface search: SyntaxError: Unexpected end of JSON input
```

こんなエラーが出ました。
解決するために実行したことを備忘録として書いておきます。

まず[githubのIssues](https://github.com/rtfeldman/node-test-runner/issues/383)にはまず

```
npm i npm@latest -g
```
したあとに
`rm -rf elm-stuff`で直ったと書いてあったのでそれを実行したが私の環境では直りませんでした。
ではどうやって解決したのかというと

```npm
npm i elmi-to-json
```
これで依存しているライブラリの最新バージョンがインストールされ、無事に`elm-test`ができるようになりました。
今度似たような問題に出くわした時でかつ調べたことを実行してダメだったときは依存ライブラリのほうを疑ってみようと思います。
Heoku postgresqlの時間設定を日本時間に直す

#概要
heroku初心者です。herokuのPostgresqlの時間設定を日本時間へ変更したいので調べてみました。

##herokuのDBへ接続

```
heroku pg:psql
```

##現在の時間を表示

```
select NOW();

 now              
------------------------------
 2021-01-26 22:14:24.35026+00
(1 row)
```

##日本時間へ変更する

```
Set timezone TO 'Asia/Tokyo';

select NOW();
              now              
-------------------------------
 2021-01-27 07:15:16.055218+09
(1 row)

```

##終了
CTRL＋D
Eコマースのコンバージョンを増やすための7つの心理的なコピーライティングのコツ

ご存知のように、心理学は私たちが人間の行動を理解するのに役立ちます。その上、それは私達が人々に特定の反応を引き起こすために私達の行動と言葉を修正するのを助けます。したがって、心理的なアプローチはあなたのコピーライティングを改善することができます。

より多くの訪問者を顧客に変えるために心理学を使用したいですか？そのため、コピーを作成する際には心理的な観点を考慮する必要があります。

次のヒントは、ライターをコンバージョンを促進するコピーライターに変えます。

![copywriting tricks for e-commerce](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705866/9142182b-5cf2-3afc-3256-81b6eca856da.jpeg)

ストーリーで人々を引き込む

物語は最初から存在します。それらは娯楽、歴史的出来事の記録、そして今日では売り上げを伸ばすために使用されています。

物語は人々の感情的な反応を引き起こします。彼らの感情に駆り立てられて、ウェブサイトの訪問者は衝動買いをする可能性が高くなります。さらに、ストーリーがつながりの構築につながることを考えると、消費者はあなたのブランドと「結びつく」でしょう。その結果、彼らは繰り返し購入する可能性が高くなります。

多くのブランドは、ストーリーテリングを使用して新しい顧客を獲得しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/705866/4f5a2cef-37dd-6d32-21d0-1f516572b95c.png)

ノベルティに依存する

何か新しいものやなじみのないものにさらされると、脳はドーパミンを放出することが証明されています。その結果、コピーに「新しい」という言葉を使用すると、消費者の興奮を即座に高めることができます。

あなたの潜在的な顧客の頭脳は、何か新しいことに言及することで明るくなります。

数字の力を使う

あなたのコピーの特徴的な数字はあなたが事実に基づいてあなたの主張をしていることを示します。

したがって、数字は2つのことを行うことができます。1つは読者の注意を引くこと、もう1つはその情報に信頼性を追加することです。

次の見出しのバリエーションを考えてみてください。

ウェブサイトのコンバージョンを増やす方法
ウェブサイトのコンバージョン率を200％向上させた方法

2番目の見出しは、結果を正確に示しているため、より有望に見えます。

詳細については、[こちら](https://whidegroup.com/blog/psychological-copywriting-tricks-for-e-commerce/)をご覧ください。
docker volume 操作

```
# volumeのリスト
docker volume ls

# volumeの情報確認
# バーチャルマシン上の保存先が出るので実際にそのpathは存在しない
docker volume inspect <volume name>

# 削除
docker volume rm <volume name>

# どのコンテナでも使われていないvolumeを削除
docker volume prune
```
KONTAKT音源で鍵盤の色分けを行うときの効率的なKSPの書き方

# はじめまして

二次元系ドスケベサウンドデザイナーのくらびすたです。
主に同人エロゲーへのアセット提供を行っています。
詳しい実績はWebサイト https://klv-canvas.atmospherejp.info/ をご覧ください。
あとドスケベサウンド全般の話はDLsite傘下サイトCi-en https://ci-en.jp/creator/120 に書いています。

Qiitaさんへ
卑猥な言葉が並びますがどうか許してください
くらびより

# 目標

**鍵盤の色分けを行うのに使い回しの利く書き方を用意する**
たとえば「コントラバスの音域は赤、チェロの音域は黄色、ビオラの音域は緑、バイオリンの音域は青」のような色分けを行いたいときのことですね。

## きっかけ

この1年くらいでいわゆる音声作品を手掛けるようになりました。
ただあまり余裕がないもので、ガチンコフォーリーや立ち会い収録ができず…~~それにこういう仕事って声優に手柄が集中するし~~
少しでもラクしてリッチなものを作りたいという考えから、いろいろ巡り巡って普段音楽制作に使っているKONTAKTを活用することを思いつきました。

**そう、エッチな音ってループものが多いんです！**ペロペロとかギシギシとかアンアンとか。
加減速の調節とか面倒だったんですが、サンプラーにブチ込めばツマミひとつで済んでしまう！これをやらない手はないぞと。
ついでにワンショットもの（一発鳴らして終わる音）もアサインしたら、キーボードひとつであらかたの効果音が付けられるというわけです。

でもとりあえず鍵盤に並べただけではどの種類かが紛らわしい！あと見た目がダサい！ので、色分けをしたくなったのでした。

# コード

```
on init
	declare %range[8*2] := (...
		{clothes}...
			7,$KEY_COLOR_RED,...
		{rub}...
			2,$KEY_COLOR_LIGHT_ORANGE,...
		{handjob}...
			1,$KEY_COLOR_YELLOW,...
		{titfuck_loop}...
			3,$KEY_COLOR_GREEN,...
		{titfuck_oneshot}...
			1,$KEY_COLOR_CYAN,...
		{touch}...
			2,$KEY_COLOR_BLUE,...
		{piston}...
			2,$KEY_COLOR_VIOLET,...
		{ejaculation}...
			7,$KEY_COLOR_MAGENTA)
	declare $done_range := 0
	declare $count := 0
	declare $key := 48

	while($done_range < 8)
		$count := 0
		while($count < %range[$done_range * 2])
			set_key_color($key,%range[$done_range * 2 + 1])
			inc($count)
			inc($key)
		end while
		inc($done_range)
	end while
end on
```

## （自分用）解説

Qiita覗きに来る人は絶対僕よりプログラミング慣れしているので解説もクソもって感じです。

まず鍵数と色の組み合わせを配列で宣言しています。1次元しか使えないので詰め詰めにしています。
KSPでは {} の中身がコメントです。

```
	declare %range[8*2] := (...
		{clothes}...
			7,$KEY_COLOR_RED,...
		{rub}...
			2,$KEY_COLOR_LIGHT_ORANGE,...
		{handjob}...
			1,$KEY_COLOR_YELLOW,...
		{titfuck_loop}...
			3,$KEY_COLOR_GREEN,...
		{titfuck_oneshot}...
			1,$KEY_COLOR_CYAN,...
		{touch}...
			2,$KEY_COLOR_BLUE,...
		{piston}...
			2,$KEY_COLOR_VIOLET,...
		{ejaculation}...
			7,$KEY_COLOR_MAGENTA)
```

「色付けが済んだ範囲」の個数を数えるカウンターと色付け最中用のカウンターを用意します。

```
	declare $done_range := 0
	declare $count := 0
```

色付けする対象の鍵を保持する変数です。音が入っている最初の鍵のノートナンバーをあらかじめ埋めています。

```
	declare $key := 48
```

set_key_color() を気が済むまで実行します。\$range[$done_range * 2 + 1]は疑似多次元配列の2番目の箱を参照している箇所です。
僕は配列が0から始まることを忘れていたせいで無駄なオフセットを入れてチグハグな色付けをしてしまい、無駄な時間を溶かしました。
1から始まるアレもなんかたまにあるじゃないですか。MIDIのProgram Changeとか。

```
	while($done_range < 8)
		$count := 0
		while($count < %range[$done_range * 2])
			set_key_color($key,%range[$done_range * 2 + 1])
			inc($count)
			inc($key)
		end while
		inc($done_range)
	end while
```


# 課題

ドラム音源には「ドがバスドラ、レがスネア、ファ♯がクローズハイハット…」といったお決まりの配置があるのですが…
この書き方だとそういう飛び地のものに対して対応しきれないですね。[^1]
却ってコードが間延びしてしまうので、そっちはそっちで必要に迫られたら組もうと思います。
あと今回なんかは色定数（\$KEY_COLOR_hogehoge）を内部的には2飛ばしとかで作っているはずなので、そもそも疑似多次元配列なんて面倒臭いもの作る意味なかったかもしれない。（アホ）

[^1]: シンセサイザーの業界標準「General MIDI」の規定ではFGABCDの連続した白鍵がタムになっていて、その間にハイハットのF♯G♯A♯とクラッシュシンバルのC♯が差し込まれているのです。
コーディングテストでよく使いそうなアルゴリズムメモ(Python、初級レベル)

# はじめに
たぶん初級レベルと言われるコーディングテストでよく使えるかなと思うメソッドやアルゴリズムをメモしたいと思います。具体的にはとりあえず標準入力の受け付けとリストでわりとよく使うかなというやつらを載せたいと思います。

本記事で書かられている処理たちはこの処理たちです。
- 入力受付
- リスト操作

# メソッド、アルゴリズム集
## 入力受付
扱う処理たちは次の処理たちです。

- 空白くぎりで入力受付
- カンマ区切りで入力受付
- 複数行の入力受付

```algorithms.py
# 標準入力をString型でmy_listに代入
line = input()

# 標準入力を空白" "区切りでmy_listに代入
line = input().split(" ")

# 標準入力をカンマ","区切りでmy_listに代入
line = input().split(",")

# 複数行の標準入力をmy_listに代入
# 各行が一つのインデックスに文字列として格納される
lines = []
while True:
    s = input()
    if s:
        lines.append(s)
    else:
        break
```

## リスト

扱う処理たちは次の処理たちです。
- 要素からインデックスを検索
- 逆順並び替え
- 部分の切り出し
- 要素の結合
- 要素の入れ替え

```algorithm.py
# リストmy_listを次のように宣言
my_list = [0, 1, 2, 3, 4, 5, 6, 7]
# 要素からインデックスの検索。resultには2が代入される
result = my_list.index(2)

# リストmy_listを次のように宣言
my_list = [0, 1, 2, 3, 4, 5, 6, 7]
# リストの逆順並び替え。返り値なし
my_list.reverse()

# リストmy_listを次のように宣言
my_list = [0, 1, 2, 3, 4, 5, 6, 7]
# リストから部分的にリストを抽出。[0, 1, 2, 3]がmy_list_partsに代入される
my_list_parts = my_list[0:4]

# リストmy_listを次のように宣言
my_list = [0, 1, 2, 3, 4, 5, 6, 7]
# リスト要素の結合
print("".join(my_list))
# 01234567

# リストmy_listを次のように宣言
my_list = [0, 1, 2, 3, 4, 5, 6, 7]
# 要素の入れ替え。インデックス0とインデックス7を入れ替え
my_list[0], my_list[7] = my_list[7], my_list[0]

```

# おわりに
自分はコーディングテスト初級者なのですが、自分なりにコーディングテストを受けていて多用したメソッド、ないしアルゴリズムたちだったので備忘録的にまとめました。よかったら使ってください。随時書き足していけたらいいなと思います。
【git】開発ブランチのマージ時に使うコマンド(fetch, --prune, merge）についてのまとめ

私は現在、オンラインプログラミングスクール「やんばるエキスパート」で、４人チームで共同開発を行っています。

## 開発現状
ブランチは開発用のdevelopブランチをメインとしており、自分で作業する時は、developブランチから新しい作業ブランチを切って作業しています（ここでは仮に `feature/hoge_fuga` とします）。そして、コンフリクトの解消時の注意点として、現在の開発ブランチにマージする手順をスクールの教材では、

```
git branch で作業ブランチにいることを確認後
git fetch --prune
git merge origin/develop
```
を行うように記載されており、「fetchってなに？」「--pruneってなに？」「merge origin/developって何で行うの？」と疑問になったので、自分で調べてまとめてみました。


## git fetch --pruneとは？
```
git fetch
```
が、リモートリポジトリから最新情報を取ってくるコマンドで、`--prune`オプションをつけることで、自動的にリモートリポジトリで消されたリポジトリを削除してから、ローカルリポジトリにも反映させてくれます。



## ローカルリポジトリの作業ブランチにorigin/develop（開発用）ブランチをmergeする

現状、ローカルリポジトリには作業ブランチである`feature/hoge_fuga`と `origin/develop`が存在しています。そして、`origin/develop`はリモートリポジトリと結びついています。`

```
git fetch --prune
```
で`origin/develop`が最新情報になってますのでここで、


```
git merge origin/develop
```
コマンドを使う事によって、ローカル環境の`feature/hoge_fuga`が最新の状態に更新されるということになります。

## まとめ
スクールの教材などを行っていると、良い方向に誘導してくれますが、それだけではいけないと思ってます。自分の頭で考え、「これってどういうこと？」というのは今後も深堀りしていきたいと思います。もし今回のまとめが「ここ違うよ！」って点がありましたら教えていただけると嬉しいです。最後までお読みいただきありがとうございました。

## 参考文献
- [リモートで消されたブランチが手元で残ってしまう件を解消する](https://qiita.com/yuichielectric/items/84cd61915a1236f19221)
- [git fetchの理解からgit mergeとpullの役割](https://qiita.com/osamu1203/items/cb94ef9da02e1ec3e921)
DBのindexって何?

運用しているシステムで一部表示に時間がかかっているページがあり、原因を探っていると数秒かかっているクエリを見つけた。この際に「index使えばいいやん」的なことを言われて言われるがまま作業したが、色々疑問だったのでまとめた。

## Indexとは?
Indexとはレコードを高速に検索するための仕組み。Indexテーブルと呼ばれるテーブルを作成、それを使ってレコードを検索する。初期状態では、主keyに対してindexが割り当てられている。

## なんで検索が速くなる?
Indexを貼られたカラムはデータを特定の並び順にして、Indexテーブルに保存される。並び替えができていると、より効果的な探索アルゴリズムを利用することができるため、検索が速くなる(NがlogNになったりする)

### Userテーブルnameカラムの例

nameについて並び替えられていない例(nameでの検索では、前から順に検索していく必要がある)

|  ID  |  Name  |
| ---- | ---- |
|  1  |  tanaka  |
|  2  |  yamane  |
|  3  |  sato  |
|  4  |  abe  |
|  5  |  endo  |
|  6  |  wada  |
|  7  |  yabe  |

nameについて並び替えられた例(nameでの検索では、logNのオーダーの検索アルゴリズムが使える)

|  ID  |  Name  |
| ---- | ---- |
|  4  |  abe  |
|  5  |  endo  |
|  3  |  sato  |
|  1  |  tanaka  |
|  7  |  yabe  |
|  2  |  yamane  |
|  6  |  wada  |



## Indexが有効な場合

ただし、indexを利用することが全てのケースで有効であるとは限らない。厳密には、検索の際に速度が低下する訳ではないが、全体を俯瞰した時に有効ではない場合がある。

### 検索対象表の行数が多い
N と LogNの差が生きてくる

### 検索対象の表の更新が少ない
Indexテーブルの更新が頻繁に発生しない。(insertとかupdateする際に、indexの情報も逐次更新しなければんならないため時間がかかるようになる)

### 検索対象の表の追加削除が少ない
これに関しても上と同じ理由

追加だが、Indexを利用すると単純にデータ量が増える

## まとめ
最初に書いた問題は、indexを適切なカラムに貼ることでで600倍速になって嬉しかった
SQLite3でUPDATE SELECTが使えるようになったが、VBAから使用できなかった話

### SQLite3でのUPDATE FROM

あーなんかUPDATE FROMの文法でSQL書きたいなー
って日がたまにありますよね。

嘘です。

この度、SQLite3のバージョン3.33から、
UPDATE FROM が使えるようになったそうなので
遊びでさわってみました。

やっぱりゾロ目はいいですね。
（すでにバージョン3.34になってましたが）

で、先に結論を書いておくと、できなかった！という内容になります。
試したことを書いているので、詳しい方どなたか教えてください！！

### 環境の話

さて、まずは以前から触っていた環境説明から。
というほどでもないのですが、念のため書いておきます。

1.Windows 10
2.Excel 2016（マクロ起動でDB操作）
3.SQLite3 バージョン3.34
4.ODBCデータソース(64ビット) ← よく分からない
5.A5:SQL Mk-2 Version 2.15.0

で、実行してます。

### 処理内容

まず、やりたいSQLを簡略して書くと…

```sql
UPDATE
    tableA
SET
    columnA = tableB.columnB
FROM (
    SELECT
        columnKey
        , tableC.columnC + tableD.columnD AS columnB
    FROM
        tableC
        , tableD
    WHERE
        省略
) AS tableB
WHERE
    省略
AND tableA.columnKey = tableB.columenKey
```

こんな感じで、UPDATE FROM の形です。
で、こんな感じのSQLをExcelのシートに入力された内容に応じて、
マクロがinsertやら、updateやらを実行してくれる系のものがあったりします。

### A5での動作確認

マクロを起動してできたSQLをまずはA5で実行。

実行前にA5の参照しているSQLite3.dll を差し替え忘れずにね！

で、既存のDBファイルの差し替え方が分からず・・・
まあいいやと、create table 等のSQLは残してあったので、
新規でDB作成＋テーブル作成でDBファイルごと差し替えてしまった。

で実行したところ・・・
無事想定通り更新ができていた！

### VBAでの動作確認

じゃあ早速マクロに組み込んで実行したところ、

```
near"FROM": syntax error(1)
```

あら、FROM 前後にスペース入れ忘れ（SQL動的作成あるある）か？と思ったが、違う様子。。。

試しに、debug.printにて出力した結果をA5にて実行したところ、
あれーうまく出来てるぞと・・・

### VBAで実行しているSQLite3.dllを探して

あぁ、VBA側のSQLite3.dll差し替えてないじゃん！
おじさん気づいちゃったよ。

と思い探してみたところ、どこや…？となり、
とりあえずパスが通っているところをかたっぱしから探したところ、
Cドラのある場所にいたので差し替え。

ダメでした。

うーん…！

！！

odbcデータソース経由してるから、そっちの参照先か！
と思いましたが、それっぽいものは見当たらず。。

google先生にも聞いてみましたが、残念ながら記憶の奥底にしまってしまった様子。
私では探しだせませんでした。

### 結局

大人を舐めるなよ！！と言わんばかりに旧スタイルのSQLをマクロに実装。
ちょっと切なくなった夜でした。

どなたかVBAとSQLite3の関係を教えてください。

#### ～雑談～

切なくなった日は「Can't take my eyes off you」を見て元気を出してます。
皆さんもぜひ！