OmniAICreator/Qiita-1.07M huggingface dataset:
【初心者】Keyboard Maestroで超効率的に生きよう【Mac】

# はじめに
今回は、macOS全般でKeyboard Maestroができることで、自分がよく多用する行動をマクロ化してみました。

# 普段多用する行動
僕が普段多用する行動としては、下記の二点です。
1. ページのタイトルとページのURLを取得して、MarkDownの形式にする
2. Safariで開いていたサイトをChromeに移動して、お気に入り登録する

そのため、この二つを簡単にすることができるマクロを組みました。

# 組んだマクロ
開いているブラウザから(ChromeTitleをSafariTitleに変更すればSafariでも使えます)、ページのタイトルとページのURLを取得するマクロです。

![スクリーンショット 2021-03-25 11.04.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559163/058d2d58-93d7-bad9-bd89-959683bb364b.png)

[CHromeで開いているサイトのタイトルとURLをMarkDown形式で得る](https://github.com/YUMA-NAGAO/SettingMac/blob/main/%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E8%A8%AD%E5%AE%9A/KeybordMaestro/MakeLink(MarkDown)Chrome.kmmacros)

Safariで開いているページをChromeで開くマクロです。
![スクリーンショット 2021-03-25 11.05.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559163/8254a23c-6d4e-4458-f8a9-8f4cad5b766b.png)
[SafariでのページをChromeで開くマクロ](https://github.com/YUMA-NAGAO/SettingMac/blob/main/%E3%82%A2%E3%83%97%E3%83%AA%E3%81%AE%E8%A8%AD%E5%AE%9A/KeybordMaestro/OpenChrome.kmmacros)

# 参考文献
[初学者目線で見たプログラミング学習において最も大切な｢質問する｣ことについて - Qiita](https://qiita.com/tera_at/items/cb9f63b04f759ca10e54)
[Keyboard Maestroの使い方|はっきり言って最強のMac作業高速化ツールです](https://storehouse-techhack.com/keyboard-maestro-hack/)
バリデーションの書き方(Rails)

#バリデーションとは
バリデーションは、正しいデータだけをデータベースに保存するために制約をかける事です。
`model`に書くことでデータベースに保存する前に受け取った情報を正しいのか判定させます。

##空でないこと
```ruby:
validates :name, presence: true
```
##空であること
```ruby:
validates :name, absence: true
```
##一意性であること(重複していないこと)
```ruby:
validates :name, uniqueness: true
```
##文字数制限
```ruby:
validates :name, length: { minimum: 2 }  # 2文字以上
validates :name, length: { maximum: 50 } # 50文字以下
validates :name, length: { in: 2..50 }   # 2文字以上50文字以下
validates :name, length: { is: 6 }       # 6文字のみ
```
##Boolian型
```ruby:
validates :publish, inclusion: { in: [true, false] }
```

#数値制限
```ruby:
validates :fee, numericality: { greater_than: 0 } 
validates :fee, numericality: { ess_than: 250 }
validates :fee, numericality: { greater_than: 0, less_than: 250 }
#greater_than: 0   0 < fee 0より大きく
#ess_than: 250   250 < fee 250より小さい
```






##参考

[Active Record バリデーション Railsガイド v.6.1](https://railsguides.jp/active_record_validations.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE%E6%A6%82%E8%A6%81)
MacのターミナルでExcelファイルとbase64のエンコード/デコード変換

Macのターミナルで、Excelファイルをbase64にエンコードしたり、base64をデコードしてExcelファイルを生成する方法を残しておきます。

# Excelファイル → base64

```
base64 -i template.xlsx [-o output.txt]
```

`-oオプション`を付けない場合は、base64がターミナル上に出力されます。


# base64 → Excelファイル

```
echo "BASE_64_STRING" | base64 --decode > template.xlsx
```

ご参考までに。
Vimで複数行コメント（ブロックコメント）

## 概要
Vimで複数行の先頭に//とか入れてコメントアウトする方法はよく見かけるのですが，
コメントアウトしたい範囲の上下にコメント文字を入れる，いわゆるブロックコメントを簡単に行う方法が見当たらなかったので，メモします．

## コマンド
例えばC言語の場合, Shift-Vで行選択をして

```
:s/\%V\(^\_.*$\)\%V/\/\*\r\1\r\*\//
```
と打つことで，選択範囲をコメントアウトできます．
また，解除には再び行選択をして

```
:s/[\*\/]\{2}\n//
```
と打つことで, コメントアウトを解除できます.
![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1229552/f5cf43fa-b1ed-91a3-6c31-01afe8025ce7.gif)
## コマンドが長すぎる...
というわけで，[プラグイン](https://github.com/matsuda-slab/CommentOut)を用意しました．
.vim/plugin などに置いてお使いください.
,, で選択範囲のブロックコメント
,u で選択範囲のブロックコメント解除
になります．C以外の複数の言語でも動作します．

もっと簡単な方法があったら教えて下さい．
Amazon ECR とは

## 勉強前イメージ

Elastic container なんとか・・かな？
Docker的なやつ？

## 調査

### Amazon ECR とは

Elastic Container Registry の略で
Dockerのコンテナイメージを保存しておくためのレジストリで、
Dockerコンテナイメージを保存・管理・デプロイが簡単に出来ます。
ECSやEKSにも統合されています。

### 特徴

- フルマネージドレジストリ

フルマネージド型なので、
コンテナレジストリを動かすためのインフラや運用、スケーラブルなど不要になります。

- 安全に共有およびダウンロード

コンテナイメージはHTTPS経由で転送され、保管時には自動的に暗号化されます。
またIAMを使用してイメージへのアクセス制御を行えるようにポリシーの設定が出来るため細かく設定できます

- 高可用性や耐久性

コンテナイメージはs3に保存され、冗長化されるので安心して利用できます。

- デプロイワークフローを簡素化する

ECSやEKSに統合されているため、開発から稼働まで簡単に数sメルことが出来ます。
開発で使用していた同様のコンテナイメージを本番用にデプロイすることが出来ます。

### ECRのコンポーネント

- レジストリ

AWSアカウントごとに用意されており、
レジストリ内にイメージリポジトリを作成し、イメージを保存します。

- 認証トークン

イメージをpushまたはpullするにはECRレジストリに対して認証が必要です。

- リポジトリ

ECRのイメージリポジトリには、Dockerイメージ、OCIイメージなどが含まれます。

- リポジトリポリシー

リポジトリポリシーを使用して、イメージへのアクセス権を制御します。

- イメージ

コンテナイメージをpushまたはpullします。
ECSやEKSで使用することが出来ます。

## 勉強後イメージ

実際に触ってないからあまりイメージ沸かなくて難しいけど、
Dockerイメージを保存しておく場所って感じかな？
yumリポジトリ的な？合ってる？

## 参考

- [Amazon Elastic Container Registry](https://aws.amazon.com/jp/ecr/)
- [Amazon Elastic Container Registry とは？](https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/what-is-ecr.html)
- [【AWS】Amazon Elastic Container Registry(ECR)について解説します。](https://www.acrovision.jp/service/aws/?p=2761)
API Gateway + Lambda Authorizer + Lambdaプロキシ統合 + AWS SAM CLIを組み合わせたときのCORS設定

表題の通りです。苦しめられたので解決方法を共有します。

ポイントとしては、

* プリフライト用にOPTIONSメソッドを受け入れる必要がある (Access-Control系のヘッダーも返す)
    * AWS::Serverless::ApiのCorsプロパティを定義すれば、自動的にOPTIONSメソッドが作成され設定したヘッダーが返されるようになる
    * [CorsConfiguration \- AWS Serverless Application Model](https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/sam-property-api-corsconfiguration.html)
* LambdaでAccess-Control系のヘッダーを返す
    * 普通にレスポンスにヘッダーを含めればOK
    * ↓「Lambda または HTTP プロキシ統合への CORS のサポートを有効にする」の項目を参照
    * [REST API リソースの CORS を有効にする \- Amazon API Gateway](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-cors.html)
* 400系、500系の場合のレスポンスヘッダーはGatewayResponseで設定すれば良い
    * [amazon web services \- Error on setting CORS header for API Gateway lambda authorizer \- Stack Overflow](https://stackoverflow.com/questions/61790022/error-on-setting-cors-header-for-api-gateway-lambda-authorizer)

ハマりどころとしては、

* Corsプロパティを定義する際、AWS::Serverless::ApiのAuthプロパティで、AddDefaultAuthorizerToCorsPreflightをfalse(デフォルトでtrue)にしない限り、プリフライトのOPTIONSメソッドにまでLambda Authorizerが介入してしまう
    * プリフライトの送信内容はこちらで制御できないため、ほぼ確実にAuthorizerで弾かれてしまう
    * 弾かれたときにAccess-Control系ヘッダーを返しても、ステータスコード200以外は認められない
    * Lambda AuthorizerでOPTIONSメソッドのときだけ無条件で200を返してもいいが、AddDefaultAuthorizerToCorsPreflightをfalseにした方が色々スマート

一応サンプルのtemplate.ymlを残しておきます。

```yaml:template.yml
  ResourceApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: v1
      Cors:
        AllowMethods: "'GET'"
        AllowHeaders: "'authorization'"
        AllowOrigin: "'*'"
        MaxAge: "'180'"
      GatewayResponses:
        DEFAULT_4XX:
          ResponseParameters:
            Headers:
              Access-Control-Allow-Methods: "'GET'"
              Access-Control-Allow-Headers: "'authorization'"
              Access-Control-Allow-Origin: "'*'"
              Access-Control-Max-Age: "'180'"
        DEFAULT_5XX:
          ResponseParameters:
            Headers:
              Access-Control-Allow-Methods: "'GET'"
              Access-Control-Allow-Headers: "'authorization'"
              Access-Control-Allow-Origin: "'*'"
              Access-Control-Max-Age: "'180'"
      Auth:
        AddDefaultAuthorizerToCorsPreflight: false
        DefaultAuthorizer: LambdaRequestAuthorizer
        Authorizers:
          LambdaRequestAuthorizer:
            FunctionPayloadType: REQUEST
            FunctionArn: !GetAtt checkTokenFunction.Arn
            Identity:
              Headers:
                - Authorization
              ReauthorizeEvery: 0
```
CLI操作について

CLI操作を理解するために記事を書きたいと思う。
ちなみに使っているOSはMacです。

### ターミナルとは

■ターミナル
ターミナルとは、PCに命令をすることができるツールで
環境構築を行える。環境構築を実行するにはコマンドライン
というツールが必要となる。

■コマンドライン
コマンドライン (または コマンドラインインタフェース：CLI )とは、コンピュータに対して文字を打ち込んで操作を行うことのツール。

■GUI(グラフィカルユーザインターフェース)
コマンドラインとは対照的に、グラフィックを用いて操作を行う仕組み。
例えば、マウスをクリックして、ファイルを開くなどが該当する。

CLIとGUIでは圧倒的にCLIの方ができること多い。
CLIでは、PCに対しての操作のほとんどが行えると言って良いほどに、
様々な操作を行うことができる。

### ディレクトリについて
■ディレクトリ
ディレクトリとは、コンピュータ上で複数のファイルを整理するための入れ物のこと。
簡単に言ってしまえば、フォルダのことをいう。PCの実体はディレクトリによる階層構造になっており、ディレクトリの中にさらに多くのディレクトリやファイルが保存されている。

ディレクトリにはいくつか種類がある。

■ルートディレクトリ
ディレクトリは階層構造になっている、あるディレクトリは他のディレクトリに属している。
ルートディレクトリはその階層構造の一番上にあるディレクトリのこと。

■カレントディレクトリ
ターミナルで 現在作業中となるディレクトリのことをカレントディレクトリと呼ぶ。
ターミナルではここを基準に、PCに命令を出す。
ターミナルでは必要に応じて作業するディレクトリを移動しコマンドを実行していく。移動するたびにカレントディレクトリが指し表すディレクトリは変わる。

■ホームディレクトリ
ホームディレクトリは、 新規にターミナルを立ち上げた場合に作業中となるディレクトリのこと。

### パスについて
ターミナルを使った操作では、どのディレクトリのどのファイルを開くのか、どのディレクトリに移動、削除、作成をするのか、指定するディレクトリの場所を全て文字列で表現する。
この表現のことをパスという。

■パス
パスとはディレクトリやファイルの所在を示す文字列のこと。
ディレクトリは階層ごとに「/」で区切る。パスの指定方法は絶対パスと相対パスの2つがある。

■絶対パス
絶対パスは ルートディレクトリから指定するパス。
Macの全ディレクトリにおけるルートディレクトリは「/」。
全てのディレクトリやファイルはここからたどることができる。
そのため、絶対パスで指定するときにはパスの一番最初に/を指定する。

■相対パス
相対パスはカレントディレクトリから指定するパス。
ルートディレクトリから指定しないため、パスの始めに「/」をつけない。
カレントディレクトリ直下のディレクトリやファイルであれば、どのようなディレクトリ階層にあるのか指定することなく簡単にパスの指定ができる。

絶対パスは、どのディレクトリで作業していても指定した場所に移動できるというメリットがあるが、パスをルートディレクトリからたどって指定する必要があるため、記述が冗長になる場合があるというデメリットもある。
相対パスは、記述をシンプルにパスの指定が可能となるメリットがあるが、カレントディレクトリがどこにあるのかによって、指定するパスを変更する必要がある。
試しにcode-server使ってみた！

## 環境
- EC2
- Docker

## 初めに
Dockerのimageに`code-server`が出てきた！
試しに使ってみよう！
と思い構築を行い。記録用にここに記事として書いとこてな感じ
で作成しました。
EC2やセキュリティグループの設定、Dockerなどの知識はここでは省かせてもらいますので、公式ドキュメントで調べてみてください。

## とりあえず構築
簡単に言うとDockerHubに上がっているイメージを使って構築

### Dockerfile
```Docker
FROM codercom/code-server

USER root

# パッケージの更新
RUN apt-get update -y

RUN apt-get install -y docker docker-compose

RUN apt-get clean

USER coder

RUN cat /etc/group | grep docker
```

### docker-compose.yml
```docker
version: "3"
services:
  code:
    build: 
      context: .
      dockerfile: ./Dockerfile
    restart: unless-stopped
    command: code-server
    environment:
      PASSWORD: [任意のパスワード]
    ports:
      - 80:8080
    volumes:
      - ./projects:/home/coder/project
      - ./code-server:/home/coder/code-server
      - /var/run/docker.sock:/var/run/docker.sock
```

## できたら実行！
- コマンド
   - docker-compose up --build
- 指定のブラウザで`localhost`にアクセス
- ログイン画面が表示された

## EC2にUPしてみる
- sshでEC2に接続 ※pemファイルの権限は600に変更してあること前提
  - ssh -v -i [pemファイル] ec2-user@[Elastic IP]
- gitを使ってリポジトリをClone
- マウント先のフォルダに遷移
  - 例の場合：`/var/www/code-server`
- Dockerのサービスを起動
  - service docker start
- コンテナを起動
  - docker-compose up -d
- Amazon Route 53はコスト面からやってないので、直接IPでHttp接続
  - http://[Elastic IP]
- Local同様の画面が確認できた！

### 実際の画面
![スクリーンショット 2021-03-25 10.03.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329303/1f5bc396-e7dc-b8f5-b9b5-a074e283d39b.png)
 
## 今後
- カラーやプラグインが設定できればより良いものになりそうなので、そこができるか調べ試そうと思う
- 現状手動で起動しなければいけないので、自動で起動できるようにしたい！

## リンク
- 今回使用したImage
  - https://hub.docker.com/r/codercom/code-server
VisualStudioの拡張機能が表示されない


## 拡張ギャラリーは構成されていません。ギャラリーはオプションダイアログボックスの[拡張と更新]ページで構成できます。

visual studioのバージョンを上げた際に拡張機能の代わりに上記のメッセージが表示されるようになってしまいました。

既にissueされてたので、それにそって解決しました
https://developercommunity.visualstudio.com/t/vs-2019-manage-extensions-online-and-updates-is-no/953753

1. visual stuidoを起動していたらまず落としてください。
1. フォルダでdevenv.exeを見つける
C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\devenv.exe

2. 右クリックで互換性のトラブルシューティングを実行
3. 問題のトラブルシューティングを選択 
「以前のバージョンのWindows...」にチェックが付いてるのが問題でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/802f3172-e511-5cbf-4199-353fcb64abc3.png)

なので外して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/fc9c39b3-52b8-7082-9b7f-31aa6d9fb461.png)

次に調査しませんを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/fe5e03e9-c38b-7b45-d6c8-1157b668e7e6.png)


visual stuidoを起動すると治ってるかと思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139166/fd0e9d36-423c-7c94-c2ca-e2c894c51a53.png)
【21.03.24の記録】ようやくscssを導入する

Sass(scss)久々にやらなきゃなーとは思っていたのですが、
正直HTML, CSSってプログラミング言語じゃないの？何が違うのかわからん..みたいな時にちょこっとやった程度だったので、「ネスト式で書ける」くらいの認識しか持っていなかった

#やっと気づいたscssの良さ
####cssの記述だけでなく余計なHTML記述も減らせる

swiper.jsを導入していた時のこと。
スライダーを遷移させる左右のボタンが、通常時には非表示でhover時だけ表示される、というカスタマイズがあった。

```swiper.html
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
```

もしcssでこの左右のボタンの色をどちらも変えたい、となった時、

```swiper.css
swiper-button-prev, swiper-button-next {
color: #fff;
}
```

となる。
が、scssなら

https://digipress.info/tech/introducing-swiper-js/

このHTMLをいじっていい感じのデザインにしたかったので、色々とサイトを回ってcss記述を見たいたら、
scssで
####色の管理が、cssよりも更に楽

https://qiita.com/manabuyasuda/items/ae42db5604cd723fb3cd

cssでも最初にroot登録しておけば楽に色変換ができる。
が、scssだと値: キー

#導入するにはRubyが必要らしいがエラーが出た
MacOSを使用しているので、Rubyは標準でインストールされている。
が、パスがうまく通ってないらしくpermissionエラーが出た



  439  vi /.bash_profile
  440   echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
  441  echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
  446  which ruby
  447  bundle install
  448  export PATH="/usr/local/opt/ruby/bin:$PATH"\n
  449  bundle install
  450  cd ~/.bash_profile
  451  cmd
  452  pwd
  453  vi ~/.bash_profile
  454  gem install
  455  gem install sass
  456  sass -v
  457  which gem
  458  which ruby
  459  rbenv versions
  460  cat ~/.bash_profile
  461  source ~/.bash_profile
  462  gem install gem
  463  gem install sass
  464  sass -v

```
% gem install sass
ERROR:  While execut`ng gem ... (Gem::FilePermissionError)
    You don't have write permissions for the /Library/Ruby/Gems/2.3.0 directory.
```

https://qiita.com/nishina555/items/63ebd4a508a09c481150

結構同じ自体に陥ってる人がいるらしい。

`% which ruby`
でRubyがどこにあるか確認。

[このZenのサイト](https://zenn.dev/raika/articles/ded57ef73c4b55b148da)を参考に、
rbenvをインストールし、シェルファイルの中にパスを書いてみた。

`% gem install sass`
を打ってみる。
が、また同じ事態に。

[このサイト](https://qiita.com/k3ntar0/items/eb8cdbd8eba9da388def)によると、
シェルファイルに追記した内容を反映するには

```
$ source ~/.bash_profile
```

コマンドを打たないといけないらしい。(よく見たらzenのサイトにも書いてあった。見落としてた)
反映させてから再度`% gem install sass`をすると、無事sassのインストールができたのでバージョンを確認。

```
% sass -v
Ruby Sass 3.7.4
```
バージョンが表示されればok.

#cssをscssに自動変換する
一回cssで書いちゃったから書き直すのだるいな〜自動でできないかな〜と思ってたら
やっぱりあった。左側にcssをコピペして、真ん中の矢印を押すと変換できます。

http://css2sass.herokuapp.com/

#使い方の参考になるサイト

https://dev.classmethod.jp/slide/scss-tutorial/

https://qiita.com/manabuyasuda/items/ae42db5604cd723fb3cd
オンライン施設予約システムを実現する#1 概要編

#はじめに
　大学施設のオンライン予約システムを制作した備忘録を含めて投稿します。

　今回は概要部分の説明とします。
***
　オンライン化するツールは世の中にいくつもあるのですが、利用登録（アカウント作成）が不要・学内関係者のみ利用できるようにするなど課題があります。
　単に、メールやチャットで担当者に連絡する・EXCEL・PDF等で申請書を提出するなどの方法もありますが、担当者の負担軽減・複数担当者を配置するなど管理面での効率化も目指しました。

　以上より、大学で包括ライセンスで利用できるoffice365を活用したシステム開発を行いました。
　office365には学内関係者の氏名やメールアドレス情報など利用者情報がすでに登録されている・MSTeamsはオンライン講義で利用しているなど様々な利点がありました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598641/69fff47c-1d59-e4ff-3691-cae9152c82aa.png"width=100%>
###主な機能

* 施設予約申請
* 施設予約状況
* 施設申請承認（スタッフ向け）

#システム構成
各種ツールを連携させることで短期間での開発を実現しました。
基本的にはツール同士の組み合わせで実現しているので少し自由度が下がってしまいますが、

MSTeams：各種システム利用・メンバー管理
SharePoint：データ管理
PowerAutomate：フロー処理
PowerApps：UI開発

利用者が実際に利用するのはMSTeamsですが裏では様々なツールが動いています。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598641/707fd9cd-302c-79f2-3645-56cae0f239a2.png" width=80%>

#システム画像（一部）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598641/f555e6a8-bd6f-05c7-26da-8c2693180d72.png" width=80%>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/598641/a86fcc60-d9f3-d954-498f-7037307eeda0.png" width=80%>
SQLを学んでみた⑦(トランザクション)

実務でSQLやDBについて理解していないといけないと思い勉強を始めました。
その内容をまとめます。

## トランザクションはなぜ必要か

DBMSにSQL文で指示すれば基本的には間違った処理にはならないですが、
データの書き換え途中で別の人が同じデータを更新していたり、PCの電源が落ちて処理が途中で中断してしまったりするとデータがおかしくなることは考えられます。

エラーハンドリングと同じで「そもそも正しく処理されない可能性」を考えることは大切です。

## 例えば

Aさんが自分の口座から10000円をBさんに振り込みしたとします。

①Aさんの口座の残高が10000円減る。
②ここで異常がおきて処理が中断。
③Bさんの残高は増えない。

みたいなことが考えられます。

ただ単に残高が減っただけという恐ろしい事態に...
銀行のシステムを作ってくれている方々のおかげで安心して振り込み処理ができているんですね。ありがたや。


## トランザクションとは

`「処理をひとかたまりにする」`ことを言います。

先ほどの例でいうと
①Aさんの残高が10000円減る。
②Bさんの残高が10000円増える。
をひとかたまりにするので、どちらかだけ実行されることはありえないということになります。
つまり、`どちらも実行される`か`どちらも失敗する`のどちらかということです。


## 使い方

`BEGIN`から`COMMIT`までのSQL文を1つのトランザクションとして扱います。

```
BEGIN;
処理
COMMIT;
```

また、取り消しをしたい場合は以下のようにします。

```
BEGIN;
処理
ROLLBACK;
```

上記のようにトランザクションすることで誰か他の人がDBを変更できないように明示的にロックをかけていることにもなるようです。

以上です。
Unityで自作スライダーの実装

UnityのuGuiのsliderは非常に便利なのですがFillAreaに画像をアタッチしても伸縮で表示されて絵的にイマイチです。なので自作のスライダーを設置しようとしましたが、uGuiのSliderの使い方の解説の情報ばかりで自作のスライダーの設置方法がみつからなかったので自分用につくりました。

![Slider1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/7fd324a9-4b4c-cd48-8274-41e01132a1ef.png)
を分解すると
![Slider0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/c856cb50-5de0-578b-9d3b-4c2b6c385912.png)
土台部分はImage、バー部分はSpriteRendererとSpriteMaskで作成します
![Slider2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/06e78b29-9c3b-1f10-4af1-862933dc8272.png)
ヒエラルキー上ではこんな感じです
![Slider3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1146955/bd61d8ea-6531-f391-2ecb-58a967d54170.png)
土台部分にEventTriggerをアタッチして、DragEventを追加します。
(EventTriggerはRaycastTargetが有効化されたImageが同じオブジェクトにある場合のみイベントを起こすので土台はImageでなくてはなりません)

受け取り側のスクリプト

```C#
using UnityEngine.EventSystems;
    public float PixelPerUnit= 100f;
    public void OnSliderDrag(BaseEventData e)
    {
        PointerEventData pointer = e as PointerEventData;
        if (pointer.dragging)
        {
            Canvas canvas = GetComponentInParent<Canvas>();
            RectTransform rect = GetComponent<RectTransform>();

            Vector3 wpos = Vector3.zero;
            RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, pointer.position, canvas.worldCamera, out wpos);

            Vector2 LeftTop = new Vector2(-rect.sizeDelta.x * rect.pivot.x, -rect.sizeDelta.y * rect.pivot.y) / PixelPerUnit;

            value = (wpos.x - transform.position.x - LeftTop.x) / rect.sizeDelta.x * PixelPerUnit;
        }
    }

```

PointerEventDataで受け取る座標pointer.positionはスクリーン上の座標なので土台のImageを描画しているキャンバスを

```C#
Canvas canvas =  GetComponentInParent<Canvas>();
```
で取得し、そのキャンバスの対象のカメラを
canvas.worldCamera
から取得し、

```C#
RectTransform rect = GetComponent<RectTransform>();
Vector3 wpos = Vector3.zero;
RectTransformUtility.ScreenPointToWorldPointInRectangle(rect, pointer.position, canvas.worldCamera, out wpos);
```
でワールド座標wposに変換します。

あくまでワールド座標なので、スライダーの表示位置からどのくらいの位置にあるかということも計算しないといけません。
そこでRectTransform のサイズとピボットから左上の座標を取得しているのが

```C#
Vector2 LeftTop = new Vector2(-rect.sizeDelta.x * rect.pivot.x, -rect.sizeDelta.y * rect.pivot.y) / PixelPerUnit;
```
です。

今回は横方向のスライダーなので

```C#
value = (wpos.x - transform.position.x - LeftTop.x) / rect.sizeDelta.x * PixelPerUnit;
```
で正規化されたスライダーのドラッグ位置が取得できます。
ちなみにPixelPerUnitは、TextureのPixelPerUnitの値です。


ここまでやっておいてなんですが透明なuGuiのスライダーを手前に置いて、そのvalue値を表示用のスライダーに反映させるほうが簡単だと思います。

ですが何かに応用できそうなのでメモとして残しておきます。
光学ドライブをEjectするCLIプログラムを作った

---
# はじめに

Microsoft-WindowsMediaPlayer(WMP)のCOMコンポーネントを呼び出すことで、光学ドライブをEjectするCUIなプログラムを作った。

---
# なぜ作った?

そこに、Eject APIがあったからさ

---
# 使い方

「[CD-ROMドライブからディスクをEjectするCUIなプログラム](http://rocketeer.dip.jp/sanaki/free/free162.htm)」から、ダウンロードし、zipファイルを解凍して、出てきた「sEjectCDRom.NET2.exe/sEjectCDRom.NET4.exe」を実行するだけ。

- .NET Framework2.0 用 : **sEjectCDRom.NET2.exe**
- .NET Framework4.0 用 : **sEjectCDRom.NET4.exe**

---
## 使い方(詳細)

引数なしで、
`c:\>sEjectCDRom.NET2.exe`
or
`c:\>sEjectCDRom.NET4.exe`
とすると、接続されている全ての光学ドライブをEjectする

例えば、以下のような引数で実行すると、

`c:\>sEjectCDRom.NET2.exe d q`
or
`c:\>sEjectCDRom.NET4.exe d q`

Dドライブと、QドライブだけをEjectする

引数は何個でも指定できる。

---
## 使用上の注意

Ejectはできるが、Insertはできない。

---
# 以上
【Cloud9】failed to write new configuration file /home/ubuntu/.gitconfig.lock

## Error

Rails チュートリアルをやるために Cloud9 を開いたところ下記のエラーが発生。
Tab 補完が効かないなど変な挙動になった。

```
error: failed to write new configuration file /home/ubuntu/.gitconfig.lock

┌──────────────────────────────────────────────────────────┐
│                 npm update check failed                  │
│           Try running with sudo or get access            │
│           to the local update config store via           │
│ sudo chown -R $USER:$(id -gn $USER) /home/ubuntu/.config │
└──────────────────────────────────────────────────────────┘
```


## Translate

> failed to write new configuration file /home/ubuntu/.gitconfig.lock
↓
> 新しい設定ファイルの書き込みに失敗しました /home/ubuntu/.gitconfig.lock


## Resolve

```
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
・
・
・
/dev/xvda1      9.7G  9.7G     0 100% /
```

ディスク容量が圧迫されて書き込み処理等の操作が正しく行われなくなっていると予想。
今まで作成した別のアプリの削除を実施したところ、元の挙動に戻った。


```
xxx:~/environment $ rm -rf hello_app
xxx:~/environment $ rm -rf toy_app
```
Git push前に直前のコミットをなかったことにする方法

## 目的

- push前に直前のコミットをなかったことにする方法をメモ的にまとめる

## 方法

- ローカルリポジトリ内で下記コマンドを実行して直前のコミットをなかったことにしてソースの状態も直前のコミットのをする前の状態に戻す。

    ```terminal
    $ git reset --hard HEAD^
    ```

- ローカルリポジトリ内で下記コマンドを実行して直前のコミットをなかったことにしてソースはそのままにする。

    ```terminal
    $ git reset --soft HEAD^
    ```
今さらのリングバッファ

無線でデータをやりとりするセンサを作っていたんですが、データの保存にリングバッファが必要になりました。
「今さら自作しなくても」とも思ったのですが･･･
[**こちらに引っ越しました**](https://yokaton.com/mcu-rl78-memo/#i-11/)
ログの設計

## ログレベル

|ログレベル  |説明  |内容|対応 |
|---|---|---|---|---|
|EMERGENCY  |緊急事態 |使用しない|-|
|ALERT  | 警報 | 自社だけでは対応出来ないエラー |即時に対応が必要|
|CRITICAL　|危機 |自社で対応可能なエラー  | 即時に対応が必要 |
|ERROR  | エラー | 即座に対応が必要ではないが、記録や監視が必要な情報 |場合によっては対応が必要 |
|WARNING | 警告 | エラーではない例外 | 対応不要 |
|NOTICE  | 通知 | 正常だが記録しておきたい情報 | 対応不要 |
|INFO  | 情報 | イベントやSQLのログ | 対応不要 |
|DEBUG  | デバッグ | デバッグ情報 | 対応不要 |

## ログに出すべき情報
- 日時
- ルート名
- user_id
- uuid
- ip


## ログを出すタイミング
|タイミング  |レベル  |内容|
|---|---|---|---|
| 処理開始時 | INFO | 入力値 |
| SQL実行時 | INFO | アクション<br>単数ならID 複数なら件数<br>(SQL文) |
| 判定実行時 | INFO | 判定の結果 |
| 外部API連携時 | INFO | リクエストヘッダー<br>リクエストURI<br>リクエストボデイ<br>レスポンスヘッダー<br>レスポンスHTTPステータス<br>レスポンスボディ |
| エラー時 | ERROR<br>WARNING | メッセージ<br>ファイル<br>行数<br>(トレース) |
| 処理終了時 | INFO | リダイレクト先 |
| その他必要な時 | INFO<br>DEBUG | 必要な情報 |
【Swift】モーダル遷移かつNavigationBarも表示させたいかつフルスクリーンで表示させたい

# どういうことか

- 下からヌッと出てくるモーダルで遷移させたい
- そいつにNavigationBarもつけたい
- さらにフルスクリーンで表示させたい

コードで書きます。

# 実装

たとえばボタンを押したときのアクションなんかに書く。

```swift:ViewController.swift
let storyboard: UIStoryboard = self.storyboard!
let vc = storyboard.instantiateViewController(withIdentifier: "nextView")

let nav = UINavigationController(rootViewController: vc)
nav.modalPresentationStyle = .fullScreen

self.present(nav,animated: true)
```

閉じるボタンがないのでNavigationBarとかに作るといいと思う。
おわり(´・ω・｀)
rootless dockerの入力補完を有効にする

補完なしはちょっと辛くなってきたので調べました
軽く調べた感じだと公式ドキュメントに載ってないっぽい？（探せてないだけ？）

## 環境
- Ubuntu 20.04
- rootles docker

## 方法
とりあえず[これ](https://github.com/docker/cli/blob/master/contrib/completion/bash/docker)を`/etc/bash_completion.d/`の下に置いてあげればいい。
よくわからなければCompose用のコマンドを参考にしながらやれば大丈夫だと思います。

## 補足
- [Command-line completion](https://docs.docker.com/compose/completion/)
    - これはCompose用のcompletion導入方法
- [Command-line completion](https://docs.docker.com/machine/completion/)
    - これはDocker Machine用のcompletion導入方法

## おわりに
Ubuntuに普通のやつを入れてたらこのcompletionは一緒についてきてたんでしょうか？
知ってる人がいたら教えてください！
rosbagループ実行の方法

rosbagを使用して認識系のプログラムのテストしている時などにループ実行にすると再立ち上げする手間が省けて便利です。

```bash:
#コマンドから
rosbag play test.bag --loop
または
rosbag play test.bag -l

#rosrunから
rosrun rosbag play test.bag --loop
または
rosrun rosbag play test.bag -l
```

roslaunch

```xml:
<node name="rosbag_play"
  pkg="rosbag" type="play"
  args="test.bag --clock --loop">
</node>
```

※rosbagは現在のroscore時間を使用します。--clockオプションを使用するとroscore時間を無視してバグファイル時間が使用されます。

※ループの他に便利そうな機能にトピック名の変換機能もあります。引数に```topic1:=topic2```のように入れるとtopic1がtopic2に変換されます。

参考

https://ppdr.softether.net/ros-rosbag-options
【Laravel】「ヘルパ」PHP関数を使っていこう

今回はヘルパ関数について改めて触れる機会があったので
忘備録としてまとめておく。
公式を参考にしているのでより正確な解釈を知りたい方は
最後にリンクを載せてますのでそちらを御覧ください！

##「ヘルパ」PHP関数とは
Laravelで定義されている便利なグローバル関数。
例えばよく使うものでいくと
`auth`や`old`、`env`あたりがすぐに触れるでしょうか。
ちなみに僕は上記の関数は使ってましたがグローバル関数としての認識をもって使ってませんでした。
極端に詳しく調べなくてもいいかと思いますが仕組みを理解して使うと
簡潔な実装につながるかと思うので機会があれば処理を追ってみるといいでしょう。

##様々な関数
割とたくさんの関数があるのでよく使うものを纏めておきます。

```PHP
// 指定された変数の内容を表示し、スクリプトの実行を停止します。
dd($value);

// 環境変数の値を取得します。取得できない場合はデフォルト値を返します。
env('APP_ENV', 'production');

// セッションに一時保持データーとして保存されている直前の入力値を取得します。
old('value', 'default');

// Authenticatorインスタンスを返します。Authファサードの代わりに使用できます。
auth()->user();

// viewインスタンスを返します。
view('auth.login');

// 指定値を返します。関数の２番目の引数としてクロージャを渡たすと、
// クロージャが実行され、その戻り値を返します
$callback = function ($value) {
    return (is_numeric($value)) ? $value * 2 : 0;
};
$result = with(5, $callback);

// 指定した名前付きルートのURLを生成します。
route('route.name', ['id' => 1]);

// 設定変数の値を取得します。
// 設定値はファイル名とアクセスしたいオプションを「ドット」記法で指定します。
// デフォルト値が指定でき、設定オプションが存在しない時に返されます。
config('app.timezone', $default)
```
上記以外にも便利な関数はたくさんあります。
ぜひともまずは使ってみる、試してみることをやっていきましょう！

参考
[laravel.jp](http://laravel.jp/)
Qiita Daily Survey memo 2021.03.25

# Qiita Daily Survey memo 2021.03.25
Qiita の記事を可能な限り毎日読むために、読んだmemoを公開することでモチベーションを維持しようという試み。

## [道の真ん中をきれいにするプロジェクトマネジメント～イケてるチームになるための10原則～](https://qiita.com/yasuoyasuo/items/37cc24440b278363339e)
中野 ヤスオ＠ARI(yasuoyasuo)さんの記事。
守るところは守ろう、のようなプロジェクトマネジメントの話かな、と思って開きましたが内容は全然違いました。
日本っぽいなと思いほっこりしました。
まさに「うんうん」とうなづきながら読ませていただく内容でした。
特に私に刺さったのは「所有感の原則」でした。
これは自分のもの、と認識すると責任感が生まれて積極的になるというのは、なるほどなーと思いました。
一歩引き気味だなー…という方も多いので、意識してみようかなと思いました。


## [ほぼ独学・未経験者がモダンな技術でポートフォリオを作ってみた【Rails / Nuxt.js / Docker / AWS / Terraform / CircleCI】](https://qiita.com/aki0151/items/f39ef43c9d9fc1b87d9a)
aki0151 さんの記事。
コンビニ商品をレビューしたりヘルスケアをしてくれるアプリを作成された、という記事になります。
私のイメージしているポートフォリオというと就活の時のアレですが、こういうのもポートフォリオなのですね。
記事ですが、読んでいて笑いが出てくるほどきれいに書かれています…。SUGOI。
こんな感じでプロジェクト状況が整理されていたら、動きやすいだろうなーと思いました…ちょっと真似してみようと思います。
また、作成されたポートフォリオですが、記事同様きれいな仕上がりになっており、とても見やすいです。
加えて、おすすめの第一候補に「オマールソースの小海老トマトクリームパスタ」が来ていることから、信頼性が非常に高いことがわかります。
一部ですが、栄養成分表が記載されているので、栄養観点からのレコメンドとかがあると面白いかもと思いました。
[マクドナルドで一日分の栄養を取れる組み合わせを計算したら衝撃の結果に](https://qiita.com/takobaya391076/items/49b15c1fa36734b3fa53)


## [文系大学生が渋谷近辺のweb系上場メガベンチャーに内定をもらうまで](https://qiita.com/granB/items/e1af3873d1833077cf28)
grand blue(granB) さんの記事。
VRChatで知り合った文系学生の方も就活中で、IT系に就活していますが、苦戦中のようです。
そんな中、どんなことしたのかなーと興味があり記事を開きましたが…。
> Progateを何周もしたり、Railsチュートリアルをやったり、ネットにあったブログアプリや、○○クローンみたいなものを作ったりしていました。

や
> ただ正直に「わからないです。。」というと面接の時間を使って丁寧に教えてくれる面接官がほとんどでした。

なるほど納得でした。
興味を持ったことに対して、積極的に情報を取りに行ける。
ちゃんと手を動かして作ってみる、やってみる。
分からないことをごまかさず分からないと伝えられる。
社会人になってからも大事な素養が、面接している方に伝わったのだろうなーと思いました。
また、ITやったことないけど働いてみたい！という方には、非常に参考になるサクセスケースだなと思いました。

## つれづれ
自分が就職活動をしているときは、面接官や会社・社会と「戦っている」感覚で活動していましたが、今思い返すと非常にもったいなかったなと思います。
人生で1度だけ、非常に強い「新卒」という優先権を行使して、無条件にいろんな企業の話を聞くことができる権利を有する時期。
私は絵を描く活動をしていたので、pixivさんとか、お話をすごく聞きたかった…。
お互いに自分の状況と将来を話して、「いいね！」と思ったら一緒に働くマッチングのようなイメージで活動すればよかったなーと。

…書いていて思いましたが、新卒権限ほどはないにしても、今でも興味ある企業さんにお話し聞くこと自体は可能なのでは…？
そう考えると、少し元気がでてきました！
アジャイル開発における定量的品質予測

## これはなに？
アジャイル開発における品質予測の知見が自分の中になかったので一通り調べてみて、その結果をまとめてみました。


## 結論
定量的な品質予測方法は大きく分けて以下の2つがあります。

①ユーザーストーリーに対して受け入れ基準を作成し結果を分析する(難易度低)
②品質と連動している代用特性を見つけて測定する(難易度高)


## 内容
定量的な品質予測方法は大きく分けて以下の2つがあります。

### ①ユーザーストーリーに対して受け入れ基準を作成し結果を分析する

これはアジャイルでは基本的にやっているプロダクトの品質を測定するもので、
受け入れ基準を満たしていること = 要件を満たしていると言う意味になります。


受け入れ基準の作成に関しては[JSTQBのシラバス](http://jstqb.jp/dl/JSTQB-SyllabusFoundation-AgileExt_Version2014.J01.pdf)が参考になりました。

以下JSTQBのシラバスからの抜粋
>ユーザストーリーは、重要なテストベースとして機能する。次のアイテムもテストベースとなる可能性がある。

>- 以前のプロジェクトでの経験
- システムの既存の機能、フィーチャおよび品質特性
- コード、アーキテクチャおよび設計
- ユーザプロファイル（コンテキスト、システム構成およびユーザの振る舞い）
- 既存および以前のプロジェクトの欠陥に関する情報
- 欠陥分類法での欠陥の分類
- 適用可能な標準（航空関連ソフトウェアでは[DO-178B]など）
- 品質リスク（3.2.1 項を参照）



### ②品質と連動している代用特性を見つけて測定する

①で担保できるのは新規実装部分の品質だけでプロジェクト全体（新規実装外等)の品質までは担保されていません。

そこで、フローやリソースなどの代用特性を用いて測定するという方法があります。

例はNTT DATAさんの[アジャイル開発での品質保証](https://www.nttdata.com/jp/ja/data-insight/2020/102201/)から参照します。


>たとえば、「正しいプロセスで開発すれば、正しいプロダクトができる」という仮説に基づいて、「プロセス品質」を測ることは、従来からよく行われています。それに加えて、アジャイル開発では、開発者のスキルやチームの成熟度といった「リソース品質」がプロダクトの品質に影響するという考えから、リソース品質も代用特性として使われます。リソース品質には、バーンダウンチャートやベロシティなど、進捗や生産性に関するメトリクスが含まれます。つまり、開発者やチームが計画通りに作業ができて、高い能力を発揮できていれば、開発されるプロダクトの品質も高いという仮説です。

この例であるように、開発者のスキルやチームの熟練度等のリソース品質がプロダクトの品質に影響することを踏まえて測定する
ただし、この手法は開発者のスキルや成熟度という定性的なものを定量化出来ているという前提があって初めて成り立つので難易度は高いです。

## 所感
今回参考になった`JSTQB アジャイルテストのシラバス`や`定量的品質予測のススメ 1`はまだ自分の中にきちんと落とし込めていない部分があるのでそこも含め引き続きアウトプットしていこうと思います。




## 参考サイト
- [ISTQB Foundation Level Extension シラバス](http://jstqb.jp/dl/JSTQB-SyllabusFoundation-AgileExt_Version2014.J01.pdf)
- [定量的品質予測のススメ 1](https://www.ipa.go.jp/files/000005133.pdf)
- [アジャイル開発の品質管理技法](https://www.fujitsu.com/jp/group/fst/about/resources/featurestories/about-agile-05.html)
- [アジャイル開発での品質保証](https://www.nttdata.com/jp/ja/data-insight/2020/102201/)
haml imageタグ

__hamlのimageタグの使い方を学んでいたのですが、「class」属性が付けられなかったので、
備忘録のために記述します。（class属性が付与できずcssをあてらなくて困った( T_T)　）__
#やりたいこと
hamlのimageタグ「class:」属性を付けたい！

#記述方法
__html__

```html
<img src="verification/doraemon.png" alt="自分のイラスト" class="myimage" >
```

__haml__

```haml
= image_tag "verification/doraemon.png", alt: "自分のイラスト", class: "myimage"
```
#結果
無事にクラス属性を付与できた。
cssで画像サイズを変更したかったのですが、class属性が付与できず直接タグの中にサイズ書いてのがスッキリできました。

```haml
#before
= image_tag "verification/doraemon.png", size: "100x80", alt: "自分のイラスト"
#after
= image_tag "verification/doraemon.png", alt: "自分のイラスト", class: "myimage"
```
iOSネイティブアプリのhttp通信の内容を確認する

# はじめに
iOSネイティブアプリのhttp通信の内容を確認したい方向けです
### こんな時に便利
- webViewで表示されているページのurlが知りたい時
- ビルド済みのアプリでAPIのレスポンスを確認したい時
- 人のアプリがちょっと気になる時

###いるもの
- mac
- iPhone
- Fiddler Everywhere
- 確認したいアプリ

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [FiddlerEverywhereのインストール](#fiddlereverywhereのインストール)
1. [FiddlerEverywherの設定](#fiddlereverywhereの設定)
1. [iPhoneの設定](#iphoneの設定)
1. [確認](#確認)

<a id="#インストール"></a>
# FiddlerEverywhereのインストール
FiddlerEverywhereをインストールしてください


https://www.telerik.com/download/fiddler-everywhere

<br><a id="#FiddlerEverywhereの設定"></a>
# FiddlerEverywhereの設定
- HTTPS -> Capture HTTPS traffic にチェックを入れる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/30fb160f-514f-e59d-8560-c0a3294a733a.png" width=60%>
- Connentions -> Act as system proxy on startupとAllow remote computers to connectにチェックを入れる<br>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/9b683d7a-6767-074d-0178-615cb3658f9c.png" width=60%>
<br>


<a id="#iPhoneの設定"></a>
# iPhoneの設定
- macとiPhoneを同じWi-Fiに接続する
- プライベートIPアドレスを調べる<br>`$ networksetup -getinfo Wi-Fi`で調べられます
- 設定 -> Wi-Fi から接続中のWi-Fiを選択しプロキシを構成<br>サーバのところはプライベートIPアドレスを入力してください<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/5cf448e6-f416-6c1f-8d3e-8be075b77e58.png" width=30%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/565b4f4c-d5d2-c211-0889-7134f80612ec.png" width=30%>
- iPhoneのsafariから`ipv4.fiddler:8866`にアクセスしFiddlerRoot certificateからプロファイルをダウンロード<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/dbd64e70-9c0a-05bf-856d-2626ecc936aa.png" width=30%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/0d326b04-f150-71ca-2933-95376c455695.png" width=30%>
- 設定 -> 一般 -> プロファイル からダウンロードしたプロファイルを許可
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/9334ee5c-51f9-89c4-a704-7e6326b9ace2.png" width=30%>

<a id="#確認"></a>
# 確認
- 適当なネイティブアプリを開く<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/a0ae8bcd-b0bc-2158-ad32-dc2094c3f98b.png" width=30%>
- Fiddlerにキャプチャが表示されていればOKです<br>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/8df73e05-170c-c20c-1cb8-dc900893a9df.png" width=30%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/22e4cbf8-ddd6-1221-8e81-b9c3d55f06ad.png" width=20%>
- webViewで表示されていたページをブラウザから開くことができました<br><img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1237483/0e0d9624-58ce-121d-fa0e-1ba2cf0477a9.png" width=20%>
スコープについて　Python競プロメモ③

使用言語　Python3

```
def vertical(aa,bb):
    num = aa + bb
    return num

num = 5
vertical(1,2)
print(num)

=>3
  5
```
上のようなコードの場合、def内にあるnumはlocalな変数のため、def外になると適用されない。そのため、vertical(1,2)では3を返すが、print(num)ではglobalな変数である5を返す。

次に、def内にあるnumをglobalな変数にしてみるとどうなるかを書く。

```
def vertical(aa,bb):
    global num
    num = aa + bb
    return num

num = 5
vertical(1,2)
print(num)

=>3
  3
```
このコードを上から順にみていくと、
①まずnum = 5が代入される
②vertical(1,2)が実行され、num = 3が新たに代入され、numが返される。
③print(num)により、②で代入されたnumが返される。

こういう手順を踏むので、先ほどのコードの結果とは異なったものが返されるというわけである。
【Flutter】スプラッシュ画面を実装してみる【flutter_native_splash】

##本記事で行うこと。

1. flutter_native_splashを導入する
2. pubspec.yamlファイルを設定する
3. スプラッシュ画面を作成する

##1. flutter_native_splashを導入する

### そもそもスプラッシュ画面とは？

アプリを起動すると、起動画面を表示するまでに少し時間がかかります。
その起動画面が表示するまでの時間に表示される画面がスプラッシュ画面です。
デフォルトだと、読み込んでる間は白背景、つまり白いスプラッシュ画面が表示されます。
Flutter製アプリの実装では、スプラッシュ画面を作る手段の一つとして、
**flutter_native_splashパッケージ**があります。
とても簡単に実装できたので、オススメです。
パッケージを使わなくても、スプラッシュ画面を作ることができるみたいです。

### flutter_native_splashを導入する。

https://pub.dev/packages/flutter_native_splash

```pubspec.yaml
dependencies:
  flutter_native_splash: ^1.1.5+1
```

pubspec.yamlファイルのdependenciesに記述した後、
pub getを行うの忘れないようにしましょう。
これで、導入は完了です。

##2. pubspec.yamlファイルを設定する

今回のパッケージはdartファイルにインポートせずに使用することができます。
インポートの代わりに、pubspec.yamlファイルに設定を記述する必要があります。
画像と背景色を設定していきます。

```pubspec.yaml

～～～～～～
dependencies:
  flutter_native_splash: ^1.1.5+1

flutter_native_splash: //インデント注意
  image: "images/splash.png"  //表示したい画像
  color: "FAF3F3"  //背景色、カラーコードで指定

dev_dependencies:
  flutter_test:
    sdk: flutter

～～～～～～

```

これで設定は完了です。

##3. スプラッシュ画面を作成する

最後にflutterコマンドを使用して、設定した内容でスプラッシュ画面を作成します。

```
$ flutter pub run flutter_native_splash:create
```

これで作成できました、動作確認してみましょう。

![splash.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463548/39900b3e-1aa4-ca94-0db6-69cc5c0e4df5.gif)

これで、スプラッシュ画面を実装することができました。
定期的にネットワーク速度を計測してスプレッドシートにまとめる part1

## できたもの
こんな感じで1時間ごとに自宅のネットワーク速度を計測してGoogleスプレッドシートにまとめてくれるようになりました。

![スクリーンショット 2021-03-25 0.03.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354517/ea45b82d-9bc4-a01d-6592-440d1ff7fa6a.png)

ネットワーク計測とGASにPOSTをリクエストするスクリプトの作成とGASでウェブアプリの作成が主な作業内容です。

下記を参考に作成しました。

https://qiita.com/tomatosum/items/40cc34015b1aa96bfc63

## ネットワーク速度の計測
pythonのツールであるspeedtestを使用して計測します。

https://github.com/sivel/speedtest-cli

まずはインストールします。

```bash
$ pip install speedtest-cli
```

これで計測できるようになりました。
下記が例です。

```bash
$ speedtest --simple
Ping: 10.21 ms
Download: 83.54 Mbit/s
Upload: 90.17 Mbit/s
```

## 速度計測用スクリプトの作成
後々、GASにPOSTすることも考慮して、スクリプトを作成します。
下記が作成したスクリプトです。
速度の計測に失敗した場合は3回までリトライするようにしています。

```bash:test.sh
#!/bin/bash
########################################
# スピードテスト用スクリプト
#
#
########################################

# スピードテストコマンド
command="/opt/anaconda3/bin/speedtest --simple"

########################################

echo "Start speed test!"

NEXT_WAIT_TIME=0
until RET=`$command` || [ $NEXT_WAIT_TIME -eq 3 ]; do
  # リトライ回数×60秒後にリトライ
  sleep $(( (NEXT_WAIT_TIME++) * 60 ))
done

echo $RET

echo "End speed test!"
```

スクリプトを実行できるようになりました。

```bash
$ sh test.sh 
Start speed test!
Ping: 13.226 ms Download: 88.75 Mbit/s Upload: 5.55 Mbit/s
End speed test!
```

## 最後に
コマンドでネットワーク速度を計測できるようになったところで part2 に続きます。

https://qiita.com/amatsukix/items/a4af7e956c88762e988f

## 参考
https://qiita.com/yokobonbon/items/67deb3fab84b0c0954e0
Power Automate Desktop お試しメモ（随時更新）

# 概要

話題になったPowerAutomate Desktop for Windows10を試し、各種機能でわかったことを以下にまとめました。

# Webオートメーション

- アドオンがインストールされていないブラウザを起動すると「`Chrome を制御することができませんでした (ブラウザーとの通信が失敗しました。アドオンがインストールされていることを確認してください)。`」が表示される
- ボタン、リンクを指定しても指示通りに動作しない  
  Webレコーダ機能で作ると認識されることがある

# UIオートメーション

- Windowsアプリケーションの操作は「ウインドウのUI要素をクリックする」のほうが安定する  
  マウスを実際に操作するようになるため、動作の再現度が高い
- 古いアプリケーション（WPFじゃないアプリ？）だとUI要素として認識されない
- UI要素のセレクターが開くたびに変化することがあります。その場合は、「*」で指定することで認識できることがある

# そのほか

- 現時点、作成したフローをエクスポートできない

## フローの共有

作成したフローを共有する方法は以下になります。

- 同一ログインユーザであれば、異なるPCでフローが自動共有される
- 作成中のフローをコピー→クリックボード→ペーストで他人に渡すことができる  
  ただし、まだUI要素の渡し方がわからない
DonkeyCarを自動運転ドローンにする<方針＆目標設定>

#0.目的
DonkeyCarをベースに自動運転が行えるドローンの製作を目指します。
その製作の過程など自身の記録も含めて残せれたらと思います。

#1.ドローンの選定
今回使用するドローンは、RYZEのTelloにしました。
理由としては、製品としての完成度はもちろん、価格も約13000円と手ごろでサイズも小さく、これなら家の中でも実験が行えそうです。そして、一番の理由は、SDKが用意されているからです。
今回は、このSDKを利用してRapsberryPiからTelloを制御しようと思います。

#2.システム構成
Telloは、本体自体にプログラムを書き込む訳ではなく、外部からwifi経由で動作指示を行い制御するので、コントローラ自体は、何処にあっても良いのですが、今回はスタンドアローンで動作することを目標にします。また、ドローンやるのでFPVも出来るようにしようと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378484/8aed0459-2a08-aa15-57dc-8a25a4abf513.png)

#3.制御対象について
平面の移動であれば、標準DonkeyCarのように、スロットルとステアリングの二つの制御値を使えば可能です。さらに、アクチュエータ部を改造し、メカナムホイールを使った機体であれば、前後・左右・回転の三つの制御値を使うことも可能です。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">メカナムホイールで自動運転！曲がり方が独特！<a href="https://twitter.com/hashtag/DonkeyCar?src=hash&amp;ref_src=twsrc%5Etfw">#DonkeyCar</a> <a href="https://twitter.com/hashtag/RaspberryPi?src=hash&amp;ref_src=twsrc%5Etfw">#RaspberryPi</a> <a href="https://twitter.com/hashtag/%E3%83%A1%E3%82%AB%E3%83%8A%E3%83%A0%E3%83%9B%E3%82%A4%E3%83%BC%E3%83%AB?src=hash&amp;ref_src=twsrc%5Etfw">#メカナムホイール</a> <a href="https://t.co/m8Lb3S5S3U">pic.twitter.com/m8Lb3S5S3U</a></p>&mdash; taigamaru (@taigamaru1) <a href="https://twitter.com/taigamaru1/status/1346427277182046209?ref_src=twsrc%5Etfw">January 5, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

さらにドローンでは、上下動作も可能なため、上下・前後・左右・回転の四つの制御値を使って操作・自動運転できるようにします。コースは、輪っかをくぐるようなものにしてみようかと考えています。

#4.目標
その１：スタンドアローンで動作すること
その２：FPVで操作できること
その３：上下・前後・左右・回転の四つの制御値を使って操作・自動運転できること
Oracle Cloud Infrastructure で Always Free のコンピュート・インスタンスを作成できない時は

## 問題
Oracle Cloud Infrastructure で Always Free コンピュート・インスタンスを作成できない。

## 回避策
Oracle Cloud Infrastructure（以後「OCI」と記述）に、別のブラウザで接続してみましょう。

## 説明
ここでは、OCI Free Tier への申込みからログイン、仮想クラウド・ネットワーク（VCN）の作成までの手順は省略します。OCIホーム・リージョンは「Japan East (Tokyo)」、接続クライアントのOSには「Windows 10 Pro (64-bit)」を使用しました。
（以下のスクリーンショットは、2021年3月24日に取得しました。）

ブラウザは、OCI推奨の「Google Chrome」でログインしています。
コンソール左上のハンバーガーメニューから「コンピュート」→「インスタンス」を選択します。必要であれば左側メニューの中ほどにある「コンパートメント」を選択して、「インスタンスの作成」ボタンを押します。
「コンピュート・インスタンスの作成」ウィンドウが開きますが、なぜか「イメージ」と「シェイブ」が非選択になっています。
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/333ab235-cfc8-43de-4b34-3a75d2cdffad.png)

右上の「編集」リンクを押します。イメージ欄に、問題が発生しました、とエラー表示されています。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/23bca50a-7551-8c89-7860-934d36478360.png)

「イメージの変更」ボタンを押します。現在のシェイブと互換性のあるイメージ・ビルドがありません、と警告表示されています。「イメージの選択」ボタンは押せますが、実際は選択されません。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/5bb45ff8-28f2-798a-a00e-e791a84d10c3.png)

「コンピュート・インスタンスの作成」ウィンドウにもどって、「シェイブの変更」ボタンを押します。
「仮想マシン」と「専門と前世代」を選択します。シェイブの欄に Always Free 対象の「VM.Standard E2.1 Micro」が表示されていますが、該当行のチェックボックスが Disabled 状態であるため、選択できません。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/5194d730-8cd7-3c0f-113f-53a590edbd7a.png)

結局、「イメージ」と「シェイブ」を選択できないので、コンピュート・インスタンスを作成できませんでした。当初 Always Free のリリース時、アクセスが集中してリソース不足になったと聞いていましたので、数日待ってみましたが、状況は何も変わりませんでした。

では、「Microsoft Edge」でログインしてみましょう。
ブラウザがサポートされていないとメッセージが表示されます。けれどChromiumベースのEdgeだったら、たぶん大丈夫でしょう。（SafariもFirefoxも試していません。）
「現在のブラウザで続行」リンクを押します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/f12ffd46-3eff-bbaa-00bb-e882ac37bd25.png)

上記と同じ手順で、「コンピュート・インスタンスの作成」ウィンドウが開きます。こんどは「イメージ」と「シェイブ」が選択されています！
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/330eb1da-840e-b0c0-7725-a1b81ac398d8.png)

右上の「編集」リンクを押します。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/2a853b31-cf0f-d357-5ac9-fed9695e97e8.png)

「イメージの変更」ボタンを押します。Oracle Linux 8 も選択できます。
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/03cb1ff2-aed1-3915-55ac-be0ae89585a4.png)

「シェイブの変更」ボタンを押します。Always Free の場合、他の選択肢はないようですが、該当行のチェックボックスが Enabled 状態になっています。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1234050/fb30447f-499b-debb-b6ba-49a9bb237fed.png)

あとは通常の手順で、コンピュート・インスタンスの作成を進めることができました。

原因はよくわかりません。私のクライアントPCの問題かもしれません。
OCIは、インターフェース等がいつの間にか変わっていたりするので、この問題も、ふと気づいたときには発生しなくなっているかもしれないですね。
[Rails] simple_calendarでデフォルトの属性名”start_time” 以外の属性を使用する場合。

`simple_calendar` を導入し、view、controllerを作成している前提です。
[simple_calendar導入方法](https://qiita.com/isaatsu0131/items/ad1d0a6130fe4fd339d0)

デフォルトでは `start_time` のみが属性名として使用されます。
それ以外の属性名を使用したい場合は、 `attribute: :開始時間の属性名, end_attribute: :終了時間の属性名` を `events:` の後に続けて追記します。

以下は、 `start_at` `end_at` に属性名を設定した例です。

```:views/blogs/index
<%= month_calendar events: @blogs, attribute: :start_at, end_attribute: :end_at do |date, blog| %>
  <%= date.day %>
   ...

<% end %>
```
Rustにおけるタプルにアクセスするする方法

# 概要
* Rustのタプル型にアクセスする場合、２通りのアクセス方法があります。
* ちなみにタプル型とは、下記のような複数の型の値を一つの複合型にまとめものです。

```Rust
fn main() {
    let tup: (i32, f64, u8) = (100, 1.2, 3);
}
```

## パターンマッチングを使用してのアクセス
* 下記にパターンマッチングを使用した時のアクセスしたものです。

```Rust
fn main() {
    let tup = (100, 1.2, 3);
    let (x, y, z) = tup;

    println!("{}", y);
}
```


## ピリオドを使用してのアクセス
* アクセスしたい値の番号をピリオド(.)の後ろに書くことで、タプルの要素に直接アクセスすることができます。

```Rust
fn main() {
    let x: (i32, f64, u8) = (100, 1.2, 3);

    let one_hundred = x.0;

    let one_point_two = x.1;

    let three = x.2;
}
```

# 参考文献
* [THE BOOK 3章](https://doc.rust-lang.org/book/)
ポインタと値の覚え方


新人の頃、なかなか覚えられない私にベテランが教えてくれた覚え方です。
C言語を勉強している方の助けになれば、うれしいです。

   * &　(<font color="red"><strong>ア</strong></font>ンパサン<font color="red"><strong>ド</strong></font>)・・・ アドレス

   * ＊　(<font color="red"><strong>ア</strong></font>ス<font color="red"><strong>タ</strong></font>リスク) ・・・ 値
Rustにおけるスカラー型と複合型

# スカラー型
Rustにおけるスカラー型は4つあります。

* 整数
* 浮動小数点数
* 論理値
* 文字

## 整数

|大きさ|符号付き|符号なし|
|----|----|----|
|8-bit|i8|u8|
|16-bit|i16|u16|
|32-bit|i32|u32|
|64-bit|i64|u64|
|arch|isize|usize|

* 例えば**u32型**の場合、符号なし整数になるので、32ビット分のサイズを取ります。
* ちなみに符号付きと符号なしは、数値が正負どうかを示します。
* **isize型**と**usize型**は、プログラムが動作しているコンピュータの種類に依存します。
* 64ビットアーキテクチャの場合、64ビットになります。
* 32ビットアーキテクチャの場合、32ビットになります。

## 浮動小数点数
* Rustの浮動小数点型は、**f32型**と**f64型**の２つです。
* 基準型は**f64型**です。

### f32型
* f32型は、単精度浮動小数点数で、32ビットです。

### f64型
* f64型倍精度浮動小数点数で、64ビットです。

## 論理値
* Rustの論理値型は、**true**と**false**の２つです。

例: 

```Rust
fn main() {
    let f: bool = false;
}
```

## 文字
* Rustの文字は、**char型**です。
* char型は、ユニコードのスカラー値を表します。
* そのため、アクセント文字、中国語、日本語、韓国語、絵文字、ゼロ幅スペースは有効なchar型になります。

# 複合型
* 複合型とは、複数の値を一つの型にまとめることができます。
* 複合型には、2種類の複合型があります。

## タプル型
* タプル型は、複数の型の値を一つの複合型にまとめ上げるものです。
* ()の中にカンマ区切りの値のリストを書くことで生成します。

例:

```Rust
fn main() {
    let tup: (i32, f64, u8) = (500, 6.4, 1);
}
```

* またタプル型からパターンマッチングを使用して、個々の値を取り出すことができます。

例:

```Rust
fn main() {
    let tup = (500, 6.4, 1);
    let (x, y, z) = tup;

    println!("{}", y);
}
```

[実行結果]

```
❯ cargo run                
   Compiling variables v0.1.0 (/Users/yoshitaka.koitabashi/Desktop/variables)
warning: unused variable: `x`
 --> src/main.rs:3:10
  |
3 |     let (x, y, z) = tup;
  |          ^ help: if this is intentional, prefix it with an underscore: `_x`
  |
  = note: `#[warn(unused_variables)]` on by default

warning: unused variable: `z`
 --> src/main.rs:3:16
  |
3 |     let (x, y, z) = tup;
  |                ^ help: if this is intentional, prefix it with an underscore: `_z`

warning: 2 warnings emitted

    Finished dev [unoptimized + debuginfo] target(s) in 1.42s
     Running `target/debug/variables`
6.4
```

* ただ、実行した結果を見てわかるように、使用していない値に関しては**_**を付けてと怒られるので、正しく使うなら下記のようになります。

```Rust
fn main() {
    let tup = (500, 6.4, 1);
    let (_x, y, _z) = tup;

    println!("{}", y);
}
```

[実行結果]

```
❯ cargo run
   Compiling variables v0.1.0 (/Users/yoshitaka.koitabashi/Desktop/variables)
    Finished dev [unoptimized + debuginfo] target(s) in 0.22s
     Running `target/debug/variables`
6.4
```

* この例では、まずタプルを生成し、それを変数tupに束縛しています。
* その後、**let**とパターンを使ってtup変数の中身を3つの個別の変数(x、y、z)に変換しています。

=> この過程を**分配**と呼びます。

## 配列型

* 配列型は、複数の値のコレクションを得ることができます。
* 配列の全要素は、同じ型でなければならない。
* またRustの配列は固定長の為、一度宣言されたらサイズを伸ばすことも縮めることもできません。
* Rustでは、配列に入れる要素は[]内にカンマ区切りのリストとして書きます。

例:

```Rust
fn main() {
    let a = [1, 2, 3, 4, 5];
}
```

* 配列は、スタック上に確保されるメモリの為、添え字によって配列の要素にアクセスすることができます。

```Rust
fn main() {
    let a = [1, 2, 3, 4, 5];

    let first = a[0];
    let second = a[1];
}
```

# 参考文献
* [THE BOOK 3章](https://doc.rust-lang.org/book/)
(JS) 　Strorageオブジェクトでストレージデータを保存する

#はじめに
Webアプリでは、クッキーを利用することで、クライアントに対して、小さなデータ（テキスト）を保存することができます。
しかし、JavaScriptでは、クッキーを操作しにいので、代わりにWebStorageを利用し、データを保存することがおすすめです。
ストレージは、データを特定するキーと値の組み合わせで保存されます。

#ストレージにデータを保存する
``` storageData.js
  // localStorageプロパティの戻り値を変数に格納
  let storage = localStorage;
  // 保存方法①
  storage.setItem('lang1', 'JavaScript');
  // 保存方法②
  storage.lang2 = 'PHP';
  // 保存方法③
  storage['lang3'] = 'Ruby';

  // 取得方法①
  console.log(storage.getItem('lang1'));  //JavaSciript
  // 取得方法②
  console.log(storage.lang2); //PHP
  // 取得方法③ 
  console.log(storage['lang3']); //Ruby
```

上記のようにデータの保存や取得は、複数あります。
ストレージの内容は、ブラウザの開発者ツールの[Application]タグの[Local Storage]から確認することができます。
![set/get data](https://i.gyazo.com/8a5bf52e45fced52a0cc788e1b2aa193.png)

#データを削除する
```storageData.js
  //削除方法①
  storage.removeItem('lang1');
  //削除方法②
  delete storage.lang2;
  //削除方法③
  delete storage['lang3'];
```

![delete data](https://i.gyazo.com/8a5bf52e45fced52a0cc788e1b2aa193.png)
また、clearメソッドを使うことで、データを全て削除することができます。

``` storageData.js
 //全てのデータを削除
 storage.clear();
```

#ストレージにオブジェクトを保存/取得する
ストレージに保存できるのは、基本的には文字列です。文字列の方法でオブジェクトを保存してしまうと、内部的に文字列化されてしまうので、のちにオブジェクトとして復元することができなくなってしまいます。
オブジェクトを復元できる形でストレージに保存したい場合は以下のように行います。

```storageData.js
  // localStorageプロパティの戻り値を変数に格納
  let storage = localStorage;

  //profileオブジェクト生成
  let profile = {name: 'Tom', age: 23, height: 180};
  
  //オブジェクトを復元可能な文字列に変換する。
  storage.setItem('profile',JSON.stringify(profile));

  // 文字列をJSON.parseメソッドに渡す
  let data = JSON.parse(storage.getItem('profile'));

  console.log(data.age) //23
```

![set ObjectData](https://i.gyazo.com/d00df2574dcc28aa306e6fe9a9c09cf2.png)

__JSON.stringifyメソッド__を使い、保存することで、内部的に文字列にされたとしても、オブジェクトのような記法で書かれた文字列になるので、復元が可能になります。
データを取得する時は、__JSON.parseメソッド__に文字列を渡すことで、文字列からオブジェクトに復元します。

上記の仕組みをクラスとして準備すれば、オブジェクトの変換をあまり意識せずにオブジェクトを保存/取得することができるのではないでしょうか。
RubocopがCircleCI上でのみエラーになる事象について

# 事象
ローカルでは問題なくrubocopを実行できたのですが、
Githubにプッシュ、CircleCI上でrubocopを実行すると以下のようなエラーが起きました。

```
#!/bin/bash -eo pipefail
mkdir -p /tmp/rubocop-results
bundle exec rubocop . --out /tmp/rubocop-results/check-results.xml --format progress
/home/circleci/electronote/.rubocop.yml: Warning: no department given for AsciiComments.
404 "Not Found" while downloading remote config file http://shopify.github.io/ruby-style-guide/rubocop.yml
/usr/local/lib/ruby/2.7.0/net/http/response.rb:124:in `error!'
```


# 結論

### 原因
ローカルとCIで、bundle installのインストール先パスが異なることが原因でした。

ローカル：
/usr/local/bundle

CI：
{プロジェクトディレクトリ}/vendor/bundle

CIではプロジェクトディレクトリ下にインストールされるため、
rubocop実行時に、このディレクトリ内にある.rubocop.ymlを読み込んでいたものと思われます。

### 対策
vendorディレクトリをrubocopのチェック対象外に追加すると解決しました。

```project_dir/.rubocop.yml
inherit_from: .rubocop_todo.yml

AllCops:
  Exclude:
    - 'db/**/*'
    - 'node_modules/**/*'
    - 'bin/*'
    - 'log/**/*'
    - 'public/**/*'
    - '.git/**/*'
    - 'tmp/**/*'
    - 'vendor/**/*'
```

# 解決までに試したこと
いずれも効果ありませんでしたが、以下の方法を試してみました。

### (1) CircleCI設定ファイル書き換え

#### 変更前:

```.circleci/config.yml
version: 2.1
orbs:
  ruby: circleci/ruby@1.1.0
  ...

jobs:
  test:
    ...
    steps:
      ...
      - ruby/rubocop-check
      ...
```

#### 変更後:

```.circleci/config.yml
version: 2.1
orbs:
  ruby: circleci/ruby@1.1.0
  ...

jobs:
  test:
    ...
    steps:
      ...
      - run:
          name: Rubocop check
          command: bundle exec rubocop
      ...
```

#### 結果:
変化なし

### (2) 不要なrubocop.ymlをコメントアウト

上述のエラー文を見ると、

```
404 "Not Found" while downloading remote config file http://shopify.github.io/ruby-style-guide/rubocop.yml
```

**「何でshopifyが出てくんねん！」**

となったので、このURLがどこから湧いて出てきたのか調べてみました。

```bash

$ grep -r http://shopify.github.io/ruby-style-guide/rubocop.yml ./*
./vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.5/.rubocop.yml:#   - http://shopify.github.io/ruby-style-guide/rubocop.yml
```

どうやらbootsnap-1.4.5のディレクトリにもRubocopの設定ファイルがあり、そこで呼び出されているらしい。
というわけで、呼び出している箇所をコメントアウト。

#### 変更前:
```project_dir/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.5/.rubocop.yml
inherit_from:
  - http://shopify.github.io/ruby-style-guide/rubocop.yml

AllCops:
  Exclude:
    - 'vendor/**/*'
    - 'tmp/**/*'
  TargetRubyVersion: '2.2'

...
```



#### 変更後:
```project_dir/vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.5/.rubocop.yml
# inherit_from:
#   - http://shopify.github.io/ruby-style-guide/rubocop.yml

AllCops:
  Exclude:
    - 'vendor/**/*'
    - 'tmp/**/*'
  TargetRubyVersion: '2.2'

...
```

変更してからCI環境にSSH接続し、rubocopを実行。

参考：
https://qiita.com/yu-croco/items/41d2114c94e3a6ea748a

#### 結果:
何か違うエラーが出てきた😇

```
$ bundle exec rubocop
/home/circleci/electronote/.rubocop.yml: Warning: no department given for AsciiComments.
Error: The `Lint/HandleExceptions` cop has been renamed to `Lint/SuppressedException`.
(obsolete configuration found in vendor/bundle/ruby/2.7.0/gems/bootsnap-1.4.5/.rubocop.yml, please update it)
```


### (3) vendorディレクトリをrubocopのチェック対象外に追加

上述の通り、上手く動きました。
めでたしめでたし。

# 参考

CircleCIでのみrubocopがエラーになる
https://qiita.com/kabi5/items/40ea864757162e931be1