OmniAICreator/Qiita-1.07M huggingface dataset:
[Rails] 直打ち禁止方法

#直打ち禁止とは？
instagram風アプリなどの作成時に、投稿者のみ、編集や削除ができるようにすることです。
`current_user` などで `view` のみを制御してもURLに直接 `https:///XXX/edit` などを打ち込むと投稿者以外のアカウントでも編集できてしまいます。これを出来なくすることを直打ち禁止といいます。

#前提
railsで `devise` を導入していること。

#実装方法
`application_controller` に、before_actionメゾットを追記します。

```:application_controller
before_action :configure_permitted_parameters, if: :devise_controller?
```

次に、直打ち禁止させたいcontrollerページに以下を追記します。
今回は `post_controller.rb` という名前の `controller` ページに追記していきます。

```:post_controller.rb
before_action :authenticate_user!
before_action :ensure_correct_user, { only: [:edit, :update, :destroy] }
```

`authenticate_user!` はログインしているユーザーのみ使えるようにするメゾットです。(`devise` で使えるようになるヘルパーメソッド)
`before_action :ensure_correct_user` を追記し、 ` { only: [:XXX] }` に直打ち禁止したいアクションを追記します。今回は `edit`, `update`, `destroy` を追記しました。

また、同じcontrollerページ(今回は `post_controller.rb` )の `private` より上に下記のコードを追記します。

```:post_controller.rb
def ensure_correct_user
    @post = Post.find_by(id: params[:id])
    return unless @post.user_id != current_user.id

    redirect_to posts_path
  end
```
投稿したユーザーとログインしているユーザーのidが違うとき、 `posts_path` にリダイレクトするようになります。
ウォーターフォール型開発とアジャイル型開発の違い

二つの開発の違いを復習がてらに、備忘録として書いていきたいと思います。


##ウォーターフォール型開発
『区切られた全ての工程が正しい』という前提で進める方法。
この前提を守りながら進めるため、プロダクトはプロジェクト立ち上げ当初作成した要求仕様を忠実に実装し、その仕様を全て満たした時点で開発完了となります。
当初の要求仕様通りに進むという特徴から、**契約時に契約内容、責任範囲が明確**となるメリットがある一方、要求仕様作成時に要求ミス・漏れがあった場合や、開発途中で要求に変更があった場合、別途仕様変更として追加費用や開発期間が発生する可能性があるというデメリットがあります。


・大きなプロジェクトに向いている。
・基本的に途中の変更は無し。
・チーム事に役割分担されている。
・実装が終わり次第、工程事にテストする。
　

　　
　
##アジャイル型開発
アジャイルとは『すばやい』『俊敏な』という意味で、反復 (イテレーション) と呼ばれる短い開発期間単位を採用することで、リスクを最小化しようとする開発手法の一つです。
アジャイル型開発手法にはいろいろなバリエーションがありますが、例えば次のような進め方で開発をします。

**１**：顧客とエンジニアが少数精鋭の共同開発チームを作ります。（開発するプロダクトの規模によっては同時に複数のチームを立ち上げることもあります。）
**２**：共同開発チームは開発範囲全体をいくつもの短い範囲、おおむね2週間程度でできると思われる範囲、に区分します。そして業務プロセスの優先度を考慮し、どの範囲から着手するかを決定します。
**３**：共同開発チームは2週間という期間内に、その範囲の要求の決定、実装、テスト、修正、リリースを行います。
**４**：リリースできた機能や残っている業務プロセスの範囲を検討し、次に着手する優先すべき区分を決めます。

上記の**2から4のサイクルを繰り返して開発**を進め、全体の完成度を高めていきます。　　

　　
・優先度の高い重要な機能から着手できる。
・実際に動く画面、機能を試し、ミスに早い段階で気づくことができる。
・開発の途中で業務プロセスが変更になった場合、未着手の部分は変更された内容で実装できる。
S3で静的ウェブサイトを作る ただしCLIで

# はじめに
S3はストレージサービスの一つですが、静的なWebサイトを作ることができるとか。その実験をした際の覚書です。

# 内容
S3にWebサイトを作ります。なるべくCLIで作りましたが、最後のアクセスポリシーだけコンソールから作業しました。

## S3バケット作成

```Shell
# バケットの作成
$ aws s3 mb s3://talomina
make_bucket: talomina

# htmlファイルの登録 通常のindexとエラー時用のhtmlを置きます。
$ aws s3 cp index.html s3://talomina/
$ aws s3 cp error.html s3://talomina/

# バケットをwebsiteに設定する indexとエラー時用のhtmlを指定します。
aws s3 website s3://talomina/ --index-document index.html --error-document error.html
```
## S3バケットのアクセスポリシー設定
下記のようにポリシーファイルを作成します。ここではバケットのGetObject権限を全Principalにtalomina直下のすべてをAllowしています。

```json:policy.json
{
  "Id": "Policy1615385524659",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1615385522502",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::talomina/*",
      "Principal": "*"
    }
  ]
}
```
json形式のポリシーファイル作成はコンソールの[AWS Policy Generator](https://awspolicygen.s3.amazonaws.com/policygen.html)を利用して作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/3a262b5e-a803-2166-2498-8f0d1d8897fd.png)

作成したポリシーをS3にputします。

```Shell
#ポリシーの設定
$ aws s3api put-bucket-policy --bucket talomina --policy file://bucketpolicy.json
#ポリシーの確認
$ aws s3api get-bucket-policy --bucket talomina

#ポリシーの削除（参考：ここではやらない）
$ aws s3api get-bucket-policy --bucket talomina
```
これでS3の設定は完了です。

## アクセス確認
ブラウザ上で表示されるか、確認します。
URLはhttp://[bucket-name].s3-website-[region].amazonaws.comです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/0c3f1c8c-a0d7-029c-f7d8-9727ef2fa277.png)

エラーも表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/e12edc53-626e-5b70-18e7-dc4bf2ec2fbc.png)


# おわりに
思ったよりも手間なくウェブサイトを作ることができました。~~サイトをhttps化するなら[AWSでWebサイトをHTTPS化する覚書](https://qiita.com/talomina/items/d0299f81934d2661bb5b)の「ELBをドメインに紐づける」の手順で可能です。~~

2022年11月20日追記:後で気づいたのですが、この時点で既に[HTTPS化されていました](https://talomina.s3.ap-northeast-1.amazonaws.com/index.html)。

S3はイレブンナイン(99.999999999%)の可用性が売りなので通常のWebサイトとしては十分なのではないでしょうか。

## 料金
S3はストレージとしてのデータ保管料とデータ取り出しに料金がかかります。[こちら](https://aws.amazon.com/jp/s3/pricing/)のサイトをもとにざっくり計算すると月に5円くらいでしょうか。

* データ保管料：0.025USD/GB
* データ取出料：0.0047USD/GET、SELECT、他のすべてのリクエスト (1,000 リクエストあたり)

# 参考文献
* [私のバケットポリシーに間違った VPC または VPC エンドポイント ID が登録されます。ポリシーを修正してバケットにアクセスできるようにする方法を教えてください。](https://aws.amazon.com/jp/premiumsupport/knowledge-center/change-vpc-endpoint-s3-bucket-policy/)
* [AWS CLIを使って、Amazon S3で静的ウェブサイトをホスティングしたい
](https://dev.classmethod.jp/articles/amazon-s3-website-hosting-with-aws-cli/)
コードのストックはNotionが最適解！？

#はじめに
プログラミングの勉強もしていて、Notionを使っているので、コードの保存に可能性を見出したくて、色々と考えてみました。

##Notionでのコード保存方法

マークダウン記法が使えるので、
`(バッククオート)を3つ打つだけです。

##Notionでコードを保存するメリット

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/741816/85f9bb60-6d6a-bf59-916a-7038767d8049.png)


- 右上にある、`Copy`から、コードを丸々コピーできる。
- `Caption`で簡単な説明文をコードブロックの下に記述することができる。
- ハイライトに対応している言語が数多くある。
- コードブロックの外で見出しをつけたり、色をつけたりすることでレイアウトが可能
- 説明をコードの中に書かなくて済む
- 一つのページに、コードブロックを分けることで、様々な言語を保存することができる

↑一番最後のメリットが、テキストエディタにはできないもっとも大きなメリットだと感じました。

##汎用的に使えそうな場面

- テストコード
- フォームタグセットのHTMLとCSS
- プログラミングの問題の記録
gitにて、初回push時にエラー「Missing or invalid credentials.」となりpushできなかった話（解決までの流れも記載）

##記事概要
吾輩は猫である。
git練習中。
pushを行ったところ、下記エラーが出たため、解決を試みた。

結末としては、いろいろ触っていると解決できたので、エラー発生時の状況、エラー原因、調査・解決手順を残しておく。

```言語:エラー内容
Missing or invalid credentials.
Error: socket hang up
    at connResetException (internal/errors.js:570:14)
    at Socket.socketOnEnd (_http_client.js:440:23)
    at Socket.emit (events.js:228:7)
    at endReadableNT (_stream_readable.js:1185:12)
    at processTicksAndRejections (internal/process/task_queues.js:81:21) {
  code: 'ECONNRESET'
}
```

## 状況
環境はmacOS。
VScode上で初めてターミナルを起動し、
git add
→　git commit
→　git push
したところ、git pushした際に、冒頭のエラーが発生。
pushできず。


##エラー内容
冒頭のエラーメッセージにおいて重要なのはおそらく下記の部分。

```:重要な部分（仮）
Missing or invalid credentials.
```
直訳すると「資格情報が無い、または無効」
んん、わからん。「資格情報」とは何を指しているのか。
後述するエラー原因調査を経ての推測だが、『資格情報』と言うのはユーザ名とパスワードのこと。

つまり、本エラーは「pushコマンドを実行しているお主は誰だ。名乗らぬ者はpushさせぬぞ」と言っておられる。


## エラー原因調査・解決手順
まず、どこに原因があるのかを大きく切り分けることにした吾輩。
ずばり、原因はgit側かVSCode側かを探っていく。

と言うことで、VSCode上で行っていたgit pushを、普通にターミナルで行ってみることに。
これで、VSCode上のターミナルでpushした際のエラーが出れば、エラーの原因としてVSCodeのターミナルか通常のターミナルかといった違いは関係ないと言うことができると思ふ。

通常のターミナルでgit pushを行ったところ、ユーザ名とパスワードの入力を尋ねられた。
問われるがまま入力すると、push成功。

_:(´ཀ`」 ∠):{えぇ・・・

その後、VSCode上でgit add、git commitを再度行った上でgit pushしてみると、ユーザ名とパスワードを尋ねられ、問われるがまま入力。
pushできました。

_:(´ཀ`」 ∠):{えぇ・・・

と言うことで、pushできなかった要因は、push時にユーザ名とパスワードを入力しなかったからと思われる。
なぜ、初回のVSCodeターミナルでのpush時にユーザ名とパスワードを尋ねられなかったのか。
VSCodeの設定か、gitの設定か・・・結局、何の設定だったのかは分けられなかったけれど、エラー内容はわかった。
もう少し余力が出てきたら、そのあたりも調査してみます。
CommandInvokationFailure: Unable to install APK to device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.

###エラーと環境
 > CommandInvokationFailure: Unable to install APK to device. Please make sure the Android SDK is installed and is properly configured in the Editor. See the Console for more details.

Player SettingsのScripting BackendをIL2CPPに変更したところ、
上記のエラーが発生し、Build And Runが実行できなかった。

エディター : Windows 10、 Unity 2020.1.17f1
実機 : Android 11


###解決策

接続先のAndroidにある同じアプリ(正確には同じパッケージ名のもの)をアンインストール。
これでできた。
Devise 複数のモデルで同時にログイン出来ないようにする方法

## はじめに
例としてECサイトなどで、deviseをつかってUserモデルとStoreモデルを作成した場合、デフォルトではそれぞれのモデルで同時にログインや新規登録が可能です。今回はそれを修正したいと思います。

## コントローラーを表示する

```
$
rails generate devise:controllers users
rails generate devise:controllers admins
```

## ルーティング

```config/routes.rb
devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations'}
devise_for :stores, controllers: { sessions: 'stores/sessions', registrations: 'stores/registrations'}
```
これを忘れるとコントローラー内でオーバーライドした内容が反映されないので注意しましょう。

## モジュールの作成

```../controllers/concerns/accessible.rb
module Accessible
  extend ActiveSupport::Concern
  included do
    prepend_before_action :check_user
  end

  protected
  def check_user
    if current_store
      flash[:notice] = '店舗として既にログインしています。'
      redirect_to(current_store) and return
    elsif current_user
      flash[:notice] = 'ユーザーとして既にログインしています。'
      redirect_to(root_path) and return
    end
  end
end
```
check_userメソッドではそれぞれのモデルでログインしている場合はリダイレクトする処理を行っています。
これをコールバックに登録するのですが、理由は後述しますがbefore_actionではなくprepend_before_actionに登録しています。

## モジュールの読み込み

```../controllers/users/registration_controller.rb
class Users::RegistrationsController < Devise::RegistrationsController
  include Accessible
  skip_before_action :check_user, except: [:new, :create]
  .
  .
  .
end
```
ここでは、自分のアカウント情報にアクセスして編集する目的と、edit,update,destroyアクションはdeviseのデフォルトの機能によりログインしているアカウントしかアクセス出来ないという理由でchek_userメソッドを呼び出していません。

```../controllers/users/sessions_controller.rb
class Stores::SessionsController < Devise::SessionsController
  include Accessible
  skip_before_action :check_user, only: :destroy
  .
  .
  .
end
```
ログアウトする必要があるのでdestroyアクションには適用していません。
これで完成です。

## before_actionではなくprepend_before_actionにコールバック関数を登録している理由
[devise/app/controllers/devise/sessions_controller.rb](https://github.com/heartcombo/devise/blob/master/app/controllers/devise/sessions_controller.rb)
より、

```
.
.
prepend_before_action :require_no_authentication, only: [:new, :create]
prepend_before_action :allow_params_authentication!, only: :create
.
.
.
# POST /resource/sign_in
  def create
    self.resource = warden.authenticate!(auth_options)
    set_flash_message!(:notice, :signed_in)
    sign_in(resource_name, resource)
    yield resource if block_given?
    respond_with resource, location: after_sign_in_path_for(resource)
  end
```
createアクションにはprepend_before_actionが登録されており、それらのメソッドが実行されると
current_userがtrueを返してしまいます。よってモジュール内で指定したcheck_userメソッドはprepend_before_actionに登録する必要があります。

## 参考
https://github.com/heartcombo/devise/wiki/How-to-Setup-Multiple-Devise-User-Models

## 最後に
:require_no_authenticationメソッドや:allow_params_authentication!の中身をちゃんと理解していないので理解したいと思います。
何か間違った点や理解が怪しそうなところがあれば是非ご教授ください！
Vuetify v-data-tableのslotの探検

# デフォルトの表示
単純にデータを渡して、v-data-tableで表するとこのような表示になります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/8fd93901-5f2d-b2f4-8424-982ba8f94024.png)


# Slotの働き調査

item.\<name\> slotを使うことで表示を変更できます。試しに"AAA"を指定すると
manufactureの列がAAAになりました。

```vuejs
<template>
  <div>
    <v-data-table :headers="headers" :items="desserts">
      <template v-slot:item.manufacture>
        AAA
      </template>
    </v-data-table>
  </div>
</template>
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/f19bf5d2-ed9d-3e5e-d9b3-42514294071a.png)

# 特定の列の表示方法を変更する

試しに、メーカ名の前にiconを付加してみます。データの値は、`props.item.manufacture`に格納されています。
propsの部分は、`v-slot:item.manufacture="XXX"` の"XXX" 部分と同じ文字にします。

```vuejs
<template>
  <div>
    <v-data-table :headers="headers" :items="desserts">
      <template v-slot:item.manufacture="props">
        <v-icon>mdi-home</v-icon>{{props.item.manufacture}}
      </template>
    </v-data-table>
  </div>
</template>
```
予想通りの結果が得られました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/beb2a931-5aa8-0a16-8c74-a9021c76621e.png)

# データをEditできるようにする

Editできるようにする列のslotにv-edit-dialogを指定するとデータを編集できるようになります。
v-edit-dialogのinput slotに入力に使用するコンポーネントを指定する必要があります。
この例ではv-text-fieldを使い、type="Number"（数値入力用）を指定しいます。
`v-model.number="props.item.quantity"` の様に.numberを付けておくと、入力値が数値して扱われるので、001のような入力をしても1に変換されるようになります。

```vue
<template>
  <div>
    <v-data-table :headers="headers" :items="desserts">
      <template v-slot:item.quantity="props">
        <v-edit-dialog
          :return-value.sync="props.item.quantity"
        >
          {{ props.item.quantity }}
          <template v-slot:input>
            <v-text-field
              v-model.number="props.item.quantity"
              label="Edit"
              single-line
              type="Number"
            ></v-text-field>
          </template>
        </v-edit-dialog>
      </template>
    </v-data-table>
  </div>
</template>
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/71c24d47-a32a-3626-3854-d4895324e480.png)
擬似セレクター [: ]


##visited, hover, focus, active

visited, クリックした後ずっと
hover,   カーソルを合わせたとき
focus,   最後にクリックしたもの
active,  クリック中のもの


##:nth-child

:nth-child(odd),  奇数
:nth-child(even), 偶数
:nth-child(2n + 1)
「spanが5つあって3番目のspanのみ指定したい」ようなとき使える


##:nth-of-type

:nth-childの上位互換

##&:not(　)

&:not(.cls)の場合、「clsクラス以外の」という意味になる
Nginx ロードバランサー基本設定

#まず始めに
　今回はNginxのロードバランサー(負荷分散)・エラー時の設定についてまとめました。

#ロードバランサー(負荷分散)とは？
　Webサイトへのアクセスを振り分ける機械をロードバランサーといいます。
　英語の「**load（負荷）**」＋「**Balancer（釣り合いをとるためのもの）**」が由来で
　**負荷分散装置**とも呼ばれています。
　公開当初はさほどアクセスがないサイトでも、急に人気が出てアクセスが集中することも多いです。
　そうした場合に備え、ユーザーからのアクセスをさばくWebサーバを複数台用意しておき、システムの処理能力が不足してきた場合には、サーバの台数を増やして処理性能を維持できるようにしておくのが一般的です。

　負荷を分散することで、TAT・TPSなどの**パフォーマンスの低下防止**や
　システムダウン時の**可用性の向上**が得られます。
　　※TAT(Turn Around Time:応答時間)
　　※TPS(Transactions Per Second:リクエスト処理率)

#ロードバランスの方法
　負荷分散といってもリクエストの振り分け方には様々な方法があります。
　Nginxでは下記の方法が設定可能です。
　・**Round-Robin**…アプリケーションへのリクエストはconfの上から順に分配されます。　　　　　　
　・**Least-Connected**…次のリクエストは接続の数がもっとも少ないサーバに割り当てられます。
　・**Ip-Hash**…同じクライアントからのリクエストはサーバーが利用不可の場合を除いて
              常に同じサーバに割り当てられます。

#Nginxの設定方法
　デフォルトでは上記で説明したRound-Robinの設定となります。

```nginx.conf
…
http {
    upstream test_app {
        server test1.example.com;
        server test2.example.com;
        server test3.example.com;
    }

    server {
        listen 80;

        location / {
            proxy_pass http://test_app;
        }
    }
}
…
```

###Least-Connected


```nginx.conf
…
    upstream test_app {
        least_conn;
        server test1.example.com;
        server test2.example.com;
        server test3.example.com;
    }
…
```

###Ip-Hash

```nginx.conf
…
    upstream test_app {
        ip_hash;
        server test1.example.com;
        server test2.example.com;
        server test3.example.com;
    }
…
```

　また、リクエストの振り分けの比率を設定するが可能です。

```nginx.conf
…
    upstream test_app {
        server test1.example.com weight=3;
        server test2.example.com;
        server test3.example.com;
    }
…
```
　上記のような設定だと
　test1:test2:test3 = 3:1:1　の比率になります。
　Ip-Hashでの設定は不可です。

###可用性の向上
　１つの後続サーバがダウンした際にリクエストの振り分け先から外し、リクエスト処理を継続します。
　Nginxは独自のヘルスチェックを行うことはなく、リクエストに含んでいます。
　リクエストの応答がエラーの場合、該当のサーバを振り分け先から外します。

```nginx.conf
…
    upstream test_app {
        server test1.example.com max_fails=3 fail_timeout=30s;
        server test2.example.com down;
        server test3.example.com backup;
    }
…
```
　**max_fails**…エラーの際にリトライする回数を設定できます。デフォルトは1。
　**fail_timeout**…振り分け先から外した後に再度リクエストを振り分けるダウン期間を設定できます。
　　　　　　　デフォルトは10s。
　**down**…該当サーバを振り分け先から外します。
　**backup**…該当サーバ以外のサーバがすべてダウンした時にこのサーバに振り分けます。
　　　　　Sorryサーバ設定としても活用できます。

　
#最後に
　以上がNginxのロードバランス基本的な設定となります。
　他にも細かなエラー時の設定などができるので、そちらは別記事でまとめようと思います。

　最後まで読んでいただきありがとうございました。
【CSS】外部ファイル読み込みで@importを使う方法

#プログラミング勉強日記
2021年3月15日

#@importとは
　外部のCSSファイルを読み込むときに使う。CSSファイルが１つだと記述量が多くなってしまうので、ファイルを分割するときに使われる。

```css:@importの使い方
/* 同じ階層にファイルがあるとき */
@import url("cssファイル名");

/* 違う階層にファイルがあるとき */
@import url("cssファイルが入ってるフォルダ名/cssファイル名");
```

#サンプルプログラム
　最初に`header.css`と`body.css`ファイルを作る。
　次に、`main.css`を作成して`header.css`と`body.css`も@importで読み込む。

```css:main.css
@import url("./header.css");
@import url("./body.css");
```

```html:HTMLファイル
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title>Sample</title>
    // main.cssの読み込み
    <link rel="stylesheet" href="./main.css" />
  </head>
  <body>
  </body>
</html>
```

#参考文献
[@import](https://developer.mozilla.org/ja/docs/Web/CSS/@import)
[外部ファイルを読み込む！CSSで@importを使う方法【初心者向け】](https://techacademy.jp/magazine/13018)
Pytorchのtensorが占有しているGPUのメモリを開放する方法

# 結論
GPUに移した変数をdelした後、torch.cuda.empty_cache()を叩くと良い。

# 検証1:delの後torch.cuda.empty_cache()を叩きGPUのメモリを確認

``` 
Python 3.7.8 | packaged by conda-forge | (default, Jul 31 2020, 02:25:08) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> torch.__version__
'1.6.0'
>>> import GPUtil
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
|  0 |  0% |  7% |
>>> a = torch.rand(1, 1000, 1000, 1000).to("cuda")
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
|  0 |  0% | 26% |
>>> del a
>>> torch.cuda.empty_cache()
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
|  0 |  0% |  7% |
```

# なぜdelの後にtorch.cuda.empty_cache()を叩くのか
delだけではキャッシュが残ってしまうから。
そのため、torch.cuda.empty_cache()でキャッシュも消す必要がある。

# 検証2:検証１のコードの合間にキャッシュとキャッシングアロケータのメモリを可視化
``` 
Python 3.7.8 | packaged by conda-forge | (default, Jul 31 2020, 02:25:08) 
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import torch
>>> torch.__version__
'1.6.0'
>>> device = torch.device("cuda:0")
>>> torch.cuda.get_device_properties(device=device).total_memory
24032378880
>>> torch.cuda.memory_reserved(device=device) # キャッシュ
0
>>> torch.cuda.memory_allocated(device=device)# キャッシングアロケータ
0
>>> a = torch.rand(1, 1000, 1000, 1000).to("cuda:0")
>>> torch.cuda.memory_reserved(device=device) # 大規模なtensorを作ったため0ではなくなっている。
4001366016
>>> torch.cuda.memory_allocated(device=device)# 大規模なtensorを作ったため0ではなくなっている。
4000000000
>>> del a
>>> torch.cuda.memory_reserved(device=device) # del aをした後でもキャッシュは変わらず
4001366016
>>> torch.cuda.memory_allocated(device=device)# キャッシングアロケータのメモリの占有は0になる
0
>>> torch.cuda.empty_cache()
>>> torch.cuda.memory_reserved(device=device) # キャッシュが0になる
0
>>> torch.cuda.memory_allocated(device=device)# 前回が０だったので変わらず
0
``` 

# 参考
https://pytorch.org/docs/1.6.0/cuda.html?highlight=torch%20cuda%20empty_cache#torch.cuda.empty_cache
https://pytorch.org/docs/stable/cuda.html?highlight=torch%20cuda%20memory_reserved#torch.cuda.memory_reserved
【Kotlin初心者】intentを使って画面遷移してみた

## 画面遷移する方法

Androidアプリを作成する際に必須の画面遷移の実装についてメモを書きます。

NextActivity.ktというClassを指定してstartActivityにintentを渡してあげるだけで、
画面遷移が可能です。

```MainActivity.kt

val intent = Intent(this, NextActivity::class.java)
startActivity(intent)

```
[Python] リスト内包表記

# 概要
1: リスト内包表記とは
2: リスト内包表記の使い方①（基本型）
3: リスト内包表記の使い方②（基本形＋if文）

最近、リスト内包表記の使用頻度が増えてきて、なぜ使用した方が良いかを実感できたため、備忘録として記載。

# 検証環境
OS：18.04.5 LTS
Python：3.6.9

## 1: リスト内包表記とは
* for文などの反復処理を比較的シンプルに書くことのできる記法である。
* for文を使用してループ処理するよりも、実行速度が早い
* 関数型言語の記法
※　Python言語は、オブジェクト指向PGと関数型PGの両面の特徴を持つ

## 2: リスト内包表記の使い方①（基本型）
#### 基本の型

```python
[ 式 for 繰り返し変数 in シーケンス ] 
```

#### 例1: 文字列(string型)で格納されているリストを数値(int型)に変換する

```python

# データ
point_list = [ '80', '100', '20', '30', '40' ]

# 実行
point_list = [int(i) for i in point_list]

# 結果
[80, 100, 20, 30, 40]

```

#### 例2: 数値(int型)で格納されているリストを文字列(string型)に変換する
```python

# データ
point_list = [ 80, 100, 20, 30, 40 ]

# 実行
point_list = [str(i) for i in point_list]

# 結果
['80', '100', '20', '30', '40']

```

## 3: リスト内包表記の使い方②（基本形＋if文使用）

* if文を使用すると、<strong>繰り返し変数</strong>の判定で<strong>True</strong>のデータのみリストに追加する

```python

# データ
point_list = [ '80', '100', '20', '30', 'AL' ]

# 実行
point_list = [int(i) for i in point_list if i.isdigit()]

# 結果
[80, 100, 20, 30]

```
Xcode シュミレーター @が打てない時の対処法

#Xcodeのシュミレーターで「@」が打てない！！！ 
iOSのシュミレーターでキーボードから記号を入力すると、不思議なことに`@`が`[`になったり、なんだか色々とおかしくなってた。。。

別に`/`とか`:`みたいな記号はユーザー入力で使われることは滅多に無いのでいいんですが、、、

**`@`はログイン周りの処理で使うので、`@`が打てないのは困ります！！**

かといって、シュミレーター内のキーボードを毎回使うのも面倒やし:confused:

#解決法
![スクリーンショット 2021-03-15 22.41.41.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/b89593a3-3ad5-454f-ad02-7e89c0bfc901.jpeg)

`|/O＞Keyboard＞Connect Hardware Keyboard`のチェックを外す→もう一度チェックをつける

よくわかりませんが、これだけで正常になりました。。。

#追記
コメント欄より

>シミュレーターだと JIS キーボードを使ってても US キーボード配列になるらしいです！
なので shift + 2 で @ が入力できるらしいです:relaxed:

@am10 さん、ありがとうございます！！
bitbucketでリモートブランチを削除 (git)

### 目的

bitbucket でリモートブランチを削除する時に、WebサイトでGUIから行っていましたが

コマンドから実施する方法を調べました。

### 解決策

削除したいリモートのブランチを trash-test とします。

#### 実施コマンド

```
$ git push --delete origin trash-test
```

```
$ git push origin :trash-test
```

#### 出力結果

```
$ git push origin :trash
To https://bitbucket.org/hogehoge/fugafuga.git
 - [deleted]         trash-test
```

※ 記事を書いてみたものの、危ないコマンドなので実施するときは気をつけてください。

あまり使う機会はないかもしれません

### 参考

- [http://passingloop.tumblr.com/post/18015576208/remove-remote-branches-by-git-push](http://passingloop.tumblr.com/post/18015576208/remove-remote-branches-by-git-push)
- [https://qiita.com/yuu_ta/items/519ea47ac2c1ded032d9](https://qiita.com/yuu_ta/items/519ea47ac2c1ded032d9)
ridgepoleでfulltext indexを貼る方法

## MySQLの全文検索インデックス

MySQL5.6から、`fulltext` インデックスを貼ることができるようになった。（pluginによるparserの変更は5.7から?)

## ridgepoleでfulltext indexを貼ると発生する問題

```rb

create_table :fuga do
  ...
  t.text :hoge
  ...
end

execute("CREATE FULLTEXT INDEX fk_hoge ON fuga(hoge) WITH PARSER ngram")
```

この書き方だと、冪等性がなく、
2回目以降に実行すると、一度、 `remote_index :hoge` が行われたあとに、再度、 `execute` の `CREATE FULLTEXT INDEX` が呼ばれてしまう。`create_table` 句で `name` に対するindexを貼っていないための模様

この状態だと、マイグレーションを走らせるたびに、重いINDEXを貼る作業が毎回行われるので、回避するべき事象となる。

## 対処方法

```rb

create_table :fuga do
  ...
  t.text :hoge
  t.index :hoge, type: :fulltext, ignore: true # これを追加
  ...
end

execute("CREATE FULLTEXT INDEX fk_hoge ON fuga(hoge) WITH PARSER ngram") do |c|
  # INDEXが登録済みの場合は再実行しない
  rows = c.raw_connection.query("SHOW INDEX FROM fuga")
  rows.none? { _1[2] == 'fk_hoge' }
end
```

`ignore` を含んだ、TableDefinitionを追加し、 `execute` にINDEXの存在を確認するブロックを渡すことで、再実行してもOKになる。
[超参考](https://so-wh.at/entry/2019/01/12/232306)
nodeのhttp-serverをローカルにインストールして、起動する

# とりあえずしたい事

普通にnodeで簡易的なサーバーを立てたいけど、グローバルにインストールするのはイヤなので、
ローカルに立てるよ。

##　フォルダ構成はこうしたい

```
プロジェクトフォルダ/
   node_modules/
   html/
       index.html
       ＜ここにhtmlをおきたい＞
　 ＜nodeのプロジェクトでよく有る、あれやこれや＞.json
　 etc...
```

この状態で`localhost:8080`にアクセスしたら
`index.html`が表示するようにしたい

# http-serverをインストールして使えるようにする。

## インストールコマンド

``` 
npm install http-server
```

## 起動

```
node_modules\.bin\http-server
```
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57329/f662c112-ea83-ee62-30d7-c87bf5fb0080.png)


## 毎回こんなコマンド叩くの嫌なので、npm scriptに入れる

### package.jsonに追加

```
{
  "name": "×××××",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
	"server":"node_modules/.bin/http-server ./html", //追加 htttpルートはhtmlフォルダになる。
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "http-server": "^0.12.3"
  }
}
```

### 起動はカレントディレクトリで

```
npm run server
```
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57329/3d9e8043-45b5-4e2c-3ca1-1713ccac8ed1.png)
【2023年更新版】郵便番号APIサービス比較

2023年2月更新しました。

ECサイトで郵便番号から住所を自動入力する機能は今や必須となっていますが、自前で実装するのは非常に大変です。理由としては、日本郵便が提供しているCSVがかなりクセのある仕様となっており、そのままでは使うのは難しくなっています。また、郵便番号の件数が１２万件以上あるうえ、定期的にCSVが更新されるため、メンテナンスのコストも高くなります。なので、外部の郵便番号APIサービスを利用する場合が多いと思います。私も仕事で開発しているECサイトで使用するために調査したのでまとめます。

# 調査したサービス

* [zipcloud](https://zipcloud.ibsnet.co.jp)
* [PostcodeJP](https://postcode-jp.com/)
* [ケンオール](https://kenall.jp/)
* [api-zipcode.jp](https://api-zipcode.jp/)
* [ポストくん](https://postcode.teraren.com/)

商用利用可能なものに限定しています。

# 料金比較

| | 価格 | 料金形態 | 支払い方法 | 無料枠 |
|:-:|:-:|:-:|:-:|:-:|
| zipcloud | 無料 | - | - | - |
| PostcodeJP | ¥0〜3,400/月 | 月定額 | クレジットカード | リクエスト制限 |
| ケンオール | ¥5,500〜66,000/月 | 月定額 | クレジットカード | 最大30日 |
|api-zipcode.jp | ¥500/50,000リクエスト | 従量課金 | クレジットカード | 1,000リクエスト無料 |
|ポストくん | 無料 | - | -| - |

2023/02/16 時点

# サービス詳細

## zipcloud

[http://zipcloud.ibsnet.co.jp/](http://zipcloud.ibsnet.co.jp/)

郵便番号APIの世界ではかなり有名ではないでしょうか。
なんといっても無料で提供していただいています。
郵便番号CSVも独自に整理されており、加工済みのCSVもダウンロードできます。

| CSV整形済 | ローマ字 | 事業所の個別郵便番号 |
|:-:|:-:|:-:|
| ○ | - | - |


## PostcodeJP

[https://postcode-jp.com/](https://postcode-jp.com/)

料金形態が細かく別れており、目的に合わせて選択できます。
APIの機能が豊富でドキュメントもしっかりしています。リクエストレートやリクエスト回数が無制限のプランもあるので、大規模なECサイトでも安心だと思います。

| CSV整形済 | ローマ字 | 事業所の個別郵便番号 |
|:-:|:-:|:-:|
| ○ | - | ○ |


## ケンオール

[https://kenall.jp/](https://kenall.jp/)

名前のインパクトがすごいです。。例のあのファイルの名前ですね。
郵便番号データの整形にかなりのこだわりを感じます。京都市の「通り名」などにも対応しているので、正確な住所を検索したい時は安心だと思います。

| CSV整形済 | ローマ字 | 事業所の個別郵便番号 |
|:-:|:-:|:-:|
| ○ | - | ○ |


## api-zipcode.jp

[https://api-zipcode.jp/](https://api-zipcode.jp/)

従量課金なので、使用頻度が低い場合はお得だと思います。
郵便番号が特定のエリアに該当するかを判定するAPIがあります。例えば、163-8001が東京都の新宿区以外の22区内か？のような判定ができます。ECサイトの配送エリア判定に使えるかもしれません。

| CSV整形済 | ローマ字 | 事業所の個別郵便番号 |
|:-:|:-:|:-:|
| ○ | ○ | ○ |



## ポストくん

[https://postcode.teraren.com/](https://postcode.teraren.com/)

個人利用、商用利用が無料で行えます。REST API, GraphQLで郵便番号の検索を行えます。
事業所の郵便番号も検索できます。
マスタデータはzipcloudのデータを利用しています。


| CSV整形済 | ローマ字 | 事業所の個別郵便番号 |
|:-:|:-:|:-:|
| ○ | ○ | ○ |


# おわり

郵便番号から住所検索は自前でやるのは大変なので、外部のサービスを利用した方が結果的に効率的だと思います。サービスごとに特徴があるので、一度無料枠で試してみて自分に合ったサービスを探していただければと思います。
TeensyでAudio処理のバッファサイズと優先度を変える

## バッファサイズ ##
TeensyではAudio処理のバッファサイズがデフォルトで128固定だが、これは変えることができる。~/Library/Arduino15/packages/teensy/avr/cores/teensy4/AudioStream.h (Macの場合) を見るとAUDIO_BLOCK_SAMPLESをAudio.hをインクルードする前に定義すれば良いように見える。

```AudioStream.h
// AUDIO_BLOCK_SAMPLES determines how many samples the audio library processes
// per update.  It may be reduced to achieve lower latency response to events,
// at the expense of higher interrupt and DMA setup overhead.
//
// Less than 32 may not work with some input & output objects.  Multiples of 16
// should be used, since some synthesis objects generate 16 samples per loop.
//
// Some parts of the audio library may have hard-coded dependency on 128 samples.
// Please report these on the forum with reproducible test cases.  The following
// audio classes are known to have problems with smaller block sizes:
//   AudioInputUSB, AudioOutputUSB, AudioPlaySdWav, AudioAnalyzeFFT256,
//   AudioAnalyzeFFT1024

#ifndef AUDIO_BLOCK_SAMPLES
#define AUDIO_BLOCK_SAMPLES  128
#endif
```

ただ、なんかそう定義しても動かないことがあったので、このファイルの値を直接書き換えている。16の倍数で、となっているが8までは動作確認できた。4にしたら動かなかった。

## 優先度 ##
~/Library/Arduino15/packages/teensy/hardware/teensy/hardware/avr/1.59.0/cores/teensy4/AudioStream.cppを開き、"priority"で検索して見つかる下記の部分を変更するとたぶん変えられる。デフォルトの208だとCPU負荷が高くなった時にバッファアンダーランが起きたので、128に変更して使っている。もっと小さい値（優先度が高くなる）にしたら、I2Sの入力をパススルーしている部分でバリバリとノイズが乗ったので、優先度を高くしすぎてもダメなケースがある。

```AudioStream.cpp
bool AudioStream::update_setup(void)
{
    if (update_scheduled) return false;
    attachInterruptVector(IRQ_SOFTWARE, software_isr);
    NVIC_SET_PRIORITY(IRQ_SOFTWARE, 208); // 255 = lowest priority
    NVIC_ENABLE_IRQ(IRQ_SOFTWARE);
    update_scheduled = true;
    return true;
}
```
【Elasticsearch】Amazon Elasticsearch Serviceに分散表現のベクトルを格納するフィールドタイプ「dense_vector」が存在せず困った話

# はじめに
少し長くなりそうなので結論から言いますと、分散表現のベクトルを格納するフィールドタイプ**「dense_vector」**の代わりにAmazon Elasticsearch Serviceに用意されているフィールドタイプ**「knn_vector」**を使用することにして困りごとを解消いたしました。

# 困ったこと
Elasticsearch 7.3のリリースで追加された高次元ベクトルのドキュメントスコアリング機能を用いてとある文章の機械学習を行い、**「テキスト類似性検索」**を実装しました。
始めにElastic社のElasticsearch（以下、Elasticsearch）を使用してローカル環境で機械学習を行っており、その後しばらくして学習済データをAmazon Elasticsearch Service（以下、Amazon ES）に移行する必要が出てきました。その際にエラーが発生し、後続作業が中断する事態となってしまいました。

※テキスト類似性検索（または類似文書検索）とは「文章を数値化し、その数値の類似度をもって検索対象の文章群の中から検索条件に近い文章を選択する自然言語処理の技術」です。

# 原因
エラーの原因は単純なことでした。存在しないフィールドタイプを使用しようとしてエラーとなってしまっていたのです。
Elasticsearch上で分散表現のベクトルを格納する際にフィールドタイプ**「dense_vector」**を使用していたのですが、Amazon ESに該当のフィールドタイプが存在しなかったのです。

# 対処法
何か手はないかとAmazon ESのドキュメントを読み漁ったところ、**「KNN」**というアルゴリズムがフィールドタイプ**「knn_vector」**として用意されていることがわかりました。
Amazon ESの開発者ガイドを見てみると

>関連する k-近隣住民 アルゴリズム、KNN Amazon Elasticsearch Service では、ベクトル空間内の点を検索し、ユークリッド距離またはコサインの類似性によって、それらの点の「最も近くの隣人」を見つけることができます。ユースケースには、推奨 (音楽アプリケーションの「あなたにおすすめの曲」機能など)、画像認識、不正行為の検出などがあります。

と書いてあります（日本語ページの原文ママ）。何やら**「dense_vector」**と同様に高次元ベクトルを格納できるフィールドタイプのようです。

試しにAmazon ES上にフィールドタイプ**「knn_vector」**のフィールドを定義し、**「dense_vector」**に格納していたベクトルデータをインポートしてみたところエラーなく登録できました。

# 検索クエリの違い

フィールドタイプが異なるので検索クエリも変わってきます。

## １．Elasticsearchの「dense_vector」

```
"query": {
    "script_score": {
        "query": {"match_all": {}},
        "script": {
            "source": "cosineSimilarity(params.query_vector, doc['text_vector']) + 1.0",
            "params": {"query_vector": target_vector}
        }
    }
}
```

## ２．Amazon ESの「knn_vector」

```
"query": {
    "knn": {
        "text_vector": {
            "vector": target_vector,
            "k": 100
        }
    }
}
```

# 検索結果の差分
アルゴリズムが異なるため、当然検索結果も違ってくると思います。
今回は**「それらしい結果が取得できている」**で検証を終えています。
いつかちゃんと検索結果の違いについて調査しようと思います。

# 参考サイト
[Amazon Elasticsearch Service>開発者ガイド>KNN](https://docs.aws.amazon.com/ja_jp/elasticsearch-service/latest/developerguide/knn.html)
[Amazon ElasticsearchServiceのK-NNを触ってみる](https://qiita.com/jnit/items/4bd00a1e16ab7883d1ad)
[ベクトルフィールドを使ったテキスト類似性検索](https://www.elastic.co/jp/blog/text-similarity-search-with-vectors-in-elasticsearch)
[Elasticsearchで分散表現を使った類似文書検索](https://yag-ays.github.io/project/elasticsearch-similarity-search/)
Windowsでも$historyがしたい！～コマンド履歴を確認するには～

# はじめに
Linuxでは`history`コマンドを使うことで、過去に使用したコマンドを表示することができます。
Windowsで同じことを実現するにはどうしたらよいのか？ということを書いたのが、この記事です。

PowerShell, CMD（コマンドプロンプト）の2パターンで記述します。

# 結論として一番伝えたいこと

PowerShellで、これを打てばよい
` type (Get-PSReadlineOption).HistorySavePath -Tail 20`

# PowerShell

## PowerShellにおいて、同一セッション内で使用した履歴を参照したい

`Get-History`、あるいは`h`で参照できます。
セッション内の履歴なので、PowerShellを終了する（ウィンドウを消す）とその履歴は消えます。

「あのときに使ったコマンドなんだったっけ..」という場合には、残念ながら使えません。
その場合は次項の方法を試してください。

## PowerShellにおいて、過去に使用したコマンドすべてを参照したい

`(Get-PSReadlineOption).HistorySavePath`というコマンドをPowerShellで実行することにより、履歴が保存されたテキストファイルのパスを表示できます。

CLIでの履歴表示にこだわる場合は、次のような操作でそれを実現できます。
Linuxの`cat`（ファイルの中身を表示する）に相当する`type`コマンドと、パスを表示する上記のコマンドを併用することで、コンソール上で履歴を表示できます。
`type (Get-PSReadlineOption).HistorySavePath`

しかし、このままだと大量のログが吐き出されかねないので、最後の数行だけ表示するよう、Tailコマンドを使って加工する方法も紹介します。
ここでは20行を表示することにします。

` type (Get-PSReadlineOption).HistorySavePath -Tail 20`



## CMD（コマンドプロンプト）で履歴を参照したい
同一セッション内の履歴を参照する方法は見つかりましたが、それ以前に実行したコマンドを参照する方法を見つけることはできませんでした。

同一セッションであれば、`doskey /history`を実行することで履歴を表示できます。

# 参考

- [コマンドプロンプトでコマンドの実行履歴（ヒストリ）を取得する](https://www.atmarkit.co.jp/ait/articles/1809/27/news035.html)
- [PowerShellの完全な履歴を取得する](https://qiita.com/yuta0801/items/ad0cf608144fb1546e54)
- [Powershellコマンドログについて](https://for0n6x.hatenablog.com/entry/2018/08/07/093736)
- [Windows Powershellによる最後から特定の行数ほど前からテキストファイルを出力する方法を紹介](https://www.wannko.net/powershell/file/get-content2.html)
とりあえず React + TypeScript で適当なサンプルページを作りたい ②

### 前回
https://qiita.com/KennyKTA/items/c05c5047953777eeb5c4

### 今回やること
- React + Boot Strap でなにがしかの実装を行う。
- React + Boot Strap によるグリッドシステムの実装を行う（次回に譲るかも）。

補足：
軽く調べるとレイアウトの配置はグリッドシステムというものを使うそうだ。別の技術もあり得るだろうが、今回は一通り走ることが大目標なので、これを採用する。Boot Strap という聞いたことのある名前の技術がReactにグリッドシステムを提供しているようなのでこれをターゲットに実装する。

### 今回やらないこと
- 特になし


### 開発
- React BootStrap の公式ページのGet Start に従っていく。

https://react-bootstrap.github.io/getting-started/introduction

React Boot Strap のパッケージをインストール

```
npm install react-bootstrap bootstrap
```

アプリのソースを以下のように実装。

```App.tsx
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { LanguageServiceMode } from 'typescript';
import { Button } from 'react-bootstrap';

function App() {
  return (
    <div>
      <h1>this is sample</h1>
      <Button>this is sample <button type="submit"></button></Button>
    </div>
  );
}

export default App;
```

ローカルサーバの立ち上げを実施。

```
npm start
```

以下のようなページが表示された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/002d7abb-5fe1-de49-4245-fd7c04b3fc2f.png)

どうやらReact Boot Strap はUIコンポーネントも提供しているらしい。かなり色々できそうだが本丸はグリッドシステムなので、そこを重点的に調べる。グリッドシステムに関しては次回に譲る。


### その他
- グリッドシステムを調べる過程で面白そうなものを見つけた。別の機会に調べたい。
https://github.com/react-grid-layout/react-grid-layout

- React の公式から辿って知ったのだがCodeSandboxというWebサービスがある。
https://codesandbox.io/
node.js のIDE環境で、作成したReactアプリを簡易にホストしてくれるらしい。
開発環境を構築する手間が省けるし、npm start のようなサーバ立ち上げのコマンドも不要だ。
実装の挙動だけを簡単に確認したい場合はこれでもいい気がしてきた。
Lambda で返ってくる文字列でハマった

# 問題
Lambda、API Gateway を使って Web ブラウザからの入力結果を処理していた。Lambda 関数の戻り値に不要なダブルクォーテーションがついていた。

以下のような Lambda 関数を作成した。

```lambda_function.py
if bool:
    return 'Exist'
else:
    return 'NotExist'
```

lambda_function.pyの戻り値がresponse.text()に格納されるのだが、bool が True であるにも関わらず、result === 'Exist' の結果が false になっていた。

```main.js
fetch(url, requestOptions)
.then(response => response.text())
.then(result => {
  if (result === 'Exist') {
    alert('存在します。');
  } else {
    alert('存在しません。');
  }
})
```

ログを見ると、result の値が `""Exist""` となっていた。そこで replace メソッドを使った。

```main.js
fetch(url, requestOptions)
.then(response => response.text())
.then(result => {
  if (result.replace(/"/g, '') === 'Exist') {
    alert('存在します。');
  } else {
    alert('存在しません。');
  }
})
```

# replace

```js
'Hello, WORLD!'.replace(/o/ig, '')
// 結果："Hell, WRLD!"
```

- i フラグ：大文字と小文字の違いを無視して置換
- g フラグ：指定した正規表現にマッチするすべての文字列を置換（グローバルマッチ）

# 参考記事
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/String/replace
【Golang】標準入力から1文字のキー入力を読み込む（enter いらずの On KeyPress/KeyDown っぽいやつ）

# Go言語で標準入力のキー押下（`KeyPress`）を検知する

> Golang で**標準入力から1行ごとではなく、1文字だけ取得する方法**を知りたい。

正確には [TTY](https://ja.wikipedia.org/wiki/Tty) からの標準入力を 1 文字欲しいのです。Javascript で言うところの `onkeypress` のキーイベントを取得したいのです。

つまり、ターミナルやコマンドラインなどのユーザー入力（標準入力）で `y` -> `enter` でなく、**`y` キーを押しただけで `y` を検知したい**のです。

[「golang 標準入力 1文字 読み込む」で Qiita 記事に絞ってググって](https://www.google.com/search?q=site:qiita.com+golang+%E6%A8%99%E6%BA%96%E5%85%A5%E5%8A%9B+1%E6%96%87%E5%AD%97+%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80)も、[競プロ](https://ja.wikipedia.org/wiki/%E7%AB%B6%E6%8A%80%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0)の課題にあるような「改行区切りで得られた文字列から、最初の文字を取得する」ような例や[パイプ渡し](https://ja.wikipedia.org/wiki/%E3%83%91%E3%82%A4%E3%83%97_(%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF))の例ばかりだったので、自分のググラビリティとして。

## TL; DR <sub><sup><sub><sup>（今北産業）</sup></sub></sup></sub>

1. こういうこと 👇 をしたい人向け

    ```shell-session
    $ go run . <enter>
    Key press => a
    Key press => b
    Key press => c
    Key press => d
    ...(ctrl+c)
    signal: interrupt
    ```

1. @mattn さんの素晴らしい <code>[github.com/mattn/go-tty](https://github.com/mattn/go-tty)</code> パッケージの `tty.ReadRune()` を使う。
    - ソース: https://github.com/mattn/go-tty @ GitHub
    - ドキュメント: https://pkg.go.dev/github.com/mattn/go-tty#section-readme
    
    （こいつやー！と思ったらスターを付けましょう）

1. `tty` 入力を監視し、1 文字（`rune`）検知するごとにゴニョゴニョする。

- 動作確認済み環境
    - Intel Core i5（2.7 GHz デュアルコア）
        - macOS Catalina 10.15.7, Debian GNU/Linux 10 (buster), Alpine Linux v3.13
    - ARMv7 Processor rev 4 (v7l)
        - Raspbian GNU/Linux 9 (stretch),
    - Go version 1.16
- 併せて読みたい
    - [Go言語+WindowsTerminalで「ブロック崩し」を作ろうと挑戦したが四苦八苦[termbox-goは未使用]](https://qiita.com/good_kobe/items/6dee929b6a983fd8d917#_reference-18dd4df7e105062a31c5) @ Qiita

## TS; DR <sub><sup><sub><sup>（マスター、動くものをくれ）</sup></sub></sup></sub>

```go:main.go
package main

import (
	"fmt"
	"log"

	"github.com/mattn/go-tty"
)

func main() {
	tty, err := tty.Open()
	if err != nil {
		log.Fatal(err)
	}

	defer tty.Close()

	fmt.Println("Ready. Press any key ...")

	for {
		r, err := tty.ReadRune()
		if err != nil {
			log.Fatal(err)
		}
		fmt.Println("Key press => " + string(r))
	}
}
```

[Go Playground](https://play.golang.org/) では `tty` からの標準入力のテストができないため、再現性のために Dockerfile も置いておきます。

```go:go.mod
module sample/tty

go 1.16

require github.com/mattn/go-tty v0.0.3
```

```dockerfile:Dockerfile
FROM golang:1.16-alpine

COPY . /app
WORKDIR /app
RUN go mod tidy
```

```shell-session:macOS,Linuxのターミナル（要Docker）
$ # ファイルの確認
$ tree .
.
├── Dockerfile
├── go.mod
└── main.go

0 directories, 2 files

$ # 実行環境（コンテナ・イメージ）のビルド
$ docker build --tag sample/tty .
...

$ # `go run .` と同じことをコンテナ内で実行
$ docker run --rm --interactive --tty sample/tty go run .
Ready. Press any key ...
Key press => a
Key press => b
Key press => c
Key press => d
Key press => e
(ctrl+c)
signal: interrupt
$
```                    

macOS とラズパイ3+B（Raspbian GNU/Linux 9, stretch）の Docker で動きました。また、Docker 内で `darwin` と `arm` 向けに静的ビルドすれば、ビルドしたバイナリをエクスポートしてローカルで実行しても動きました。
【Rails】Webpacker::Manifest::MissingEntryErrorの対処法【Docker】

#環境
Ruby 2.6.6
Rails 6.1.1
Docker 20.10.2
#はじめに
Docker環境でRailsアプリを開発中に、サーバーを起動しhttp\://localhost:3000/にアクセスすると発生。
Rails6ではwebpackerが標準サポートとなり、webpakerのインストールにはパッケージマネージャーであるyarnが必要。
#エラーの解決方法
####１）まずyarnで必要なライブラリをインストールする

```linux
$ bin/yarn
```

####２）次にwebpackでJavaScriptのコンパイルをする

```linux
$ bin/webpack
```

####３）最後にJS配信用のdevサーバーを起動する。（自動でwatch＆コンパイルされる）

```linux
$ bin/webpack-dev-server
```

これをした後に一応docker-compose up -dで再起動し、localhost:3000にアクセスすると表示されました！
２と３はどちらかだけでも良いかも？？

######参考
 [【Rails6】Webpacker::Manifest::MissingEntryErrorが出たときの対処法](https://qiita.com/masatwork/items/1b5d190cc76f5eeffbb7)

[【Rails】インストール時につまづきがちなエラー集】](https://blog.yuhiisk.com/archive/2018/04/24/rails-error-collection.html#Webpacker)
【就活用】MacでPDFを圧縮・パスワードを設定する方法

#はじめに
就職活動では企業から履歴書・職務経歴書を送付するよう指示があります。
その際、圧縮とパスワードの設定をするよう言われるときがあり、その方法の共有です。

#やること
１ PDFの圧縮

2 PDFのパスワードの設定


##1 PDFの圧縮
下記のURLにアクセスしサイトの指示に従い、PDFの圧縮を行います。

https://www.adobe.com/jp/acrobat/online/compress-pdf.html?mv=search&sdid=5JRH8JQH&ef_id=Cj0KCQjwi7yCBhDJARIsAMWFScN27_Nu9JwurmR_zpRvdUOE3NTgzY_M4xClSzzHbTpCB8zbwV3KlO8aAvS2EALw_wcB:G:s&s_kwcid=AL!3085!3!401093830965!b!!g!!%2Bpdf%20%2B%E5%9C%A7%E7%B8%AE!8270482221!85592991757&gclid=Cj0KCQjwi7yCBhDJARIsAMWFScN27_Nu9JwurmR_zpRvdUOE3NTgzY_M4xClSzzHbTpCB8zbwV3KlO8aAvS2EALw_wcB

PDF圧縮アプリです。

##2 PDFのパスワードの設定
① デスクトップ左上の「ファイル」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/8c95b44b-bd9c-f7d3-d627-1bd7b19fc9e6.png)


②ファイルの中の「プリント」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/7c58fe35-51e2-cc5b-9fcf-dca15c62b53a.png)

③左下の「PDF」をクリックし、「PDF」として保存をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/a32efc74-9332-1372-b068-8b093603773e.png)

④セキュリティオプションをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/ac9ed9d9-2907-2c01-a2d2-a5aaa28b86a2.png)

⑤写真のようにチェックボックスにチェックを入れ、「パスワード」を任意で入力する。確認には同じパスワードを入力し「OK」をクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/e1d5417e-d967-e007-dd68-b649b7cda18c.png)

⑥1つ前の画面に戻り、「保存」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/9b490664-b269-5ce4-7319-751ca977f97b.png)

⑦写真のように「置き換え」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/07fd2c14-8dee-a64e-695e-65dfa53149fd.png)

⑧パスワード付きのPDFの完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/4d4b196b-9280-4654-0546-8ff1c7bf079d.png)

**※１と2の手順を逆にすると実行できないので注意です。**

#なぜ企業が指示を出すのか
※上記の番号と対応しています。
1 ・MacとwindowsなどのOSの違いで開けないファイルがあるからです。
　・PDF化することで履歴書の改ざんを防ぐことができるからです。
　・エクセルやワードではバージョンによって開けないこともあり、印刷ページがずれることもあるからです。
　 PDFであればPC環境に左右されることも少ないので、印刷や管理をしやすいためです。

2 PDFを暗号化するため圧縮することと、容量を軽減できるからです。

　個人情報となるので、もし外部に情報が漏れても問題ないようパスワードを設定します。
　※しかしパスワードを別メールでお送りすることは無意味である可能性があります。諸説あり。

以上です。
coreaudiodがメモリを大量に占有しているときの対処法

coreaudiod が大量にメモリを占有しているときに、メモリを解放するための方法です。

調べても同様の事例は多く見つからなかったため、OS 固有の問題ではなく環境の依存しているのかもしれません。(Soundflower や BlackHole などが原因？)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155587/8b2fb712-fffb-3246-88bd-7a929ede2083.png)

`killall coreaudiod` すると音が何も聞こえなくなってしまうため、`launchctl` から再起動します：

```sh
sudo launchctl stop com.apple.audio.coreaudiod && sudo launchctl start com.apple.audio.coreaudiod
```

数秒で coreaudiod が再起動されメモリが解放されます :tada:
DynamoDBの古いデータを自動削除する機能の紹介

# 9０日以上経った古いデータを削除したい

DynamoDBはデータを保存する容量によっても課金されますので、古いデータ量が大きい場合は削除するだけでコストダウンになります。そんな時、Lambdaを定期実行して削除していっても構わないのですが、DynamoDBにはぴったしな機能があります。

# Time to live(生存時間)
この機能はNumber typeのカラムを指定し、生存時間を決めます。例えば90日とか。そうすると、AWSが自動で指定したカラムの値をチェックして古ければ削除してくれます。
コード書かなくてよいので便利です。

しかし、重要な条件があります。
指定したカラムの値が`秒単位のUnix Timestamp`である必要があります。
とりあえず React + TypeScript で適当なサンプルページを作りたい ①

### 目的
- 記事を作成することでMarkdownの仕様に慣れる。
- React と TypeScript に慣れる。

### やること
- とにかくReact + TypeScript でサンプルページを作る。
- まずGUIをレイアウトできるようする。
- 使えそうなComponentは持ってきて利用する。

### やらないこと
- 適切なコンポネントの切り分けはしない。
- 適切なprops の伝搬はしない。
- Redux などの設計思想の取り込みはしない。
- デザインの美しさは問わない。
- レスポンシブ対応はしない。
- GUIに紐づく処理の開発はしない。とにかく目に見えるものだけ作ってみる。

やらないことは事前に割り切って決めたほうがよい。走りきることが大事で、目移りしないため工夫だ。そのため妥協点をやらないこととして後で追加するかもしれない。

### 設計
とにかく作るといっても作るもののイメージがないことには始まらないので、作成対象を設計した。設計はQiitaのブログを表示した際のレイアウトを参考にした。
![QiitaBluePrint.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/51b4b67f-39b0-c414-d43f-ef03abb6678a.png)

上記をもとに開発を進めていこうと思う。この記事は意思表示とレイアウト作成までとし、ここまでで終了する。記事も小分けに書いていかないと、大作化してしまい結局最後まで書かないと考えているからだ。
Nuxtでlocalhost:3000がなんかおかしい

久しぶりの案件で、

```
npm run dev
```

でlocalhost:3000をいつものように立ち上げようとしたら
あれ？ずっとローディングがぐるぐる・・・

エラーとか、WARNとか潰していったけど解決せず・・・
違うブラウザでみたら見れた

ということはキャッシュかなとおもって消したら、表示はされたけともう一回みるとだめ・・・

# 原因
1つ前の案件でPWAをしてたことが原因。
それのサービスワーカーが保存されていて悪さしていたみたい。
全然気づかなくてハマりましたとさ。
`*': false can't be coerced into Integer (TypeError)

### aとbの積が偶数か奇数か

はまった書き方

```ruby
a,b = gets.chomp.split(" ").map(&:to_i)
if a*b.odd? 
  puts "Odd"
else
  puts "Even"
end

```

エラー文

```
`*': false can't be coerced into Integer (TypeError)
```

### 原因
`a*b.odd?`の判定において数字のaとb.odd?のboolean値を掛け算しようとしていたため。
(a*b)と書くのが正解。
【GAS】①Classroomのコース一覧を取得する

# 目次
1. [【GAS】①Classroomのコース一覧を取得する](https://qiita.com/oktaSI/items/223515dcc8214175c726)（このページ）
2. [【GAS】②Classroomのコースを新規作成](https://qiita.com/oktaSI/items/38e7fc3bb897de93fdb4)
3. [【GAS】③Classroomのコース情報を変更](https://qiita.com/oktaSI/items/9c8bd51b4eed1989d080)

# はじめに

GASによるコーディングをする際、spreadsheetやgmail、drive等は基本サービスであるGoogle Workspaceサービス内に含まれているため、書籍も含めて情報が比較的豊富に存在している。その一方でClassroomはAdvanced Googleサービスに含まれるため情報が乏しく、公式マニュアルも現在は使えないメソッドがそのまま書かれていたりと整備が追いついていない状況も見受けられる。ここではそのような状況に鑑み、ClassroomをGASで扱うために必要な基本的な知識を整理していく。

筆者のGAS開発歴は3ヶ月にも満たないため、表現や説明も適切ではない部分が多々あるだろうがご容赦願いたい。

# サービスの追加

GASでClassroomに関するものを扱うためには、スクリプトエディタで「Google Classroom API」サービスを追加する必要がある。最新のIDEでは「サービス」→「Google Classroom API」を選択→「追加」で設定可能。

# Classroomの一覧を取得

バインドされていないスプレッドシートをGAS内で指定して扱う際にはシートIDを指定する必要があり、IDはそのスプレッドシートを示すURLで確認できる。

残念ながらClassroomでは同じ方法で各コースのIDを知ることができないため、既存のコースに修正を加えるためには、まずコース一覧を取得してコースIDを調べる必要がある。そのための構文は以下の通り。

```javascript

Classroom.Courses.list()
```

実際には各コースが多くの情報を含んでいるため、以下のコードでは全てのコースをログで表示できない場合が起こり得る。

```javascript

function myFunction() {
  Logger.log(Classroom.Courses.list());
}
```

[公式ページ(Manage Courses)](https://developers.google.com/classroom/guides/manage-courses#apps-script_2)にある以下のコードを用いれば"コース名（コースID）"の形式で出力されるので活用すると良い。optionalArgsで指定できる項目は[Method: courses.list](https://developers.google.com/classroom/reference/rest/v1/courses/list)を参照のこと。

```javascript
/**
 * Lists all course names and ids. 
 */
function listCourses() {
  let courses = [];
  let pageToken = null;
  let optionalArgs = {
    pageToken: pageToken,
    pageSize: 100
  };
  while (true) {
    let response = Classroom.Courses.list(optionalArgs);
    courses = response.courses;
    if (!pageToken) {
       break;
    }
  }
  if (courses.length === 0) {
    Logger.log("No courses found.");
  } else {
    Logger.log("Courses:");
    for (course in courses) {
      Logger.log('%s (%s)', courses[course].name, courses[course].id);
    }
  }
}
```
LO,VO,DTO,DAO,PDO(＝LVD2P)について簡単に解説してみた

#初めに(前書き)

巷には、「VO」「DTO」「DAO」「PDO」というものはありましたが、ただ一つ筆者の考えられる限りでは、もう一個あってもいいのではと思いました。
それは・・・「LO」です。・・・またまた下らない記事になりそうですが、(お時間は取らせませんので)お付き合いのほど、よろしくお願いいたします(笑)。



#本題(本文)

「LO(Logic-Object)」とは、JavaのMathクラスのようなもので、これ自身はデータを保持せず、なんらかの(一定の)計算やオペレーションをする機能を表すためのオブジェクトです。※これが今回筆者が新たに提案したいものです。
ご存じの通り、「VO(Value-Object)」とは、なんらかの値を表すオブジェクトです。
ご存じの通り、「DTO(Data-Transfer-Object)」とは、対ネットワーク＆対データベースなどで受け渡しされるデータを表すオブジェクトです。
ご存じの通り、「DAO(Data-Access-Object)」とは、データベースにデータ(DTO)を登録する、または、データベースからデータを取得する機能を表すオブジェクトです。
ご存じの通り、「PDO(Persistent-Database-Object)」とは、データベースに永続的にデータを格納するためのオブジェクトです。
ちなみに、「LO」は、VOを入力値として受け取って、同じくVOを出力値として呼び出し元に渡す役割があります。VOに一定の加工・変換を施すということです。



#終わりに(後書き)

いかがででしたでしょうか？。またプログラミングに(余計な？)概念を持ち込むことになりそうで恐縮ですが、いままでのプログラミング上では「LO」は発見されてなかったのではないかと思い、(いきりたって)(勝手に)記事を書き上げた次第です(笑)。これが正当な概念になるかは別として、読者様の頭の片隅に置いていただけると幸いです。
Docker使ってみた。

Dockerの仕様。

Dockerfile（アプリコード・ライブラリー・ベースイメージ）

↓（作成）

イメージ

↓（作成・起動）

コンテナ

## **イメージを作成・作るコマンド**

```jsx
docker image build -t sample/webrick:latest .
```

-t はタグの名前をつける。今回はsample/webric
:latest はバージョン情報
. は今いるディレクトリ

**イメージができたか確認コマンド**

```jsx
docker image ls
```

## コンテナの作成・起動コマンド

```jsx
docker container run
```

今回はこちらのコマンドでやった。

```jsx
docker container run -p 8000:8000 --name webrick sample/webrick:latest
```

-p 8000:8000 はポート番号の指定。
ローカルの8000ポートをdockerの8000ポートに接続するよー。

—name webrick コンテナの名前

sample/webrick:latest イメージの名前とバージョンを追記

## コンテナの起動状況の確認コマンド

```jsx
docker container ls
```

起動中であれば以下のように出てくる。

```jsx
******-mbp:docker eryumeng$ docker container ls
CONTAINER ID   IMAGE                   COMMAND                  CREATED        STATUS        PORTS                    NAMES
87760adc745a   sample/webrick:latest   "ruby /var/www/main.…"   39 hours ago   Up 39 hours   0.0.0.0:8000->8000/tcp   webrick
******-mbp:docker eryumeng$
```

また起動中のも停止中のも確認するならば、

```jsx
docker container ls -a
```

## コンテナの停止

```jsx
docker container stop webrick ///webrickはコンテナの名前
```

## コンテナ削除

```jsx
docker container rm webrick  ///webrickはコンテナの名前
```

## ログを確認

```jsx
docker container logs webrick  ///webrickはコンテナの名前
```

## 起動中に他のコマンドを使用したい時

```jsx
docker container exec webrick ruby -v ///webrickはコンテナの名前・またruby -vを使用。
```

## 使用していないコンテナの削除

```jsx
docker system prune -a //今使っていないものを一気に削除
```

Dockerfile

```jsx
CMD [ "/bin/bash" ]
```

## コンテナ起動（あと色々）

```jsx
docker container run -it -p 4567:4567 --name sinatra -v ${PWD}/src:/var/www sample/sinatra:latest
```

-it は上記のCMD [ "/bin/bash" ]を実行するために。

${PWD}/src:/var/www　こちらをしないと新しくファイルが作られた時に、もう一度イメージから作成しないといけなくなる。またリアルタイムでファイルの変更が見られる

src/var/wwwを参照しますよーと言っている。

上記のならないように。

Dockerfile

```jsx
FROM ruby:2.7

WORKDIR /var/www

COPY ./src /var/www

RUN bundle config --local set path 'vendor/bundle'
RUN bundle install

CMD ["bundle","exec", "ruby", "app.rb"]
```

イメージを作り。

```jsx
docker image build -t sample/sinatra:latest .
```

コンテナ起動とローカルサーバー起動

```jsx
docker container run -p 4567:4567 --name sinatra -v ${PWD}/src:/var/www sample/sinatra:latest
```


学んだことで次はDockerでRailsを構築していきまーす。


今回はここまで。
ありがとうございました。
投稿に失敗して画面遷移されても入力された値が消えないようにするには

自己紹介を記述し内容をDBに保存するプログラムを作成していて空白箇所がある場合はDBに保存されずに同じpathに遷移されて、入力された内容は消えないようにするはずが全部消えてしまってどこのコードがいけないのか悩んでいて解決したので記事に出そうと思います。
以下コード
-
def new
 introdune = Introduce.new()
end

def create
 introduce = Introduce.new(introduce_params)
 if introduce.save
     ridirect_to root_path
 else
     render :new

最初はこのようなコードを書いていたのですがこれだと条件分岐でfalseになった際にnewに遷移されるのですがここで遷移されるnewではまだ何も記述していない状態なので実質入力した値が消えたような現象に陥っていました。
どうすれば良いか考えた結果、elseとrender :newの間にintroduce = Introduce.new(introduce_params)ともう一度記述することによって値が消えることなく画面遷移が行われました。
スプレッドシートからマークダウン式テーブルに変換する方法

#概要
マークダウン記法はすごく便利ですが、マークダウンのテーブルは一からマークダウンで書くのは地獄です。
Qiitaは`culumn x rows`でショートカットできるのですが、それでも大変です。

![Videotogif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643906/854f334d-7314-149a-28cf-ff535bb7e069.gif)


一回スプレッドシートで作成→マークダウンに変換するのが楽でやりやすいのでその方法をメモします。

#やり方

今回はこちらのツールを使わせていただきました。
↓
[https://www.tablesgenerator.com/](https://www.tablesgenerator.com/)

前まではスプレッドシートの拡張機能に同じようなモノがあったみたいですが、最近無くなってしまったみたいです。

説明することもないくらい操作は簡単で、
スプレッドシートでテーブルを作成してコピーをしたものを貼り付けるだけです。

あとから列を追加したりすることも可能なので、とても使い勝手が良く愛用しています。

culumn数は20まで、rows数は500までと制限があるみたいですが、マークダウンでそんな大きい表はほぼ作らないと思うので気にする必要はなさそうです。