OmniAICreator/Qiita-1.07M huggingface dataset:
[GAS]DiscordにTwitterの投稿通知を投げる

# ■実現したいこと

- discordのコミュニティ内で、特定の複数Twitterアカウントのツイート通知をdiscordに流したい
- 無料が良い
- なるべくオンタイムで通知してほしい
- コードでもGUIでも特に指定なし

# ■処理サマリー

1. twitter-apiのセットアップ
2. 取得したBearerTokenを使用してリクエスト
3. データがあればDiscordに通知を投げる

# ■事前準備

### GASについて調べた

- 定期実行のやり方
    - コード記載
    - 左側時計アイコン(トリガー) > トリガーを追加 > 呼び出したい処理を選択＆実行間隔選択
- test実行
    - デプロイではなく、デプロイをテストで処理をテスト実行出来る

# ■内容

## 1. Twitter API キーの取得

以下記事を参考に。

[https://di-acc2.com/system/rpa/9688/](https://di-acc2.com/system/rpa/9688/)

## 2. authentication 設定

### 2-1. developer.twitter.comのdashboard画面の**User authentication settings**で認証の設定をする

- callbackUrl
    - https://script.google.com/macros/d/[SCRIPT_ID]/usercallback
- WebsiteUrl & Terms of service & Privacy policy
    - 自分のTwitterのプロフィールページ

### 2-2. 発行されたBarerTokenをコピーする

## 3. コードをコピペする
[こちら](https://github.com/91works/DiscordTwitterNotificationBot)にコードが載ってます。

# ■詰まりポイント

### 最初はTwetterWebService + OAuth1の記事を参考に実装してたが、よくわからんエラーが頻発して諦めた

- [こちらの記事](https://kanoe.studio/archives/1460)を参考に最初試した
- が、API自体が結構updateかかってるから？サクッといかなかったので別のアプローチで実現した

### Tweet検索時のreply&retweetの弾き方がぱっと見わからなかった

- [https://developer.twitter.com/en/docs/twitter-api/tweets/search/integrate/build-a-query](https://developer.twitter.com/en/docs/twitter-api/tweets/search/integrate/build-a-query)

> Matches on Retweets that match the rest of the specified rule. This operator looks only for true Retweets (for example, those generated using the Retweet button). Quote Tweets will not be matched by this operator.
> 
> Example: data @twitterdev -is:retweet
> 
- githubのissueの検索とかと同様で、-をつけるつけないで切り替えられるのに気づくのに時間がかかった

# ■参考にしたサイト
- リクエスト関連のヒント
    - https://zenn.dev/specially198/articles/54d0b957f185b8
- discord投稿関連
    - https://qiita.com/Eai/items/1165d08dce9f183eac74

# 最後に

背景としては・・

- 自社でやっているdiscordサーバーに自社に関連するメンバーのTweet通知を飛ばしたいなと思ったから
- 話のネタにもなるし、コミュニケーションを活発させる1つの材料になったらなと

って思ってサクッと実装しようと思いました。
ビルド構成によりプログラムを切り替える(Visual Studio)

# 環境
Visual Studio2019
Windows10
C++
# プリプロセッサ定義
* **プロジェクトを選択し、右クリックから「プロパティ」を選択**
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368850/0225e05a-afc3-3573-7ca2-bac18702c89c.png)

* **プロジェクトのプロパティから、設定したいビルド構成を選択**
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368850/87dd49ae-9ee2-4a50-910f-62b640175b6e.png)

* **C/C++→プリプロセッサ→プリプロセッサの定義→編集を選択**
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368850/582e87d8-6410-6f62-558a-18d3ddb2ddfd.png)

* **プリプロセッサ定義を編集**
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368850/9c7ab6e2-9092-3dc2-bc3a-2859e97a2445.png)

* **#ifdefで**
```C++
//Debugの時
#ifdef _DEBUG
	std::cout << "Debugです。" << std::endl;
#endif

//Releaseの時
#ifdef _RELEASE
	std::cout << "Releaseです。" << std::endl;
#endif
```
【備忘録】Node.jsをバックグラウンドで動かす方法

# はじめに
node.jsをバックグラウンドで動かすための方法を調べたので未来の自分のためにも書き残しておきます。

# 方法① foreverモジュールを使う
以下のコマンドでインストール
```console
sudo npm install -g forever
```
実行
```
forever start hoge.js
```
プロセスの起動を確認
```
forever list
```

# 方法② Dockerコンテナ化する
jsファイルがあるディレクトリに移動してDockerfileを作成。中身に以下の内容を書く。
```Dockerfile
FROM node:16-alpine3.15
WORKDIR /app
COPY . .
RUN npm install
CMD ["node", "hoge.js"]
```
ビルドする。ここではラズパイ上でdockerコンテナを稼働させることを想定しています。ラズパイで使いたいイメージは、ビルド時にプラットフォームを明示しておかないとうまく動作しない可能性があるので「--platform」を使う。
```docker
docker build --platform linux/arm64/v8 -t hogeimage .
```
コンテナを稼働させる。
```
docker run -dit --name (任意のコンテナ名 ) hogeimage:latest
```
dockerを使うことでバックグラウンドで動かすことができました。

# さいごに
状況に応じて使い分けるといいです。foreverは導入が楽ですが、稼働させたいサーバにフォルダ丸ごと持っていく必要があったため、あまりスマートなやり方じゃないなあと感じました。
【Ruby on Rails】Rspec, Factorybot等の導入

# Rspecのinstall

基本的には、document通りやる。
https://github.com/rspec/rspec-rails


```Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 6.0.0'
end
```

```
bundle
```

```
rails generate rspec:install
```

# Factorybotのinstall

```Gemfile
group :development, :test do
  gem 'factory_bot_rails'
end
```

```rails_helper.rb
Rspec.configure do |config|
...
  config.include FactoryBot::Syntax::Methods
end
```
これで、createでfactorybotが呼ばれる

factoryを作成するのは、

```
rails g factory_bot:model user
```
Rのdplyr::filterを使って 行名 rownameでフィルターをかける場合

data_frameというデータフレームがあり、a1, b1という行名のみのデータフレームを表示したい場合、以下のようにする。

```R
data_frame %>% dplyr::filter(row.names(.) %in% c("a1", "b1"))
```
row.names(.)の　”.” を忘れないように。
RockyLinux8 vps環境設定4) 時間設定の変更

RockyLinux8 vps環境設定3) 他のサーバとのssh接続
https://qiita.com/naga_kt/items/f887ee7f71453ac25255
の続き。WebArena Indigo(RockyLinux8.4)及びKagoya(RockyLinux8.5)での環境設定について述べる。

　Kagoya(RockyLinux8.5)では、デフォルトがJST時間である。
　
　WebArena Indigo(RockyLinux8.4)では、デフォルト設定のままではUTC時間である。

~~~linux
$date
Wed Dec 15 23:42:06 UTC 2021
~~~

　不便なのでJSTに変えておく。
　ここでUTC時間なのはdateだけでなくて、cronもUTC時間で動いている。同時に変える必要がある。

## タイムゾーンの変更

　時間設定の変更は以下のようにして行なう。/etc/localtimeのリンク先を変えることで、タイムゾーンを変更すればいい。

~~~linux
#cd /etc/
#ls -lrt localtime
lrwxrwxrwx. 1 root root 25 Oct  5  2018 localtime -> ../usr/share/zoneinfo/UTC
#ln -sf  /usr/share/zoneinfo/Asia/Tokyo localtime
#ls -lrt localtime
lrwxrwxrwx. 1 root root 30 Dec 16 08:54 localtime -> /usr/share/zoneinfo/Asia/Tokyo
#date
Thu Dec 16 08:54:29 JST 2021
~~~



## cronの時間設定の変更

　以下も行なってcornの時間設定も変更する。

~~~linux
#service crond restart
Redirecting to /bin/systemctl restart crond.service
#service rsyslog restart
Redirecting to /bin/systemctl restart rsyslog.service
~~~

　cronのログは/var/log/cronに吐き出されているが、crondだけでなく、rsyslogも再起動することで、ログにJSTで吐き出されるのを確認することができる。


---

RockyLinux8 vps環境設定5) Swapの設定
https://qiita.com/naga_kt/items/a8649ea8da7303a7e6a6
に続く。

---

### 参考記事

CentOS
Amazon Linuxでタイムゾーンを変更してcronの実行時刻にも反映させる
https://qiita.com/owlbeck/items/b8379971890edb755cac

CentOS
Cronがutcで動いてる場合に
http://yoshitsugufujii.github.io/blog/2016/02/03/change-crons-timezone/
S3について

## S3とは？
**安価で耐久性が高いAWSのクラウドストレージ**
  - 1GBで約3円/月(0.023USD/GB・月)
  - 容量無制限。１ファイルは5TBという制限あり
  - バケットやオブジェクトにアクセス制限を設定できる
## よく使われる単語
  - **バケット**
    - オブジェクトの保存場所。名前はグローバルでユニーク
  - **オブジェクト**
    - データの本体(保存するファイルなど)
    - 格納するとURLが付与される
    - バケット内のオブジェクト数は無制限
  - **キー**
    - 付与されたURLのパス
## よくある利用シーン
  - **静的コンテンツの配信**
    - 画像をS3から配信する
  - **バッチ連携用のファイルを置く**
    - S3にファイルを置いて、バッチでそのファイルを参照して処理を行う
  - **ログなどの出力先**
    - 定期的にS3にログを送る
  - **静的ウェブホスティング(静的なウェブサイトを公開すること)**
    - S3から直接公開できる
## Webサーバーではなく、S3を使う理由
  - WEbサーバーのストレージが画像でいっぱいになるのを防ぐ
  - HTMLへのアクセスと画像へのアクセスを分けることで負荷を分散する
  - サーバーの台数を増やしやすくする
    - webサーバーを増やしたときに画像を同期する必要が出てくる(スケールアウトが難しい)
  - コンテンツ配信サービスから配信することで画像配信を高速化できる
    - 画像をキャッシュできるため
【Ruby on Rails】rails newコマンドについて

# PostgreSQLでrails newしたい場合

```
rails new <appname> -d postgresql
```

# Dockerでrails newする場合

まずはDockerfileを作成。

```Dockerfile
FROM ruby:2.7
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs npm postgresql-client
RUN npm install --global yarn
RUN mkdir /myapp
WORKDIR /myapp
ADD Gemfile /myapp/Gemfile
ADD Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
ADD . /myapp

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 4000
CMD ["rails", "server", "-b", "0.0.0.0"]
```

ドキュメントの内容をversion以外そのまま。
https://docs.docker.jp/compose/rails.html

次にGemfileを。
```Gemfile
source 'https://rubygems.org'
gem 'rails', '6.1.6.1'
```

空のGemfile.lockを作成
```
touch Gemfile.lock
```

最後にdocker-compose.ymlを作成
```docker-compose.yml
version: '3.9'
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 4000 -b '0.0.0.0'"
    stdin_open: true
    tty: true
    volumes:
      - .:/myapp
    ports:
      - "4000:4000"
    depends_on:
      - db
```

```:entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /cuon_cms/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

rails newをする。
```
docker-compose run web rails new . --force --database=postgresql
```

雛形ができるが、DBの設定がまだなので、行う。
```config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test
```

docker compose upを実行したときに、
webpackerのエラーが出たら、
```
docker-compose run web rails webpacker:install
```

```
docker-compose run web rails webpacker:compile
```

DBを作成
```
docker-compose run web rails db:create
```
確かRails7だとこんなエラーは出ずにすんなり行けた気がするが...
ソリューションアーキテクト対策_Aurora篇

## はじめに
試験勉強した際のメモを自分用に記事化。
内容は公式やBlack Beltの写経ですので目新しいことはありません:pray:


## Aurora概要
AuroraはMySQL, PostgreSQLと互換性のあるクラウド向けのRDBであり、従来のエンタープライズデータベースのパフォーマンスと可用性に加え、オープンソースデータベースのシンプルさとコスト効率性も兼ね備えている。

性能的には標準的なMySQLデータベースと比べて最大で5倍、標準的なPostgreSQLと比べて最大で3倍高速である。
また、商用データベースと同等のセキュリティ、可用性、信頼性を1/10のコストで実現する。

読み込み処理の性能としては100ミリ秒未満。


## Auroraの特徴を箇条書きで
・PostgreSQL10.4と互換性がある
・MySQL5.7と互換性がある
・可用性は99.99%である


### AuroraのDR(リージョン障害レベル)
AZじゃなくてリージョンで障害が発生しても秒単位で復旧させたい場合は、異なるリージョンにリードレプリカを作成する。
マルチAZのフェールオーバー、マルチAZ構成はAZ障害には対応できるけどリージョン障害には対応できない


### Auroraのパフォーマンス増強
リードレプリカを増加させる。最大15個。
Auroraのレプリカは、AuroraDBクラスターの読み取りオペレーションのスケーリングと可用性の向上に利用されるリードレプリカである。
Auroraインスタンスのタイプ変更でもパフォーマンスは上がるが、こちらはコストがかかる。


### Aurora Serverlessについて
処理負荷が一定ではないユースケースにおいて、高性能なパフォーマンスが可能なRDBが必要な場合には、Aurora Serverlessを使用する。
最小と最大のキャパシティを設定して、それに基づいたスケーリングを行う。
自動的に起動/シャットダウンし、自動でスケールアップ/スケールダウンする。
サーバーレスアプリケーション向けに発生ベースで利用可能な、柔軟なリレーショナルデータベースとして利用が可能。


### Auroraのフェールオーバーについて
クラスターが3つのAZで構成されており、RDSと同様にマルチAZのフェールオーバーが可能。
リードレプリカを作成している場合は15秒程度でフェールオーバーが可能。無い場合は15分ほど。



- Athena
S3内のデータに対してSQLクエリを実行できるサービス。
標準のSQL式を使用して解析を行う。結果も数秒以内に配信される。

- Amazon Macie
機械学習によりS3の機密データを検出・分類・保護するフルマネージド型サービス

- Redshift Spectrum
S3の格納データに対して、Redshiftから直接クエリを実行できる。
Athenaと同様、高度なビッグデータ解析を行う。


## サーバレスアーキテクチャとRDB
サーバレスアーキテクチャとRDBは互換性が低いらしい。
なのでAWSでサーバレスアーキテクチャを実装するときはRDSとAuroraは向かない。
そういうユースケースではDynamoDBが適している。
ElastiCacheはインメモリ型でキャッシュとして機能する。よってLambda関数を起動するデータ処理イベントには不向き。


## おわりに
引き続き追記します！
以上です。
docker(compose)+postgresで /var/lib/postgresql/data のバインドマウントをする

# はじめに
postgresにおけるvolume設定でいまいち理屈がわかっていなかったので、下記残しメモ
WSL基準での記載となってしまっていますが、他の環境でも同じ考え方で対応できるかと思います。
※ 2023/12/31 フォルダの所有者が原因ではなく、権限が原因であることを再度書き直し（対策としては問題はなかった）

## 確認環境
1. 記載当初
    - windows10 pro 
    - wsl2(20.04.5 LTS (Focal Fossa))
    - Dockerのバージョン
        - Docker version 20.10.18, build b40c2f6
        - docker-compose version 1.29.2, build 5becea4c
1. 書き直し時
    - WSL2(Ubuntu22.04.3 LTS)
    - Docker (24.0.6)
    - Docker Compose (2.4.1)
    ※Docker Desktop ではありません

## 状況
docker-compose.yml で以下のようにvolume設定をカレントディレクトリ内で設定して docker-compose で up する

```yaml
version: '3'

services:
  pgdb:
    image: postgres:14.5
    ports:
      - 5432:5432
    volumes:
      - ./data:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
```


# 原因
~~postgresイメージはGIDが999で動作しているが、WSLで/mnt/... 以下のフォルダにマウントをすると、UID が変更できないので、マウントするフォルダに対して、フォルダ所有者の変更ができずに不具合が起こってしまう（、、みたいです）
DockerfileでGIDを変更してビルドしてみましたが、どうも内部で999になって、外では1000になるのでパーミッションエラーでNGになってしまいます、、（フォルダは777になっているので問題はなさそうなんですが、、）~~


原因はフォルダの権限でした。/mnt/... 以下のフォルダにバインドマウントをするとパーミッションが777から変更できませんので、Windows管理の保存領域以外の場所を使う必要が出てきます。フォルダのパーミッションは700or750にするべきのようです。（こういうログが出ていました）
```
    postgres-db-1  | 2023-12-31 01:56:53.024 UTC [82] DETAIL:  Permissions should be u=rwx (0700) or u=rwx,g=rx (0750).
    postgres-db-1  | child process exited with exit code 1
```

また、フォルダの所有者についてですが、 
```
    volumes:
      - ./data:/var/lib/postgresql/data`
```
のようにcomposeを設定して、ホスト側(`./data`)の所有者のGID,UIDを1000にして、`docker compose up` すると、dataの中身は999のGID,UIDで作成されますが、きちんと起動するし、動作も問題なさそう（基本的なCRUDのSQLは実行可能）なので、あまり関係なさそうです。（とはいえ、所有者1000の中に999のファイルが入っている歪な構成になりますのでお勧めはしませんが、、）

# 対策
パーミッションを777にするのはやめましょう。
また、WSLではpostgresのマウントをするときは、 /mnt/... のWindows領域は使わないようにしましょう。もしくは、バインドマウントではなく、ボリュームマウントを定義して、そちらで永続化をしましょう、、
※デフォルトのUIDが1000も多い(nodeとか)ので、あまり意識する場面は少ないかと、、

またWSL使用時のときはDockerfileで
```Dockerfile
RUN groupmod -g 1000 postgres
RUN usermod -u 1000 postgres
```
を実行すると、歪な構成になることを回避できます。

# 終わりに
１年くらい色々やってみて、やっと核心っぽいところまたどり着いた気がします。
Dockerのコンテナが動かない原因究明は本当に難しい…
【cron】PATHの設定方法

## 設定方法
### crontabでPATH定義
`crontab`ファイルの中で、`PATH`を以下のように定義できます。

```:crontab
PATH=/usr/bin:/bin:/opt/homebrew/bin
* * * * * コマンド
```
以下のように記述しても`$PATH`は展開されません。

```:crontab
PATH=$PATH:/opt/homebrew/bin
* * * * * コマンド
```

### bashコマンドなどに`-l`オプションを付与
`bash`コマンドや`zsh`コマンドに`-l`オプションを付けることでログインシェルとして実行できます。

```:crontab
* * * * * bash -l -c "コマンド"
* * * * * bash -l ファイルパス
```
ただし`-l`でログインシェルとして実行する機能のあるシェル以外では使用できません。

なお`shebang`でも上記と同様のことが実現できます。

```sample.sh
#!/bin/bash -l

```
ソリューションアーキテクト対策_ELB篇

## はじめに
試験勉強した際のメモを自分用に記事化。
内容は公式やBlack Beltの写経ですので目新しいことはありません:pray:


## ELB
### ALBの特徴
レイヤー7に対応し、HTTP/HTTPSリスナー対応
WebsocketとHTTP/2のリクエストを受付
1インスタンスに複数ポートを登録可能
ターゲットグループでのヘルスチェックが可能
★リクエスト内容を確認して分散先を振り分ける、コンテントベースルーティングが可能

ちなみにWebsocketプロトコルとは、WebサーバとWebブラウザの間で双方向通信ができるようにするプロトコルのこと。
ALBが対応している。


### パスルーティングについて
URLパスに基づいてリクエストを転送するルールを持つリスナーを作成できる。
これをパスルーティングという。

パスルーティングを使用して、1つのALBで複数のバックエンドサービスにトラフィックをルーティングすることができる。
よってパスベースルーティングによってトラフィックの制御が可能。


### ELBのクロスゾーン負荷分散
有効な全てのAZの登録済みターゲットにトラフィックを分散する。
なので複数のAZにわたって全インスタンスに着信要求を均等に分散することが可能になる。

ちなみにリクエストルーティングを用いて任意のルールによって分散処理を実現することが可能。
ただし着信要求を均等に分散するためにはクロスゾーン負荷分散の方が適している。

### ELBのロードバランシング機能あれこれ
#### ヘルスチェック
EC2インスタンスの正常/異常を確認し、利用するEC2の振り分けを行う

#### クロスゾーン負荷分散
配下のEC2の負荷に応じて、複数のAZに跨るEC2インスタンスに均等に負荷分散を行う

#### 暗号化通信
SSL/TLS証明書をELBに設定することでHTTPSまたはTLS通信を実施することができる

#### スティッキーセッション
セッション中に同じユーザから来たリクエストを継続して同じEC2に送信する

#### Connection Draining
インスタンスが登録解除されるか異常が発生した場合に、そのバックエンドインスタンスへの新規リクエスト送信を中止する

#### ログ取得
ELBのログ取得を有効化するとS3バケットにログを収集する

## CLB, ALB, NLBの違い
### CLB
・レイヤー4と7に対応しており、TCP, SSL, HTTP, HTTPSリスナーを使用
・古いタイプなのでALB/NLBの利用を優先する
・データ転送(GB単位)に応じて課金される
・IPアドレスが可変であるため、指定時にDNSのみ利用可能

### ALB
・レイヤー7に対応しHTTP/HTTPSリスナーに対応
・URLのパス(フォルダ名)に基づいたパスルーティングが利用可能
・時間に応じたロードバランサーキャパシティユニット(LCU)の使用量で課金される
・IPアドレスが可変であるため、指定時にDNSのみ利用可能
・デフォルトでクロスゾーン負荷分散が有効

### NLB
・L4NATロードバランサでTCPリスナーに対応(戻りトラフィックがNLBを経由しない)
・時間に応じたLCUの使用量で課金される
・NLBのサブネット拡張サポート(サブネットを追加できる)
・固定IPのためDNS, IPどちらも利用可能
・ALBよりも高パフォーマンス処理が可能
・デフォルトでクロスゾーン負荷分散が可能

## ELBとCA証明書
ELBにCA証明書を設定することで、SSLを使用して転送中のデータを保護する。
保護するのは以下。
・ロードバランサーとHTTPSセッションを開始するクライアント間のトラフィック暗号化
・ロードバランサーとEC2インスタンス間の接続


## おわりに
引き続き追記します！

簡単ですが以上です。
Gitを使いこなせるようになりたい

#はじめに
git、githubをはじめて使用するにあたって、調べたことをまとめます。

# 調べたこと

[GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~](https://qiita.com/shizuma/items/2b2f873a0034839e47ce)
[gitのremote urlを変更する(レポジトリ移行時)](https://qiita.com/minoringo/items/917e325892733e0d606e)
[すべてのローカルブランチをpushする](http://git-use.goodhead.work/pages/287)
[【Git】リポジトリを複製する方法【コミット履歴の引き継ぎなし】](https://reasonable-code.com/repository-copy/)

# その他で気をつけること
gitpushなどを行うとき、現在ログインしているユーザーを意識すること。

[Linuxの権限確認と変更(chmod)（超初心者向け）](https://qiita.com/shisama/items/5f4c4fa768642aad9e06)
Ruby on Rails をTermuxに導入

# やりたいこと
- termuxにRuby on Railsを導入したい
- ググるといくつか参考になる情報あるが、どれを試しても導入できない

# 環境
- Android 12
- 最小限でMySQLを使用したRailsアプリを作成します


# 構築手順
古いスマホにTermuxを入れてそこにRuby on Railsを導入する。


## Termuxをインストール
※以下ページご参照ください。（「Termuxのインストール」まで）
https://qiita.com/tatuya911/items/840107699190451a4651

:::note info
GooglePlay以外からアプリのインストールする場合は
「不明なアプリのインストールを許可」をしてください。
※自己責任でのインストールになります。
:::

## お決まりのコマンドを実行
`apt upgrade`途中に出てくる選択肢は Enter(N) でOK。
```shell:Termux
~ $ apt update
~ $ apt upgrade
```

## 必要パッケージをインストール
```shell:Termux
~ $ pkg install ruby clang make binutils pkg-config libxslt git mariadb
```
※以下ページを参考にさせていただきました
https://github.com/termux/termux-packages/discussions/8855

ここからはgemでインストールしていきます。
```shell:Termux
~ $ gem install nokogiri --platform=ruby -- --use-system-libraries
```
termuxでnokogiriをインストールするときは上のオプションがいるようです。
ここでrailsをインストールしていきます。

```shell:Termux
~ $ gem install rails
```
環境によるかもしれませんが、rails newするときに、以下コマンド実行するように言われます。
先にやっておきましょう。
```shell:Termux
~ $ gem update bundler
```

あたらしくRailsアプリケーションを作成します。
（termux_appの部分はご自由にどうぞ）
```shell:Termux
~ $ rails new ./termux_app -d mysql
```

このようなエラーが出ます。
```shell:Termux
rails  importmap:install
rails aborted!
LoadError: cannot load such file -- nokogiri/nokogiri
/data/data/com.termux/files/home/termux_app/config/application.rb:7:in `<main>'
/data/data/com.termux/files/home/termux_app/Rakefile:4:in `require_relative'
/data/data/com.termux/files/home/termux_app/Rakefile:4:in `<main>'
bin/rails:4:in `<main>'
```
エラー内容謎ですが、Gemfileを編集して回避していきます。


## Gemfileの編集
以下の通りGemfileを編集します。
- nokogiriのオプション追加
- tzinfo-dataのオプション削除（コメントアウト）
```diff_shell:Termux
~ $ nano Gemfile
+  gem "nokogiri", force_ruby_platform: true

- gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ]
+ gem "tzinfo-data"
+ #, platforms: %i[ mingw mswin x64_mingw jruby ]
```

Gemfileを編集したら、Gemfileでインストールします。
```shell:Termux
~ $ bundle install
```
これで正常にRailsアプリケーションが作成されます。

## Rails起動(失敗...)
まだまだです。。以下コマンドで起動をするとエラーが発生します。
```shell:Termux
~ $ rails s
```

## MySQLのエラー回避
ここが一番難航しました。。
複数エラーが発生するので、一つずつ対処していきます。

まず、空ファイルの「mysqld.sock」を作成します。
```shell:Termux
~ $ touch /data/data/com.termux/files/usr/var/run/mysqld.sock
```
※以下サイトを参考にさせていただきました。
https://qiita.com/tkmd35/items/c26d1dffca4be0a4f017

次に、以下コマンドでmysqlを起動します。
```shell:Termux
~ $ mysqld_safe
```

termuxのユーザでmysqlに入り、rootユーザを追加します。
```shell:Termux
~ $ mysql -u $(whoami)
~ $ set password for 'root'@'localhost' = password('');
```

先程作成したrootでmysqlに入り、DBを作成します。
```shell:Termux
~ $ mysql -u root
~ $ rails db:create
```

## Rails起動(成功！！)
以下コマンドで起動します。
```shell:Termux
~ $ rails s
```

# 最後に
恐らくですが時間とともにこのやり方できなくなるかもです。
非エンジニアがテスター業務についてざっくり流れを書いてみる・そして感じたこと

# 0. なぜこの記事を書くのか
私は、非エンジニアです。ご縁があって、エンジニア上司の元で働くことになり、
Webアプリと、ネイティブアプリのテスター業務を経験しました。

丁寧に、上司からご説明いただきましたが、
多くの場合、「テスト環境ってなに？」「テストケースとはなに？」という問いで頭の中がいっぱいでした。

テスター業務を渡された時の備忘録として、テスター業務の大まかな流れをまとめることで、
いつかどこかにいるテスター業務を依頼された非エンジニアの方の一助になればいいなと思い、ここに記します。


# 1.テストとは
新規機能の開発、または機能の修正後に、プログラム・システムが問題なく動作するか確認する工程です。テストで発見した不具合を発見することで、リリース前にバグなどを早期に発見→修正ができるため、プログラム・システム・アプリケーションの品質を保つために重要なものです。

# 2.テスト実施までの流れ
1. テスト内容の確認
1. テスト方法の確認
1. テスト実施（本番）
1. テスト結果の報告（レポート）

# 3.テスト内容の確認
テスト実施前に、以下の7点を確認しておくと、テストの概要を理解しながら、スムーズにテストを進められます。
1. テストの目的・・・今回のテストはなぜ行われるのか
1. テストの対象
1. テスト方法
1. 環境
1. デバイス・OS
1. レポート方法
1. おおよそのスケジュール


事前に開発メンバーに、以下のものが共有されるので、
こちらを元に、テスト内容を理解するといいでしょう。

#### ＜開発メンバーから提供されるもの＞ 
   - テスト環境
   - テストケース（多くの場合、スプレッドシートに記載されています）

※テストケースイメージ画像（[引用元画像はこちらからお借りしました](https://blog.aiqveone.co.jp/testcase/)）
![スクリーンショット 2022-09-17 15.55.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2614869/78b572e3-dbd8-fa08-cf4a-179952e2ccf3.png)


### <span style="color:#ff69b4">★ Tips★用語説明</span>

| 用語 | 意味 |
| -------- | -------- |
|  テスト対象    | テストで確認したい「機能」や「画面上の挙動」のこと。例えば、旧データテーブルへのトラッキングデータへの書き込みを止めた後に、旧データテーブルのトラッキングデータ書き込まれないことが「テスト対象」となる。    | 
|テスト環境  | 環境にはサーバー環境の種別があり、①本番環境②検証環境（staging）③開発環境（devlopment環境）があり、多くの場合②検証環境（staging）で行われる。 |

テスト環境のイメージ図
![スクリーンショット 2022-09-17 15.58.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2614869/4266c90e-c068-de1c-e0b4-149bcf47feaf.png)
[イメージ図の引用元](https://techracho.bpsinc.jp/morimorihoge/2019_12_02/84025)

# 4.テスト方法の確認

3.の確認後、テスト本番前にテスト環境にログインして、テストケース通りに動作するか、表示が変わるのかなど触ってみましょう。その際に、不明点・テストにあたり必要な情報があれば開発メンバーに問い合わせましょう。

#### ＜具体例＞
・コマンドを打ってAPI情報が帰ってくるか確認するとテストケースに書いてあるが、APIパラメータを指定してほしい。
・管理サイトの〇〇メニューをクリックした後に、▲▲画面を表示とあるが、そもそもその画面が実装されていないので確認できない。▲▲画面を見れるようにしてほしい。
・iOSの実機がないから、ください。
などなど

# 5.テスト実施（本番）
開発メンバーからテスト実施の指示が来たら、実際にテストケースに沿ってテスト対象を確認しましょう。都度、不明点があれば開発メンバーに問い合わせます。


# 6.テスト結果の報告（レポート）
テスト実施後に、3.で確認したレポート方法でテスト結果を報告します。
多くの場合、スプレッドシートに「テスト実施日」「テスト実施者」「結果」欄があります。こちらを元に、開発メンバーは修正をするのか、次の工程に進むのか判断しますので必ず記入してください。
なお、修正があった場合に、再テストを行う場合があります。

# 7.終わりに
テスター経験を通して、アプリ・システムの質向上や、バグの発見など、
作っておしまい。という世界ではないのだと、開発メンバーに混じってテスターをしていると実感するばかりでした。

余談ですが、過去に細かな仕様書がなく、開発者も退職済みで、
ただしシステムだけがあるといった結合テストを経験したことがあります。

エンジニア上司との相談の上ですが、
・どこまでのテストを行うか
・このシステムを使用するエンドユーザーにとって、どんな不具合が起きたら、一番まずいのか

といったケースを洗い出しました。
実際にそのシステムを触り、どういった挙動が起こるのか、このボタンを押したら、
データベースには何が書き込まれるのか・・・・という手探りの中、テストケースを作成しました。

いくらでも時間を掛ければ細かなバグを探し出しすこともできるでしょう。
しかし、どのレベルの品質を担保させるかといった上流の判断も非常に絡まる業務だと、テスター業務を通して感じました。

非エンジニアの皆さん、テスター業務の背景をなんとなく想像しながら進めると、案外面白いものが見えるかもしれませんよ。
ホストと同じユーザーでコンテナを起動する方法


コンテナからマウントしたファイルなどをいじると、ホスト側ユーザーと所有者が異なってしまう問題があります。
これが結構煩わしいので、ホスト側ユーザーと同じUID、GIDでマウント先のファイルを扱う方法を考えてみました。

コンテナ起動時に、ホスト側と同じUID、GIDを持つユーザーを作成して、コマンドを実行する方針です。


# 実装
## ディレクトリ構成
```
sample/
| Dockerfile
| entrypoint.sh
| run.sh
```

## Dockerfile
```Dockerfile
FROM debian:bullseye-slim
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
```

## entrypoint.sh

1. 環境変数として受け取った `LOCAL_UID` `LOCAL_GID` でグループとユーザーを作成します。
1. マウント先の所有者を 1. で作成したユーザーとグループに chown します。 (一応)
`chown -R $UNAME:$UNAME /opt/app`
1. 作成したユーザーで任意のコマンドを実行します。
`exec su $UNAME -c '...'`

```entrypoint.sh
#!/bin/bash

# ホスト側の実行ユーザーと同一のUID, GIDを持つユーザーを作成
HOST_UID=${LOCAL_UID}
HOST_GID=${LOCAL_GID}
UNAME="app"

# グループIDを指定してグループを作成
# -g: グループIDを指定する
groupadd -g $HOST_GID $UNAME

# ユーザーIDを指定してグループを作成
# -u: ユーザーIDを指定
# -o: ユーザーIDが同じユーザーの作成を許す
# -m: ホームディレクトリを作成する
# -g: ユーザーが属するプライマリグループを指定する(グループID or グループ名)
# -s: ログインシェルを指定する
useradd -u $HOST_UID -o -m -g $HOST_GID -s /bin/bash $UNAME
export HOME=/home/$UNAME

# マウント先のを所有者作成したユーザーとグループに変更
chown -R $UNAME:$UNAME /opt/app

# 作成したユーザーで任意のコマンドを実行
exec su $UNAME -c 'id | tee /opt/app/id.txt'
```

## run.sh

1. `docker run` 時に環境変数にユーザーIDとグループIDを設定します。

```run.sh
#!/bin/bash

SCRIPT_DIR=$(cd $(dirname $0); pwd)
cd $SCRIPT_DIR

# イメージのビルド
IMAGE_TAG="exec_host_user:latest"
docker build -t $IMAGE_TAG .


# 現在の実行ユーザー・グループを環境変数に設定してコンテナを起動
LOCAL_UID=$(id -u)
LOCAL_GID=$(id -g)
docker run \
  -e LOCAL_UID=$LOCAL_UID \
  -e LOCAL_GID=$LOCAL_GID \
  -v $SCRIPT_DIR/app:/opt/app \
  $IMAGE_TAG
```

# 実行方法

```bash
bash run.sh


# コンテナで作成されたファイルを確認 (ファイルの所有者がコンテナ起動ユーザーになっている)
ls -alF app/id.txt
```
Swift 5.7の変更点つまみ食い

# 言語と標準ライブラリ

Swift 5.7では、言語と標準ライブラリに多くの改良が施されています。

* `if let`構文や複数のクロージャ構文における型アノテーションなど、一般的な定型文で利用できる新しい省略記法。
* 言語仕様上の制限を解除することによって、ジェネリックプログラミングの親和性を改善。
* 新しいアノテーションとオプトイン診断により、データ競合の安全性が強化されました。
* 分散環境におけるアクター分離。
* 既存のポインタAPI群の使い勝手を改善。
* 文字列処理のための全く新しい言語サポートとAPI。

# ジェネリクスの改善された実装

ジェネリクスを扱いやすくする言語仕様の改良に加えて、型検査のジェネリクス実装が完全に書き直され、正確さとパフォーマンスが改善されました。

新しい実装では、多くのバグが修正されました。
コレクションの`SubSequence`関連型に対する同一型要件のような複雑な同一型要件の処理と、`Self.Element == Self`という要件を定義する`CaseIterable`プロトコルを使用したコードに関連するものです。

ジェネリクスの新しい実装によって、パフォーマンスも向上しました。
プロトコルと関連型の特定の構成で、型検査の時間はSwift 5.6では指数関数的なスケールしていましたが、Swift 5.7では線形になりました。

# 自動参照カウントの改善

Swift 5.7では、最適化が許可されているときに変数の寿命を短くするための新しいルールを指定することによって、ARCの動作はより予測可能で、ユーザーフレンドリーで、パフォーマンスも良くなっています。
ルールを強制するために、コンパイラは「各変数の語彙的スコープ」を追跡する新しい内部表現を採用しました。
これには、既存の最適化の更新に加えて、いくつかの最適化を新たに実装する必要がありました。
拡張された変数寿命に依存する最も一般的なプログラミングパターンが、プログラマが明示的に `withExtendedLifetime()`を使用しなくても安全に実行できるようになりました。
これにより、最適化されたビルドでは実行時に発生する「診断が困難なライフタイムバグ」から保護されます。
また、既存のソースを壊すことなく、より強力な最適化を導入することも可能です。

# コード補完

関数呼び出しの引数、変数、およびグローバル関数のコード補完が、Swiftの型チェッカーに緊密に統合されました。
これにより、コード補完は曖昧なコードやエラーのあるコード内部でより正確な結果を提供できます。

以下は、 `+` の後を補完する場合の例です。
コード補完は、周囲のコンテキストに一致するものとして `int` と `string` を提案します。
エディタは、これらの提案結果を `array` よりも上位にランク付けすることができるようになりました。

```swift
func makeIntOrString() -> Int {}
func makeIntOrString() -> String {}

let array = [4, 2]
let int = 42
let string = "Hello World!"
makeIntOrString() +
```

次の例は、欠けている引数を補完する場合です。
最初の引数は「整数の `1`」なので、コード補完は `secondInt` 引数ラベルのみを提案します。
`secondString`は省略されるようになりました。

```swift
func add(_ firstInt: Int, secondInt: Int) {}
func add(_ firstString: String, secondString: String) {}
add(1, )
```


引用元: [Swift.org Swift 5.7 Released!](https://www.swift.org/blog/swift-5.7-released/)
2カ月FE攻略～0日目～

# 目次
[1.はじめに](##-はじめに)
[2.Pythonを導入しよう](##-Pythonを導入しよう)
[3.VSCodeを導入しよう](##-VScodeを導入しよう)
[3.基本操作と四則演算編](##-基本操作と四則演算編)
## はじめに
前回は使用する書籍の紹介を行いました。（Markdown式の記述を推奨してくださった方、ありがとうございます。）
<br>この記事では午後試験対策としてPythonを選んだ理由、導入手順、初歩的なコードについて書きたいと思います。
## なんでPython？
理由は大きく2つあります。
- アルゴリズムをきちんと学ぶことで午前問題との相乗効果を狙っている。
- データ分析をRで扱ってきたが、データサイエンスとしてはPythonの方が一般的（なイメージ）なので学び直したい。

つまりは基本情報技術者試験の勉強を足掛かりにして、実用的なデータサイエンスを学びたいというわけです。
## Pythonを導入しよう
前提として、この日記ではPython3.10.6を使っています。
<br>まずは[ここから](https://www.python.org/downloads/)ダウンロードページに飛びましょう！
そして特に理由がなければ、Download the latest version for Windowsから最新Ver.をインストールすればいいと思います。
(ここは自分もよくわかってないです。)
<br>**インストールの際の注意点**
まずは下部にある、Add Python 2.10 to PATHにチェックを入れます。
<br>Customize Installationから
- Documentation
- pip
- tcl/tk and IDLE
- Pythontest suite
- for all users(requires elevation)

にチェックが入っていることを確認してください。
<br>次にAdvanced Optionsの設定です。
- Customize install locationではBrowseでLocal Disk(C:)を直接指定しましょう。これでユーザーネームによるエラーを防げます。

次にチェックを付ける場所です。
- Install for all users
- Add Python to environment variables

は確実にチェックしましょう！確認が出来たら、インストールをしてください。

## VScodeを導入しよう
実際にPythonを動かしていく環境として、Visual Studio Codeというエディターを使用します。
<br>Microsoftのソフトで、[このページ](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)からダウンロードできます。
<br>インストール後、起動すると右下に日本語パッケージを導入しませんか？というポップアップが出ます。クリックして日本語化しましょう！
出なかった場合は【ファイル→ユーザー設定→拡張機能】からも導入できます。
検索窓に「Japanese Language Pack for VS Code」を入力するとページが出てくるので、そこからインストールしましょう。
<br>同様にPythonの拡張機能もダウンロードする必要があります。検索窓に「Python」と入力し、ページからインストールしてください。
## 基本操作と四則演算編
各種インストールが終わったら、早速VScodeを使ってみましょう。
その前に、デスクトップらへんに空のフォルダを作っておくと便利です。コーディングしたファイルをまとめて収納できます。
<br>【ファイル→新しいテキストファイル→もう一度ファイル→名前を付けて保存】
保存のとき、**ファイルの種類：Python**に変更することを忘れないでください。

では実際に変数の宣言と、四則演算をしていきます。
変数のイメージはラベル付きの箱です。アルゴリズム編の流れ図だと「1→変数a」のような書き方がされていますね。
これは __変数aの箱に1をしまう処理__ を表しています。
<br>Pythonだとこの流れ図とは反対向きに記述していきますが、考え方は同じです。

```Python:変数aに1をしまう
変数a = 1
print(変数a)
```
このプログラムをVScodeの右上の▷から実行してみると、下部のターミナルという欄に1と表示されると思います。
printは()の中身を表示しろという命令になので、変数aに1がしまわれていることが確認できます。
<br>次に、四則演算についてです。
|  足し算  |  引き算  |  掛け算  |  割り算  |
| :---: | :---: | :---: | :---: |
|  ＋  |  －  |  ＊  |  ／  |

<br>Pythonでは、表の記号（演算子）を使ってそれぞれ四則演算を行います。
```Python:足し算
変数a = 1
変数b = 2

変数c = 変数a + 変数b
print(変数c)
```
このコードを実行すると、変数aと変数bを足した結果である3が、変数cにしまわれていることが確認できます。
他の演算子についても実行してみましょう。
```Python:その他の四則演算
変数d = 変数a - 変数b
print(変数d)

変数e = 変数a * 変数b
print(変数e)

変数f = 変数a / 変数b
print(変数f)
```
後輩向けの導入も兼ねたため、あまりFEとは関わらない記事内容になってしまって申し訳ありません。
<br>長々と続けても読みづらいと思いますので、今回はこの辺で失礼します。
chmod +x したファイル(コマンド)と autoload した関数との挙動の違い

### `chmod +x foobar`について
何か記述したファイルを実行可能にする場合、`chmod +x foobar` を実行します。

```zsh
% cat hello-john
echo "Hi, there"
% ./hello-john
zsh: permission denied: ./hello-john
% chmod +x hello-john
% ./hello-john
Hi, there
```

### `autoload`について
zsh では`autoload`を使って関数を呼び出すことができます。(何かのタイミングで既に`.zshrc`に`autoload -U bashcompinit && bashcompinit`を記載してあったのですが、どういう意味か気になって最近調べた次第です。)

```zsh
% cat ~/.zsh/functions/hello-john
echo "Hi, there"
% which hello-john
hello-john not found
% autoload -Uz $HOME/.zsh/functions/hello-john
% which hello-john
hello-john () {
	# undefined
	builtin autoload -XUz /Users/<username>/.zsh/functions
}
% hello-john
Hi, there
% which hello-john
hello-john () {
	echo "Hi, there"
}
```
(`autoload`の引数は絶対パスでもいいみたいです。つまり使いたい関数が`FPATH`に入っていなくても直接`autoload`の引数に持って来れば使えるみたいです。)

### 挙動の違い
1. `autoload` は関数をデフォルトで**遅延読み込み**するそうなので、`.zshrc` の読み込みが早くなり、`zsh`の新しいインスタンスの立ち上がりが速くなるそうです。
2. 遅延読み込みしてくれるのなら自作のスクリプトは全部`autoload`して使えばよさそうな気がしましたが、`chmod +x`したファイルが別のインスタンスとして実行されるのに対し、`autoload`で読み込んだ関数は**現在のインスタンスで実行される**ため、例えば`cd`コマンドを実行するスクリプトを記述した場合、現在のディレクトリに対してそれが実行されてしまいます。現在のディレクトリを変更したくない場合は`chmod +x`した実行ファイルを使うか、あるいはスクリプトに

```zsh:~/.zsh/functions/foobar
current_dir=$(pwd) # 現在のディレクトリを記憶
hogehoge # メインの内容
cd $current_dir # 元のディレクトリに戻る
```

と記述するかというところでしょうか。
3. また、`autoload`で読み込む関数では**シバングは利用できない**(無視される・全てシェルスクリプトとして解釈される)ようです。例えば`python3`で記述したスクリプトは`#!/usr/bin/env python3`シバングを頭に書いて`chmod +x`を使うしかないようです。

### 引用・参考

https://qiita.com/yuku_t/items/77c23390e52168a2754a

https://qiita.com/mollifier/items/6fdeff2750fe80f830c8

### メモ
内容に間違いがありましたらご指摘お願いします。
AWSのクレデンシャルをコンテナに引き継ぐ方法

コンテナ起動時に `AWS_ACCESS_KEY_ID` と `AWS_SECRET_ACCESS_KEY` を環境変数に設定することで、ホストで利用しているAWSのクレデンシャル情報をコンテナに引き継ぐことができます。

```bash
PROFILE=hogehoge
AWS_ACCESS_KEY_ID=$(aws --profile $PROFILE configure get aws_access_key_id)
AWS_SECRET_ACCESS_KEY=$(aws --profile $PROFILE configure get aws_secret_access_key)

docker run \
  -e AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID \
  -e AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY \
  <イメージ名> <CMD>
```
Rails6 に Bootstrap5を導入しよう！


こんばんは。
Railsの案件にアサインされることになリました新米です。
環境構築でつまづきたくないので、備忘録として書き残しておきます。

### 必要な対応
#### CSS
- `bootstrap popper`インストール
```
yarn add bootstrap @popperjs/core
```
package.json に設定が追加されます。
```
  "dependencies": {
    # 一部抜粋
    "bootstrap": "^5.2.1",
    "popper.js": "^1.16.1",
  },
```

#### スタイルインポート
```
mkdir app/javascript/stylesheets
touch app/javascript/stylesheets/application.scss
```

作成された`application.scss`に以下を追記
```
@import '~bootstrap/scss/bootstrap';
```

#### JavaScript
`yarn`でインストールしたパッケージのimport
`app/javascript/packs/application.js`に以下を追加
```
import 'bootstrap';
import '../stylesheets/application';
```
#### レイアウトへの登録
レイアウトに`stylesheet_pack_tag`を追加。
`stylesheet_pack_tag`を使うことでWebpackで.cssや.scssファイルのスタイルシートを読み込むことができる。

`app/views/layouts/application.html.erb`に以下コードの追加
```
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>

<%# ここに追加 %>
<%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```

#### 動作確認
```
<div class="dropdown">
  <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
    Dropdown button
  </button>
  <ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
    <li><a class="dropdown-item" href="#">Action</a></li>
    <li><a class="dropdown-item" href="#">Another action</a></li>
    <li><a class="dropdown-item" href="#">Something else here</a></li>
  </ul>
</div>
```

Dropdownが起動すればOK
![スクリーンショット 2022-09-17 15.15.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2842674/251d5981-d542-c7ab-80d9-8df71bdffd15.png)
GISデータ(ラスター・ベクター)をPythonで処理する

# GIS for python

GISデータ(ラスタ・ベクタ等)をPython上で扱う上で便利なライブラリの紹介。
その他、再投影方法と、`matplotlib`を用いた描写方法まで

## ライブラリ群

||`osgeo.gdal`|`geopandas`|`rasterio`|
|---|---------|-----------|----------|
|扱えるデータ形式|ラスターデータ|ベクターデータ|ラスターデータ|
|描写機能|なし？|あり|あり|

### 1. `osgeo.gdal`

- gisデータを扱うための基本ライブラリ
- 基本データタイプは`osgeo.gdal.Dataset`

#### `gdal.Dataset`

- **データ本体**、**左上ピクセルの座標情報(geotrans)**、**投影情報**などで構成
- 左上のピクセルの座標は(lat, $\varDelta$lat, 0, lon, 0, $\varDelta$lon)の順(set型)

```python
# tifファイルから各種データを読込む
from osgeo import gdal
src_ds = gdal.Open('input.tif')
src_arr = src_ds.GetRasterBand(1).ReadAsArray()  # データ本体をnumpy.ndarray型に変換
src_geotrans = src_ds.GetGeoTransform()  # 左上ピクセルの座標情報をtupple型に変換
src_proj = src_ds.GetProjection()  # 投影情報をstr型に変換
```
---

### 2. `geopandas`

- ベクターデータを読みこみ`Pandas`とほぼ同じ表形式で扱うことができるPythonライブラリ
- 基本データタイプは`geopandas.geodataframe.GeoDataFrame`
- 公式ドキュメント[https://geopandas.org/en/stable/]

#### `geopandas.geodataframe.GeoDataFrame`

- `pandas`と同様の表形式で、属性情報と`geometry`を保存

```python
import geopandas as gpd
gdf = gpd.read_file('input.shp')  # shpファイル以外にもgeojsonなども読込可
```

---

### 3. `rasterio`

- ラスターデータを扱うためのライブラリ
- `gdal`よりもより簡単にデータの取得が可能
- geotransは`rasterio.Affine`型で、($\varDelta$lon, 0, lon, 0, $-\varDelta$lat, lat)

```python
import rasterio
with rasterio.open('input.tif') as src
    src_arr = src.read(1)
    src_geotrans = src.transform
```
  

---

## 再投影

`gdal.Warp`を使用する

- `gdal.Warp(
    out_path, input,
    srcSRS, dstSRS,
    outputBounds=(xmin, ymin, xmax, ymax),
    resampleAlg='average',
    srcNodata, dstNodata)`
  - 返り値を受け取ると、再投影後の`gdal.Dataset`となる

|引数|type|概要|
|---|----|---|
|out_path|`str(path)`|出力先ファイルのパス|
|input|`str(path)`or`gdal.Dataset`|入力データのパス、もしくは`gdal.Dataset`型変数|
|srcSRS|`str(EPSG: or Wkt code)`|入力データの座標系情報(省略可能)|
|dstSRS|`str(EPSG: or Wkt code)`|出力データの座標系情報|
|outputBounds|`array like(xmin, ymin, xmax, ymax)`|出力後の切り出し位置(省略可能)|
|resampleAlg|`str`|リサンプリング方法|
|srcNodata|`int or float`|入力データのNodata値|
|dstNodata|`int or float`|出力データのNodata値|

---

## 描写

### ベクターデータ

`geopandas`を使用する

- `gdf.plot(ax)`
  - 指定したaxisにgdf内のベクターデータを表示

```python
import geopandas as gpd
from matplotlib import pyplot as plt
fig, ax = plt.subplots()
gdf = gpd.read_file('input.shp')  # shpファイルの読込
gdf.plot(ax=ax, color='none')  # color='none'でポリゴン内の塗りつぶしなしに指定可能
```

### ラスターデータ

`rasterio`を使用する

- `rasterio.plot.show(arr, transform)`
  - `numpy.ndarray`にgeotransをつけて表示する

|引数|type|概要|
|---|----|---|
|arr|`numpy.ndarray`|表示したいArray likeなデータ|
|transform|`rasterio.Affine`|左上のピクセルの座標($\varDelta$lon, 0, lon, 0, $-\varDelta$lat, lat)|

```python
import rasterio
from rasterio import plot as rplt

with rasterio.open('input.tif') as f:
    raster_trans = f.transform  # geotransを読込み、rasterio.Affine型に変換
    raster_arr = f.read(1)  # バンドの中身を読込み、numpy.ndarray型に変換

fig, ax = plt.subplots()
rplt.show(raster_arr, transform=raster_trans)
```
画面からウィンドウが消えた時の対処法

# 画面からウィンドウが消えた時の対処法
対象:複数ディスプレイとシングルディスプレイを使い分ける人

## 前提条件
- Windows環境
- タスクバーなどからウィンドウを選択できる
- キーボードが正常に動く

## 手順

### 1.ウィンドウを選択する
表示したいウィンドウを選択(タスクバーから選択)します

### 2.メニューを表示する
[Alt] + [Space] キーを同時押ししウィンドウのメニューを表示する

### 3.移動を選択する
メニューから[移動 (M)]を選択する

### 4.移動枠を表示する
[←][↑][→][←]キーのいずれかを押下し移動枠を表示させる

### 5.ウィンドウをマウス移動させる
移動枠がマウスに追従するため、表示させたい位置でマウス[左クリック]する
[python] ファイルの場所（パス）を得る方法

# はじめに
会社のシステムがかなり古く、独自で自動化システムを作ることを目指している。
会社のデータの多くはエクセルで管理され、ファイルの場所を指定することが絶対必要条件になる。

# 環境
python 3.7.8
window 10

# Code
### パスの指定方法
```python
path = r'C:\Users\junsa\Desktop\python'
## 文字列の中の '\'を認識するので、rawの「 r 」を書くことで認識しなくする
file_name = 'labo.py'
print(path + fr'\{file_name}')
# 'C:\Users\junsa\Desktop\python\labo.py'
## 文字列の前に f を書くことで変数を入れることができる。
```

### 現在のファイルのパスを得る
```python:
import os 

print('getcwd:      ', os.getcwd())
print('__file__:    ', __file__)
#getcwd:       C:\Users\user\Desktop\python
#__file__:     labo.py

##パスに存在するファイル名をすべて得る
list = os.listdir(os.getcwd())
print(list)
# ['.git','labo.py', 'README.md', '__main__.py', '__pycache__']
```

### パスのファイル名を得る（拡張子あり、なし）
```python
import os 

filePath = r'C:\Users\junsa\Desktop\python\labo.py'

print(os.path.basename(filePath))
# labo.py
print(os.path.splitext(os.path.basename(filePath)))
# ('labo', '.py')
```


### ファイルのフォルダ名を得る
```python
import os 

filePath = r'C:\Users\junsa\Desktop\python\labo.py'
# ファイルのフォルダ名を得る
dir_name = os.path.dirname(filePath)
print(dirname)
# C:\Users\junsa\Desktop\python

# フォルダの下位フォルダ名を得る
sub_dir_name = os.path.dirname(dir_name)
print(sub_dir_name)
# C:\Users\junsa\Desktop
```


### ファイルのフォルダパスとファイル名を得る方法  
```python
import os

filePath = r'C:\Users\junsa\Desktop\python\labo.py'

base_dir_pair = os.path.split(filePath)
print(base_dir_pair)
## ('C:\\Users\\junsa\\Desktop\\python', 'labo.py')
```


環境によって拡張子で場合分けする時もある。
私の会社の場合、エクセルのファイルの拡張子が 'xls', 'xlsx', 'xlsm'などがあり、
拡張子によってはライブラリーが利用できない時も多い。

`os.path.splitext`で拡張子で場合分け、`os.path.dirname`でフォルダで場合分けをすると、予期せぬエラーを予防することができる。

[python 公式Document](https://note.nkmk.me/python-os-basename-dirname-split-splitext/)
Python標準ライブラリのsmtplibでメールを送信する

# はじめに
Python標準ライブラリである、**smtplib**を使ったメール送信についての学習記録になります。
GmailのSMTPサーバーを利用してメール送信を試してみます。
Python3.9で書いています。

# 事前準備
- Googleアカウントの二段階認証プロセスをONに設定します。
- アプリパスワードを生成。

# ディレクトリ構成
```
# tree
.
├── send_mail.py
└── settings.json
```
# 書いたプログラム
シンプルにしてあるつもりです。
```python:send_mail.py
import smtplib
from email.mime.text import MIMEText
import json

def send_gmail(mail_from, mail_to, mail_subject, mail_body):

    settings_file = open('settings.json','r')
    settings_data = json.load(settings_file)

    """ メッセージのオブジェクト """
    msg = MIMEText(mail_body, "plain", "utf-8")
    msg['Subject'] = mail_subject
    msg['From'] = mail_from
    msg['To'] = mail_to

    # エラーキャッチ
    try:
        """ SMTPメールサーバーに接続 """
        smtpobj = smtplib.SMTP('smtp.gmail.com', 587)  # SMTPオブジェクトを作成。smtp.gmail.comのSMTPサーバーの587番ポートを設定。
        smtpobj.ehlo()                                 # SMTPサーバとの接続を確立
        smtpobj.starttls()                             # TLS暗号化通信開始
        gmail_addr = settings_data['gmail_addr']       # Googleアカウント(このアドレスをFromにして送られるっぽい)
        app_passwd = settings_data['app_passwd']       # アプリパスワード
        smtpobj.login(gmail_addr, app_passwd)          # SMTPサーバーへログイン

        """ メール送信 """
        smtpobj.sendmail(mail_from, mail_to, msg.as_string())

        """ SMTPサーバーとの接続解除 """
        smtpobj.quit()

    except Exception as e:
        print(e)
    
    return "メール送信完了"


# 直接起動の場合はこちらの関数を実行
if __name__== "__main__":

    """ メール設定 """
    mail_from = "test@gmail.com"       # 送信元アドレス
    mail_to = "test@yahoo.co.jp"         # 送信先アドレス(To)
    mail_subject = "件名"                   # メール件名
    mail_body = "本文"                      # メール本文

    """ send_gmail関数実行 """
    result = send_gmail(mail_from, mail_to, mail_subject, mail_body)
    print(result)
```

Gmailのアドレスと、アプリパスワードは外部ファイル化しておきます。
```json:settings.json
{
    "gmail_addr": "test@gmail.com",
    "app_passwd": "applicationpassword"
}
```
【Tips】AWS SDKのエンドポイントを別のHTTPS Serverに変更する

# はじめに
AWSでの試験を楽にするためにLocalStackを使用したかったが、やむを得ない事情でローカルPCで起動することができなかったのでAWS上で起動することになり、その際通信をセキュアにするためにSSL化したら面倒くさかったのでメモ。

# AWS SDK(Java)編
JavaのSDKでは、以下のように変更をする

```Java
import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder;
import com.amazonaws.client.builder.AwsClientBuilder;

// (中略)
  final AmazonDynamoDB ddb = AmazonDynamoDBClientBuilder.standard()
                               .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(
                                 System.getenv("ENDPOINT"),
                                 "us-east-1"))
                               .build();
// (以下略)
```

証明書の情報は、予め```keytool```でJavaに登録しておこう。



# AWS SDK(Golang)編
Go SDKでは、以下のように変更をする

```Go
import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/credentials"
	"github.com/aws/aws-sdk-go/aws/session"
)

// (中略)
	sess, _ := session.NewSession(&aws.Config{
		Region:           aws.String("us-east-1"),
		Credentials:      credentials.NewStaticCredentials("dummy", "dummy", ""),
		S3ForcePathStyle: aws.Bool(true),
		Endpoint:         aws.String(os.Getenv("ENDPOINT")),
	})
// (以下略)
```

なお、Golangの場合は、証明書の情報は、起動時に環境変数AWS_CA_BUNDLEに渡せば良い。
RockyLinux8 vps環境設定1) TeraTermからログインするまで

　WebArena Indigo及びKagoyaのRockyLinux8のVPSサーバを環境設定する機会を得た。WebArena IndigoはRockyLinux8.4、KagoyaはRockyLinux8.5だった。バージョンの違いのためであるかはわからないが、両者に微妙な違いがあった。設定方法を書き残しておく。

　WebArena Indigoについては、CentOS7、RockyLinux8、Ubuntu20.04LTS（一部まで）の3種類のOSでの環境設定を下記から始まるスレッドに記載してある。
https://qiita.com/naga_kt/items/0dd2f2e80bfd7a4666f8

# コントロールパネルでの設定【WebArena Indigoの場合】
　設定は以下に従ってやっていく。

コントロールパネルにログインする（Indigo）
https://help.arena.ne.jp/hc/ja/articles/360050605513/

SSH鍵を作成する（Indigo）
https://help.arena.ne.jp/hc/ja/articles/360049805674/

インスタンスを作成する（Indigo）
https://help.arena.ne.jp/hc/ja/articles/360049806534/

　ここでOSを選ぶようになる。

SSH接続でインスタンスにログインする（Indigo）
https://help.arena.ne.jp/hc/ja/articles/360049807634/

　ここにログインするために必要な情報は書いてある。

>ホスト名：作成したインスタンスのIPアドレス
パスフレーズ：空白
ポート：22
鍵：SSH鍵の秘密鍵（private_key.txt）
インスタンスのIPアドレスの確認方法：
[インスタンス管理]→[インスタンス]に移動し、作成したインスタンス名のIPアドレスの欄を確認してください。
ユーザ名：、rocky

 しかし、ログインするための具体的な手順はサポート外ということで書いてない。

# コントロールパネルでの設定【Kagoyaの場合】
　設定は以下に従ってやっていく。

ログイン用認証キー作成
https://support.kagoya.jp/vps/manual/index.php?action=artikel&cat=15&id=1&artlang=ja

インスタンス作成(Linux OS)
https://support.kagoya.jp/vps/manual/index.php?action=artikel&cat=16&id=55&artlang=ja

　ここでOSを選ぶようになる。

SSH接続の設定
https://support.kagoya.jp/vps/manual/index.php?action=artikel&cat=25&id=9&artlang=ja

Tera Term の設定方法
https://support.kagoya.jp/vps/manual/index.php?action=artikel&cat=26&id=11&artlang=ja

>ホスト名：作成したインスタンスのIPアドレス
パスフレーズ：空白
ポート：22
鍵：SSH鍵の秘密鍵（ダウンロードした名前.key）
ユーザ名：、root


# TeraTermでの設定
　PC上でTeraTermを用いて以下の方法でログインできるようにした。

1.TeraTermを起動して最初に表示される「新しい接続」の画面で「Cancel」をクリックする。

![a1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2384942/90df6580-ac72-7408-3706-0b0764637186.png)

2.ツールメニューの [設定(S)] から [SSH認証(A)] を選ぶ。

![a1_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2384942/f6d2c9ec-8446-4285-de5c-85336f78445e.png)

3.「SSH認証設定」画面で、[User name] にWebArena Indigoの場合は「rocky」、Kagoyaの場合は「root」を入力し、[Use RSA/DSA...] にチェックを入れ、ダウンロードした秘密鍵を指定する。「OK」をクリックする。


![a1_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2384942/9e074696-d086-bf9f-e6b9-8e020dd10a55.png)

4.TeraTermのツールメニュー [ファイル(F)] から [新しい接続(N)] を選ぶ。起動した「新しい接続」画面で、ホスト(T)にIPアドレス、TCPポート#(P)に22を入れる。「OK」をクリックする。

![a1_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2384942/6a113977-2d32-1d3c-2c42-3d2bfdddbb31.png)

5．「SSH認証」画面で「OK」をクリックする。

![a1_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2384942/3831de3e-4729-703c-29da-f436ab2f6d07.png)

6.TeraTermがWebArena Indigoの
/home/centos
に接続できる。

7.TeraTermのツールメニュー  [設定(S)] から [設定の保存(S)] を選んで、設定を保存しておく。



---

RockyLinux8 vps環境設定2) ユーザ追加
https://qiita.com/naga_kt/items/4b5cd8b37ef66018cec6
に続く。
【Swift】完全FreeなQRReaderを作った

当記事は以下の記事の派生です。
(この記事だけでも理解いただけるはずです。)

https://qiita.com/ikaruga/items/c0c591910577f64cc415

## アプリに特別な記載は要りません。

ライブラリ名：QRReader

https://github.com/kirasoga/QRReader

## demo動画

![Videotogif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633771/50595b94-57b2-4af2-e6f8-095558ae6daa.gif)

## 使い方
podが入っている前提で進みます。

### Installation(導入方法)
インストールするには Podfile に次の行を追加するだけです。

``` Podfile
pod 'QRReader'
```

### How to Use(利用方法)

インスタンスを作成する。

``` ViewController.swift
let myQRCodeReader = QRReader()
```

カメラの画面を表示する。delegateの紐付けがされる。(frameで読み込み範囲の設定もできる)

``` ViewController.swift
self.myQRCodeReader.setupCamera(vc:self)
```

QRコードを読み込んだ時の処理。
⚠️extensionに書いてください。

``` ViewController.swift
func metadataOutput(_ output: AVCaptureMetadataOutput,
                    didOutput metadataObjects: [AVMetadataObject],
                    from connection: AVCaptureConnection) {
    if let metadata = metadataObjects.first as? AVMetadataMachineReadableCodeObject {
        guard let barCode = self.myQRCodeReader.previewLayer.transformedMetadataObject(for: metadata),
              let barCode = barCode as? AVMetadataMachineReadableCodeObject else {
            return
        }
        // frame following mode(枠追従モード)
        self.myQRCodeReader.followingBorder(barCode.bounds)
        // stopCamera
        self.myQRCodeReader.stopCamera()
        
        if let str = metadata.stringValue {
              print(str)
        }
    }
}
```

Author(作成者)
KiraSoga, sogakira0202@gmail.com

## 最後に
iOSアプリ開発をしています。
主にSwiftですが、最近は熱が入ってきてFlutterも🦾
色々やってます。もし良かったら見てってください。

https://sogablog.net/
【備忘録】ALBアプリケーションベースのスティッキーセッションがfavicon.icoのせいで効かなかった話

業務で遭遇した現象でエビデンスも何もないし雑だが、自分用の備忘録として残しておく。

# 事象
AWS上に乗っけているオンラインアプリケーションに不具合があるとお客様から問い合わせがあった。事象は下記。

・アプリにログインしようとするとログインできずエラー画面が表示される
・エラー画面からログイン画面に戻り、再びログイン試行すると正常にログインできる
・ブラウザにはChrome、Edge(Chroniumu版)を使用。

# 環境
・ALB-EC2(webサーバ)-EC2(Apサーバ)-RDS‥という構成
・EC2とRDSはマルチAZ配置
・EC2(Apサーバ)にTomcatを導入しており、Javaアプリケーションが乗っている
・ALBにはアプリケーションベースのスティッキーセッションを設定しており、Tomcatが発行するCookie「JSESSIONID」に紐付けてCookie「AWSALBAPP-0」〜「AWSALBAPP-4」を発行するようになっている

# 原因
・ログを調査したところ、ログイン時にセッション切れが発生していたことが確認できた
・更にwiresharkを用いてパケットの中身を見たところ、ログイン画面アクセス時のfavicon.ico取得後に「AWSALBAPP-0」の値が空になっていることが確認できた
・「AWSALBAPP-0」の値が空になったことで、ログインボタンを押下した時のリクエストにてTomcatが初めて来たリクエストと認識し、新しいJSESSIONIDを発行
・その後の処理にて、JSESSIONIDが一致しないことでアプリ側のセッション有効性チェックに抵触してエラーとなっていた

# なぜfavicon.ico取得後に「AWSALBAPP-0」の値が空になったのか？
・クライアントからサーバ側にfavicon.ico取得リクエストを送る際にJSESSIONIDが付与されていなかった
・JSESSIONIDに依存するAWSALBAPP-0の値も空になった

# なぜfavicon.ico取得時にJSESSIONIDが付与されていなかったのか
・HTMLにfavicon.icoへのリンクが記載されていなかったことが原因。
・リンクが記載されていないとブラウザのデフォルト挙動でfavicon.icoを取得しようとするが、その際JSESSIONIDが付与されないらしい。([Chromeのセッションがリクエストされないときはfavicon.icoがないからかも](https://lets-try-simo2.net/chrome-jsessionid/)を参考にした推測)

なお、2回目以降にログインエラーが発生しなかった理由は、favicon.icoの取得リクエストが送られていなかったからだった。(おそらく「favicon.icoがない」という情報がブラウザにキャッシュされるから？)

# 解決策
アプリのjspに、favicon.icoへのリンクを明示的に設定してあげたら、取得時のリクエストにJSESSIONIDが付与されるようになり、AWSALBAPP-0の値も空にならなくなり、セッションエラーも発生しなくなった。
ブランクありのエンジニアが現場復帰して躓いたこと part.1

## これは何？
エンジニアブランク4年強(もう素人)の私が、エンジニア復帰後に、悩んだことや学んだことを定期的に記事にしていければと思い、書いているものになります。
同じような悩みに至った方や共感できる方はいいねいただけると嬉しいです！
※使用中の技術 Ruby on Rails / React（TypeScript）
※ブランクの期間は、マーケティングをしておりました。


# ~ Pager編 ~  
![スクリーンショット 2022-09-17 12.28.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2322481/6f92b9c8-8db3-ac65-082d-ef29a6de7526.png)

ショッピングサイトでよく見かけるページ送りの処理を実装しようと思い、参考になりそうな他ページのプログラムを見つけにいく。(コピペ戦略です)
それっぽいの見つかりホッと一安心と思いきや

```ruby: SnapshotsController.rb
...

SNAPSHOTS_COUNT_PER_PAGE = 10
@item.snapshots.page(params[:page]).per(SNAPSHOTS_COUNT_PER_PAGE)

...
```

:thinking: **悩み**
→ Active Recordの機能にpage / per なんてあったっけ？どっからこのメソッド出てきた？
→ そもそもControllerでのページ送りの処理この1行だけ？
→ 昔、PHPとかでpagerの処理は愚直に書いたことがあるので、下記みたいな**総ページ数**や**現在のページ数**などを取得する処理がどこかにあるはずと思っていた。
```ruby
...

def total_page
    @total_page ||= [(snapshots_count / SNAPSHOTS_COUNT_PER_PAGE.to_f).ceil, 1].max
end

def current_page
    @current_page ||= params[:page].present? && params[:page].to_i.in?(1..total_page) ? params[:page].to_i : 1
end

..
```


:ok_woman: **答え**
`kaminari` というGemを使用していた。
→[【rails】kaminariを使ってページネーションを作る - Qiita](https://qiita.com/you8/items/df68aaee3010e282d1ae)

:thinking:感想
世の中には便利なGemがいっぱいあるなと思いつつ、プログラムの中でいきなり出てくると「どっから出てきた？」となってしまうので、今使用しているGemがどのような場面で使用されているのかのリスト(エクセルでもなんでも)があると開発効率が上がりそうと思いました。



# ~ 突然出てくるやつ編 ~

```ruby:article_findable.rb 
module ControllerConcerns
  module ArticleFindable
    private

    # @return [Article]
    # @raise [ActiveRecord::RecordNotFound]
    def find_article!
      article = current_user.articles.find_by!(uuid: params[:article_id])
      fail ::Article::PermissionError unless article.try(:readable_by?, current_user)

      article
    end
  end
end
```


:information_desk_person: **前提**
→ article_findable.rb というファイルに下記みたいな修正の pull request が届いたとします。
(実際にはこのような簡単な内容ではないです)
```diff_ruby
- article = current_user.articles.find_by!(id: params[:id])
+ article = current_user.articles.find_by!(uuid: params[:article_id])
``` 

:thinking: **悩み**
→ `current_user` とか `params` とかって、どっから出てくるの？


:ok_woman: **答え**
→ Controllerからincludeされることを前提に作成されているため、そちら側に `current_user`が存在している。


:thinking:感想
少し考えればわかるので、少し大袈裟に書いています。
include の他にも、 継承 / mix-in / extend など拡張の方法は色々あると思いますが、継承以外は、ある程度前提の知識がないと途端にプログラムが追いづらくなるのかなと思った次第です。
意図しないクラスから呼び出される場合もあると思いますし、個人的には、設計を工夫して可能な限り継承以外の拡張機能はあまり使いたくないなと思ってしまいました (慣れてきたら考えは変わるとは思います)


# 最後に
今後も躓いたポイントなどがあった際には、どんどん記事にしていこうと思っています。
また、まだ知識が浅いので、誤った表現などあれば指摘いただけますと幸いです。
私が使ってきた中で特に便利だと感じたChromeの拡張機能 2個

## これは何？
世の中には無数の拡張機能があると思いますが、その中でも私が特に便利に感じた拡張機能を紹介します。
基本は独断と偏見にはなりますが、画面共有した際に数人から `その拡張機能なんですか?` って聞かれるくらいには必要としている人がいると思います。

また、過去に紹介されている方もいるようでしたが、古い記事が多かったのと2つ合わせて紹介している記事はなかったため、改めてこの拡張機能が広まると良いなと思ってます。

## Copytables
- Webページ内にあるテーブルの特定の列の内容だけコピーしたい時がないですか？
- テーブル選択範囲の数やエクセルみたいに選択範囲の計算がしたい時がないですか？

**そんな課題を解決してくれるのが、この【[Copytables](https://chrome.google.com/webstore/detail/copytables/ekdpkppgmlalfkphpibadldikjimijon?hl=ja)】です。**



## 使い方
- 例えば下記のような表があったとして、投稿数の列の値だけコピーしたいとなった場合

|チーム名|メンバー数 |投稿数| 作成日 |
|-|-|-|-|
|A-team|13|32|2022-04-01|
|B-team|109|568|2022-02-03|
|C-team|56|254|2022-01-01|
|D-team|33|45|2022-09-17|

普通にやると。。
<img width="400" alt="表1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2322481/5aa29030-0338-ad39-3938-e03f70810c63.png"/>


Copytablesを入れていると、特定のKey(私の場合はMacでoption) を押しながら選択すると特定列のみのコピーが可能です。
また、同時に画面の左上にエクセルのように選択範囲の個数や計算結果が出ます。
<img width="400" alt="表2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2322481/f0a4a40f-1c52-72f4-730e-f243b932a9ce.png"/>
<img width="400" alt="計算式" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2322481/09492049-0dbd-c333-9bd4-9e6f532dadf7.png" >

Re:dashなどのBIツールの表の一部を使って、**SQLのIN句などに使いたい時** / **テストデータとして一旦配列とかに入れたい時** / **エクセルにコピーしたい時**などにとても役に立ちました。



## Slack Channels Grouping
- リモートワークの広がりによって、さらに広く使われているチャットアプリの「Slack」
- 便利が故にチャンネル数が多くなりチャンネルが見辛くなってないですか？

**そんな課題を解決してくれるのが、この【[Slack Channels Grouping](https://chrome.google.com/webstore/detail/slack-channels-grouping/lcbnhfianneihfgkmfncnhpkpghedbkm)】です。**


## 使い方
- 使い方はとても簡単で、ただインストールするだけで、ハイフン (-) とアンダースコア (_) で命名規則を揃えていただいていれば、階層関係のようにチャンネルリストを整理してくれます！

![unnamed.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2322481/ae60e415-83c0-5633-aaf5-6e9fe03c0f53.jpeg)


これでチャンネル迷子にならずにすみますね！迷わずに済んだ時間だけ開発に使えます！
作者の方も記事をあげているようでしたのでリンクさせていただきます。
https://qiita.com/yamadashy/items/9480cf4f9c9419b76d90


## 最後に
- 今回は紹介だけで終わってしまいましたが、次回は実際に独自の拡張機能なんかを作れたら良いなと思っています。。
- 最後まで見ていただきありがとうございました。