OmniAICreator/Qiita-1.07M huggingface dataset:
sendmsg: Invalid argument

# 概要
UDPでsendmsgをしようとした際に以下のエラーが出力されたのでその対応メモ

```
sendmsg: Invalid argument
```

# 詳細

以下はエラーが発生した際のsendmsgする関数の一部抜粋です。

```
void sender(struct addrinfo *res_local, struct addrinfo *res_remote, unsigned int usecs) {

    int sock;
    unsigned char buf[BUF_LEN] = {"0"};
    unsigned char buf2[BUF_LEN] = {"0"};

    sock = socket(res_remote->ai_family, res_remote->ai_socktype, res_remote->ai_protocol);
    
    struct iovec iov[2];
    iov[0].iov_base = (void*) buf;
    iov[0].iov_len = sizeof(buf);
    iov[1].iov_base = (void*) buf2;
    iov[1].iov_len = sizeof(buf2);

    struct msghdr msg;

    msg.msg_name = (void *) res_remote->ai_addr;
    msg.msg_namelen = res_remote->ai_addrlen;
    
    msg.msg_iov = iov;
    msg.msg_iovlen = 2;
    
    while (1) {
        errno = 0;
        int k = sendmsg(sock, &msg, 0); 
        if (k < 1) {
            if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
                perror("sendmsg EAGAIN?");
            } else {
                perror("sendmsg");
                return;
            }   
        }   
        fprintf(stderr,".");
        usleep(usecs);
    }   

    close(sock);

}
```

msghdr構造体を宣言時に初期化をすれば、「Invalid argument」が出なくなったことを確認しました。

```
struct msghdr msg = {};
```
SSH接続でrootログインを無効化して新しいユーザーでログインする方法（あんま良くないけど既存の公開鍵を流用する場合）

# 概要
 - サーバーにrootでログインするのはセキュリティ上よくないので，新しいユーザーを作ってそれを使わないとSSHで接続できないようにしたい．
 - パスワードログインも使えないようにしたい．
 - (セキュリティ的に良くないけども)すでにrootで登録した公開鍵(authorized_keys)を新しいユーザーでもそのまま流用したい
    - この記事では鍵生成はクライアント側で行っているという前提で話を勧めます．

## 環境
- サーバー(ホスト) : Ubuntu 20.04 LTS (ConoHa VPS)

## 留意事項
 - **手順[3]で，新しいユーザーでSSHログインが可能になったのを確認するまでは，手順[4]には絶対に進まないでください．下手するとサーバーから締め出され二度とログインができなくなります**

# [1] 新しいユーザーを作成
rootでサーバーにログインし，以下のコマンドで新しいユーザーを作成してください．`<username>`は使いたいユーザー名に置き換えてください．

```
adduser <username>
```

パスワードを二回聞かれますので，使いたいパスワードを入力し次へ進んでください．

その後，ユーザーのプロフィールに関する質問(フルネームや電話番号など)を聞いてくる場合がありますが，空欄のまま全部スキップしてください．最後に `Is the information correct?` と聞かれたら，`Yes`と入力して完了です．

作成したユーザーを，`sudo` グループに追加します．

```
gpasswd -a <username> sudo
```

## 参考にさせていただいた記事

ubuntu ユーザを追加して sudo 権限をつける - Qiita
https://qiita.com/white_aspara25/items/c1b9d02310b4731bfbaa

# [2] 公開鍵ファイルのコピー

新しく作成したユーザーに公開鍵のファイルをコピーします．

```
mkdir /home/<username>/.ssh
cp /root/.ssh/authorized_keys /home/<username>/.ssh/authorized_keys
```

先ほど作成した `.ssh` フォルダと，コピーした公開鍵ファイルのパーミッションと所有者を変更します．これをしないと新しいユーザーでログインができません．

```
cd /home/<username>
chmod 700 .ssh
chmod 600 .ssh/authorized_keys
chown -R <username> .ssh
```

念のため，ここでサービスを再起動しておきます．

```
systemctl restart sshd
```

これで**新しいユーザーでも**，同じ鍵ペアで**ログインが可能**になります．

# [3] 新しいユーザーでログインできるか確かめる

一度サーバーからログアウトし，先ほど作成したユーザーで公開鍵暗号方式でログインしてみます．クライアント側でOpenSSHを使っていて，`.ssh/config` にホスト情報を記載している場合は， `root@<ホスト名>` のrootの部分を新しいユーザー名に書き換えるだけでOKです．

# [4] SSHの設定を変更する

**新しいユーザーでログインできると確認できてから**，サーバー側のSSH設定を変更します．ターミナル上で使えるテキストエディタを，サーバーに用意しておいてください．(ここではVimを使っています)

```
sudo vim /etc/ssh/sshd_config 
```

sshd_configのファイルで，以下の設定が書かれている行を見つけ，それぞれ設定を書き換えてください．このファイルでは，先頭が#で始まる行はコメント扱いとなっていますので，コメントアウトされていたら先頭の#を取り除いてください．(以下の設定項目はconfigファイルとは順不同です)

```
PermitRootLogin no
PasswordAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
```

サービスを再起動すると設定が反映されます．

```
sudo systemctl restart sshd
```

これで**rootログインとパスワードを使ったログイン**ができなくなります．

念のため，rootユーザーの公開鍵ファイルも削除しておきましょう．

```
su
Password: <rootユーザーのパスワード>
rm /root/.ssh/authorized_keys
exit
```

以上で一連の作業は終了となります．お疲れ様でした．
AmplifyとEC2の通信でハマったところ

# 構成
フロント
React→Amplify
サーバー
Rails→EC2 + RDS

以下のように通信が流れるようなインフラを作った。その時詰まったところをまとめ。
ちょっと雑なので後で見返して修正する。正直ハマりすぎて疲れた。。。
Amplify→Route53→ELB→EC2→RDS

# EC2のSSL化
当然っちゃ当然だけどAmplify側がHTTPSなのでEC2もHTTPS化する必要あり。

### 設定時につまずいたところ
unicornでポート指定してなかった→listenの設定
unicornだと80番使えない。80番はルート権限でしか使えない→nginx経由でソケット通信させる仕様に変更
ルートパスにルーティングが組まれていない場合ELBのヘルスチェックでこけるのでヘルスチェックのURLをカスタムする

# CORS設定
React側から通信するときにCORSの設定ができていなくてエラーになった。
そのときにやった設定

**axios側**

```ts
export const api = axiosBase.create({
  baseURL:
    process.env.NODE_ENV === 'production'
      ? `本番URL`
      : 'ローカルURL',
  responseType: 'json',
  withCredentials: true,
  headers: {
    ContentType: 'application/json',
    Accept: 'application/json',
  },
})
```
`withCredential: true` というのがどうも重要みたい


**rails側**

```ruby
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins "http://localhost:3000", "フロント側の本番URL"

    resource "*",
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head],
      credentials: true
  end
end
```
Rails側でもcredentials: trueを入れる必要がありそう？

どうもoriginが
`"https://hogehoge.com/"`みたく最後にスラッシュがついてるとエラーになるっぽい？
これのせいで30分以上ハマった

# RDSの文字コード設定
RDSのデフォルト設定では日本語を受け付けないようで、以下のようなエラーに。
```
ActiveRecord::StatementInvalid (Mysql2::E
rror: Incorrect string value: '\xE3\x83\x9B\xE3\x82\xB2' for column 'name' at ro
w 1):
```

### 解決策
パラメータグループでutf-8で保存するようにする
すでにrailsでマイグレーション済みの場合にはmigrate:resetして文字コードを適用させる
Windows10のRstanの実行エラー:Error in prep_call_sampler(object) :の対処

#1.実行環境
```
OS:windows10
R:Version 4.1.0 
Rstudio:Version 1.4.1717
rstan:2.21.2
```

#2.トラブル
WindowsでRstanを動かすと、最近、このようなエラーが出て止まってしまうことが多くて困っていました。

```R:console
Warning in system(paste(CXX, ARGS), ignore.stdout = TRUE, ignore.stderr = TRUE) :
  'C:/Rtools/mingw_/bin/g++' not found
Error in prep_call_sampler(object) : 
  the compiled object from C++ code for this model is invalid, possible reasons:
  - compiled with save_dso=FALSE;
  - compiled on a different platform;
  - does not exist (created from reading csv files).
```
Warningは気にしなくてもよいみたいですが、Error in prep_call_sampler(object) :以下が出て止まります。

Ubuntu版RとWindows版Rの２つを使っていたのが悪かったのだろうかと思っていました。

#3.解決！

![gamen.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161102/15f1a06d-c182-9ea5-a267-9018377423be.png)

作業ディレクトリの中のRdataファイルを削除して、Rstudioを再起動すると直りました。
Rの削除、再インストール、rstanのversionを落とす等もいろいろと試しましたが、最終的には実に簡単に直りました。

#4.Enjoy
AtCoderログ：0061 - AGC 012 A  

# 問題

https://atcoder.jp/contests/agc012/tasks/agc012_a

## 問題文
> AtCoder Group Contestの参加者に $3N$ 人が参加します。$i$ 番目の参加者の 強さ は整数 $a_i$ で表されます。参加者が $3$ 人 $1$ 組となるようにチームを $N$ 組作ることにしました。$1$ 人の参加者が複数のチームに所属することはできません。
> チームの強さはチームメンバーの強さのうち $2$ 番目に大きい値で表されます。 例えば、強さが $1,5,2$ のメンバーからなるチームの強さは 
$2$ になり、強さが $3,2,3$ のメンバーからなるチームの強さは 
$3$ になります。
> $N$ 組のチームの強さの和としてありうる値のうち、最大の値を求めてください。

## 制約
> ・$1 \le N \le 10^5$
> ・$1 \le a_i \le 10^9$
> ・$a_i$ は整数

## 収録されている問題セット
- [AtCoder に登録したら次にやること](https://qiita.com/drken/items/fd4e5e3630d0f5859067) ([第06問類題](https://qiita.com/drken/items/fd4e5e3630d0f5859067#%E7%AC%AC-6-%E5%95%8F--abc-088-b---card-game-for-two-200-%E7%82%B9))

# 回答
## 回答1 (AC)
最もシンプルなアプローチは全探索です。しかし、最初のチームは $3N$ 人から $3$ 人を選ぶので $O(N^3)$ 通りの場合があり、これだけでTLEになっていまいます。そこで全探索しない方法が必要です。

$3N$ 人の参加者を強い順にソートし、強い方から $N$ 人を $\square$、次の $N$ 人を $\circ$、最後の $N$ 人を $\triangle$ で表すことにします。今、$i$ 番目のチームに $\triangle$ が2人いる、つまり $(＊, \triangle, \triangle)$ になったとしましょう。ここでチーム内の表記は強い順とし、＊ は $\square, \circ, \triangle$ のいずれかを表します。$\triangle$ は全部で $N$ 人なので、どこかに $\triangle$ が含まれないチームがいるはずで、それを $j$ 番目のチームとします。$j$ 番目のチームの $3$ 人目が $\circ$ であったとすると、$i$ 番目の $2$ 人目と $j$ 番目のチームの $3$ 人目を入れ替えることで、$i$ 番目のチームの強さは $\triangle$ から $\circ$ に上昇するので、入れ替えた方がチームの強さの総和は大きくなります。$j$ 番目のチームの $3$ 人目が $\square$ の場合も同様です。このような操作を繰り返すことにより、チームの強さの総和を最大にするには、全てのチームの $3$ 人目は $\trianble$ になっている必要があることがわかります。

![agc012a-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1589302/aacee784-0723-f1cc-1915-080257ee3f33.png)

$N$ チームの $1$ 人目と $2$ 人目を全探索しようとしてもまだ計算量が大きいので、さらなる工夫が必要です。$\circ$ の中で強い順に $\circ(1)$ $, \circ(2),\dots,\circ(N-1),\circ(N)$ とかきます (丸囲み数字と思ってください)。$i$ 番目のチームに $\circ(N-1)$ が、$j$ 番目のチームに $\circ(N)$ が所属しているとすると、$\circ(N-1)$ と $\circ(N)$ はどちらも $2$ 人目になっているはずです。そこで $i$ 番目のチームの $2$ 人目 (つまり $\circ{(N-1)}$ と $j$ 番目のチームの $1$ 人目を入れ替えると、$i$ 番目のチームの $2$ 人目は＊となるので、チームの強さの総和は増大します。つまり $\circ{(N-1)}$ と $\circ{(N)}$ は同じチームに所属した方が良いのです。

![agc012a-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1589302/058c7992-9853-37d1-709c-1a6e6f482541.png)

同様に考えることで、$\circ{(N-3)}$ と $\circ{(N-2)}$ は同じチーム、...、$\square(1)$ と $\square(2)$ は同じチームに所属するのが良くて、チームの強さの総和が最大になるのは以下のような場合であることがわかります。このとき、チームの強さの総和は「$2$ 人目の強さ+$4$ 人目の強さ+...+ $2N$ 人目の強さ」となります。

![agc012a-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1589302/4a53ed9e-3681-a71a-6108-45d9b136d3e9.png)

上記の考察により、チームの強さの総和になる場合が特定できました。コードの処理としては、$3N$ 人のメンバーの強さを配列 a() で受け取り、強い順 (降順) にソートし、1 人目, 3 人目, ..., 2n-1 人目の強さの合計を出力すれば良いでしょう。コードではインデックスが 0 から始まるため、上記の考察とインデックスがずれていることに注意してください。コードは以下のようになりました。

```C++:agc012a-1.cpp
#include <bits/stdc++.h>
using namespace std;
 
int main() {
  int n;
  cin >> n;

  vector<int> a( 3*n, 0 );
  for ( int i=0; i<3*n; i++ ) {
    cin >> a.at(i);
  }
 
  sort( a.rbegin(), a.rend() );
  
  int64_t sum = 0;
  for ( int i=0; i<n; i++ ) {
    sum += a.at(2*i+1);
  }
 
  cout << sum << endl;
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/agc012/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/agc012/editorial.pdf)
回答1と同じ方針でした。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0060 - ABC 156 C](https://qiita.com/RoadLynton/items/5a8edde41621903ba438)
小さなDX②：python sqlite3で食事の内容を決める

#カロリー表データベースを見て、食事を決める。
何を食べるかを考える・悩む時間をなくすことで、時間を有効活用する。
やせたいので、カロリーを意識した食生活にする

参考（sqlite3操作）：https://qiita.com/saira/items/e08c8849cea6c3b5eb0c
##目次
1.条件、ルール
2.Excelで作成したカロリー表をpandasで読み込む
3.pandasで読み込んだデータをデータベース化（.db）する
4.データベースからカロリーとその食物を出力する

###1.条件、ルール
・食べるものはデータベースに登録されたものだけとする。
・1日の摂取カロリーの目安を2300kcalとして、この値を超えないようにする。
・飲み物は、水、コーヒー、ビールしか飲まないので、ビールだけ意識。
・食べたいものが増えたらデータベースに追加する。
（悩む時間の削減と1日の摂取カロリーが上限超えなければ良い）
###2.Excelで作成したカロリー表をpandasで読み込む
```python:pandas,excelデータ読み込み
import pandas as pd

#excelデータは事前に作成。
#１列目には食べ物の名称、２列目にはそのカロリー（kcal）がまとめてある
df = pd.read_excel("kcal_table.xlsx")
```
3.pandasで読み込んだデータをデータベース化（.db）する

```python:sqlite3
import sqlite3

#データファイルの名称はカロリー.db
dbname = "カロリー.db"
conn = sqlite3.connect(dbname)
cur = conn.cursor()

#テーブル名をfoodsとし、if_exists="replace"で書き換え設定とした
df.to_sql("foods",conn,if_exists="replace",index=None)

conn.commit()
conn.close
```
###4.データベースからカロリーとその食物を出力する
```python:データベース出力
import sqlite3

#作成したカロリー.dbを操作
dbname = "カロリー.db"
conn = sqlite3.connect(dbname)
cur = conn.cursor()

#データが多くなると、大量に出力されるかもしれないと考え、下限を設定
#食事の下限カロリーを入力
print("下限値を入力")
under = int(input())

#食事の上限カロリーを入力
print("上限値を入力")
upper = int(input())

#where kcal BETWEENで、kcalフィールド内で下限〜上限値内である食事を選択
#order by kcal desc で、kcalフィールドの値を降順で出力
select_sql = f'SELECT * FROM foods where kcal BETWEEN {under} and {upper} order by kcal desc'

#このexcelデータの場合、cur.execute(select_sql)の結果は、食事名とカロリーの組み合わせがリスト化されている
#[(豆腐,９０kcal),(食事名,カロリー),...]のように。
#なので、for文を使って出力
for row in cur.execute(select_sql):
    print(row)

cur.close()
conn.close()
```
※mac ターミナルでの出力結果
![screen 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698556/5d2538f9-33a8-6ccb-8b08-94fb0f9dfef7.png)

##所感
データベース、SQLは使い慣れていないため、いい勉強になりました。

ただ、上画像を見る限り、ろくな食生活でなさそうです。
DXより食事の質を改善した方がいいかもしれない。
git checkout ブランチをした際の Your branch is ahead ofの意味

そしてgit checkout task2-1をしたところ、次の様に表示されました。

Your branch is ahead of 'origin/task2-1' by 1 commit.
(use "git push" to publish your local commits)

意味としては、
リモートの task2-1 ブランチに対して、ローカルのtask2-1ブランチが1コミット進んでます。
"git push" 使って、あなたのローカルのコミットを公開してください。

と言われています。

初学者向けに「コミットが進んでいる」ということがどういうことかといいますと、コミットが1つ多い、と言う意味です。
（当てはまる言葉が見つからないので見つかりましたが追記します。）

したがって、指示にしたがっても良いのであれば従いましょう。




ローカルリポジトリの task2-1 ブランチのコミットを
リモートリポジトリの master ブランチに push すればOKです。

git push origin [ローカルブランチ]:[リモートブランチ]

の書き方になります。

この書き方で、

[ローカルブランチ]を[リモートブランチ]に pushできます。
Docker内mysqlを繋ぐまでの話。【コピーOK】

環境

mysql8.0.9
rails2.6.3

config/database.ymlファイルは以下の通り。




config/database.yml
default: &default
adapter: mysql2 #使うデータベースはmysqlを宣言する。アプリ内にもインストールしといてください。
encoding: utf8mb4
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
username: root #mysqlのユーザ名です。docker_compose.ymlmのMYSQL_USERと同じにする必要があります。
password: password #mysqlにログインするために必要なパスワード。docker_compose.ymlmのMYSQL_PASSWORDと同じにする必要がある。

development:
<<: *default
host: db #docker_compose.ymlと同じにする必要がある。今回はdbという名前になります。
database: portfolio_development #docker_compose.ymlのMYSQL_DATABASEと同じ名前にする必要がある。

test:
<<: *default
database: portfolio_test #ここはとりあえずこの名前にしとく。

production:
<<: *default
database: AWSのRDSの識別子
host: エンドポイント
docker_compose.ymlファイルは以下の通り。

わかりやすいように環境変数を使わない形で記述しました。実際に参考にする場合は環境変数を使用してください。

docker_compose.yml
version: '3'
services:
db: #database.ymlのhostと同じにする必要がある。今回はdbという名前にします。
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: password #必須です。ないと動きません。docker_compose.ymlファイルだけに書けばOKです。
MYSQL_DATABASE: portfolio_development #database.ymlのdevelopmentと同じ名前にする必要があります。
MYSQL_USER: root #mysqlにログインするユーザー。database.ymlのusernameと同じにする必要がある。
MYSQL_PASSWORD: password #mysqlにログインするパスワードです。自身で設定する必要があり、database.ymlのpasswordと同じにする必要がある。
ports:
- '3306:3306'
command: --default-authentication-plugin=mysql_native_password
volumes:
- ./tmp/db:/var/lib/mysql/data
web:
build: .
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
volumes:
- .:/myapp
ports:
- "3000:3000"
depends_on:
- db
stdin_open: true
tty: true
command: bundle exec rails server -b 0.0.0.0
volumes:
mysql-data:
driver: local




上記ファイルのポイント

・ローカルアプリ内のdocker-compose.ymlファイルにはMYSQL_ROOT_PASSWORDが必須。

・ローカルアプリ内のdocker-compose.ymlファイル内のコンテナ名を、database.ymlファイル内のdevelopment内のhost名にする必要がある。

・docker-compose.ymlファイル内のMYSQL_USER名とMYSQL_PASSWORDはdatabase.ymlファイルで設定したユーザ名、パスワード名と一致させる必要がある。

・MYSQL_ROOT_PASSWORDはdocker-compose.ymlファイル内で定義する。

・dockr-compose.ymlファイルのMYSQL_DATABASEはdatabase.ymlファイルで設定したdatabase:と同じにする。

これら5こ覚えてりゃOK。だいたいミスするのは上記の部分。

つまづいた点

Unknown MySQL server host 'db' (-2)。

gemfile内のdevwlopmentnimysql2を書いてなかったのが原因かも。
他にも解決策はあるので注意。

Docker内でmysqlを繋ぐ際に便利なコマンド
mysql -u root -p

ユーザ名が合わなくて何度も使った。
mysqlにログインする。事前にmysql.server startを行う必要がある。
このコマンドを入力した後にパスワードを求められるが、初めて使用する場合は間髪入れずエンター押してもOK。その場合のパスワードは空白になる。そんな感じでいろいろパスワードを決めれます。
初めてではない場合は登録しているパスワードを入力して、中でパスワードを更新する必要がある。この更新のsql文がmysqlのバージョンによって異なるようなので注意。
当然パスワードを空白にすればdatabase.ymlとdocker_compose.ymlのパスワードの欄は空白で良い。

docker rmi $(docker images -q)

イメージを削除する。ちょっと危険。

docker-compose down --volumes

ボリュームを削除する。
database.yml、dockder_compose.ymlが正しく入力されているのにUnknown database ''とか言われる場合は過去のボリュームを参考にしてる場合が多い。

docker-compose up -d --build




コンテナの作成。

docker rmi ID名 -f

強制削除。docker imagesで表示したイメージ名のIDを指定すれば削除できる。
gitのエラーUpdates were rejected because the remote contains work that you do not have locally. 〜the remote changes (e.g., 'git pull ...') before pushing again.の解決法

前提

・現在ブランチAにいる。
・ブランチAでgit add、git commit -m"メッセージ"、git push origin ブランチAをした。
・git checkout masterをし、masterブランチでgit merge ブランチAをした。
・リモートのmasterブランチに反映させるために、masterブランチにいる状態でgit push origin masterをしたところ、次のように表示された。

hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.




原因

the remote contains work that you dohint: not have locally.
→リモートはあなたがローカルで持ってないworkを持っている。

つまりリモートリポジトリ（github上のリポジトリ）のmasterブランチには存在するのに，ローカルのmasterブランチには存在しないcommitがあるということ。

「リモートリポジトリのmasterブランチにはコミットhogehogeがあるのに、なんでローカルのmasterブランチにはコミットhogehogeがないの？おかしくね？」と言われています。

手順

・masterブランチにいる状態でgit checkout -b ブランチBをすることによって、git pull origin masterをする用のブランチBを作成し、ブランチBに移動する。
・git pull origin masterをしてリモートリポジトリのmasterブランチをローカル環境のブランチBのなかにpullする。

・するとローカル環境がリモートリポジトリのmasterブランチの内容に変わる（ブランチ名はブランチBとなっています）のでいったん本当にこれをローカルのmasterブランチにpushして良いのかを確認する。

・オッケーだったらgit add、git commit -m"メッセージ"、git push origin ブランチBをする。

・そしてgit checkout masterをしてmasterブランチに移動し、git merge ブランチBをする。

そしてマージした内容をリモートリポジトリのmasterブランチに反映させるためにgit push origin masterをする。

以下、手順の部分をコマンドに置き換えました。

$ git checkout -b ブランチ2 #masterブランチにいる状態で行ってください！

$ git pull origin master

$ git add -A

$ git commit -m"メッセージ"

$ git push origin ブランチB

$ git checkout master

$ git merge ブランチB

$ git push origin master




ポイント

リモートリポジトリのmasterブランチを反映させるためのブランチを作成することが大事。記事中だとブランチBがその役割。
開発中においてテストブランチの方ではな、直でmasterブランチにgit pull origin masterするのは危険です。
Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.などのnginx周りのファイルのエラーを知るコマンド

sudo systemctl start nginxをしたら次のエラー

Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.

解決法
sudo nginx -tコマンドを使用する

sudo nginx -tを使用すると細かなミスに気がつくことができます。

systemctl status nginx.serviceだと起動に成功しているか、していないかを判別することしかできません。

sudo nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: [emerg] open() "/var/www/rails/Portfolio/current/log/nginx.access.log" failed (2: No such file or directory)
nginx: configuration file /etc/nginx/nginx.conf test failed
[shogo@ip-10-0-0-193 Portfolio]$



この場合current/log/nginx.access.logファイルを作成すればok。
Dockerfile、docker-compose.ymlの中身で使われるコマンドや意味の説明

コンテナ

仮想環境そのもの。

イメージ

Dockerコンテナを実行する際に必要なもの。

Dockerfile

Dockerのイメージを自動で作成してくれるファイル。

Docker compose

複数のコンテナからなるサービスを構築、実行する手順を自動的にし、管理を用意にする機能。```docker compose hogehoge``` というコマンドを実行することで、そのファイルから設定を読みこんえ全てのコンテナを起動することができる。

Dockerfileの中身でよく使われるコマンド
FROM

使用するイメージとバージョン

-qq

エラー以外何も吐かないようにする

-y

全てyesで実行する設定。これなしだと途中で止まってしまうので自動的でイエスで進んでもらうために必要。

RUN

コマンドの実行

WORKDIR

作業ディレクトリ先の設定

COPY

コピー元とコピー先のファイルまたはディレクトリを指定

docker-compose.ymlで使われるコマンド
service

アプリケーションを動かすための各要素のこと。
通常はwebとdb（Mysql、Postgresql）と名前をつける。

rm -f tmp/pids/server.pid

pidはプロセスIDのこと。pidはそもそも開発用サーバーを起動するときにtmp/pids/server.pidに書き込まれる。終了するときにserver.pidが削除される。
server.pidが書かれているとサーバーが起動中と判断される。rails sが実行できないときにserver.pidを削除するとうまくいく可能性がある。終了する際にはrmによって削除する必要がある。

ports
ports:
- "3000:3000"

コンテナ内のポート3000番をホストの3000番にマッピングする。コンテナ内に立てたサーバにhttp://localhost:3000でアクセスできるようになる。
これがないとコンテナにアクセスできない。
例えば、下記のようにするとhttp://localhost:3001でコンテナ内に立てたサーバにアクセスできる。

ports:
- "3001:3000"





volumes
volumes:
- ./db/mysql/volumes:var/lib/mysql




データを永続化するためにある。
コンテナは消すことができるが、仮装環境を捨ててしまうとデータベースも一緒に破棄されてしまう。volumesを捨てるとデータを永続化することができる。
ホストの./db/mysql/volumesをコンテナ内の/var/lib/mysqlにマウント（同期）するという意味。
Dockerのコンテナとローカルのファイルを同期している。つまりdockerのコンテナが破棄されてもローカルのファイルが残っているという事になる。

.がホストのディレクトリ全てを意味している。
エラーAn error occurred while installing mysql2 (0.5.3), and Bundler cannot continue. Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/'` succeeds before bundling.の解決方法

何回も忘れるのでメモ。

原因

Gemfile内にmysql2を書いてない。

解決法

ターミナルで下記を打ち込む。

$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl/lib"

Gemfileに下記をかいて、bundle installする。




gem 'mysql2', '~>0.5.3'




なぐり書き
rails s 時のエラー「Address already in use - bind(2) for "0.0.0.0" port 3000」の解決法【初心者】

結論：別のポートで立ち上げるのが早い
rails s -p 3001

というコマンドを入力すればOKです。

サーバーを立ち上げる際のlocalhost:3000は実は3000以外にも数字があるので3001番などで立ち上げるのが手っ取り早いです。

エラー内容

rails sをすると以下のようなエラーが出ます。

/Users/shogo/environment/sample_app/vendor/bundle/ruby/2.6.0/gems/puma-3.9.1/lib/puma/binder.rb:269:in initialize': Address already in use - bind(2) for "0.0.0.0" port 3000 (Errno::EADDRINUSE)




解決方法

localhost:3000が使われているという意味なので、localhost:3001番でサーバーを立ち上げてあげます。

以下のコマンドをターミナルに入力します。

rails s -p 3001

これで解決です。

どうしても3000番でサーバーを立ち上げたいということであれば以下のURLを参考にしてください。

備忘録として手短に。何かあれば追記します。


もっと詳しくみるにはこちら
Dockerコンテナネットワークにコンテナの残骸が残ってしまった場合の対処記録


Docker コンテナネットワークにコンテナの残骸が残ってしまった場合の対処記録

ここではコンテナネットワークを「`nginx_default`」として、
コンテナは docker ps -a でも存在しない状態とする.

#### エラーログ

> ERROR: error while removing network: network nginx_default id 1579f5ba164110a988d35967a5aa3133a65d4d465662afa54de51ad6a0494001 has active endpoints

#### 参考にした記事

https://qiita.com/shundayo/items/8b24af5239d9162b253c


#### 手順

ネットワーク「`nginx_default`」に残っているコンテナを探し出す

```bash
$ docker inspect nginx_default
略
        "Containers": {
            "61025d49a6b27cb53b11b8fb449ba2d3566aea5304e300248ce46a71c4539f57": {
                "Name": 🛑"myfld_elasticsearch_fluentd2",
                "EndpointID": "7cf55e3f906d313d09bffa25d3e990036483e248cc68a91c77f1adeb34182d74",
                "MacAddress": "02:42:ac:1b:00:06",
                "IPv4Address": "172.27.0.6/16",
                "IPv6Address": ""
            }
```

次のコマンドによって、上記コンテナ🛑をネットワーク「`nginx_default`」から外してやる.

```
$ docker network disconnect -f nginx_default myfld_elasticsearch_fluentd2
```

なお、上記 `myfld_elasticsearch_fluentd2` のところを `6102` では失敗した
Gitについて一日学び、用語をまとめてみた

#概要
Gitについての知識が皆無だったので、１日使って大枠を学んでみました。ここでは備忘録として用語を書き留めておきます。
##前提知識
`Ruby on Rails`
独学でRailsを勉強しています。Gitの知識はなく、エディターでのコードを管理していました。開発の日があくと、前回どこまでやったかわからないなど、無駄な労力を使っていました。プログラミングについてそれなりに学び、実際に何か作り始める前に、Gitを学んでおけばよかったと感じています。
#内容
Git特有の用語が多く訳がわからなくなることが多かったため、ここでは用語を備忘録としてまとめておきます。

|　　　　用語　　　　 |  　　　　　　　　　　　　　　　　　　　意味　　　　　　　　　　　　　　　　　　　　|
|:---------:|:--------------------------------------------------------------|
|Git|バージョン管理システム。履歴を残すことができる。|
|リポジトリ|Gitのファイル保管場所。|
|ローカルリポジトリ|自分のPC上のリポジトリ。|
|リモートリポジトリ|サーバ上のリポジトリ。ネットを介す。|
|コミット|変更履歴を更新する作業。|
|コミットメッセージ|コミットの際に記載。変更内容をわかりやすく書く。|
|ブランチ|マスターブランチと並行して作業をする場所。最終的にマスターブランチにマージ。|
|マージ|ブランチ同士の結合。ローカルの状態を最新のリモートリポジトリに同期。|
|プッシュ|ローカルリポジトリからリモートリポジトリへ変更履歴をアップロード。|
|プル|リモートリポジトリからローカルリポジトリへ変更履歴を取得。|
|フォーク|リモートリポジトリを複製して、別のリモートリポジトリとして作成する作業。|
|クローン|リモートリポジトリの複製を自分のPCにダウンロードしてローカルリポジトリとする作業。|
|フェッチ|リモートリポジトリの最新の情報を取得。|
|コミットの流れ|ファイルの変更→ステージングに追加→コミット|
|破棄|変更内容を破棄。|
|削除|ファイル自体を削除。|
|プッシュの流れ|コミット→プル→プッシュ　常に最新の状態をローカルリポジトリで保つ。|
|Already up-to-date|すでに最新状態。|
|Fast Forward|新しい環境を取り込んだ。|
|Auto Merge|同ファイルの同箇所の変更がなく、自動でマージが完了。|
|Conflict|同ファイルの同箇所が変更されており、マージできなかった。|

#最後に
Gitについて一通り学んだので、これからの開発に取り入れ、使いこなせるようにしていきたいと思います。
この記事が誰かのお役に立てれば幸いです。
pythonの内包表記でFizzBazz問題を解いてみた【python初心者】

<!-- 発端や概要を記載 -->
pythonのループ処理について、for文より内包表記のほうが速くて簡潔に書けるので
オススメ！的な記事をよく見かけたので、実際どれくらい早くなるのかFizzBazz問題で試してみました。


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [FizzBazz問題について](#Chapter1)
1. [解答](#Chapter2)
1. [結論](#answer)

2021/8/8 ソースコード(main.py) 全体的に修正
2021/8/9 ソースコード(main.py) 全体的に修正

<!-- 各チャプター -->
### <a id="#Chapter1">1.FizzBuzz問題について</a>

> 1から100までの数をプリントするプログラムを書け。
> ただし3の倍数のときは数の代わりに｢Fizz｣を、
> 5の倍数のときは｢Buzz｣と出力し、
> 3と5の両方の倍数のときには｢FizzBuzz｣と出力すること。

有名な問題で、上記の要件を満たすプログラムの作成が目的となります。

### <a id="#Chapter2">2.解答</a>

```python:main.py
import time

def fizzBuzz(list):
    
    #for文の場合
    # result = []
    # for i in list:
    #     if(i % 15 == 0):
    #         result.append('fizzBazz')
    #     elif(i % 5 == 0):
    #         result.append('bazz')
    #     elif(i % 3 == 0):
    #         result.append('fizz')
    #     else:
    #         result.append(str(i))
    
    #内包表記の場合
    result = ["fizzBazz" if number%15 == 0 else
                'Buzz' if number % 5 == 0 else
                'Fizz' if number % 3 == 0 else
                number
                for number in list]
    
    return result

def main():

    #連番の配列
    number_list = range(1, 101)
    fizzBuzz_list = fizzBuzz(number_list)

    #fizzBazz問題の回答
    for answer in fizzBuzz_list:
        print(answer)

if __name__ == '__main__':
    try:
        # 時間計測開始
        time_start = time.time()
        # 処理を書く（ここでは1秒停止する）
        main()
        # 時間計測終了
        time_end = time.time()
        # 経過時間（秒）
        time = time_end - time_start
        #処理時間
        print('################################')
        print('処理時間: ' + str(time))
    except Exception as error:
        #例外エラー
        print(error)
```


実行結果

```
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
fizzBazz
～中略～
97
98
Fizz
################################
処理時間: 4.649162292480469e-05
```

* main()関数で普通にFizzBazz問題を解く
* 内包表記でどれくらい早くなるかmain()関数の実行前後で処理時間を計測

~~なかなか平凡な解答になりました。~~
そこそこ、簡潔なコードになりました。

### <a id="#answer">結論</a>
#### 実行速度の差は分からないが記述量は減る

fizzBuzz()内のコメントアウトしたfor文で書いたロジックと比べると
コード量が少なくスッキリします。

実行速度については比較しては見たのですが明確な差は出ませんでした。
負荷や処理量を増やすため、連番のリストを100から100万まで増やしてみたりしましたが
特に処理時間に差は出なかったです。
PythonからSlackにメッセージを送信する

# このページの概要
Pythonで特定の処理を実行後、slackで通知する機能の実装手順をメモとしてまとめている。

# 1. 準備
slackへPythonからメッセージを送信するには、Pythonの関連ライブラリーのインストールやSlackウェブページでの簡単な設定を済ましておく必要がある。

## 1-1. 必要なPythonライブラリーのインストール
以下を実行してslackライブラリーをインストール。

```
pip install slack
```
## 1-2. slack botの作成
以下urlからslackのアプリ作成画面を開く。
https://api.slack.com/apps

*  **「Create New App」をクリックし、アプリを作成開始**
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861209/c546cbe4-cf5f-a32a-2722-2953213ee5df.png)

* **「From scratch」を選択**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861209/aaebd9e1-317b-e5ab-89f5-a68b77f7ee4a.png)

* **任意の「App Name」を入力し、workspaceを選択後「Create App」をクリック**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861209/a6845609-10e0-f49a-f442-b875c1ce27f2.png)

*  **「Permission」をクリックし、権限設定を開始する**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861209/d128d115-807e-8929-6657-6d43e6d61122.png)

* **「Scope」として以下の2つの権限を追加**
    * chat:write
    * im:write

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861209/2fe47b42-a8e9-b06b-d533-888fbd2f0822.png)

* **「Install to Workspace」をクリックし、アプリを対象のワークスペースに取り込む**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861209/efe7fd4a-8e48-d4e7-8e71-e354572d92f1.png)

* **発行されたトークンをコピーしてメモ帳等に控えておく**
この「トークン」というのは、作成したアプリをプログラムから呼び出す際に使用するパスワードのようなものなので重要。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861209/14a9830f-0fa1-9783-ad6e-d345417d466a.png)

# 2. Pythonコードの作成
* チャンネルへのメッセージの送信
* ダイレクトメッセージの送信
の2種類のコードについて記述する。

## チャンネルへのメッセージの送信
* **Slack上にて先ほど作成したAppを選択し、送信先のチャンネルを追加する**
下の例であれば、#testチャンネルへメッセージを送信したいので、#testをアプリに追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1861209/892e0951-b338-3247-a1a0-f7a1caa06df0.png)

* **コード内にトークンやチャンネル名を設定して実行**

```python
import slack

OAUTH_TOKEN = '控えておいたトークン'
CHANNEL_NAME = 'チャンネル名'

client = slack.WebClient(token=OAUTH_TOKEN)

response = client.chat_postMessage(
    channel=CHANNEL_NAME,
    text="chat bot test message")
```
AWS CDK ワークショップ for Python の cdk init アナウンス和訳

AWS公式が出しているCDKワークショップのPythonコースをコツコツと進めてます。

https://cdkworkshop.com/30-python/20-create-project/100-cdk-init.html

↑ここでcdk initした時のアナウンスの内容を残しておきたいなと思ったので、自分のためにも投稿
（`/cdkworkshop/README.md`の内容でもある）



# 和訳した文章とコマンド

## CDK Pythonプロジェクトへようこそ!

このプロジェクトの内容を調べてみてください。このプロジェクトは、Amazon SNSトピックにサブスクライブするAmazon SQSキューを含むスタック(`cdkworkshop_stack`)のインスタンスを持つCDKアプリのデモです。
スタック(`cdkworkshop_stack`)のインスタンスを持つCDKアプリのデモです。

cdk.json`ファイルは、CDKツールキットにアプリの実行方法を伝えます。

このプロジェクトは、標準的なPythonプロジェクトのように設定されています。 また、初期化プロセスでは、このプロジェクト内に仮想環境を作成し、.venvディレクトリの下に保存します。 virtualenvを作成するには、パスに `python3` の実行ファイルがあり、`venv` パッケージにアクセスできることが前提となります。何らかの理由で仮想環境の自動作成に失敗した場合は、initプロセスが完了した後に手動で仮想環境を作成することができます。

MacOSおよびLinuxで仮想環境を手動で作成するには，以下の手順に従います．

```
$ python3 -m venv .venv
```

initプロセスが完了し、仮想環境が作成された後、以下の
ステップで仮想環境を有効化することができます．

```
$ source .venv/bin/activate
```

Windowsプラットフォームであれば、次のようにして仮想環境をアクティベートします。

```
% .venv\Scripts\activate.bat
```

virtualenvが有効になったら、必要な依存関係をインストールすることができます。

```
$ pip install -r requirements.txt
```

この時点で、このコード用のCloudFormationテンプレートを合成することができます。

```
$ cdk synth
```

これで、helloディレクトリに含まれているソースコードの調査を始めることができます。
非常に些細なテストも含まれており、以下のように実行できます。

```
$ pytest
```

他のCDKライブラリなどの依存関係を追加したい場合は、requirements.txtに追加して再実行してください。
requirements.txtファイルに追加して、`pip install -r requirements.txt`コマンドを再実行してください。
コマンドを実行してください。

## 便利なコマンド

 * `cdk ls` アプリ内の全てのスタックをリストアップします。
 * `cdk synth` 合成されたCloudFormationテンプレートをエミットします。
 * `cdk deploy` このスタックをデフォルトのAWSアカウント/リージョンにデプロイします。
 * `cdk diff` デプロイされたスタックと現在の状態を比較する
 * `cdk docs` CDKのドキュメントを開く

お楽しみに


www.DeepL.com/Translator（無料版）で翻訳しました。

# ワークショップやってみての所感
Cloud9でやってますが、中断するとCDKでデプロイできなかったりしてなかなか進まない。。。

上記ワークショップをCloud9でやるなら丸一日かけてがっつりやることをお勧めします。
「入力として使用」で渡した変数の親Botへの影響

#はじめに
https://qiita.com/etoootak/items/94401434ac4eed6c3c16
の続きです。
親子Bot間で変数を渡し、子Bot側で変数の値を更新した場合に、親Bot側変数がどうなるかを確認してみました。
なお、「入力として使用」だけを使います。

![args.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/336c121b-4fae-1762-bdda-3771fc5ec905.jpeg)


(5)の表示は、(1)と同じになるか？
それとも(4)で書き換えた値になるか？

#結果
##子の書き換えた値になるもの
リスト、ディクショナリ、データテーブル

##子の影響を受けないもの
数字、文字列、レコード

#さいごに
真面目に考えるといろいろ難しいけど、これらが実運用で影響する事はたぶん無いかな。
（2021/8/8 Comunity Edition サーバ１ build9664で確認）
初めてのJavaプログラミング　Java実行環境の準備（JDKのインストール）

初期設定忘れそうなので、備忘録的なやつ

※コンパイラ言語は初めて触るがいろいろ手間がかかりそう……

**JDK(Java Development Kit):開発用に必要なツール群**
javac(コンパイラ)やjavadoc(コードビューア的な奴)を含んでいる

**JRE (Java Runtime Environment):Java実行環境**
インフラ話に絡めるとEMCのUnisphereとか実行するのに動いてる認識
JDKにも含まれている

<h4>環境準備の流れ</h4>
①JDKのインストール

②システム環境変数(JAVA_HOME)の設定
インストールしたディレクトリを設定。
一般的にC:\Program Files配下

```
<CMD prompt>
>set JAVA_HOME
JAVA_HOME=C:\Program Files\Java\jdk-16.0.2
```
→javaを実行する中でプログラムが参照する為に設定が必要。


③Path設定
Pathを通した場合のコンパイル実行
実行ファイルを読み込む為、パスを設定しておく
→実行自体は絶対パスで出来るが面倒

```
javac" hello.java
```

Pathを通さない場合のコンパイル実行

```
"C:\Program Files\Java\jdk-16.0.2\bin\javac" hello.java
```
<参考ページ>
https://www.javadrive.jp/start/install/index4.html#section2
【AWS】CodeCommitからgit cloneする手順

#はじめに
普段GitHubを使っているのでCodeCommiからのgitクローンのやり方がわからず、多大な時間を使ってしまったので、多くの方の時間削減につながれば幸いです。

#前提
ソースコードがCodeCommitにありレポジトリやIAMなどアカウントが作成せれている。

#開発環境
macOS BigSur
バージョン 11.5.1


#手順
公式ガイドを参考すると以下の手順になりますが、単にクローンするだけであれば不要な設定もありました。

1、AWS CLI インストール ← 不要
2、AWS Secret Access Keyを作成する ← 不要
3、aws configureファイルの設定 ← 不要
4、gitconfigファイルの設定
5、git keychainを無効にする
6、認証情報の取得
7、git clone

1〜３までは必須では無く（厳密には必要かもしれませんが）４以降でクローンはできました。重要で必須なのは５と６です。
今回簡単にできた方法を紹介します。

###目次（手順）
1、git keychainを無効にする
2、IAM の自分のロールで認証情報を取得
3、git clone


#実装
それでは実際に作業を進めていきます。

##１、git keychainを無効にする


まず、git クローンしてみます。

```:ターミナル
git clone https://git-codecommit/xxxxxxxxxx
```


この時点では`fatal: Authentication failed for `が返ってきます。
GitHabではこれだけで良かったのですが、CodeCommitの場合、Keychain Access ユーティリティで保存されている認証情報の有効期限が15分しかないのでこれを無効にする必要があります。

https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/troubleshooting-ch.html#troubleshooting-macoshttps

```
git config -l --show-origin | grep credential
```
このコマンドで下記のhelper=osxkeychainを探します。
`file:/path/to/gitconfig  credential.helper=osxkeychain`


helper=osxkeychaiがあればコメントアウトします。
xx/xx/xx/gitconfigのファイルパスのgitconfigの中にあります。

```
cd xxx
```
とかで対象のパスに移動しコメントアウトしてください。
ファイルには色んな行き方があるみたいなので、いずれかの方法を試してください。


##2、IAM の自分のロールで認証情報を取得

認証情報作成して、ユーザー、パスワードを取得します。
![スクリーンショット 2021-08-08 13.19.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/769854/2058a41b-cf04-09f4-8f7e-56af0866cbc9.png)



##3、git clone

git クローンします。
この時点でユーザーやパスワードを聞かれず、何かしらエラーが返っていたら環境に問題があるので、gitconfigやenvの中身を見て余分なものは削除してください。


```:ターミナル
git clone https://git-codecommit.xxxxxxxxxx

Username for 'https://git-codecommit.xxxxxxx': 
Password for 'https://git-codecommit.xxxxxxx': 
```

ここで先程作成した認証情報を打ち込むとクローンされます。


#最後に
この手順で簡単にクローンできますが、僕の場合は環境に問題があって解決するのに2日くらい費やしてしまいました。
この、トラブルシューティングの記事もいずれ更新できれば思ってます。






#参考

Keychain無効

https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/troubleshooting-ch.html#troubleshooting-macoshttps



AWS公式ガイド

https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/setting-up-https-windows.html#setting-up-https-windows-account



Qiita

https://qiita.com/sachiko-kame/items/dff732276dffd22e7682
matplotlibのグラフで技術レポート向けのグリッドを最小労力で設定する

# 記事の目的
matplotlibでグラフ作成するときに、標準のグリッド(目盛り線)では物足りなさを感じている人も少なからずいるはず。この記事では技術レポートにおススメな筆者好みのグリッド設定を最小労力で設定する方法を提案する。

# 技術レポートに求められるグリッド(持論)
matplotlibの関数gridで表示されるおなじみの標準なグリッドは以下。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561868/ba2c98eb-ee32-44be-92d0-041f935de40e.png)

技術レポートに記載するグラフは、グラフ画像だけ見ても、それを示す値が「おおよそ」分かる程度にグリッドが細かくあるのが望ましい。ここの「おおよそ」というのにはかなり個人差があると思われるが、少なくとも標準(plt.grid()のみ)では補助目盛が無く物足りないと感じるだろう。

一方で、補助目盛間隔の値設定など毎グラフごとの細かい設定には悩みたくはない。

上記を受けて、筆者がお勧めしたいグリッドは以下。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561868/e2f6af80-b483-c964-8880-cfc3c8129450.png)

グリッド仕様のポイントを整理する。

- 主目盛は標準グリッドの通りにオートスケールで調整される
- 主目盛り1つ分は、常に補助目盛5つ分になっている
- 主目盛りは補助目盛より若干太め

これにより、目で読み取れる程度の補助目盛間隔を維持しつつ、「(主目盛間隔) ÷ 5 = (補助目盛間隔)」から瞬時に値が読み取れる。(「5」は、みんなが一番慣れ親しんでいるはずの値)

# まずはベタに実装
実装例を以下に示す。

なお、筆者がmatoplotlibを使うときには、ひと手間だが「fig, ax = plt.subplots()」でグラフオブジェクト fig , 軸オブジェクト ax (あるいは軸オブジェクト配列)を準備するようにしている。

```python:test_grid.py
import numpy as np
import matplotlib.pyplot as plt

#%% テスト信号の定義
x = np.linspace(0,3,1001)
y = np.sin(2*np.pi*x)

#%% 標準グリッドによる描画 ########
fig_1, ax_1 = plt.subplots()
ax_1.plot(x,y)
ax_1.legend(["$y=sin(2 \pi x)$"], loc=1)
ax_1.grid() # 標準

#%% おススメグリッドによる描画 ########
fig_2, ax_2 = plt.subplots()
ax_2.plot(x,y)
ax_2.legend(["$y=sin(2 \pi x)$"], loc=1)

import matplotlib.ticker as ticker
ax_2.grid(which='major', lw=0.7) # 主目盛の描画(標準)

# X,Y軸に対して、(補助目盛)×5 = (主目盛)
ax_2.xaxis.set_minor_locator(ticker.AutoMinorLocator(5))
ax_2.yaxis.set_minor_locator(ticker.AutoMinorLocator(5))
ax_2.grid(which='minor', lw=0.4) # 補助目盛の描画
```

# 関数化による汎用化
何度も書くのは大変なのと、いつも思い出しに時間がかかるので、関数setGridPreferedとしてまとめてみた。筆者は、このグリッド設定関数を、.pyでいつも作るスクリプトの上の方、ライブラリをimportする箇所のすぐ下あたりに忍ばせることにしている。

```python:func_grid.py
import numpy as np
import matplotlib.pyplot as plt

#%%
def setGridPrefered(ax):
    """
    好みのグリッドを設定するための関数

    Parameters
    ----------
    ax : matplotlibの軸オブジェクト

    """
    
    import matplotlib.ticker as ticker
    ax.grid(which='major', lw=0.7) # 主目盛の描画(標準)
    
    # X,Y軸に対して、(補助目盛)×5 = (主目盛)
    ax.xaxis.set_minor_locator(ticker.AutoMinorLocator(5))
    ax.yaxis.set_minor_locator(ticker.AutoMinorLocator(5))
    ax.grid(which='minor', lw=0.4) # 補助目盛の描画

if __name__ == "__main__":

    x = np.linspace(0,3,1001)
    y = np.sin(2*np.pi*x)
    
    #%% 使い方
    fig_2, ax_2 = plt.subplots()
    ax_2.plot(x,y)
    ax_2.legend(["$y=sin(2 \pi x)$"], loc=1)
    setGridPrefered(ax_2) # 軸オブジェクトを引数するようにして使う。
    
    #%% 複数軸のグラフの場合
    fig_3, axes_3 = plt.subplots(3,2)
    # 軸オブジェクト配列をflatにしてforループすればよい
    for ax_i in axes_3.flatten():
        ax_i.plot(x,y)
        setGridPrefered(ax_i)     
```
出力は以下。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561868/33518f0c-f0fe-c7fd-2bf2-6f800991c4cd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561868/33792e7f-450c-d58e-c84d-483e4f9feb12.png)

# 終わりに(感想)
Pythonは今や情報過多になりすぎているため、どの実装が一番「自分にとっての正解」なのかを迷うところがある。筆者も、今回のたった数行のグリッド設定関数にたどり着くまでにかなりの時間と経験が必要だった。その甲斐あって、特に筆者のようにものづくりエンジニアとして働く人にとっては、この設定方法はすぐにでも現場で使えるものになっていると自負している。ぜひご意見いただければ幸いです。

以上
小技：文字列の文字をランダムに並び替える

非実用的でとてもどうでもいい小技

```js
'文字列'.split('').sort(() => .5 - Math.random() ).join('')
```

example

```js
> 'L知っているか、死神はリンゴしか食べない'.split('').sort(() => .5 - Math.random() ).join('')
"べてっ知死るゴ食、いLリなかし神はいかン"
```

なんとなくイヌカレー空間ぽい
Golang + Lambdaでサーバレス開発時にWarning「Support for "package.include" and "package.exclude" will be removed with next major release.」が出た時の対応

# 背景

Golang + Lambdaでサーバレス開発中に`sls invoke -f 関数名`を実行すると、以下のWarningが発生しました。

```
Serverless: Deprecation warnings:

Support for "package.include" and "package.exclude" will be removed with next major release. Please use "package.patterns" instead
More Info: https://www.serverless.com/framework/docs/deprecations/#NEW_PACKAGE_PATTERNS
```

# 対処法
`serverless.yml`を以下のように書き直せばOKです。

```serverless.yml
package:
 exclude:
   - ./**
 include:
   - ./bin/**
```

↓

```serverless.yml
package:
  patterns:
    - "!./**"
    - "./bin/**"
```

`!`をつけると、excludeされるようです。
詳しくはログに記載の以下URLを見ればOKです。
https://www.serverless.com/framework/docs/deprecations/#NEW_PACKAGE_PATTERNS
消費期限切れ防止！この食材はいつまでの期限かをチェックするアプリを作ってみた

皆さま。こんにちは。　
今回も超初心者、基本アナログ人間の挑戦です！

共同や公共で使えるキッチンの消費期限の食材管理って難しいですよね？
たとえば、飲食業なども、期限が切れたものを使ってしまったら大変です。

今回は、「食材管理・消費期限ルール」をチーム内で決めたときに全員が期限を間違えがないために「食材（商品）」をかざすと「開封してからいつまで使用」できるのかがわかるアプリを作ってみました。
ただし今回のものは、「部署内、チーム内、家庭内」で決めた開封してからの賞味期限（使用期限）を通知するアプリになります。


#できたもの
食材をかざすとチーム内で決めた期限ルールの使用期限がわかります。

<iframe width="560" height="315" src="https://www.youtube.com/embed/MurKGr459B4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>


この動作をした後に、登録したLINEアカウントに期限の連絡が下記のように届きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802395/92eafcc8-513e-54f1-a60a-363154956fb9.png)

#使ったサービス
下記のサービスのインストール、アカウント登録しましょう。
◆[Node-RED](https://nodered.jp/)
　　
◆[Heroku](https://jp.heroku.com/home/)
 　 
◆[LINE Developers](https://developers.line.biz/ja/)
　　
◆[Teachable Machine](https://teachablemachine.withgoogle.com/)
　　アカウント登録学習によるモデルをつくります
　　※他にモデルがあれば不要です
◆[Code-Pen](https://codepen.io/)
　　Twitter、Githubｍのアカウントを使用し、Signe Up出来ます。

#作成構成
**流れ**
**1.事前準備** 
Node-RED、Heroku、LINE Developers詳しくはこここでは詳しく説明はしませんが、インストールとアカウントの作成をして使えるようにしておきます。

**2.独自のモデルを作る**
今回は、学習させた独自のモデルを作るためにTeachable Machineを使用しました。
学習させたのは、サンプルとして3つ（レモン、ケチャップ、白ごま）のみです。
必要にあわせて学習させてください。

**3.Code-Penを使って推論ができるWebアプリをつくる**
Code-Penの内容は下記になります。
<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="xxdavZv" data-user="ziyasumin01" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ziyasumin01/pen/xxdavZv">
  期限チェック</a> by ziyasumin01 (<a href="https://codepen.io/ziyasumin01">@ziyasumin01</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

注意：JS部分の下記部分　nodered-（自分の名前）については自分のものを入れてください。

```
axios.post('https://nodered-（自分の名前）.herokuapp.com/receiver', {message: message});
```

**4.推論の結果をNode-REDに送り連携させる**
Node-REDに推論の結果を送ります。
そして、LINEと連携させてプッシュがくるようにしています。

![フロー.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802395/f91d9d14-a3e4-ef6f-7123-4095a7ebe42e.png)
簡単に中身はこのような感じです。
httpinノード
![httpin.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802395/ce262f2e-e621-f387-af25-337d2b189282.png)
changeノード
![チェンジ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802395/2455a834-704a-a260-9203-8787752e059a.png)
delayノード
![delay.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1802395/7c2aee98-d390-1a17-8676-6a1852cc94ac.png)

#追記事項
・このアプリは、『商品（モノ）に対して何か伝えたいこと』がLINEに通知されることになるので、覚えることが出来ない内容をメモの変わりに使うことも出来るかと思っています。
・今回のものをより実用的にするためには、カレンダーと連携して、期限の日にアラームがかかるもの（LINE連携）にしていければと思っています。そうすることで、今日の期限のものは廃棄ということが覚えてなくても楽にできます。
※もちろん、食品ロスになってしまうので。期限内に使うのは大前提‥ですね。

#さいごに
新しいことを楽しく勉強中です。モノづくりはまずやりたいこと、困っていることの解決のために、どういうことをして解決するかの計画や設計図が必要ですが、知識と経験も大事でまだまだ設計図が立てられずの日々です。
困りごとの解決のあとは今後は使いやすさの追求だったりと終わりはないですよね。
わたしは、管理栄養士として仕事がら料理レシピを作っていますが、レシピ作成にも終わりはありません！

最後まで読んで頂きありがとうございました。
Herokuよくつかうコマンドまとめ

## コマンド備忘録


```ruby:マイグレート
$ git push heroku main
```

```ruby:マイグレート
$ heroku run rails db:migrate
```

```ruby:テストデータを入れる
$ heroku run rails db:seed
```

```ruby:ログを見る時
$ heroku logs
```


```ruby:ブラウザでの立ち上げ
$ heroku open
```

```ruby:データベースリセット（URLコマンドこのままうつ）
$ heroku pg:reset DATABASE_URL
```
firebase.jsのチートシート

##envファイルの生成

ディレクトリ直下に.envファイルを設置。
そのファイルにAPIキーを貼り付ける。

```.env
FIREBASE_API_KEY = '自分のapikey'
FIREBASE_AUTH_DOMAIN = '自分のapikey'
FIREBASE_PROJECT_ID = '自分のapikey'
FIREBASE_STORAGE_BUCKET = '自分のapikey'
FIREBASE_MESSAGING_SENDER_ID = '自分のapikey'
FIREBASE_APP_ID = '自分のapikey'
FIREBASE_MEASUREMENT_ID = '自分のapikey'
```
#####FIREBASE_API_KEYなどの名称は自由です。
#####ただ自分がわかるようにしよう！

##dotenvモジュール
dotenvなどのモジュールでエクスポートしておく。
nuxtなら@nuxt/dotenv

```
npm install @nuxt/dotenv
```

##nuxt.config.jsに記載

npm installできたらnuxt.config.jsに記載します。
まずはexport default の外にグローバル変数として定義しておきます。

```nuxt.config.js
require('dotenv').config();
const { FIREBASE_API_KEY } = process.env;
const { FIREBASE_AUTH_DOMAIN } = process.env;
const { FIREBASE_PROJECT_ID } = process.env;
const { FIREBASE_STRAGE_BUCKET } = process.env;
const { FIREBASE_MESSAGEING_SENDER_ID } = process.env;
const { FIREBASE_APP_ID } = process.env;
const { FIREBASE_MEASUREMENT_ID } = process.env;

export default {
}
```
その後にexport　defaultのbuildのところにenvオブジェクトを生成します。

```nuxt.config.js
export default {
....

build: {
    env: {
      FIREBASE_API_KEY,
      FIREBASE_AUTH_DOMAIN,
      FIREBASE_PROJECT_ID,
      FIREBASE_STRAGE_BUCKET,
      FIREBASE_MESSAGEING_SENDER_ID,
      FIREBASE_APP_ID,
      FIREBASE_MEASUREMENT_ID,
    },
  },
};
```
##firebase.jsにprocess.envを貼り付けて終了！
先ほど定義したenvはグローバルに利用可能なのでfirebase.jsに貼り付けます。

```javascript:plugins/firebase.js
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
import 'firebase/storage';
import 'firebase/analytics';

const config = {
  apiKey: process.env.FIREBASE_API_KEY,
  authDomain: process.env.FIREBASE_AUTH_DOMAIN,
  projectId: process.env.FIREBASE_PROJECT_ID,
  storageBucket: process.env.FIREBASE_STRAGE_BUCKET,
  messagingSenderId: process.env.FIREBASE_MESSAGEING_SENDER_ID,
  appId: process.env.FIREBASE_APP_ID,
  measurementId: process.env.FIREBASE_MEASUREMENT_ID,
};

if (!firebase.apps.length) {
  firebase.initializeApp(config);
}
export const auth = firebase.auth;
export default firebase;
```
上記のようなjsファイルを使う。
import文で呼び出したらプロジェクト内でFirebaseが使えるよ。
Docker+VueプロジェクトをHerokuにデプロイ

※自分用メモ

開発環境はDockerでフォルダをバックエンド(RailsAPI)、フロントエンド(Vue)に分けHerokuにデプロイするまでの流れです。
この記事ではフロントエンドフォルダをHerokuにデプロイするまでの行程を紹介します。

前回の記事ではバックエンドフォルダをHerokuにデプロイする行程を紹介しました。
https://qiita.com/ryota-0906/items/fdbc6e08e46ede0a3d43

#1 WEBサーバーを用意する
Herokuで動作させるためにExpressを導入します。package.jsonにも自動的に記載されます。

```
$ cd <フロントエンドディレクトリ>
$ npm install express --save
```

フロントディレクトリ直下にserver.jsファイルを作成します。
server.jsには以下のように記述します。

```server.js
const express = require('express');
const port = process.env.PORT || 8080;
const app = express();
app.use(express.static(__dirname + "/dist/"));
app.listen(port);
```

package.jsonに以下を追記します。
start はHerokuがにアプリケーション起動時に実行するコマンドです。
build は startの前にビルドしてもらうために記載します。

```package.json
"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "start": "node server.js"
  }
```

#2 Herokuにログイン&アプリ作成

Herokuにログインしてアプリ作成

```
$ Heroku login --interactive
$ heroku create <フロントエンドアプリ>
``` 

Herokuにデプロイ

```
$ cd <フロントエンドディレクトリ>
$ git init
$ git add -A
$ git commit -m "first commit"
$ git remote add heroku https://git.heroku.com/フロントエンドアプリ.git
$ git push heroku master
```
acornによるAST処理で行端にセミコロンが入らないようにする

# 概要

あんまりニーズないと思いますがacornを使ってJavascriptのAST変換→書き戻しを行う際に、行端へセミコロンを入れたくなかった為、その方法を記載します

# 環境
```
"acorn": "8.4.1"
"astring": "1.7.5"
"typescript": "4.3.5"
```

# コード
```typescript
import { parse } from "acorn";
import { generate, GENERATOR } from "astring";
const getCode = (ast: Node): string => {
  return generate(ast, {
    generator: Object.assign({}, GENERATOR, {
      ExpressionStatement: (node: any, state: any) => {
        // セミコロンを除外する為、ExpressionstatmentのみExtendsする
        const precedence = state.expressionsPrecedence[node.expression.type];
        const NEEDS_PARENTHESES = 17; // astring内より定数値コピペ
        if (precedence === NEEDS_PARENTHESES || precedence === 3 && node.expression.left.type[0] === 'O') {
          state.write('(');
          GENERATOR[node.expression.type](node.expression, state);
          state.write(')');
        } else {
          GENERATOR[node.expression.type](node.expression, state);
        }
      }
    }),
  });
}

getCode(parse("code"));

```

astringのオプションのgeneratorにて書き戻す際のロジックを拡張出来ます。
今回はExpressionstatmentの行端の";"が入らないようにしたかったので上記のコードに致しました。
AWS認定試験の概要

# はじめに

業務でAWSを使う機会があり、せっかくなら認定試験にも挑戦しようと思い、調べて見ました。

* 若干の変動はありますが、数年前から大枠は変わっていないようですね


# 試験概要

## 公式サイト
* https://aws.amazon.com/jp/certification/
    * 試験概要、試験範囲、サンプル問題などが記載

## 全体像
まず、AWSの2021年8月時点での試験体系は下記のようになっています。
![20200914221314.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/35368609-bdac-bc4b-3f83-307e571ae4cd.png)

## 役割別試験
* 役割別は3つのレベルが設定されています
    * ベーシック：6ヶ月の経験を想定した、基礎レベル
    * アソシエイト：1年の経験を想定した、実務レベル
    * プロフェッショナル：2年の経験を想定した、設計/運用ができるプロフェッショナルレベル

## 専門知識認定試験
* それぞれの専門知識分野ごとに6つ定義
    * ネットワーク、セキュリティ、機械学習、データアナリティクス、データベース、Alexa認定試験


# 勉強方法/情報源

## 公式
* AWSトレーニング
    * https://www.aws.training/
        * プラクティショナーなど、無料で使えるものもあります
        * https://www.aws.training/Details/eLearning?id=66479
* サービス別資料(Black belt)
    * https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/
* ホワイトペーパー
    * https://aws.amazon.com/jp/whitepapers/
* 公式ガイド/APIドキュメント
    * https://docs.aws.amazon.com/
* 出題範囲
    * 公式サイトからたどれます。プラクティショナーの場合は下記
        * https://aws.amazon.com/jp/certification/certified-cloud-practitioner/


## 非公式
* 書籍
    * https://www.amazon.co.jp/s?k=AWS+%E8%AA%8D%E5%AE%9A%E8%A9%A6%E9%A8%93
* Udemy
    * https://www.udemy.com/courses/search/?src=ukw&q=aws+%E8%AA%8D%E5%AE%9A%E8%A9%A6%E9%A8%93

# メリット
AWSのメリットと言うよりもベンダ試験一般に言えることですが

* AWSからお墨付きがもらえる(バッジがもらえる)
* 知識を体系化できる(業務で使わない隙間を勉強できる)

# デメリット
こちらも、ベンダ試験に一般的な内容です

* (情報処理などの国家試験と比べると)受講料が高い
* 有効性を維持するためには、定期的な更新が必要
* 実務では使わないような、知識としてだけしか使わないような部分も覚える必要がある

# 受験方法
* AWS認定のアカウントを作成
    * https://www.aws.training/Certification
* 認定試験の試験予約を行う
    * 試験区分、試験日時を選びます
    * ピアソンVUEの試験会場や在宅での受験など選びます
        * 試験センターで行う場合は空いている日や受験の流れも確認します
    * 受験料の支払いを行います
    * メールにて予約できたことを確認します
* 受験する
    * テストセンター or 自宅 で受験可能です
    * テストセンターの場合は時間までに現地に赴き、身分証明と署名・写真撮影などを行います
* 結果を確認する
    * 画面に合格・不合格はでますが、正式な結果やスコア・バッチの配布は確認作業が終わってからになります。
        * 受験後5,6時間で来ます

# その他
* 認定期間は3年間で、3年以内に同等以上の試験に合格しないと、失効となります
* 難易度/合格率
    * 公式には発表されていませんが、ネットなどで大まかな感覚的な評価はあります
* 受験料は、試験ごとに異なります
    * ベーシックが100ドル
    * アソシエイト150ドル
    * プロフェッショナル/専門知識試験300ドル
* 受験方式は、自宅もしくはピアソンVUEの試験会場で受験可能です。
[Ruby on rails]いいねの一覧表示　member doとcollection doの違い・plunkについて

<h2>初めに</h2>

以前、いいね機能&非同期通信を行いました。
今回いいねの一覧を作成したいと思います。

前回の記事はこちらから。

https://qiita.com/ki_87/items/d0cf341aac9c0f1fd73a

調べてみると色々とやり方があるみたいでした。
<h6>今回は、ルーティングでのcollectionやmember、plunkについても学べました！</h6>

<h2>ルーティング作成</h2>

```perl:routes.rb

  resources :users, only: [:show,:index,:edit,:update] do
    member do
      get :favorites
    end
  end
```

どういうルーティングにしたいかというと、
ユーザーのマイページから、そのユーザーのお気に入りしてる記事に飛びたいので、
users/1/favorites というルーティングにしたい。
となると```member do```を使用します。

<h2>member do / collection doについて</h2>

<h3>member doって何なのか？？</h3>
member doを使うと、ユーザーidが含まれてるurlを使えるようになります。
member は特定のデータに対するアクションに利用するそうです。

ルーティングはこうなります。
```users/:id/favorites```
![スクリーンショット 2021-08-08 11.36.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/c043bf5b-4a9d-8a14-95b5-055d9ef575e2.png)

<h3>collection doって何？？</h3>

今回、使用していませんが、よく目にするのが```collection do```です。
仮にここをcollection doで記述すると、
ルーティングは```　users/favorites```になります。

![スクリーンショット 2021-08-08 11.35.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/eebceb83-77b8-fb39-2d02-ff74ba851073.png)

<h4>```member```と```collection```の違いは、idがつくか、つかないか　です。</h4>
collectionは集合なのでidはなし、memberは個別なのでidありです！！

<h2>コントローラー</h2>
```perl:users_controller.rb

def favorites
    @user = User.find(params[:id])
    favorites= Favorite.where(user_id: @user.id).pluck(:post_id)
    @favorite_posts = Post.find(favorites)
  end
```

```favorites= Favorite.where(user_id: @user.id).pluck(:post_id)```
さて、この記述です。
ユーザーidが、このユーザーの、いいねのレコードを全て取得します。
そして、そのpost_idも一緒に持ってくる
それをfavoritesに代入。
結果、favoritesの中身には、何が入ってるかというと、あるユーザーがいいねした記事のidです。

<h5>whereの復習</h5>
与えられた条件にマッチするレコードを全て取得します。
<h4>plunkって何？？？</h4>
Product.pluck(:name)という記述があった場合、
productモデルのnameカラムの一覧を持ってこれる。
1つのモデルで使用されているテーブルからカラム (1つでも複数でも可) を取得することができるそう。


<h2>View</h2>
もの凄く簡単、シンプルなviewですので、参考までに。

```perl:users/show.html.erb
<p><%=link_to"お気に入り記事",favorites_user_path(@user) %></p>
```

```perl:favorites.html.erb
いいね一覧
<% @favorite_posts.each do |post|%>
<%=post.title %>
<% end %>
```

これで、いいねした記事の一覧ページが作成出来ました。

<h2>大変、参考にさせていただいた記事</h2>

https://qiita.com/oak1331/items/7d50cccba198d0b40ada

モデルに定義するやり方だったり、やり方は色々あるみたいで、
中々しっくりくる記事に出会えませんでしたが、
上記の記事でシンプルかつ簡単に実装出来ました。
コード内のconsoleを全て無効化する方法【JavaScript】

# コード内のconsoleを全て無効化する方法【JavaScript】

解説は後で付けます

Chrome、Edge、Firefoxで対応します。

```javascript:remove_console.js

let remove_console_flag=true;//フラグ
let save_console={};//console機能回復用


function remove_console(){

  const all_num=Object.keys(window.console).length;//window.consoleのObjectの総数
  
  if(Object.keys(save_console).length){
    window.console=Object.assign({},save_console);
    save_console={};
  }


  if(remove_console_flag){
    save_console=Object.assign({},window.console);//consoleのオブジェクトをコピー
    for(let i=0;i<all_num;i++){//window.consoleの総数分繰り返す
            let change=window.console[Object.keys(window.console)[i]];//log,trace,count...を取得
            window.console[change.name] = function(s){return;};//空の値を返す変数を上書き

    }
    console.log('表示されない');
    console.count('表示されない');
    console.trace('表示されない');
  }
}

function reset_console(){//consoleをもとに戻す
  remove_console_flag=false;
  remove_console();

}

remove_console();

```