OmniAICreator/Qiita-1.07M huggingface dataset:
Xcodeで「No accounts with iTunes Connect access」が出た場合

# はじめに
XcodeでアーカイブしたあとにAppConnectへUploadするタイミングで下記のエラーに当たった。
`No accounts with iTunes Connect access have been found for the team "自分のID". App Store Connect access is required for App Store Connect distribution.`

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1022988/78d23f6f-e3fe-61b6-b473-ac45f3c9282f.png)
先日まで通常通りに出来てたのに突然このようになったので、証明書やアカウントの問題なのかなーと調べたけど原因不明でした。
PCはサーバールーム保管で再起動すると会社に行かなければならないので、`ログオフ`を試した所直りました。
おそらく再起動でも問題ないと思いますが、突然なりますので注意が必要です。
HDFSの使い方メモ

## HDFSユーザーにスイッチ
```bash 
sudo su - hdfs
```

## HDFSの状況を確認
```bash 
$ hdfs dfs -ls /
Found 3 items
drwxrwxrwx   - hdfs supergroup          0 2021-02-25 06:40 /app
drwxrwxrwx   - hdfs supergroup          0 2021-02-25 06:39 /tmp
drwxr-xr-x   - hdfs supergroup          0 2021-02-25 06:54 /user

$ hdfs dfs -ls /user
Found 1 items
drwxr-xr-x   - root supergroup          0 2019-01-18 09:39 /user/hive
```

## HDFS上にディレクトリを作る
```bash 
hdfs dfs -mkdir /input
```

## HDFSにデータをコピーする
```bash 
hdfs dfs -put data.csv /input
```

## HDFSからデータを取り出す
```bash 
hdfs dfs -get /input/data.csv local.csv
```

## アクセス制御
```
hdfs dfs -chown <username> /input
```
Cloud Run for AnthosでConfigMapを使用する

Cloud Run for AnthosでConfigMapを使用する方法について記載します。

マニュアル
https://cloud.google.com/run/docs/configuring/using-configmaps?hl=ja

#Consoleで指定する場合
Advanced settings > VARIABLES & SECRETS > ConfigMapsで REFFERENCE A CONFIGMAPからconfigmapを選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/baadf19e-47de-7d52-1bec-ebc9ddd99806.png)

VolumeとしてMountするか環境変数として読み込むかを指定する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/37369991-53f8-641e-04f1-9c769c4215f3.png)

Mount Pathを指定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78184/7519aa71-7706-68f0-7065-b49b05f32c92.png)

#gcloud コマンドで指定する場合

--set-config-maps=[KEY=VALUE,…] で指定することができる。
Volume Mountする場合は、KEYがmount pointでvalueは、ConfigMapの名称を指定する。

例

```
gcloud run deploy sample \
--image=docker.pkg.dev/cloudrun/container/hello \
--set-config-maps=/opt=sample-config, \
--platform=gke \
--cluster=cluster-1 --cluster-location=asia-northeast1-a --namespace=default \
--project=my-project
```
「Google Colaboratory(GPU)上でBERTのチュートリアルを行う」の2021年2月24日時点での修正点

# 本記事の目的
　@Yuu94 様の[「Google Colaboratory(GPU)上でBERTのチュートリアルを行う」](https://qiita.com/Yuu94/items/e20373ecada2afa2cb4d)に従って BERT のチュートリアルをやってみました。内容自体はわかりやすく BERT の動作を簡単に学べるのですが、執筆時点から Google Colaboratory かそこで使われている Python のバージョンかが変わったことが原因と思われるエラーが一部で発生していました。そこで、こちらで2021年2月24日に実行した際に詰まった部分とその対処方法を共有させていただきます。
（本家記事様への編集リクエストという方法も考えましたが、編集リクエスト内容が本当に正しいのかあちら側で検証する手間が発生してしまうことを鑑みて、独立した記事での投稿といたしました。読者の皆様におかれましては本記事公開後に本家記事様が更新され既にエラー箇所が修正されている可能性についてご留意ください。）

# [GoogleDriveをマウント](https://qiita.com/Yuu94/items/e20373ecada2afa2cb4d#googledrive%E3%82%92%E3%83%9E%E3%82%A6%E3%83%B3%E3%83%88)
## 原文
```ipyenv
cd drive/'My Drive'/bert
```

## 実行可能形式
```ipyenv
%cd drive/'My Drive'/bert
```

## コメント
　元のままでは`content`ディレクトリから移動しない。これは`!pwd`などで確認できる。
　[`cd`コマンドは`%`ありでもなしでも動く](https://qiita.com/asakuraTsukazaki/items/e7eb1f0c43be1e0231c6)はずなのだが、実際に`%`なしで実行してみたところそんなメソッドは無いというエラーが出てしまった。`%`をつけることで正常に動作。ちなみに`!`をつけてもディレクトリ移動は行われない。これは[別スレッドが立ってそちらで実行されてしまうから](https://qiita.com/2-propanol/items/f6f63c3f20981df2c844)とのこと。

# [データセットの保存](https://qiita.com/Yuu94/items/e20373ecada2afa2cb4d#%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BB%E3%83%83%E3%83%88%E3%81%AE%E4%BF%9D%E5%AD%98)
## 原文
```
!git clone https://gist.github.com/60c2bdb54d156a41194446737ce03e2e.git
!python 60c2bdb54d156a41194446737ce03e2e/download_glue_data.py --data_dir glue_data --tasks MRPC
```

## 実行可能形式
```
!git clone https://gist.github.com/d1135b1d75f5513c742fabdad227fe5b.git
!python d1135b1d75f5513c742fabdad227fe5b/download_glue_data.py --data_dir glue_data --tasks MRPC
```

## コメント
[`download_glue_data.py`](https://gist.github.com/antonysama/d1135b1d75f5513c742fabdad227fe5b)には`URLLIB.urlretrieve`なる記述があり動かない。どうやらこれはPython2系での書き方のようで、[Python3系では`urllib.request.urlretrieve`とする](https://qiita.com/n_kats_/items/38512513c8978a7ab4b4)のが正しいとのこと。[こちらを修正したFork](https://gist.github.com/hohoCode/d1135b1d75f5513c742fabdad227fe5b)が存在するのでそれを使う。
機械学習 ~活性化関数~ 入門

# はじめに
機械学習を初めて1ヶ月の私ですが、
アウトプットとして今回投稿します。

勿論、機械学習初心者向けの内容にはなります。
今後もどんどんアウトプットしていきますので、
よろしくお願い致します。

# 活性化関数(activation function)
プレゼン用に作成しており、要点だけまとめておりますので下記のリンクからご覧ください。
ソースコードはjupyter notebookにまとめていますのでそちらもご覧ください。

・[活性化関数(activation function)](https://docs.google.com/presentation/d/1RxUMw-tNCb-r76t0h98dXhPbZoGgINDB3xFL9iCoPrY/edit#slide=id.p)
・[活性化関数:ReLU一族](https://docs.google.com/presentation/d/1Tcqy-vEOwOn1uaAKF3duoUUleyP0QUDG3TOQ3LrN2cY/edit#slide=id.p)
・[ソースコード](https://github.com/KozoNomamoto/activation-function/blob/main/activationfunction.py.ipynb)

# 最後に
これからもアウトプットを増やしていきたいと思っています。
特に、今までインプットしたことをエンジニアらしい方法でアウトプットしていくことが今後の目標です。
Big Surにアップデートしたらvagrantが起動しなくなった件

Big Surにアップデートしたところ、vagrantが起動しなくなった。

↓エラー
>There was an error while executing `VBoxManage`, a CLI used by Vagrant
for controlling VirtualBox. The command and stderr is shown below.

>Command: ["startvm", "b43f8d3f-5d11-4ab4-8ba2-d8896c0c0492", "--type", "headless"]

>Stderr: VBoxManage: error: The virtual machine 'ubuntu64_18_default_1592808456466_80230' has terminated unexpectedly during startup with exit code 1 (0x1)
VBoxManage: error: Details: code NS_ERROR_FAILURE (0x80004005), component MachineWrap, interface IMachin

とのこと。
調べた感じでは、virtualboxとvagrantをアップデートすれば良さそうだが...

ひとまず、vagrantをアップデートしてみる。
よくわからなかったので、mac osの2.2.14をダウンロード。

>vagrant --version
⇨Vagrant 2.2.14

バージョンアップできている。
続いてvirtualboxをダウンロード。
公式サイトからvirtualbox 6.1.18をmacosでインストールした。

しかし...エラーの内容が全く変わらない。
だが、他の方の記事を確認し、ダウンロードしたアプリケーションを許可を設定から実行して再起動を行った結果、無事起動し、ssh接続も行えた。

以下参考にしたwebサイト
https://qiita.com/syota_19910612bscplog/items/ee7e06cd23603fa529dd
↑非常にわかりやすい他の方の記事

https://www.virtualbox.org/wiki/Downloads
↑virtualbox公式サイトのダウンロード画面

https://www.vagrantup.com/downloads
↑vagrant公式サイトのダウンロード画面

ほとんど無益な記事ですみません。初投稿なので許してください。
【Rails】1日に記録できる数値の合計を制限するバリデーション

##はじめに
投稿3回目です。
文章力が赤ちゃんレベルかつ遅筆なのでまだ慣れないです...
間違い等あればご指摘よろしくお願いします。

##環境
- Ruby 2.6.3
- Rails 5.2.4

##背景/目的
- ポートフォリオで学習内容を記録するサイトを開発中。
- 学習内容は1日に何回でも記録可能であり、項目には学習時間がある。
- 学習時間の合計値が24時間/1日を超えないようにバリデーションを設定する。
- 学習内容（learningsテーブル）の詳細は下記の通り。

| カラム名 | データ型 | 説明 |
|:-:|:-:|:-:|
| date | date  | 学習日 |
| time | float | 学習時間 |

##結論

```ruby:app/models/learning.rb
class Learning < ApplicationRecord
  # 一つのユーザー(user)に対して、複数の学習記録(learning)が結びついている
  belongs_to :user

  # validateに定義したメソッドを設定
  validate :total_time_cannot_exceed_limit_time, on: :create
  validate :total_time_cannot_exceed_limit_time_for_edit, on: :update

  # 1日に記録できる学習時間の合計
  LIMIT_TIME_HOUR = 24

  # 入力された学習日に既に記録されている学習時間の合計値を取得する
  def one_day_time_sum(date)
    user.learnings.where(date: date).sum(:time)
  end

  # 入力された学習日に既に記録されている「編集対象の投稿以外の」学習時間の合計値を取得する
  def one_day_time_sum_unless_target_date(date)
    user.learnings.where(date: date).where.not(id: id).sum(:time)
  end

  # create時のカスタムバリデーション用のメソッドを定義
  def total_time_cannot_exceed_limit_time
    # [学習日が入力済]かつ[学習時間が入力済]かつ[学習日に既に記録された学習時間と入力した学習時間の合計が24時間を超える場合]
    if date.presence && time.presence && one_day_time_sum(date) + time > LIMIT_TIME_HOUR
      # エラーメッセージを表示する
      errors.add(:date, "：#{date.strftime("%Y年%m月%d日")}の学習時間の合計が#{LIMIT_TIME_HOUR}時間を超えています")
    end
  end

  # update時のカスタムバリデーション用のメソッドを定義
  def total_time_cannot_exceed_limit_time_for_edit
    # [学習日が入力済]かつ[学習時間が入力済]かつ[学習日に既に記録された「編集対象の投稿以外の」学習時間と入力した学習時間の合計が24時間を超える場合]
    if date.presence && time.presence && one_day_time_sum_unless_target_date(date) + time > LIMIT_TIME_HOUR
      errors.add(:date, "：#{date.strftime("%Y年%m月%d日")}の学習時間の合計が#{LIMIT_TIME_HOUR}時間を超えています")
    end
  end
end

```

createとupdateで処理を分けています。
コメントで処理の内容を記載しましたが、自分で読んでても正直よく分からないです。
例えば、下記のデータが既に保存されており、学習日``2021-01-01``・学習時間``4``の投稿を新たにする場合、

| id | 学習日 | 学習時間 |
|:-:|:-:|:-:|
| 1 | 2021-01-01 | 10.6 |
| 2 | 2021-01-01 | 11.4 |

入力された学習日``2021-01-01``に既に記録されている学習時間の合計値``22``時間を取得し、入力した学習時間``4``時間を足して、24時間と比較します。=> この場合26時間なのでエラーメッセージが表示されます。

これをupdateでも同じ処理にすると動作がおかしくなります。
例えば、id:``1``の学習時間を``5``時間に変更する場合、5 + 11.4 = ``16.4``時間になるのが理想です。
しかし、実際は10.6 + 11.4 + 5 = ``27``時間でNGになってしまいます。
``user.learnings.where(date: date).sum(:time)``だと編集前の学習時間も取得してしまうので、update時は``where.not(id: id)``を追記し、編集対象の投稿以外の学習時間の合計を取得するようにしています。

##参考にさせていただきました
- [Active Record コールバック](https://railsguides.jp/active_record_callbacks.html)
- [Ruby on Rails:モデルに独自のバリデーションを実装する](https://madogiwa0124.hatenablog.com/entry/2017/12/24/163013)

ここまで見て頂きありがとうございました。
ネーミングセンスがないのは許していただけると助かります😰
MySQL備忘録 - オートインクリメントの連番リセット

MySQLたまに必要な知識で忘れてしまいそうな事項を記述
テストなどでレコードを削除した後に
auto_incliment で定義したカラムの値を初期化したいときに場合がある。

```
ALTER TABLE `tablename` auto_increment = 1;
```
f.collection_selectの使い方（超ざっくり&初学者向け）

#f.collection_selectで別モデルのカラムを使って選択肢を作りたい時に役立つ情報を提供します！
まずf.collection_selectについて
書き方としては

<%= f.collection_select :保存先カラム, :選択肢に使いたいカラムを持った配列, :保存先カラムに保存したい値, :選択肢に表示したいカラム %>といった感じです。

例としては<%= f.collection_select :genre_id, @genres, :id, :name, :prompt => "選択してください" %>こんな感じです。

promptに関しては未選択の時に表示させておきたい文字を表示させることができます！！

ぜひ使ってみてください！！
ローカルGitリポジトリ、どこに置きますか？　私はこう

筆者は大学でプログラミング演習系の TA (Teaching Assistant) をしたり、ハッカソンの運営をしたりしています。

質問を受ける中で、ホームディレクトリがぐちゃぐちゃでローカル Git リポジトリの場所が一発で探せない方が多くおられることに気づきました。

そこで筆者おすすめのディレクトリ構成を紹介してみようと思います。

## ローカルGitリポジトリの置き場所

1. ホームディレクトリ (`~/`, `$HOME/`) の直下に、**リモートリポジトリのURLと対応するように**ディレクトリを切ります。
    - 例えば https://github.com/u-sho/nuxt2.9-template なら、ローカルでは `~/github.com/u-sho/nuxt2.9-template` に置きます。

```shell
~/
├── gist.github.com/
│   └── u-sho/
│       ├── bash-ascii-logo
│       └── tmux-ascii-logo
│
├── github.com/
│   ├── microsoft/
│   │   └── TypeScript/
│   └── u-sho/
│       ├── dotfiles/
│       ├── ja.vuejs.org/
│       ├── nuxt2.9-template/
│       └── u-sho.github.io/
│
├── gitlab.com/
│   └── u-sho/
⫶       ⫶
```

以上です。

### メリット

- フォークしたのか直接 clone したのかがわかりやすくなっています。
    - 上の例でいえば、`~/github.com/microsoft/TypeScript` は直接 clone したリポジトリで、`~/github.com/u-sho/ja.vuejs.org` は、自分の GitHub アカウント ([github.com/u-sho](https://github.com/u-sho)) にフォークしたリポジトリです。
- 迷子になりにくくなっています。
    - ホームディレクトリを起点としたフォルダのパスが URL と１対１で対応するため、clone したかどうか、またどこに clone したかを思い出す必要がなくなります。
    - 自分としてもわかりやすく、またメンターなど他の方に触ってもらう際もすぐに理解していただきやすいかなと思います。
- リモートリポジトリの URL が `pwd` コマンド一発でわかります。
    - `git config remote.origin.url` だと SSH のときはワンステップ必要でちょっと悲しくなります。
    - `$PS1` にカレントディレクトリを表示させている方は多いと思います。その場合、PS1 からブラウザにコピペして移動できます。

### デメリット

GitHub だけでなく、Backlog や GitLab、GitBucket など、多数の Git のホスティング先から clone していると、ホームディレクトリが混雑してしまいます。その場合は、ホームディレクトリの代わりに一つディレクトリを作って、その下に配置していくとよいかもしれません。
翻訳対象をスマートに検索する

エンジニアである以上英語を翻訳しなければならない！ なんて場面結構ありますよね。

英語が読めなくてもこの方法であれば幾分恥ずかしさが軽減されます！！

タブがいっぱい開いていたりすると翻訳ページを探すのが面倒だったりするので、
Chromeの検索バーに直接翻訳してもらいたい文言を記入して検索すると直接翻訳してもらえるようにしてみようと思います。


# 方法
### 1, Chromeブラウザを開いて右上のボタンから設定を開く
![スクリーンショット 2021-02-25 14.27.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1151249/113eba57-a353-227b-5d45-39c3f3be10c3.png)

### 2, 下へスクロールして検索エンジの管理をクリック

![スクリーンショット 2021-02-25 14.37.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1151249/2e545561-3be5-0b81-05bb-b66c8f6364fe.png)

### 3, 検索エンジンの編集
検索エンジン、キーワード、URLを記入していきます。
![スクリーンショット 2021-02-25 14.43.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1151249/ca77b747-5a14-dc1b-7af5-f5a38e65f3a6.png)

今回の場合Google翻訳を登録したいので以下になります。
検索エンジン:  Google翻訳
キーワード: 翻訳
URL: https://translate.google.com/?sl=en&tl=ja&text=%s&op=translate

%sという文字列が検索バーに入力される文字となるので任意の場所に記入していきます。

記入したら追加を押します。

### 3, デフォルトに登録する
追加が終わったら点が３つ並んでいるボタンからデフォルトに登録します。
![スクリーンショット 2021-02-25 14.53.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1151249/bc0f3dd6-b74a-908a-398a-b81589d431f8.png)

### 3, 検索バーに入力する
調べたい単語を検索バーへ入力します。
![スクリーンショット 2021-02-25 15.00.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1151249/f9271e0f-fba7-40a8-291e-3772f08c06f2.png)


### 表示が確認できました！


![スクリーンショット 2021-02-25 15.00.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1151249/2bd02878-ef35-13d2-4b05-1a4779384a38.png)


## まとめ
URLのクエリパラメータを検索バーで入力したものに書き換える方法を紹介しました。
うまく扱うことができれば普段業務で使用するツールなどにも応用できるかと思います！

最後まで読んできただきありがとうございました！
【GitHub】リモートリポジトリの設定ができているのにプッシュできない!?

#はじめに
いつも通りGitHub上のリモートリポジトリにプッシュしようとしたらなぜかできなくなっていました。
リモートリポジトリのURL設定やSSH接続もできており、原因究明に時間がかかったので備忘録として残します。

![スクリーンショット 2021-02-25 14.54.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/677381b6-4a1f-b767-d136-79b34619fa60.png)

#原因
該当リポジトリのManage accessのRoleがReadになっていたのが原因でした(チームの誰かがやってしまっていたみたい)。
こちらを**Admin**にすれば解決します。

![スクリーンショット 2021-02-25 14.57.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/e879c245-d3c0-abf8-bd48-61a981a60187.png)
PHPでAWS S3からディレクトリ単位でダウンロード

## 前提条件
AWS SDK for PHP 3.x を利用

## やってみた感想
CommandPool利用のために配列を作成する必要がなく
コードもシンプルになるのでよい

## AWS S3 バケットを再帰的にダウンロード

### 同期転送
```php:sample.php
<?php

use Aws\S3\S3Client;
use Aws\S3\Transfer;

$client = new S3Client([
    'region'  => '****',
    'version' => 'latest',
]);

// from
$source = 's3://bucket/foo';
// to ローカルディレクトリのパス
$dest   = '/path/to/destination/dir';

$manager = new Transfer(
    $client,
    $source,
    $dest,
);
$manager->transfer();

```

### 非同期転送
```php:sample.php
<?php

use Aws\S3\S3Client;
use Aws\S3\Transfer;

$client = new S3Client([
    'region'  => '****',
    'version' => 'latest',
]);

// from
$source = 's3://bucket/foo';
// to ローカルディレクトリのパス
$dest   = '/path/to/destination/dir';

$manager = new Transfer(
    $client,
    $source,
    $dest,
);

$promise = $manager->promise();
$promise
    ->then(function () {
        echo 'Done!';
    })
    ->otherwise(function ($reason) {
        echo 'Transfer failed';
    });

```

## 参考
[Amazon S3バージョン 3 での AWS SDK for PHP Transfer Manager](https://docs.aws.amazon.com/ja_jp/sdk-for-php/v3/developer-guide/s3-transfer.html)
ubuntuのターミナル(gnome-terminal)を指定の場所に指定サイズで表示

## 背景・やりたいこと

開発環境はマルチモニタ。片方はターミナルで埋め尽くしたい。
具体的には以下のように左右上下に4つのウインドウを起動・配置したい。

[![Image from Gyazo](https://i.gyazo.com/e51ac75b26d8eb08e8edb8d43f108cf2.png)](https://gyazo.com/e51ac75b26d8eb08e8edb8d43f108cf2)

## 方法（tmux断念して標準のgnome-terminalで実現）

最初に考えたのはスクリーンを4分割して表示。

残念ながら`Windows Terminal`のように簡単操作（`ctrl + alt + プラス(orマイナス)`）で分割できるターミナルソフトはLinuxにはない模様。

Microsoftさん、Linuxに移植してーーー。
Microsoftさん、Linuxに移植してーーー。
Microsoftさん、Linuxに移植してーーー。

現状、Linuxで代表的なのは`tmux`の模様。

ちょっと頑張ってみたけど、使い勝手が悪いと判断しました。理由は以下。前者が100%ではないけど頻繁に発生するので致命的。

* ウインドウのリサイズ・移動で乱れる（というか真っ黒になってしまう。ウインドウの下の方でチカチカ。操作も回復も不能）
* コピペ操作が面倒。機能しないときもある。

結局、（スクリーンの分割ができない以外は特に不満はない）標準のターミナル（`gnome-termina`)を4つ起動するというシンプルな作戦に変更。

手間取ったのはは配置。都度、配置しなおすのは面倒なので自動化したい。
ただ、ターミナルの設定で指定できるのはウインドウサイズ（列数x行数）だけで、表示位置は指定できない。

調べたら、ターミナルをコマンドラインで起動して`--geometry`オプションでサイズと表示位置を指定できた。

## `--geometry`オプション

```
$ man gnome-terminal
OPTIONS
       --geometry=GEOMETRY
                 X geometry specification (see "X" man page), can be specified once per window to be opened.
```

GEOMETRYの指定方法は、Xのmanページに記載されている。

```
$ man X
GEOMETRY SPECIFICATIONS
 -geometry WIDTHxHEIGHT+XOFF+YOFF (where  WIDTH,  HEIGHT, XOFF, and YOFF are numbers) for specifying ...
```

要するに以下のようにすれば良い。

```
/usr/bin/gnome-terminal --geometry=WxH+X+Y --window-with-profile=<name> &
```

## `--window-with-profile`って何?

別ウインドウで起動させるために必要だったので指定。（これを指定しないと同じターミナルウインドウ内の別タブで表示されてしまう）

名前は、Terminalの設定画面（`メニュー > 編集 > Preference`）で任意に指定できる。

[![Image from Gyazo](https://i.gyazo.com/b719976f6503deed431df2f66b8c1844.png)](https://gyazo.com/b719976f6503deed431df2f66b8c1844)

## geometry値の取得方法

`WxH`の部分は前述した設定画面の列数と行数に対応しています。
`+X+Y`の部分は、Xは0が左端なんですが、Y値が謎（0が最上部かと思ったら当方環境では686という変な値 ※1）

取得方法は色々とあると思いますが、当方は`devilspie2`の設定時に取得する方法を確立していたので、その方法で取得しました。

[[Ubuntu]devilspie2でウインドウサイズと位置を調整 - Qiita](https://qiita.com/s-katsumata/items/318b4c58a9e32593553b#表示位置xyとサイズwidthheightの取得)

※1:たぶんサイズの違うマルチモニタで大きい方がメインモニタになってるから
GitHub Actions を使って AWS の S3 へデプロイする

GitHub Actions を使って AWS の S3 へデプロイするための環境設定手順を記載します

## S3 バケットの作成

アップロードする先の S3 バケットを作成しておきましょう

## AWS IAM の作成

S3 へアクセス可能な IAM ユーザーを作成します

1. AWS IAM へ遷移する
2. アクセス管理のユーザーへ遷移する
3. ユーザーを追加ボタンを押下する
4. ユーザー名に適当な名前「github」などを入力し、「プログラムによるアクセス」にチェックを付けて次のステップボタンを押下する
5. アクセス許可の設定へ遷移するので、「既存のポリシーを直接アタッチ」を選択して「AmazonS3FullAccess」にチェックを付けて次のステップボタンを押下する
6. タグの追加画面に遷移するので、次のステップボタンを押下する
7. ユーザーの作成確認画面に遷移するので、ユーザーの作成ボタンを押下する
8. ユーザーが作成されたら、「アクセスキー ID」「シークレットアクセスキー」をメモするか、.csvのダウンロードをしておく

## GitHub リポジトリの Secrets へ AWS 接続情報を登録

GitHub リポジトリの Secrets へ AWS 接続情報を登録します

1. S3 へアップロードする GitHub リポジトリの Settings を選択する
2. Secrets メニューへ遷移する
3. Actions secrets で、New repository secret ボタンを押下する
4. 以下の内容で各追加する

|Name|Value|
|----|----|
|AWS_ACCESS_KEY_ID|（作成したIAMユーザーのアクセスキーID）|
|AWS_SECRET_ACCESS_KEY|（作成したIAMユーザーのシークレットアクセスキー）|
|S3_BUCKET|（アップロードする先の S3 バケット名）|

## GitHub Actions 用のワークフローを定義

1. GitHub で Actions へ遷移し、「set up a workflow yourself」のリンクをクリックする
2. Edit new file に以下の内容を記載して、Start commit ボタンを押下し、コミットテキスト「GitHub Actions の設定を追加」などを入力して Commit new file ボタンを押下する

```yml
name: Amazon S3 Upload

on:
  push:
    branches:
      - master

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      - name: Upload to S3
        env: 
          S3_UPLOAD_BUCKET: ${{ secrets.S3_BUCKET }}
        run: |
          aws s3 sync . s3://$S3_UPLOAD_BUCKET/ --delete --exclude "README.md" --exclude ".git/*" --exclude ".github/*" --exclude ".gitignore"
```

これで master ブランチへファイルをPUSHするごとに、S3 へファイルがアプロードされます

ワークフローの状態は、GitHub リポジトリの Actions へ遷移してみてください

プルリクエストマージ時にしたい場合や、S3 アップ後に CloudFront のキャッシュを削除したいなど、場合によってワークフローの定義を編集してください
Firefox アップデート 通知 オフ

#Firefoxのアップデート通知を無効にする
Firefox 78.7へアップデートしたら、更新のアップデート通知が頻繁に通知されるようになりました…

どうも、ブラウザの設定で通知をオフに出来なくなったようです。
60.6だと「Never check for updates」という選択肢で通知をオフに出来てましたが、無くなってしまったようです…
最新版へアップデートしろよという意思を感じますね
![スクリーンショット 2021-02-25 13.47.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130492/424c7d51-5419-8923-db2c-ac05df5031c3.png)


#Firefoxのアップデート通知を無効にする
どうにか通知をオフにしたいと調べたところ、distribution配下のpolicies.jsonという設定ファイルを作成/修正すればよいそうです。
[Managing Firefox Updates](https://support.mozilla.org/ja/kb/managing-firefox-updates)

[Disabling Firefox updates](https://github.com/mozilla/policy-templates/blob/master/README.md#disableappupdate)


Windows：C:\Program Files\Mozilla Firefox\distribution\
Macの場合：/Applications/Firefox.app/Contents/Resources/distribution
Linuxの場合：/etc/firefox/policies

```
$ cd /Applications/Firefox.app/Contents/Resources/distribution
$ vi policies.json
```
```policies.json
{
"policies": {
"DisableAppUpdate": true
}
}
```


Firefoxを再起動すると……


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130492/1b13bb5f-301f-7a54-859d-9db9e7b472ce.png)

でーきーたあああああああーーーーーーー
Mozillaさん保守して下さいよ（・∀・）
[解決済み]ヤマハのMD5のバグ

MS-DOSへのファイル転送をテストしていて、確認のためのツールを探していたところ、ヤマハさんmd5のコマンドを提供していました。

http://www.rtpro.yamaha.co.jp/RT/utility/md5sum/

早速ダウンロードして試してみたところ、なんだかおかしな値が返ります。

Windows 7で32Bit版のEXEを試しました。

```
C:\>md5sum yyy
571c3b2b2d3e0442b33c352acf7397d0  yyy
```

MS-DOS版(16ビット)も同じ値です。

ソースで提供されているプログラムをFreeBSD/i386でビルドして試してみました

```
% ./md5sum yyy
ad5e4192180b69500b060bb870f55d51  yyy
```

FreeBSDのコマンドでも試しました。

```
% md5 yyy
MD5 (yyy) = ad5e4192180b69500b060bb870f55d51
```

Windows 7標準のツールでも確認してみました。

```
C:\>certutil -hashfile yyy MD5
MD5 ハッシュ (ファイル yyy):
ad 5e 41 92 18 0b 69 50 0b 06 0b b8 70 f5 5d 51
CertUtil: -hashfile コマンドは正常に完了しました。
```

ソースを見てみたところ、MS-DOS,Windowsの場合-bオプションが必要でした。

提供されているソースコードはopen-watcom-v2でもコンパイルできexeが作れました。

毎回オプションを指定するのが面倒なので、[デフォルトを代えて](https://github.com/yamori813/ow-pc98/commit/90fc4fc30c9779a1e36ac91c67023f0b02e9a927)みました。
windowsでpipを実行しようとしたらアクセスが拒否された

友人のPython環境構築を手伝ったらちょっとハマったのでメモ。
大した問題ではなかったがエラーコードを載せておくのは意味があると思ったので。

## TL;DR
- ウイルスバスターが悪い。オートスキャンを切ればよい。
- McAfeeとかでも同じ症状が出るかも

## 環境
- Windows 10
- python 3.9
- Windows Powershell

##　症状

普通ににpipを実行しようとしたら少し時間経って以下のエラーが出る。

```
プログラム 'pip.exe' の実行に失敗しました: アクセスが拒否されました。発生場所 行:1 文字:1
+ pip -V
+ ~~~~~~。
発生場所 行:1 文字:1
+ pip -V
+ ~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [], ApplicationFailedException
    + FullyQualifiedErrorId : NativeCommandFailed
```

PCを再起動してすぐは普通に実行できた。しばらくすると使えなくなる。

## 原因と解決方法

ウイルスバスターがexeファイルの実行前にスキャンして`pip.exe`が弾かれてるっぽい。
起動してすぐの間だけpipが実行できたのはおそらくウイルスバスターがちゃんと起動してなかったから。
ファイルの実行前にスキャンする設定を切っておくと解決する。
スキャン自体を切らずに`pip.exe`の実行だけ許可する方法も多分あるけど、そこまで詳しく調べていない。

当然他のアンチウイルスソフトでも同様の問題が起こりうる。
当然他のCLIツールなどでも同様の問題が起こりうる。

## 感想

筆者は普段WindowsでもMacでもサードパーティ製アンチウイルスソフトを使っていないのと、Zoom越しでの対応だったのでハマった。

起動したてはスキャンが効いてないアンチウイルスソフトって大丈夫なのか。
Azure リソースグループを設計する

# リソースグループのパラメータの意味が良くわからない＆どう設計すべきかわからない

Azure上で仮想マシンを作成する際、リソースグループや、可用性セットなどわからない単語がいっぱいありました。この記事ではリソースグループというメニューについて、パラメータ毎に意味を調べたので記載しておきます。また、エンタープライズシステム向けにどのような観点から設計すべきかも個人的見解を記載してます

## おすすめ構成について
少なくともシステム単位での作成は最低限すべき。さらに800インスタンス以上リソースグループ内に作成できないようなのでその点は考慮したほうがいいです。

システム単位にすべき理由：
作成可能なインスタンス数の制限があるので、システム以上に会社といかいう範囲でリソースグループ使っちゃうと制限に引っかかってアウトになるかも。

上記以上にリソースグループの単位を細分化すべきかというと無駄に増えてもめんどくさいので上記くらいでいいかなと。

## おすすめしないケース
リージョン毎にリソースグループを作成すると、リージョン跨ぎのリソースをどこのリソースグループに参加すべきか考えちゃうのであんまりやらないほうがいいかなと思いました。

##命名規則
RG-[systemname]-[3digit number]
例として、RG-hashimoto-001
とかでいいっしょー。

## そもそもリソースグループとは？
MS社の説明は”通常は、同じライフサイクルを共有するリソースを同じリソース グループに追加して、グループとして簡単にデプロイ、更新、および削除できるようにします”とありますが・・・よくわかんねぇ。

リソースグループ単位でシステムリソースを任意の単位でグループ化し、操作できるもののようです。具体的にはリソースグループ単位で課金情報や、アクティビティログ、システムリソース一覧を参照できたり、削除、アクセスの制御ができるのできちんと設計すると運用で便利です。リソースグループより上位レイヤにあたるサブスクリプションをシステムカット、もしくはそれより小さい単位で用意すればよいかなという印象です。
個人的にはシステム担当者にサブスクリプション単位で環境を渡してその中でやりくりしてもらうのがいいかなと思いました。

## サブスクリプション
別記事にサブスクリプションを説明してますのでそちらをご確認ください。
今回のリソースグループをどのサブスクリプションに作成するかを指定するものです。

## 場所
このリソースグループという情報自体が管理保管される場所を指定する必要があるようです。正直どこでもいいですし、なにか後の設計や構築に依存するものでもないようです。
たとえば、リソースグループが管理する仮想マシンリソースの場所がリソースグループで指定した場所で固定されるということもありません。仮想マシンの作成場所は仮想マシン作成時に別途指定可能です。ただ、SSHキーはリソースグループと同じ場所に強制的に作成されます。こんなの正直どうでもいいからMS側でいい感じに管理しろよって思いますけど、これをわざわざ指定しなければならないユースケースや要件ご存じでしたらお知らせください。あんまり詳しくないですけど、データ格納先の地理的制約を受ける法律要件が厳しいヨーロッパ圏のシステムは気にすべきかも。

[MS社WEBサイト上での説明記事はこちら](https://docs.microsoft.com/ja-jp/azure/azure-resource-manager/management/overview#resource-groups)
Azure機能について記事を書く上での著作権について

今回Qiitaに投稿する記事について、基本的に画像などはフリーサイトかAzureポータル画面からのスクリーンショットを利用してます。
MS社に製品のスクリーンショットに関する著作権についての記載がありました。
いくつか要件があるようです。
MS社のWEBサイトにある画像などの拝借は許可されているかよくわからなかったので諦めました。ただポータル上のアイコンなどは使っていいようなのでそれを使うようにしてます。

https://www.microsoft.com/ja-jp/mscorp/legal/intellectualproperty-permissions.aspx
Azure SSHキーを設計する

# SSHキーのオプションが良くわからない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111921/69958b3c-0e2a-ff58-564a-83d52db78aec.png)
Azure上で仮想マシンを作成する際、リソースグループや、可用性セットなどわからない単語がいっぱいありました。この記事ではSSHキーというメニューについて、パラメータ毎に意味を調べたので記載しておきます。
概要は以下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1111921/de85e223-3e2a-e3a7-4e51-2508d1f57ad2.png)

なお、SSHキーというものがそもそもわからない人はすみません。
以下は詳細記載してます。

## SSHキーに関する設計についての個人的見解
管理大変なのでシステムごとに1つ。
仮想サーバとSSHキーは別のリソースグループでもOKなので、メインサイトとは物理的に違うサブサイトサーバ構築する場合にも複数作成は不要。


## リソースグループ
SSHキーを所属させるリソースグループを指定。
この鍵を使うサーバと同じリソースグループじゃなくてもOK。

## 地域
SSHキーのリソースグループとして指定したリソースグループの地域に自動的に決定されます。鍵が格納される場所。どこでもいい。別にこの鍵使うサーバと同じ地域じゃなくてもいい。

## キーの組名
管理上の名前。作成するキーの名前。なんでもいい。

## SSH公開キーのソース
以下2つのオプションがある
（１）既存の公開キーをアップロード
たとえば既存のAzure管轄外のシステムなどでSSH鍵を使った認証を行っている場合に、その既存システムの公開鍵、秘密鍵を今後も使いたいようなケースで利用することになると思われる。

（２）新しいキーの組の生成
Azureの管理ポータル上から秘密鍵と公開鍵を作成すること

## タグ
本番、検証、開発くらいは付与しておいた方がいいかもね。
デスクトップから Web への移行。WPFからWebに移行するなら Blazor がおすすめ

こんにちは！


本記事では、デスクトップから Web への移行。WPF から Web に移行するなら Blazor がおすすめな理由について解説します！



## なぜ Blazor が良いのか？ WPF から Blazor へ移行する際のポイントを解説

### 新しいスキルセットの習得が少ない

Blazor は .NET テクノロジーですので、WPF で慣れ親しんだ C# コードで Web フロントエンドが作れます。

既存システムの作り直しとなった場合、現行の主力メンバーが新規システムの開発に携わることも多いかと思いますが、新しいテクノロジーを採用すると学習コストが掛かってしまいます。

その点、WPF から Blazor であれば、.NET テクノロジーの経験を活かし、スムーズに Web フロントエンドへの移行を行う事が出来ます。

また、以下の記事でフロントエンドフレームワークの Angular, Vue.js, React と Blazor の構成の違いについて触れているので是非参考にして下さい。

https://blogs.jp.infragistics.com/entry/2020/10/12/133447


### 既存のライブラリが利用できる

既存資産の .NET ライブラリを利用可能なフレームワークでビルドすることでご利用できます。

既存のビジネスロジックを含んだライブラリを、ぜひ再利用しましょう。

また、MVVM アーキテクチャを採用したアプリケーションであれば、画面とビジネスロジックがうまく切り離されていれば、WPF で活用していたライブラリをすぐに Blazor でも再活用できるでしょう。


### MVVM アーキテクチャをそのまま採用できる

WPF でよく採用される MVVM アーキテクチャですが、Blazor にもデータバインディング機能があるため、Blazor でも MVVM アーキテクチャを採用することができます。

### Prism フレームワークと同等の DI 機能

WPF アプリケーションで採用の多い Prism フレームワーク、そのなかでも強力な DI 機能ですが、Blazor では標準搭載されています。

Blazor では、DI 設定時に、シングルトンにするか、毎回インスタンスを生成するかなど、Prism と同等レベルで DI の制御ができます。

### Visual Studio で開発が進められる

.NET ユーザーであれば慣れ親しんだ Visual Studio で開発が進められます。

既に Blazor のプロジェクトテンプレートも用意されているため、すぐに Blazor の動作をお試しいただく事ができます。

また、Visual Studio Code でも開発を進めることができます。

https://blogs.jp.infragistics.com/entry/blazor-getting-started-vscode

### 画面は XAML から HTML + CSS への作り直し

画面は XAML ではなく、 HTML + CSS で作り直す必要があります。

ただし、最近は HTML + CSS は扱えるエンジニアは多いですし、参考情報も非常に XAML と比較しても情報が豊富であるため、あまり大きなデメリットにはならないかと思います。


## まとめ

弊社でも最近は、WPF から Blazor への移行のご相談を頂くようになりました。

もし、お困りな点がありましたらぜひ、弊社までご相談ください！

https://jp.infragistics.com/about-us/contact-us


## Ignite UI for Blazor トライアル版を利用するには

インフラジスティックスでは充実した UI コンポーネントライブラリーを収録し、データリッチでレスポンシブなWebアプリケーションをより迅速に構築することを可能にする <a href="https://jp.infragistics.com/products/ignite-ui" target="_blank">Ignite UI</a> を開発しており、Blazor 対応の <a href="https://jp.infragistics.com/products/ignite-ui-blazor" target="_blank">Ignite UI for Blazor</a> もリリースしています。<br>
Ignite UI for Blazor はトライアル版での試用が可能です。<br>
トライアル版を利用するためには <a href="https://iam.infragistics.com/Account/Register" target="_blank">こちらのページ</a> よりアカウントの作成を行ってください。登録より30日間、弊社のテクニカルサポートをご利用いただくことが出来ますのでお気軽にお問い合わせください。<br>

また、製品をご購入をご検討のお客様は <a href="https://iam.infragistics.com/Account/Register" target="_blank">こちらのページ</a> よりお気軽にお問い合わせください。



## 開発全般に関するご相談はお任せください！

インフラジスティックス・ジャパンでは、各プラットフォームの特別技術トレーニングの提供や、開発全般のご支援を行っています。



「古い技術やサポート終了のプラットフォームから脱却する必要があるが、その移行先のプラットフォームやフレームワークの検討が進まない、知見がない。」

「新しい開発テクノロジーを採用したいが、自社内にエキスパートがいない。日本語リソースも少ないし、開発を進められるか不安。」

「自社のメンバーで開発を進めたいが、これまで開発フェーズを外部ベンダーに頼ってきたため、ツールや技術に対する理解が乏しい。」

「UIを刷新したい。UIデザインやUI/UXに関する検討の進め方が分からない。外部のデザイン会社に頼むと、開発が難しくなるのではないか、危惧している。」

といったご相談を承っています。

お問い合せは<a href="https://jp.infragistics.com/about-us/contact-us#contactform" target="_blank">こちら</a>からお気軽にご相談ください。
Elasticsearchを開いて「Kibana server is not ready yet（all shards failed）」が出て起動しないときの対応

Elasticsearchをローカルでたてていたのですが、題記のエラーが出たときにいろいろ調べて対処したので、メモしておきたいと思います。

Kibanaをブラウザから開いたときに、

```
Kibana server is not ready yet
```

こちらのエラーメッセージが画面上表示されていて、Kibanaが起動していませんでした。

Kibanaを実行したコンソールを確認すると、下記エラーが発生。

```
  log   [07:44:38.563] [warning][migrations] Unable to connect to Elasticsearch.
 Error: [search_phase_execution_exception] all shards failed
```

`shard`が全部落ちているとおっしゃっているので、確認。

`http://localhost:9200/_cat/shards`

```
.kibana_1                 0 p STARTED        27  46.2kb 172.*.*.166 node-6
.kibana_1                 0 r STARTED        27  46.2kb 172.*.*.91  node-1                            
.tasks                    0 p UNASSIGNED                              
.tasks                    0 r UNASSIGNED                              
.kibana_task_manager_1    0 p UNASSIGNED                              
.kibana_task_manager_1    0 r UNASSIGNED                              
```
(関係あるところだけ抜粋)

`.tasks`と`.kibana_task_manager_1`が`UNASSIGNED`となってしまっているのが問題でした。

この辺を参考にさせていただき、`.kibana_1`と`.tasks`と`.kibana_task_manager_1`を削除して、
再起動すれば問題ないことが判明しました。

> https://bugfix.plus/info-124194.htm

```
curl -XDELETE http://localhost:9200/ .kibana_1 
curl -XDELETE http://localhost:9200/ .kibana_task_manager_1
curl -XDELETE http://localhost:9200/ .tasks
```

これを実行して、Kibanaを再起動すれば、問題なく操作できるようになりました。
【Node.js】日時処理を扱う方法

#プログラミング勉強日記
2021年2月25日

#日付処理を使うための準備
　Node.jsで日付処理を扱うために、今回はdate-utilsを使用する。
　date-utilsはnpmパッケージの1つで、簡単にインストールすることができる。

```:date-utilsをインストールする
$ npm install date-utils
```

#現在時刻を表示する


```js
// date-utilsを呼び出す
require('date-utils');
let now = new Date();
console.log(now.toFormat('YYYY年MM月DD日 HH24時MI分SS秒'));
console.log(now.toFormat('YY年M月D日 H時MI分SS秒'));
console.log(now.toFormat('DDD MMM DD YYYY HH24:MI:SS'));
console.log(now.toFormat('M/D/YY'));
```

```:実行結果
2021年02月25日 01時52分13秒
21年2月25日 1時52分13秒
Thu Feb 25 2021 01:52:13
2/25/21
```


#参考文献
[日付に関する実装！Node.jsで書くDateの使い方【初心者向け】](https://techacademy.jp/magazine/16245)
SpringBootでlog4j2を利用した際に終了処理の出力でハマった話

# この記事の対象
Spring Boot 2.3.6
spring-boot-starter-log4j2 2.3.6

# 概要
SpringBootアプリケーションの終了処理(@PreDestroyアノテーション使用)で、ログ出力を行いたかったわけです。
終了処理後に特定のメッセージコードを含むログを出力し、それをAWS CloudWatch上のイベントトリガーにしたかったためです。

# なぜハマったのか？
終了処理が呼び出される時点で、Loggerのインスタンスが非同期で自動開放されるようである。
このため終了処理でログが出力されるか否かは、自動終了処理に左右される。

# 解決方法
これを防止するためには、log4j2.xmlのConfigurationタグにshutdownHookパラメータ設定を追加し、自動開放しないようにする。

``` log4j2.xml抜粋
<Configuration shutdownHook="disable">
```

その上でアプリケーションの終了処理でLoggerの終了処理を追加する

``` SampleApp.java
import org.apache.logging.log4j.core.config.Configurator;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
...

@SpringBootApplication
public class SampleApp {
    public static Logger logger = LogManager.getLogger(this.getClass());
    ...

    @PreDestroy
    public void shutdownHook() {

        /**
         *  アプリケーション終了処理を記載
         **/

        logger.info("ここでログがだしたかったんだけど、出力されなかったんです");

        // Logger終了処理
        Configurator.shutdown((LoggerContext)LogManager.getContext());
    }

    public static void main(String[] args) {
        SpringApplication.run(SampleApp.class, args);
    }
}
```
Qiitaとは何か~Qiitaの投稿の仕方までのまとめ

# はじめに
日々の振り返りのため毎日の日記をつけようと思ったのですが、ノートに書いていくとかさばっていくので、せっかくなのでQiitaに投稿始めました。
Qiitaを投稿し始めるに当たってQiitaのことを改めて調べたことをまとめたので、これからQiitaを始めるという方に役に立てば嬉しいです！

# Qiitaとは
2011年9月16日にサービスが開始された、日本最大級のプログラマーコミュニティ。
エラーの解決法や役立った知識などをお互いに共有し合うことでより知識を得られるサービス。

# 投稿までの準備
- まずは右上の登録のボタンからアカウントを作成。
- メールアドレスまたは、GitHubやTwitterなどの外部サービスアカウントと連携可能です。
- 自分の興味のある言語をフォローします。
- その後他のユーザーからもわかるようにプロフィール設定をしとくといいでしょう。

# 投稿
それでは投稿していきましょう

# タイトル
記事の見出しを作ります

# タグ
どんな内容かをタグで表現、付けとくと後で見返すときに便利です。

# 本文

記事はマークダウンで作成します。

# マークダウン
下記参照
[Markdown表記 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)

###### 文字拡大
＃を１〜６こを並べることで大きさを調整できます。
↓こんな感じ(これは全角使ってます。)
＃＃＃巨大化！

###### コードを挿入するときは

空白
｀｀｀rb
ここにコード
｀｀｀
のように(バッククオート3つ)(言語指定)と(バッククオート3つ)で挟みます。上の一行を開けないとコード記入のマークアップが反映されないので注意！
※上記は説明のため全角にしています。

僕はこちらに助けられました。
[Markdownの書き方](https://help.docbase.io/posts/13697#%E3%82%B3%E3%83%BC%E3%83%89%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF)


# 以上
それでは良いQiitaライフを！
ダミーデータを条件付きで表示/非表示にする方法

# はじめに
本記事は製品情報などのダミーデータを、DBにデータが保存されているかいないかで表示/非表示にする方法を解説するものです。
考えてみれば難しいことではないのですが、とても悩んで時間を使ってしまったので、今後のために残しておくことと、同じようなエラーに遭遇した方の助けになれば良いと思い、記事にしました。

##環境
- 言語:Ruby
- フレームワーク:Rails
- DB:MySQL

## やりたかったこと
DBに保存済みのレコードをトップページに表示し、DBに何も保存されていなければダミーデータの製品を表示させる。

### 該当箇所のコード(コントローラー)
```ruby
class ItemsController < ApplicationController
  before_action :authenticate_user!, only: [:new, :create]

  def index
    @items = Item.all.order('created_at DESC')
  end
```
### 該当箇所のコード（ビューファイル）
```ruby

  <% if @items == nil %>
    #製品を表示させるための処理(今回は割愛)
  <% end %>
```
結果・・・・・
エラーは発生しないものの、ダミーデータが表示されない。。。
製品情報をDBに保存してみたところ、保存した製品自体は表示されるので、DBのデータを取得してトップページに反映させる処理自体は問題ない様子。

### 原因
if文の条件式に`nil`を指定しましたが、if文がDB内を「空」と判断してくれなかった様子

### 解決策①
if文の条件式部分を下記のコードに変更 （配列の要素を指定する）
 
```ruby
<% if @items[0] == nil %>
```
nilに対し配列の１つ目、すなわち`[0]`を指定することにより、if文が「配列の１つ目が空」＝「DBにデータは保存されていない」という判断をしてくれます。
これでDBにデータが保存されている時は保存されたデータを表示し、DBにデータが保存されていなければダミーデータを表示することができました。
### 解決策②
if文の条件式部分を下記のコードに変更 （empty?メソッドを用いる）

```ruby
<% if @items.empty %>
```
emptyメソッドは要素が0の時にtrueを返すメソッドです。
これを条件式に指定することにより、DBに解決策①と同様の挙動をしてくれました。

### さいごに
nilは条件指定で頻繁に使いますが、今回はそこに頭が集中するあまり他の方法論を検討していなかったのが時間を使い過ぎた原因と思っています。
一つの書き方が完答、というわけではありませんし、柔軟に考えるためにも様々な書き方を試してみるのも大事だなと感じました。
S3のホスティングに特定のIP（VPN）経由のみアクセスする方法

## ■ 概要
S3でホスティングしたページに対して、
VPN接続している場合のみアクセスできる状態にするための方法です。

## ■ 背景
今回、このような対応をしたこんな背景になります。

- DBのスキーマを社内のみで公開したい。

という要件をいただきました。
担当のエンジニアからは検証サーバーにアップロードするのはどうかという案が出ていたのですが、
本番環境とずれてしまうことになります。
かと言って、スキーマのためだけに別のサーバーを立てるのもめんどくさい。。。

ということで、今回はS3のホスティングを利用することにしました。
処理を行わない静的なページなのでS3のホスティングで事足ります。
また、バケットポリシーを設定することで、VPN接続した時のみ閲覧できるようにできます。

ということで早速みていきましょう。

## ■ 各種設定方法
### 1. S3バケットの作成
S3に新しくバケットを作成します。
この時にブロックパブリックアクセスのバケット設定を設定しておきます。
![create_bucket_s3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75243/ab214250-0327-b2cf-ff83-37ac23a57690.png)

### 2. ホスティングを有効化
次にホスティングを行います。
新しく追加したバケットにどんな内容でもいいのでindex.htmlを設置します。
その後にS3のプロパティタブの中にある「静的ウェブサイトホスティング」の編集に遷移します。
以下のスクショのように有効にして、インデックスドキュメントをindex.htmlにします。
今回は社内用なのでエラードキュメントは設置しておりません。
![static_hosting_s3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75243/7003baff-7f36-c28d-015d-ce68f1976909.png)

完了すると、ホスティングのページで以下のようにURLが表示されるのでアクセスすると、
設置したindex.htmlの内容が閲覧できるかと思います。
![hosting_url_s3_mozaik.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75243/e7f84a65-d9cf-f766-d3a7-14e33f4fef12.png)

### 3. VPNのみ許可するバケットポリシーの設定
ここが今回のメインどころです。
結論、VPN経由のみでアクセス可能にするには以下の設定をバケットポリシーに追加します。
「バケット名に置換」と「IPに置換」の部分は設定するご自身の環境に合わせて書き換えてください。

```
{
    "Version": "2012-10-17",
    "Id": "SourceIP",
    "Statement": [
        {
            "Sid": "SourceIP",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::バケット名に置換",
                "arn:aws:s3:::バケット名に置換/*"
            ],
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "VPNのプライベートIPに置換",
                        "VPNのパブリックIPに置換"
                    ]
                }
            }
        }
    ]
}
```

VPNのプライベートIPは検証のサーバーのEC2からアクセスするためのものになります。
パブリックIPは実際にブラウザからアクセスして閲覧する用のものです。
こちらがないと閲覧できなくなるのでご注意ください。

### バケットポリシーを誤って設定してしまったら
もし、誤った設定を追加してしまうと、ご自身も閲覧や編集も行えなくなってしまいます。
その場合はAWSにルートユーザーでログインしてください。
そうすればバケットポリシーの削除や編集が行えます。


以上でVPN経由でのみ閲覧できるS3のホスティングの仕組みができます。
もし間違っている部分だったり、もっと改善できる点などをご存知でしたら、コメントをいただけると幸いです。
Laravelでページごとに個別のcssを反映させたい

#やりたいこと
※私は初心者です

.blade.phpファイルでは親レイアウトに

```php:layouts/親.blade.php
<!DOCUTYPE html>
<html lang='ja'>
<head>
  <!-- 省略 -->
</head>
  <body>
    @yield('content')
  </body>
<html>
```

```php:子.blade.php
@extends('layouts.親')

@section('content')
中身
@endsection
```
という感じでhtmlを埋め込めた。

これのcssバージョンをやりたい。
#2つのやり方があるみたい
1. 子blade内に記述するパターン  
   
普通に親側のheadタグ内で
```@yield('css')
```と書き、  

```php:子.blade.php
@section('css')
<!-- ここにcssを記述 -->
@endsection
```
とするやり方。  
2. cssファイルを読み込むパターン

```php:layouts/親.blade.php
<!DOCUTYPE html>
<html lang='ja'>
<head>
  @stack('css')
</head>
```
```php:子blade.php
@push('css')
    <link href="{{ asset('css/子.css') }}" rel="stylesheet">
@endpush
```
という感じで書く。
AKS

#概要メモ
AKSを作るとリソースグループが2つ作成される。
- マスターノードのリソースグループ
- それ以外のリソースが属するリソースグループ

AKSを作ると関連するリソースも一緒に作成される。
- ノードプールに含まれるノード（LinuxのVM）
- VMが属するVNET
- ロードバランサー
- セキュリティグループ
など

AKSを作成するとついてくるLinuxのノードにクラスタ動作に必要な機能が含まれている。
そのため、冗長構成になるよう2台以上が推奨で、クラスタを消さないとこのノードプールは消せない。

###ネットワーク
コンテナネットワーク
Azure CNI方式とKubenet方式の2つから選んでazコマンドで作成する。
Azure CNI方式：AzureのVNETで払い出されるPrivateIPをPodに付与。AKSのベストプラクティスはこっち。
Kubenet方式：K8s標準。ノードにVNETのPrivateIPを割り当ててNATで通信。

その他ネットワーク
マスターノードのAPIエンドポイントはプライベート化（VNET内からのみのアクセス）にできるが基本はパブリック。
プラベイート化するとCloud Shellからもアクセスできなくなるのであまりセキュリティ対策にはなってないかも。

クラスタの外へのアウトバウンド
3つある
- Service Endpoint
- Private Endpoint
- Azure Firewall
Service Endpoint：指定したサービス全てに対してアクセスできるようにする（Storage, SQL DB, AADなど）。他のユーザーのリソースにもアクセスできてしまうので、AADぐらいにしか使わない。ただし無償。
Private Endpoint：エンドポイントをVNETに引き込む。リソースごとにFWの設定が別途必要。KeyVault, ACR, SQL DB用に使う。ログが取れない。VNET内のAzureDNSでIPをPrivateエンドポイントに書き換える（同じドメインを別のVNETのAzureDNSで問い合わせるとPublicエンドポイントが返される）。
Azure Firewall：VNET内に作れるFW。HTTP/Sはフィルタリングができる。高い。ログが取れる。

###認証・認可




###セキュリティ
アップグレード
K8sのバージョンを選択すればIn-placeアップグレードで置き換えてくれる。ただし、切り戻しができないので事前検証がしたければ別のノードプールを足してそちらだけバージョンをあげて検証（クラスタを分けても良い）。このタイミングでノードもアップデートされる。

ノードのVM
Ubuntuは毎日更新プログラムをチェックして自動適用。再起動は自動化されてないので適時Kured。



###CICD




#課金単位
ワーカーノードのVMスペックで決まる。
リザーブドインスタンスも使える様子。

マスターノードはSLO99.5%なら無料。
アップタイムSLAのオプションを使うと以下。
- クラスター構成：99.95%
- 非クラスター構成：99.9%


#その他に知りたいこと
- Windowsコンテナを動作させるにはどうすれば良いのか（クラスタを分けるか、Windowsノードさえあればいいのか）
→AKSを作るとLinuxのノードが立ち上がるので、これの横にWindowsのノードを追加する。
Windowsコンテナを起動するときはNodeSelectorでWindowsのノードを探して立ち上げる。
https://docs.microsoft.com/ja-jp/azure/aks/windows-faq


- AKSはサービスメッシュを自分で選定しないといけないのか
→これはその様子。ECSだとEnvoy ProxyをAppMeshからコントロールするが、AKSはIstio, Linkerd, Consulから選べそう。
https://docs.microsoft.com/ja-jp/azure/aks/servicemesh-about

- Private Link


#参考
https://www.facebook.com/nobuyuki.akama.5/posts/2947887578638196
C言語　INFINITYの比較

すごく当たり前だけどメモ。

```c
#include <stdio.h>
#include <math.h>

int main()
{
	double n = INFINITY;
	double inf = INFINITY;

	printf("%4f  < %4f is %d\n", n, inf, n < inf);
	printf("%4f  > %4f is %d\n", n, inf, n > inf);
	printf("%4f  < %4f is %d\n", -n, inf, -n < inf);
	printf("%4f  < %4f is %d\n", n, -inf, n < -inf);
	printf("%4f  < %4f is %d\n", -n, -inf, -n < -inf);
	printf("%4f == %4f is %d\n", n, inf, n == inf);
	printf("%4f == %4f is %d\n", -n, inf, -n == inf);
	printf("%4f == %4f is %d\n", -n, -inf, -n == -inf);
	return (0);
}
```

```terminal
 inf  <  inf is 0
 inf  >  inf is 0
-inf  <  inf is 1
 inf  < -inf is 0
-inf  < -inf is 0
 inf ==  inf is 1
-inf ==  inf is 0
-inf == -inf is 1
```
AWS CodeCommit の使いにくい点

# 背景
AWSのサービスということもあり、[コードレビューの自動化](https://aws.amazon.com/jp/codeguru/)や[CI/CD](https://aws.amazon.com/jp/getting-started/projects/set-up-ci-cd-pipeline/)等AWSの他のサービスと組み合わせたアーキテクトが便利というCodeCommit。
これまでリポジトリ管理にGitBucketやGitHubを使ってきましたが、CodeCommitを始めて使いにくいと感じた点を少ないですがまとめました。

# 使いづらい点
### 遅い
どの操作をするにも体感遅いです。これは時と場合によるかも。
追記：概ね改善された気がします。

~~### プルリクのコメントが改行されない~~
~~全て1行で表示されてしまい見にくいです。~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/50524af5-2cbf-a09d-e24f-3b6838795409.png)


### 差分を表示できない
エラー『違いを表示できません。個別のファイルが大きすぎて表示できないか、ファイル間の全体的な違いが複雑すぎます。』と表示される場合がある。これは致命的です。ソース管理を奇麗にしろとも取れますが、基準が曖昧ですし不親切に感じます。
追記：ファイルの行数を3250行以下にしないと当該エラーが発生する。開発チームに連携した上で対応有無・時期未定とAWS公式回答。
cf. [AWS CodeCommit のクォータ](https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/limits.html)
cf. [公式フォーラムで未解決らしい](https://forums.aws.amazon.com/thread.jspa?threadID=302436)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/40657aa3-9fba-ab06-35de-47b0c5f14f91.png)

### マージする際に作成者名とEメールアドレスを毎回入力させられる
「スカッシュしてマージ」「3ウェイマージ」を選択した際は必須入力です。
せめてIAMユーザーを検索・選択できるようにしてくれればいいのに…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/3a03127d-6655-8ab2-4c33-50ed974aceee.png)

### ソースコード内の日本語をブラウザの検索機能では検索できない
英語は検索に引っ掛かります。（「コード」から表示した場合のみで、プルリクエストの日本語は検索出来た。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/c8af0bf0-1733-bc45-f8cc-bb95f2818578.png)




### プルリクエストに対して、マージ先の最新のソースを取り込む機能がない
GitBucketにあったこんな機能です。これがないとレビューの度に最新のソースを取り込んでからPUSHし直してもらう必要があったりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/39e2180e-bea0-55c0-550f-93965910be48.png)

因みにGitBucketの場合に、同じ個所に表示される競合（コンフリ）が発生した際のUIも分かりやすくて好きです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286189/8d1596a0-62c8-f16e-fcfb-4b86aec63ecd.png)

# 別のリポジトリ管理を使う
セキュリティ要件を満たすために完全プライベートリポジトリに絞ると、GitLab（CodeGuruには対応していない）とかでしょうか。これいいよというのがあればご教授頂きたいです。
Google Cloud Vertex AI Workbench のインスタンスをワンクリックで作成する方法

特定のノートブックを配布するとき、以下のような URL で download_url にダウンロード可能な .ipynb へのリンクを指定すれば、 Vertex ワークベンチ のインスタンスをワンクリックで起動可能です(1行で記述ください)。

```
https://console.cloud.google.com/vertex-ai/workbench/deploy-notebook?download_url=https://github.com/GoogleCloudPlatform/vertex-ai-samples/raw/main/community-content/alphafold_on_workbench/AlphaFold.ipynb
```

マネージドノートブックで作成する時はdeploy-notebookをdeploy-managed-notebookに変更すると良いらしいですが、2022年4月時点ではまだ動作が不安定でした。
'DataFrame' object has no attribute 'ix'の解決法

#はじめに
オライリージャパンの「Pythonではじめる機械学習」の4章のp.210の以下のコードを打ち込んだ時，エラーが発生しました．

```python
features = data_dummies.ix[:,"age":"occupation_ Transport-moving"]
#NumPy配列を取り出す
X = features.values
y = data_dummies["income_ >50K"].values
print("X.shape: {} y.shape: {}".format(X.shape,y.shape))
```
エラー内容

```python
'DataFrame' object has no attribute 'ix'
```
#解決法
調べてみると，2020年2月に導入されたpandas-1.0.0で，以前バージョン0.7.3まで使用できたDataFrameの.ixが廃止されたそうです．
しかし，代わりにlocを用いることで解決できます．

```python
features = data_dummies.loc[:,"age":"occupation_ Transport-moving"]
#NumPy配列を取り出す
X = features.values
y = data_dummies["income_ >50K"].values
print("X.shape: {} y.shape: {}".format(X.shape,y.shape))
```
loc使用後

```python
X.shape: (32561, 44) y.shape: (32561,)
```
エラーが消えました．
#参考
https://ebcrpa.jamstec.go.jp/~yyousuke/matplotlib/info.html ，2021/2/25参照
git 主なコマンドまとめ

単なるgitコマンド備忘録。
ちょいちょい追加していきます。

##リポジトリを新規作成する
```
$ git init
```

##ファイルをインデックスに追加する（ステージングする）
```
$ git add
```

##コミットする
```
$ git commit
```

##ワークツリーのファイルの状態を確認する
```
$ git status
```

##コミットのログを確認する
```
#すべて表示
$ git log

#一行で表示する
$ git log --oneline

#ファイルの変更差分を表示する
$ git log -p index.html

#表示するコミット数を制限する
$ git log -n <コミット数>
```

##変更差分を確認する
```
#git addする前の変更分
$ git diff
$ git diff <ファイル名>

#git addした後の変更分
$ git diff --staged
```

##ワークツリー、gitの記録からファイルごと削除（そもそもファイル自体が不要になった）
```
$ git rm <ファイル名>
$ git rm -r <ディレクトリ名>
```

##ワークツリーにファイルを残し、gitの記録からのみ消したいとき（パスワードファイルなどgitには上げないけど手元には残したいなど）
```
$git rm --cached <ファイル名>
```

##ファイルの移動を記録する
```
$git mv <旧ファイル> <新ファイル>
```
それは下記と同じ効果である

```
$mv <旧ファイル> <新ファイル>
$git rm<旧ファイル>
$git add<新ファイル>
```

##ブランチを作成する
```
$ git branch <ブランチ名>
```
ブランチの作成だけで、ブランチ切り替えは行いません。

##ブランチの一覧を表示する
```
$ git branch
```

##現在のブランチがどのコミットを指しているか確認
```
$ git log --oneline --decorate
```

##ブランチを切り替える
```
$ git checkout <既存ブランチ名＞
```

##ブランチの作成と切り替えを同時に行う
```
$git checkout -b <新ブランチ名>
```
切り替えると、HRADも切り替えたほうのブランチに移動する


##ブランチ名を変更する
```
$ git branch -m <新ブランチ名>
```

##ブランチを削除する
```
$ git branch -d <ブランチ名>
```
変更作業がマージされずに残っている場合は削除されない。



##変更履歴をマージする
```
$ git merge <ブランチ名>
$ git merge <リモート名/ブランチ名>
$ git merge origin/master
```
origin：GitHub(リモート)を意味する
rails db:migrateがdbに反映されない場合の解決例

rails db:migrateを行ってDBに反映されない場合は、
rails db:migrate:statusでステータスを確認します。

upの状態であれば,rails db:rollbackを行います。
rails db:rollbackは、テーブルを差し戻すという内容です。

その後、rails db:migrateを行うことでデータがdbに反映されます。

```ターミナル
○○○○○○○○@○○○Air ○○○-3419 % rails db:migrate:status 

database: ○○○○○○_3419_development

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210218055220  Devise create users
   up     20210222081535  Create items

○○○○○○○@○○○Air ○○○-3419 % rails db:rollback      
== 20210222081535 CreateItems: reverting ======================================
-- drop_table(:items)
   -> 0.0172s
== 20210222081535 CreateItems: reverted (0.0205s) =============================

○○○○○○○@○○○Air ○○○-3419 % rails db:migrate       
== 20210222081535 CreateItems: migrating ======================================
-- create_table(:items)
   -> 0.0454s
== 20210222081535 CreateItems: migrated (0.0455s) =============================
```
JavaScriptで String (文字列) を昇順 (asc)・降順 (desc) にソートする  

#はじめに: 

##やりたいこと
JS で 文字列 (String) をソートしたい。
・ "627118" -> (昇順) -> "112678"
・ "627118" -> (降順) -> "876211"
・ "Hello World" -> (昇順) -> " HWdellloor"
・ "Hello World" -> (降順) -> "roollledWH "  

#考察

## 昇順ソート
・String => 1文字1文字を配列にする (str.split('')) => sort() => 配列から文字列に戻す (strArr.join(''))　

## 降順ソート
・上記にプラスして、sort() の後に reverse()

#やったこと

```JavaScript
/**
 * @param {String} str
 * @return {String}
 */
function sortAsc(str){
    // 各文字を区切って、配列に変換
    let strArr = str.split('');
    // 昇順
    strArr.sort();
    // 配列を文字列に戻す
    return strArr.join('');
}
```

```JavaScript
/**
 * @param {String} str
 * @return {String}
 */
function sortDesc(str){
    // 各文字を区切って、配列に変換
    let strArr = str.split('');
    // 昇順
    strArr.sort();
    // 降順
    strArr.reverse();
    // 配列を文字列に戻す
    return strArr.join('');
}
```
##結果
```JavaScript
sortAsc("627118"); // 112678
sortDesc("627118"); // 876211
sortAsc("Hello, World"); // " HWdellloor"
sortDesc("Hello, World"); // "roollledWH "
```

#終わりに
もっと早いやり方あれば、コメントください。ありがとうございました。

## 関連記事: 
[Java で String (文字列) を昇順 (asc)・降順 (desc) にソートする](https://qiita.com/akiras7171/items/8a4f0429c3508ff15a09)
Railsのfind_eachやfind_in_batchesでorderにid以外を指定したい場合の解決方法

# はじめに
大量のデータにアクセスして処理を行う場合、

- メモリ不足で処理が中断されないよう、少しずつメモリに展開したい
- 途中で処理が中断されても問題ないよう、一定件数ごとにコミットをしたい

と考えることがあると思います。

そんなときにRailsで役に立つのがfind_eachやfind_in_batchesですね。

ただしこの2つのメソッドには弱点があり、<b>id(主キー/primary key)の昇順(ASC)でしかデータを扱うことができません</b>。

※Rails v6.1.0時点での情報です。

```ruby
    # NOTE: Order can be ascending (:asc) or descending (:desc). It is automatically set to
    # ascending on the primary key ("id ASC").
    # This also means that this method only works when the primary key is
    # orderable (e.g. an integer or string).
```
https://github.com/rails/rails/blob/914caca2d31bd753f47f9168f2a375921d9e91cc/activerecord/lib/active_record/relation/batches.rb#L128:title


そこで、今回は自分が指定したorderで大量データを扱いたい場合の解決方法を紹介いたします。

# 解決方法
## 前提
Rankingモデルのrank(順位)順で処理をしたい、とします。

## 実装
```ruby
@rank_offset = 0
@batch_size = 1000

def find_rankings_in_batches
  loop do
    rankings = Ranking.where('rank > ?', @rank_offset).order(rank: :asc).limit(@batch_size)
    break if rankings.blank?
    rankings.each do |ranking|
      yield(ranking)
    end
    @rank_offset = rankings.last.rank
  end
end

find_rankings_in_batches do |ranking|
  # ここに処理を書く
end
```

## 発行されたSQL
1ループ目

```sql
SELECT  `rankings`.* FROM `rankings` WHERE (rank > 0)  ORDER BY `rankings`.`rank` ASC LIMIT 1000
```

2ループ目

```sql
SELECT  `rankings`.* FROM `rankings` WHERE (rank > 1000)  ORDER BY `rankings`.`rank` ASC LIMIT 1000
```

rankの昇順かつbatch_size単位で取得できていることがわかります。

## 注意点
基本的には、<b>orderに指定するカラムはUNIQUE制約が設定されているもの</b>にしてください。
batchの切れ目で同じ値が続く場合、処理されないレコードが存在してしまうためです。
【Rails6】「いいね」が1回しかできないエラーを解消

#はじめに
いいね機能を導入して、複数回「いいね」ができるような仕様にしていました。
しかし、しばらく経ってから「いいね」が1回しかできなくなっていました。（why?）

![いいね１回.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/4bf36dff-f738-f418-c8ee-3e0b685cb771.gif)

複数回いいねができるようにしたい！

#結論
likeモデルのuniquness_ofのバリデーションを削除すると、複数回できるようになります。

導入した後に自分で設定していたのを忘れていて、焦って色々仮説立てて・・・
当たり前なのに・・・
めちゃくちゃ恥ずかしい・・・しくじってしまいました・・・

そもそもこれはエラーではないという・・


```app/models/like.rb
class Like < ApplicationRecord
  belongs_to :user
  belongs_to :answer
  belongs_to :definition

  # validates_uniqueness_of :answer_id, scope: :user_id ←削除
  # validates_uniqueness_of :definition_id, scope: :user_id　←削除


end

```

![いいね複数.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/7fd18f08-7cca-eac5-062a-c5d84a640116.gif)

#バージョン
rubyのバージョン　ruby-2.6.5
Railsのバージョン Rails:6.0.0


#恥ずかしながらやったこと

①デベロッパーモード（検証）で挙動確認
②jQueryのスクリプトタグが消えていないかの確認
③CSSが適用されているか（スタイルシートが指定されているか）の確認
④gemの相互作用の確認
⑤コードが破損しているかの確認
⑥コントローラーのcreateアクション挙動確認
⑦likeモデルの確認　←ここ！

#文法説明

validates_uniqueness_of :answer_id, scope: :user_id

validates_uniqueness_ofは唯一性を定めるためのバリデーションです。
scopeは範囲を定めます。

なので今回は、answer_idとuser_idの組み合わせが１通りしかない。
つまり、１回答に１回しか「いいね」が押せませんということです。

この記述があるかぎり一意性が担保されるということです。


#補足
今回は2時間くらいで問題に気づけましたが、デバックするときの基本は開発の全体像みることが改めて重要だなと感じました。
やったこと忘れてて恥ずかしいですが、灯台元ぐらしでありました。以後気をつけたいと思います笑
【301リダイレクト】spring framework でリダイレクトをカスタマイズ

# spring framework で301リダイレクトを簡単に
・毎回 RedirectView を作って設定とか面倒
・”*redirect301:*" でできるようにしたい
・ソース見てみたけど分かりづらい…困ったときの interceptor
・301 以外も自由にカスタマイズできそう

## 環境
・Windows10 64bit
・SpringFramework 4
・Java 8

## CustomRedirectInterceptor
```CustomRedirectInterceptor.java
/**
 * 
 * カスタムリダイレクト用インターセプタ
 *
 */
public class CustomRedirectInterceptor extends HandlerInterceptorAdapter {
	
	private static final String REDIRECT_PREFIX = "redirect:";
	private static final String REDIRECT_301_PREFIX = "redirect301:";

	public void postHandle(HttpServletRequest request, HttpServletResponse response, 
			Object handler, ModelAndView modelAndView) {
		
		if (modelAndView != null) {
			String viewName = modelAndView.getViewName();
			if (StringUtils.isNotBlank(viewName)) {
				// 301 リダイレクト対応
				if (viewName.startsWith(REDIRECT_301_PREFIX)) {
					request.setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, HttpStatus.MOVED_PERMANENTLY);
					modelAndView.setViewName( viewName.replace(REDIRECT_301_PREFIX, REDIRECT_PREFIX) );
				}
			}
		}
	}
}
```
ビュー名を取得して301用のプレフィクスだったら MOVED_PERMANENTLY をセットして
通常のリダイレクトビュー名に戻すだけ。

## インターセプタの設定
```servlet-context.xml
	<interceptors>
		<!-- カスタムリダイレクト用 -->
		<interceptor>
			<mapping path="/**" />
			<exclude-mapping path="/images/**" />
			<beans:bean class="your.own.domain.CustomRedirectInterceptor" />
		</interceptor>
	</interceptors>
```

## 書式
```java
return "redirect301:/foo/bar";
```

## 301ステータスを確認
・chrome 開発者ツール -> Network
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108113/ed5c3f0f-0344-2864-174b-d59e05e54e99.png)

以上、お疲れさまでした！