OmniAICreator/Qiita-1.07M huggingface dataset:
ブラウザのご厚意で「www.」がリンクに付いてしまったのを対処した

#はじめに
ツイッターログイン機能を実装した個人開発のWebアプリを公開しています。
自分自身で使っている分には問題なかったのですが、ログインリンクをクリックするとエラーになるという情報をユーザーさんからいただきました。
これを直した方法について記載いたします。

#現象の再現
Googleで「読書のわ」と検索し、（読書のわがWebアプリの名前）検索結果からWebアプリにリンク。
ツイッターログインのためのリンクを貼ったボタンをクリックすると確かにエラーになりました。

#なにはともあれログ確認
サーバーのログを確認すると、以下のエラーでした。
ツイッターログインのときのコールバックURLがないよというものです。

```
OAuth::Unauthorized (403 Forbidden):
```

developerサイトに確認しに行くと、設定はしてありました。なのになぜ。。

先程はSafariで確認したので、今度はChromeでもう一度Google検索から。
今度は問題なくログイン動作しました。なぜ？？？

URLをコピーして貼り付けてみると、想定と違うリンクになっているではありませんか。

ようやくタイトルの内容にたどり着きました。「www.」が勝手について検索結果にサイトが表示されていたんです。

Googleの検索順位は変わらないので、検索エンジンの問題でもなさそう。
ということはブラウザが勝手に「www.」をつけちゃったんですね。。
本来は「http://dokusyo-no-wa.com/ 」でいいものを、
「http://www.dokusyo-no-wa.com/ 」とされてしまった。

ドメイン以下でサイトを作っていたので考えもしなかったのですが、上の部分が勝手に変わってしまってはdeveloperサイトに登録したリンクとは異なってしまっており、エラーになっても致し方なし。。

対処としては「www.」をつけたリンクもコールバックURLに設定することで、無事エラーを回避して、ログインさせることができるようになりました。

#通常のエラーの場合は対処法がたくさん記事になっています
https://saruwakakun.com/memo/omniauth-twitter
こちらのサイトがわかりやすく教えてくれているので、参考に。


#最後に
エラーを教えてくださったユーザーさんには大変感謝しております。
この場を借りてお礼申し上げます。
BigDecimal の stripTrailingZeros 使ってる人は気をつけて

## はじめに

お仕事で BigDecimal の [stripTrailingZeros](https://developer.android.com/reference/kotlin/java/math/BigDecimal#stripTrailingZeros()) というメソッドを使っていて悲しくなったので記事にしました :cry: 

## stripTrailingZeros って何？

BigDecimal のメソッドで、末尾のゼロが削除された新しい BigDecimal を返します。

簡単にいうとこんな感じ

> 0.00 であれば 0
0.10 であれば 0.1

## 何があったのか

動作確認をしていると、 0.00% と表示されてしまうことがありました。

「あれ？ちゃんとエミュレーターでも動き確認してたのになぜ？？」

調べてみると stripTrailingZeros が正常に動いてなさそう、、！

なぜ〜〜〜〜 :rolling_eyes: 

## 原因

なんと、JDK7 だと正常に動作しないとのこと。。。

そりゃないよ。。

なので一部の Android 端末だと正常に動作しません :cry: 

※ [Google IssueTracker](https://issuetracker.google.com/issues/37099406) にあげられてました


こんな感じになります。正常に動作するものとしないものが混じってるのがほんと厄介で気付きにくいです。。

```kotlin
fun printStripTrailingZeros(text: String) {
  println(BigDecimal(text).stripTrailingZeros())
}

printStripTrailingZeros("1.0")
printStripTrailingZeros("0.0")
printStripTrailingZeros("0.00")
printStripTrailingZeros("0.10")

// result
// 1
// 0.0
// 0.00
// 0.1
```

## 対処方法

画面に表示する際に `compareTo` で比較して、`BigDecimal.ZERO` と等しければ 0 を表示するようにしました。
正規表現でも可能ですが、ひとまずはこれで良さそうです（めんどくさいだけ笑）

## おわりに

他にも何か気をつけた方がいい点あれば教えていただけたら幸いです :hand_splayed: 

みなさんも本当にお気をつけください！！
Macbook Pro 13 (2016) から WSL2 への移行メモ

M1 Mac 出ちゃいましたが、 Windows で行なった開発環境構築のメモです。
1ヶ月くらい使ってみて問題なく使えているのでメモを残しておきます。


## 動機

ゲーム用に買ったものの使えておらず、眠らせとくのが勿体なかったので。
また、これまで使っていた Macbook が VSCode を使った開発で使い物にならないくらい重くなっていたため。

### 追記: 2021-03-24

Macbook Pro が業務利用が困難なほど重くなっていたのは、
主に 4K モニタを繋いでいたためでした。

## 環境

- OS: Windows 10 Home x64 (2004)
- CPU: Ryzen 7 3700X

## 用途

今のところ以下の用途で使ってます。

- VSCode
- Docker Image のビルド, コンテナの複数起動
- Next.js, TypeScript
- Laravel

YouTube の配信を複数窓開きながらでもさくさくで嬉しい。
VSCode の `Bracket Pair Colorizer2` が全然重くないのも嬉しい。

## やったこと

思い出しながら書いているので、時系列が合っていなかったり抜け漏れあるかもしれません。

- WSL2 で Ubuntu 入れる
- `apt update` して必要なパッケージを入れる。
- Docker Desktop 入れて WSL と繋げる。
- `.wslconfig` を設定。
- Homebrew (Linuxbrew) を入れて必要な物を入れる。
- VSCode で `Remote Development` 入れて設定。
  - 拡張機能が WSL 側に入るようにする。
  - 常に `Remote-WSL` で VSCode が起動するようにする。
- `~/.bashrc`, `~/.bash_profile` 等設定する。
- Windows にターミナル入れる。
  - ひとまず Windows Terminal を使ってみてる。
- WSL2 から GUI アプリケーションを起動するために `VcXsrv` をインストール
    - Cypress などを起動できます。(`wsl-open` で `xdg-open` を肩代わりする方法では駄目でした)
    - 参考: [WSL2(Ubuntu18.04 LTS)をセットアップしてDocker(on Ubuntu)とGUIアプリを使う](https://qiita.com/Keiwa/items/390d89c20228edf0b16c#vcxsrv)

### .wslconfig

WSL がメモリを食いすぎないように上限を設けました。
ただ使用メモリが上限に達すると WSL がフリーズしたりハングアップするので、必要に応じて割当メモリを調整したりします。
また、 Windows からホスト名 `localhost` で WSL にリクエストが飛ばせるようにしています。

```
[wsl2]
memory={任意の数値}GB
swap=0
localhostForwarding=true
```


## 問題が起きた時の対処

### WSL が反応しない

コマンドプロンプトまたは PowerShell から以下のコマンドを実行して WSL を再起動。

```
wsl --terminate {LinuxDist名}

または

wsl --shutdown {LinuxDist名}
```

例:

```
wsl --shutdown Ubuntu
```

詳しくは `wsl --help` 参照。
上記で解決しない場合は Windows を再起動。

### WSL で Docker が見つからなくなった

Windows 側で Docker Desktop を再起動。
または Windows を再起動。

### localhost にアクセス出来なくなった

WSL を再起動。または Windows を再起動。

## その他

- WSL 上で `npm install` した時に、完了まで時間が掛かったり稀にタイムアウトで失敗する事がある。
- タスクマネージャーのプロセス一覧の `Vmmem` が WSL らしい。
- Windows のエクスプローラ等から WSL にアクセスする際は `\\wsl$` を開く。
HTTPリクエストメソッドについて

#はじめに
サーバ側の学習において理解を深める必要があると感じたので作成した。
備忘録目的でプログラミング初心者が作成しているので誤りがあるかもしれません。

#１.HTTPリクエストメソッドとは
WebブラウザからWebサーバに対する「命令の種類」の総称。

#2.HTTPリクエストメソッドの種類
###GET
WebブラウザからWebサーバにページの要求をする命令。
URLに情報が残るのでパスワード等はGETで送ってはいけない。

###POST
GETと同じくWebブラウザからWebサーバにページの要求をする命令。
ただし、URLに情報が残らないのでパスワード等も扱える。

###PUT
指定したリソースがなかったら新規作成する。
指定したリソースがあったら更新する。

###DELETE
指定したリソースを削除する。
RAWドライブに CHKDSKは使用できません

この記事では、「ファイルシステムの種類はRAWです。RAWドライブに CHKDSKは使用できません。」というエラーを解消するのに役立つ手順を説明します。問題を取り除くには、以下の手順に従ってください。<a href="https://jp.bitwar.net/howto/windows/2623.html">rawドライブにchkdskは使用できません</A>

最初は、CHKDSKおよびRawドライブとは何かを知ることが重要です。 CHKDSKは「Check Disk」の略で、コマンドプロンプトで実行してシステムの整合性を検証するコマンドです。 CHKDSKの主な機能は、ディスク内のエラーをチェックしてから修正することです。 RAWドライブはハードドライブのパーティション分割であり、Windowsオペレーティングシステムがファイルシステムを認識しないことを意味します。


ただし、CHKDSKコマンドがRAWドライブに適用されないことを後悔する必要があります。


RAW USBフラッシュドライブ、ハードディスク、またはSDカードでchkdskを実行すると、コマンドプロンプトに次のエラーメッセージが表示されます。

CHKDSK-is-not-available-for-RAW-drives1.jpg


「RAWドライブ」の原因は何ですか？

このエラーメッセージは、ディスクの破損または破損が原因でWindowsに頻繁に表示されます。


1.ドライブを安全に取り外します。

2.アンチウイルス攻撃。

3.正しくフォーマットされていない

4.認識されないファイルシステム

5.ドライブにアクセスできません


「RAWドライブに CHKDSKは使用できません」というエラーメッセージを修正する可能な方法

以下に、Windows XP、7、8、および10で「RAWドライブに CHKDSKは使用できません。」を修正するためのソリューションの一部を示します。


解決策1：エラーチェックする


ステップ1：「マイコンピュータ/このPC」と入力し、RAWドライブを右クリックして「コンテンツ」を選択します。

ステップ2：[ツール]ページに移動し、[エラーチェック]セクションで[チェック]をクリックします。

ステップ3：システムがRAWドライブをスキャンするのを待ってから、未フォーマットのRAWドライブを修復してCHKDSKを使用します。

CHKDSK-is-not-available-for-RAW-drives2.png


解決策2：再フォーマット

RAWドライブに重要なデータが含まれておらず、ファイルを失ってもかまわない場合は、フォーマットすることができます。これが最適なソリューションです。


ステップ1：WIN + Rを押し、「Diskmgmt.msc」と入力してディスクの管理を実行し、RAWドライブを右クリックします。

ステップ2：[フォーマット]オプションを選択します。

ステップ3：新しいボリュームを選択し、適切な情報（ボリュームラベル、ファイルシステム、アロケーションユニットサイズ）に変更します。

ステップ4：[クイックフォーマットの実行]をオンにし、[OK]ボタンをクリックして、RAWドライブをNTFSに再フォーマットします。


以前にそのドライブに重要なファイルを保存したことがあり、フォーマットしたドライブでそれらを失いたくない場合。では、これらのファイルをどのように取得しますか？心配しないで、最初にデータを回復してからファイルを修復する必要があります。

   詳しくは、「<a href="https://jp.bitwar.net/howto/windows/2623.html">「RAWドライブに CHKDSKは使用できません」を修正する3つの方法</A>」をご参照ください。
作業ディレクトリを指定するオプションまとめ

普段は作業ディレクトリに移動して実行することが多いコマンドについて、作業ディレクトリを指定するオプションをまとめました。（ツールに偏りがありますが・・・）

# artisan (Laravel)
実行したいプロジェクトの `artisan` ファイルを絶対パスで指定する。

```sh
php /path/to/project/artisan migrate
```

# Composer
`--working-dir` オプションまたは `-d` オプション

```sh
composer install --working-dir=/path/to/project
composer install -d /path/to/project
```

[Global Options - Command-line interface / Commands - Composer](https://getcomposer.org/doc/03-cli.md#global-options)

# Git
`-C` オプション

```sh
git -C /path/to/project pull
```

[-C <path> - Git - git Documentation](https://git-scm.com/docs/git#Documentation/git.txt--Cltpathgt)

# npm
`--prefix` オプション

```sh
npm install --prefix /path/to/project
```
[prefix - config | npm Docs](https://docs.npmjs.com/cli/v6/using-npm/config#prefix)

# Yarn
`--cwd` オプション

```sh
yarn --cwd /path/to/project install
```
[Specify working directory with yarn --cwd <command> - CLI Introduction | Yarn](https://classic.yarnpkg.com/en/docs/cli#toc-cwd)
WindowsでNimからODBC経由でOracleにアクセスする


## 流れ的にね

一連の流れ([PostgreSQLへのアクセス](https://qiita.com/6in/items/66c1a3d2d43b3b5cc869)、[MySQLへのアクセス](https://qiita.com/6in/items/66c1a3d2d43b3b5cc869))から、最後はこれにアクセスしないとダメでしょということで、Oracleへのアクセスにチャレンジしてみます。
OracleはOracle Clientが用意されているので、ODBC経由で余裕でしょーという予想です。

## Oracle Instant Clientのダウンロード
https://www.oracle.com/database/technologies/instant-client/downloads.html

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58872/9a2fa866-d72e-0561-2343-88706e0951f4.png)

### 必要なものは２つ
* Basic Package
* ODBC Package


## ODBCの設定方法

ここが一番の山場でした。

[こちら](https://enoxproduction.com/oracle-odbc/) をご参考に。
[罠](https://note.kiriukun.com/entry/20151124-oracle-instant-client-odbc)もあります。

## 接続テスト

設定情報はあくまでサンプルです。

```lisp:tnsnames.ora
oradb =
(DESCRIPTION =
 (ADDRESS_LIST =
  (ADDRESS = (PROTOCOL = TCP)(HOST = 127.0.0.1)(PORT = 1521))
 )
 (CONNECT_DATA =
 (SERVICE_NAME = xe)
 )
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58872/256bc88b-dde1-8df0-b608-86ec8e60c751.png)

```nim
import db_odbc

const datasource = "oracle_datasource"
const user_name = "user"
const password  = "password"
const database  = ""

block:
  var db = open(datasource,user_name,password,database)
  echo "opened"
  defer:
    db.close()
    echo "closed"
  for x in db.fastRows(sql"SELECT 'hello world' from dual"):
    echo x
```

```shell
opened
@["hello world"]
closed
```

## まとめ的な何か

Windows版のOracle ClientのダウンロードからのODBC データソース アドミニストレーターの設定をするまで、全行程の９割ほどかかりました。

### トラップの皆さん
* odbc_install.exeを起動するとなぜか消えるDLLファイル
* 環境変数 NLS_LANGの設定間違い
* 環境変数 TNS_ADMINのパス指定間違い
* tnsnames.oraのフォーマット

### 接続できたものの・・・

今回用意した接続確認用のOracleですが、ShiftJISでのインストールになっていたようで、日本語が入ったテーブルをSELECTすると、正しくエンコードされていないデータが表示されました。

もともと[db_odbc](https://nim-lang.org/docs/db_odbc.html)モジュールにも、`Currently all queries are ANSI calls, not Unicode.`と記述されているので、Unicodeでのクエリーは対応待ちの状態ですね。
【ラビットチャレンジ（E資格）】機械学習_線形回帰

#はじめに
本記事は、E資格の受験資格の取得を目的としたラビットチャレンジを
受講した際の勉強記録およびレポート記事である。
###参考図書
機械学習のエッセンス 
(SB Creative_加藤公一著)

#線形回帰モデル
##回帰問題
ある入力 (離散あるいは連続値) から出力 (連続値) を予測する問題

##回帰で扱うデータ
説明変数：$ \boldsymbol{x} = (x_{1}, x_{2}, ... , x_{m})^{T} \in \mathbb{R}^{m} $
目的変数：$ \boldsymbol{y} \in \mathbb{R}^{1} $
               
##線形回帰モデル
回帰問題を解くための機械学習モデルの一つ。教師あり学習。
$m$次元の入力およびパラメータの線形結合を出力する。
慣例として予測値にはハットをつける。

パラメータ：$ \boldsymbol{w} = (w_{1}, w_{2}, ... , w_{m})^{T} \in \mathbb{R}^{m}  $

線形結合：$ \hat{y} = \boldsymbol{w}^{T}\boldsymbol{x} + w_{0} = \sum_{j=1}^{m}w_{j}x_{j} + w_{0} $

##線形回帰モデルのパラメータは最小二乗法で推定
- 平均二乗誤差（残差平方和、Mean Squared Error）  
データとモデル出力の二乗誤差の和。  
平均二乗誤差が小さいほどモデル数式の直線とデータの距離が近い。

$ \qquad MSE_{train} = \dfrac{1}{n_{train}}\displaystyle\sum\nolimits_{i=1}^{n_{train}}(\hat{y}\_{i}^{(train)} - y_{i}^{(train)})^{2} $

- 最小二乗法
学習データに関して平均二乗誤差が最小となるパラメータを探索する手法。勾配が0になる点（微分したときに0になる点）を求めれば良い。

MSEをwに関して微分したものが0となる$\boldsymbol{w}$を求める：$ \smash{ \dfrac{\partial}{\partial \boldsymbol{w}}MSE_{train} = 0 }$

$ \hat{\boldsymbol{w}} = (\boldsymbol{X}^{(train)T}\boldsymbol{X}^{(train)})^{-1}\boldsymbol{X}^{(train)T}\boldsymbol{y}^{(train)} $

$\hat{\boldsymbol{y}} = \boldsymbol{X}\_{n_{new} \times m+1}\hat{\boldsymbol{w}} = \boldsymbol{X}\_{n_{new} \times m+1}(\boldsymbol{X}^{(train)T}\boldsymbol{X}^{(train)})^{-1}\boldsymbol{X}^{(train)T}\boldsymbol{y}^{(train)}$

#課題
ボストン住宅データセットの線形回帰モデルでの分析、「部屋数：4」「犯罪率：0.3」の物件の価格の予測。

■結果
　「部屋数：4」「犯罪率：0.3」の物価の価格は「4.24007956」となった。
![機械学習_線形回帰1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/791052/cbb8e678-2298-92a5-1080-a7fb477dfac5.png)
![機械学習_線形回帰2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/791052/03b75a01-662b-3f29-73e1-40c4128c55b2.png)
応用数学「線形代数」

# 応用数学　（１章：　線形代数）
- 行列
- 単位行列
- 逆行列
- 固有値・固有ベクトル
- 固有値分解
- 特異値分解

上記の６項目を元に線形代数の理解に努める。
### 行列 
スカラーを表にしたものであり、ベクトルを並べたものである。
行列積は「行」×「列」で新たな成分を求めること、連立方程式の研究の中から生まれたもの。
行列の積は

```math
\begin{pmatrix}
a & b \\
c & d
\end{pmatrix}
\times
\begin{pmatrix}
e & f \\
g & h
\end{pmatrix}
```
を計算する。
### 単位行列

```math
I = \
\begin{pmatrix}
1 & 0 & 0\\
0 & 1 & 0\\
0 & 0 & \ddots
\end{pmatrix}
```
<br>
行列の中には、単位行列という種類のものがある。
単位行列は、かけてもかけられても相手が変化しない、「１」のような行列のことを指している。

### 逆行列
ある行列Aに対して、その積が単位行列を生むような行列を逆行列という。
逆行列は掃き出し法によって求めることができる。

```math
\begin{pmatrix}
1 & 4 \\
2 & 6
\end{pmatrix}
\times
\begin{pmatrix}
x_1 \\
x_2
\end{pmatrix}
=
\begin{pmatrix}
10 \\
7
\end{pmatrix}を
```
```math
\begin{pmatrix}
1 & 4 \\
2 & 6
\end{pmatrix}
\times
\begin{pmatrix}
x_1 \\
x_2
\end{pmatrix}
=
\begin{pmatrix}
1 & 0 \\
0 & 1
\end{pmatrix}
\begin{pmatrix}
10 \\
7
\end{pmatrix}と考えて、
```
左右の係数の行列に同じ行基本変形を実行していけば、

```math
左辺は
\begin{pmatrix}
1 & 0 \\
0 & 1
\end{pmatrix}
で、
```
右辺には逆行列がもとまる。
つまり、

```math
AA^{-1} = A^{-1}A = I \
\
が成り立つ。
```

### 行列式
行列式の特徴を追記する。

<b>同じ行ベクトルが含まれていると行列式はゼロ</b>

```math
\begin{vmatrix}
\vec{v_1} \\
\vdots \\
\vec{w} \\
\vdots \\
\vec{w} \\
\vdots \\
\vec{v_2}
\end{vmatrix}
= 0
```
1つのベクトルがλ倍されると行列式はλ倍される

```math
\begin{vmatrix}
\vec{v_1} \\
\vdots \\
\lambda\vec{v_i} \\
\vdots \\
\vec{v_2}
\end{vmatrix}
= 
\lambda
\begin{vmatrix}
\vec{v_1} \\
\vdots \\
\vec{v_i} \\
\vdots \\
\vec{v_2}
\end{vmatrix}
```
他の成分が全部同じでi番目のベクトルだけが違った場合、行列式の足し合わせになる

```math
\begin{vmatrix}
\vec{v_1} \\
\vdots \\
\vec{v_i} \ + \vec{w}\\
\vdots \\
\vec{v_2}
\end{vmatrix}
=
\begin{vmatrix}
\vec{v_1} \\
\vdots \\
\vec{v_i} \\
\vdots \\
\vec{v_2}
\end{vmatrix}
+
\begin{vmatrix}
\vec{v_1} \\
\vdots \\
\vec{w} \\
\vdots \\
\vec{v_2}
\end{vmatrix}
```
行を入れ替えると符号が変わる

```math
\begin{vmatrix}
\vec{v_1} \\
\vdots \\
\vec{v_s} \\
\vdots \\
\vec{v_t} \\
\vdots \\
\vec{v_2}
\end{vmatrix}
=
-
\begin{vmatrix}
\vec{v_1} \\
\vdots \\
\vec{v_t} \\
\vdots \\
\vec{v_s} \\
\vdots \\
\vec{v_2}
\end{vmatrix}
```
### 固有値分解
正方形の行列を3つの行列の積に変換することを固有値分解という。

```math
A = VλV^{-1}
```

### 特異値分解
正方行列以外の行列を分解することを特異値分解という。

```math
M\vec{v}
=
\sigma\vec{u} \\
M^T\vec{u}
=
\sigma\vec{v}
```
これらは、

```math
MV
=
US \\
M^TU
=
VS^T となり、\\
MM^T = USS^TU^{-1} と表すことができる。
```
つまり、

```math
MM^T
```
を固有値分解すれば、その左特異ベクトルと特異値の２乗が求められることがわかる。ただし、左特異ベクトルは単位ベクトルから作らなければいけないことに注意する必要がある。
コメント機能の実装要点メモ

# はじめに
投稿に対して非同期通信でコメントできるようにする機能についてのメモ書きです。
# 前提
Ruby 2.6.5p114
Rails 6.0.3.4
macOS Catalina
# ルーティングの修正
```ruby:config/routes
  resources :items do
    resources :orders, only: [:index, :create]
    resources :comments, only: [:create]
  end
```
コメントの削除機能は実装しないため、destroyアクションは不要です。
# チャネルの作成
```ruby:ターミナル
% rails g channel comment
```
# createアクションの設定
```ruby:app/controllers/comments_controller
  def create
    @comment = Comment.new(comment_params)
    if @comment.save
      @user = @comment.user
      ActionCable.server.broadcast 'comment_channel', comment: [@comment, @user]
    end
  end
```
ActionCableの記述でbroadcastを通してcomment_channelに向けて@commentを送信しています。送信された情報はcomment_channel.jsで受け取り、テンプレートリテラルにする必要があります。
# 単体テストコード
contentが存在すれば保存できること、contentが存在しない場合保存できないこと、userと紐づいていない場合保存できないこと、itemと紐づいていない場合保存できないことをテストします。
アソシエーションを用いたデータ読み込み削減

# はじめに
この投稿はRailsで開発しているフリーマーケット機能を持ったWEBアプリケーションで、データのやり取り回数を削減できることをメモしておくものです。
# 前提
Ruby 2.6.5p114
Rails 6.0.3.4
macOS Catalina
# アソシエーション
```ruby:app/models/item.rb
  belongs_to :user
  has_one :order
```
```ruby:app/models/order.rb
  belongs_to :user
  belongs_to :item
```
```ruby:app/models/user.rb
  has_many :items
  has_many :orders
```
# itemと紐づけられたuserの情報を読み込む方法
商品詳細が表示される際に、ログインしているユーザーと出品しているユーザーが、同一人物の場合と同一人物ではない場合で条件分岐処理を行う必要がありました。前者の分岐処理の記述では余分なデータの読み込みが発生してしまいます。
後者の記述ではアソシエーションを活用した読み込みの手間の少ない可読性の高い記述となっています。

```ruby:app/views/items/show.html.erb
   <% if Order.find_by(item_id: @item.id) == nil %>
      <% if user_signed_in? && current_user.id == @item.user.id %>
        <中略>
      <% elsif user_signed_in? %>
        <中略>
      <% end %>
    <% end %>
```
```ruby:app/views/items/show.html.erb
    <% if @item.order == nil %>
      <% if user_signed_in? && current_user.id == @item.user.id %>
        <中略>
      <% elsif user_signed_in? %>
        <中略>
      <% end %>
    <% end %>
```
ancestryはawsにデプロイしただけでは使えない

#　1.どんな状態だったか
ancestryを利用して、カテゴリー機能を実装、ローカルでは動くのに本番環境で反映されないという状態

# 2原因
ancestryを使うためには、本番環境でもローカルと同じ様に
db migrateし、seedを読み込まなくてはならない

# 3解決方法
まずdb migrateします

```
$　cd var/www/app名/current
$ rake db:migrate RAILS_ENV=production
```
上手くいかない時はdbをドロップしもう一度クリエイトし直す

```
$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop

$ rake db:create RAILS_ENV=production
```
もう一度migrateします。

次にseedを反映させます。

```
$ rake db:seed RAILS_ENV=production
```
以上になります。

# 4最後に
自動デプロイをしている場合はcurrentディレクトリで操作を行う必要があるそうです
そうでない場合は~ディレクトリで大丈夫みたいです

参考にした記事
[[aws,rails]ancestryをawsにデプロイした時に反映されない状況の解決方法](https://qiita.com/KONTA2019/items/ea8829e0d19b4d7d059a)
[本番環境でrake db:seedを実行する際の注意点](https://yamaguchi-t.hatenablog.com/entry/2019/11/03/165004)
【第5回】初心者二人で0から麻雀アプリ開発

[第4回はこちら](https://qiita.com/dashun814/items/ab4f7b668fb12cacd2f8)

#改版履歴
2020/11/26 投稿



#第5回会議(2020年11月23日)
今回はいよいよ実装！……に入るための勉強会を実施しました。
これまでは個々に情報収集、学習を行なってきましたが、今回以降は足並みを揃える+毎週の学習時間確保を目的として、定例会議の場で学習した内容の共有をして行く予定です。

###議題

- プロジェクトの立ち上げ
- ヘッダー・フッター表示
- テーブル表示

#形式
今回は最初の勉強会でしたので、どんな形式で、どのように進行したかを残しておこうと思います。

####使用したツール

- google meet
- google スライド
- Xcode

####事前準備

1. お互いに学習テーマを決める
2. 一週間の間にテーマの調査・実装を行い、スライドにまとめる

####当日

1. 順番にスライド発表
2. 質疑応答
3. 課題点整理
4. 次回のテーマ決定


#勉強会
結論から言うと、実装についてはプロジェクト作成までしか実現出来ませんでした。
コンパイルエラーの解決は次週に持ち越しです……

今記事では、スライド発表後の課題点整理で挙がった内容を列挙します。

##問題① 使用しているバージョンに対応した学習ソースがない
現在、本プロジェクトで使用しているバージョンは以下の通りです
swift: 5.3
Xcode: 12.2

特に、Xcodeは最近大きなアップデートがあり、開発画面のレイアウトが大きく変わってしまったようです。
過去の記事に書いてある内容を現在のバージョンで実現する操作がどれに当たるのか、という作業に難航しています。

##問題② ライブラリに対する知識不足
第3回にて、iosSDKを使用すると漠然と決めましたが、上記のテーマを実現する方法は複数あることがわかってきました。
大きく、UIKit,swiftUI,オープンソースのライブラリを使っての実装が考えられますが、3者をあまり区別なく調査している状況です。

そのため、実装に対する共通認識を持ちづらく、お互いの調査結果についてレビューしづらいという弊害がでています。

共同開発をする上でも、基本の画面や、共通部に使用するライブラリは揃えていく必要がありそうです。

##エラーの原因がわからない
これは特にswiftUIでの実装にいえるのですが、コンパイルエラーの箇所やエラーメッセージについて、英文でわかりづらい、翻訳を駆使しても原因の特定にじかんがかかってしまう。
また、エラーの直接原因が、エラーが出ている個所でない場合があり、特定できない。

などです。

根本的な基礎知識が不足しているのが原因ではありますが、現在の学習方法では上記の問題を解決しづらいのではないかと考えています。

詰まった場合の解決策をまとめておく等の対応が必要かもしれません。

#おわりに
今回は一回目の勉強会についてお送りしました。
本来は、勉強会の成果を本記事でアウトプットしていくのがよいとは思っていますが、一記事になるほどのネタがありませんでした……

次回以降、投稿内容等も含めて、課題を消化していきたいと思います。
(会議の全体概要を投稿していくのではなく、勉強会の一部分をピックアップしてまとめるというスタイルでもいいかもしれません。ネタがあればですが。)
【Visual Studio Code】VS Codeの小ネタ紹介

# VS Codeの小ネタを紹介します

※役に立つかはわかりません🙇

<!-- こちらの環境で再現できなかったので、これに類似している拡張機能を紹介しておきます。 -->

# Better Comments

[Better Comments](https://marketplace.visualstudio.com/items?itemName=aaron-bond.better-comments)という拡張機能をインストールすると、以下のようなことができます。

|入力例|効果|
|------|----|
|`//`|通常のコメント|
|`// *`|ちょっと明るくなります|
|`// //`|取り消し線がでます|

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">お疲れ様です😌<br><br>💥VScodeの小ネタ紹介<br><br>・コメントアウトしたコードに// (スラッシュ2回)入力すると取り消し線がでます😊<br><br>・コメントアウトしたコードに*(アスタリスク)を入力すると、コメントアウトの部分が少し明るくなります😊 <a href="https://t.co/RXl0iEDi3m">pic.twitter.com/RXl0iEDi3m</a></p>&mdash; ミキ🐹@プログラミング (@mikiprogram) <a href="https://twitter.com/mikiprogram/status/1331924377496010753?ref_src=twsrc%5Etfw">November 26, 2020</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
メリークリスマスヽ(=´▽`=)ﾉ

皆様今年の[弊社アドベントカレンダー](https://qiita.com/advent-calendar/2020/digiq-tech)楽しんで頂けたでしょうか？


#### 弊社では今年も色々な挑戦をしてきました。

- GCPパートナーになるべく全面的にGCP採用を後押し
- アプリ開発の高速化の為にFlutterを採用
- Raspberry Piを利用したハードウェア開発

等など、様々な挑戦をして来ました。

日々進化していくトレンドに対応するべく
柔軟な姿勢で利用する道具を見直し・アップデートして今年も無事に乗り切る事が出来ました！


#### 来年も引き続き我々はアップデートを続けて行きます！

5Gの登場でモバイルアプリケーションの世界は更に加速して行くことと思っています。
来年はどんな新しい事に挑戦出来るのか、今からとても楽しみです！


#### 弊社では採用も積極的に行っております。
弊社エンジニア・デザイナーの記事を読んで、一緒に働いてみたいな！
と思ってくれた方おりましたら是非弊社採用窓口までご連絡をお寄せ下さいm(_ _)m

[Green](https://www.green-japan.com/company/6229)
[マイナビ](https://tenshoku.mynavi.jp/jobinfo-256081-3-6-1/)
(※アドベントカレンダーを見ました！と一言添えて頂けると嬉しいです！)

#### 今年も残りわずか！

皆様健康には十分に気を付けて、良い年をお過ごし頂けること願っております。
そして、来年をめでたく迎えられるよう祈っております(*´ω｀*)

### メリークリスマス！！！ヽ(=´▽`=)ﾉ
たった 1 行だけど OSS にコミットした

（記事内で用意したプレビューが YouTube 動画のため別リンクになっている点、ご了承くださいませ。（[参考にさせていただいた記事](https://qiita.com/yoshiki_1122/items/959782e4a726c08bcf98)））

自身でやっているブログのテンプレート（Hugo のテンプレート）に不具合を見つけて「どうせだしプルリク送るかー」と思ってプルリクを送ったらマージしてもらえたときのお話です。

[こんなブログです](https://portfolio.fairy-select.com/posts/notes/introduction/)

## :bug: 見つけた不具合

![table-of-contents.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486784/a4620b9b-0922-2f83-347a-200bff753ebd.png)

ブログの記事を PC で表示しているときに右側に表示されている `Table of Contents` の欄。クリックするとその項目のところまでヌメっと動きます。

[![ヌメっと動く動画](http://img.youtube.com/vi/xhEhZULKLGQ/0.jpg)](https://www.youtube.com/watch?v=xhEhZULKLGQ)

項目名にマルチバイト文字が入っている際にうまくいきませんでした。

[![ちゃんと動かない動画](http://img.youtube.com/vi/4-Qsv20CSNI/0.jpg)](https://www.youtube.com/watch?v=4-Qsv20CSNI)

## :mag: どうやって直す方法を探したか

エラーメッセージでいろいろググっていたら以下のような記事を見つけました。

[jQuery を用いたページ内スクロール: リンク先 ID 値が日本語である場合、エラー "Syntax error, unrecognized expression" が発生 - DEV](https://dev.to/nabbisen/jquery-id-syntax-error-unrecognized-expression-10b5)

ID 値に日本語（マルチバイト文字）が含まれている場合うまくいかないのでは？となり、上記サイトに従って `this.hash` を `decodeURI(this.hash)` にしたところ、

[![ちゃんと動いた動画](http://img.youtube.com/vi/kTN_xxt2vh8/0.jpg)](https://www.youtube.com/watch?v=kTN_xxt2vh8)

うまくいきました！！

## :fork_and_knife::meat_on_bone: リポジトリをフォークしてプルリクエストを送るまで

OSS にプルリクエストを送る流れは以下のようになります。

- OSS のソースコードをフォークする

![fork.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486784/835c4f90-f819-0f9f-6b0c-f32847f83345.png)

そうすると自分のところにリポジトリをクローンしたような形になります。

![clone-after-fork.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486784/c7f3dfb0-e249-8e07-0aa1-9742489eedbe.png)

- 自分のリポジトリで新しくブランチを作成してソースコードをいじる

- プルリクエストを送る

自分も初めてだったのでわからなかったのですが、フォークしたリポジトリと元のリポジトリを比較してプルリクエストを送ることができるみたいです。

実際のプルリクエストは [こちら](https://github.com/hugo-toha/toha/pull/164)

見事マージされて、 OSS に貢献することができました。

![pull-request.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486784/ee8da3d3-d769-a199-6411-e7d0ac0f71d4.png)

## :muscle: 貢献するのは意外と難しくない

今回 OSS に貢献するうえで初めて Git の Fork を使用しましたが、それ以外はプルリクエストを送るくらいで、普段の開発＋αくらいで貢献できたので、貢献するだけなら意外と難しくないのかもしれません。

大変だったのは、プルリクエストを英語で書くところです。

ちょいちょい Google 翻訳を使用しつつ書きましたが、それでも管理者の方にちゃんと受け入れていただくことができました。

## :convenience_store: OSS を利用するにあたって

OSS を使用するうえで最も留意しなければいけない点は、 <mark>OSS 自体にバグがあるかもしれない</mark> という点です。

開発で外部のサービスを利用するのは確かに便利ですが、そのサービスの不具合やダウンによって、自分の製品にも影響があるということを忘れてはいけません。

ですが、どうしても利用したいとき、動作してくれないと困るとき、それは世界中探せば同じ問題で困っている人がいるかもしれません。

思い切ってプルリクエストを送って承認されれば、自分の市場価値を少しだけ高められると思います。

みなさんもぜひやってみてください。
【Laravel】migrate:refresh と migrate:fresh の違い

# migrate:refresh
`down()` を実行してから `up()` を実行する。なので `down()` の内容によっては `up()` の処理に影響を与える可能性がある。[^1]

[^1]: ゴミデータを残してしまったり等

# migrate:fresh
全テーブルをドロップしてから `up()` を実行する。 `down()` は実行されない。

# 参考
- [Laravel Migrate Fresh Command - Laravel News](https://laravel-news.com/migrate-fresh)
- [データベース：マイグレーション 8.x Laravel](https://readouble.com/laravel/8.x/ja/migrations.html)
algolia(instantsearch.js)でイニシャル検索ってどうやるの？？

クリスマスまであと21日！！ヽ(=´▽`=)ﾉ
本日は再び大野が担当致しますm(_ _)m
(1日目の記事も担当しておりました！)

## `algolia`(`instantsearch.js`)でページ表示タイミングで検索ってどうやるの？？

はい、コレは純粋に私が直面した問題でした。
`algolia`はとても便利なのですが如何せん日本語の情報が少ない気がしますね・・・

**結論から言うととても簡単です。**

```javascript
instantsearch.widgets.configure({
  filters: filters,
}),
```

これを使えばいけます！！b(・∀・)

具体的なコードは以下

```javascript
// お決まりの初期化
const search = instantsearch({
  indexName: searchIndex,
  searchClient: algoliasearch('keystring', 'secretstring'),
  routing: true,
});

// 各種検索設定
search.addWidgets([
  // 検索ボックスの配置
  instantsearch.widgets.searchBox({
    container: '#search',
    placeholder: 'フリーワード...',
    showReset: true,
    showLoadingIndicator: true,
  }),

  // 初期検索条件をセット！
  instantsearch.widgets.configure({
    filters: ['available: true AND (NOT uid: null)'],
  }),

  // 検索結果表示設定
  instantsearch.widgets.hits({
    ・・・
```

こんな感じで初期検索条件を指定出来るようになっています。
(エアコーディングですが有効フラグtrueでuidがnullじゃないデータと言う検索条件を付与しています。)

初期条件の書き方はコチラを参考にしています。

[https://www.algolia.com/doc/api-reference/api-parameters/filters/](https://www.algolia.com/doc/api-reference/api-parameters/filters/)

## コレだと初期検索条件がずっと検索条件に付いちゃうんだけど・・・

はい、その通りです。
完全に初回の検索条件を指定したいだけなんだけど・・・と言う場合は`searchFunction`と言うのを初期化時に指定する事で可能です。

```javascript
// お決まりの初期化
var initialsearch = false;
const search = instantsearch({
  indexName: searchIndex,
  searchClient: algoliasearch('keystring', 'secretstring'),
  routing: true,
  // 検索前処理の追加
  searchFunction: function(helper) {
    if (false === initialsearch) {
      initialsearch = true;
      // 最初の検索条件を指定
      helper.setQuery(helper.state.query + '&available=true').search();  
    }
  }
});
```

これで初期化時の最初の検索の時だけ検索条件を変えるなどといった事が出来ます。

[https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/#widget-param-searchfunction](https://www.algolia.com/doc/api-reference/widgets/instantsearch/js/#widget-param-searchfunction)

参考になりましたら幸いですm(_ _)m
pythonのid関数の逆関数(idからオブジェクトを取得)

検索したけど以外と見つかりにくかったので、メモのつもりでここに書いておきます。

# 1. やりたいこと
`hoge = "hello world"`としてから`i = id(hoge)`としたとき、`i == 1774920137984`を得たとします。
では`id`の逆関数のようなことはどうやればできるのでしょうか。

例えば`id`の逆関数を`bi`とするなら、
`bi(1774920137984)`が`"hello world"`を返すようにするにはどうすればいいのでしょうか

# 2. 答え
**警告: このやり方を実行した結果処理系がぶっ壊れても、筆者は責任を取りません**

次のようにします。

```python
import ctypes
bi = lambda x ctypes.cast(x, ctypes.py_object).value

print(bi(1774920137984)) # "hello world"
```

おそらく、これは実行中のpythonがC言語で書かれている場合(ほとんどのpythonがこれらしい)に動作します。
Jython(Javaで書かれたpython)を利用している場合は、他のやり方があるのかもしれません。

また、適当な数字を入れた場合や、変数に格納しなかったオブジェクトのidを入力すると、処理系がフリーズしたのち、勝手に終了しました。

# 3. 参考
https://www.366service.com/jp/qa/c912a3924b47b37e78f114dc052a52c0
YWTをやってみて

プロジェクトの振り返りへYWTを導入したので、感想を記載します。

# 導入した経緯

今回作業したメンバーで継続開発していくことになったためです。
改善してより高品質なサービスを短時間で提供できるチーム作りのため、事実の把握並びに改善点の導出が必要でした。

なお、チーム規模感は以下の通りです。

- 責任者1名
- メインメンバー4名(自分含む)
- サポートメンバー2名

大きな機能の開発が終わったタイミングで実施しました。

## 検討したフレームワーク
・KPT
・YWT

## 手法選択の基準
今回のチームには短い期間で無理していろいろ作業をお願いした都合、振り返りでネガティブな雰囲気になることは避けたいと考えていました。無理のある状況でできなかった点ばかり考えると、自ずとネガティブになってしまうと思ったためです。

他の方々の発信内容を読み、
>KPTの「P」（問題）という言葉に引っ張られて、反省会みたいな雰囲気になる

という内容をいくつか目にしたので、YWTを選択しました。
※KPTも良い振り返りのフレームワークだと思うので、状況によってはこちらのフレームワークを利用したいと考えております。


# 進め方
以下を参照して流れを踏襲し、実施しました。
https://techblog.gmo-ap.jp/2020/11/12/ywt/

1. やったことを書き出す(5〜10分)
2. やったことを全員で軽く読む(5分)
3. わかったことを記載(10分〜15分)
4. わかったことについて、記載した人が説明しつつ読む(15分)
5. 次やることを話し合いつつ考える(15〜25分)  
→実際に実施してみたら40分程度かかりました。他は予定時間におさまりました。

※全体での振り返り前に個人で振り返りするよう、お願いしています。

# 実際に上記の流れで進めてみた感想
## 1. やったことを書き出す(5〜10分)
- 事前に記載してもらうスタイルでもよかったかなと思いました。
- とはいえ書く暇がない人もいるかも知れなかったので、書き出す時間を作ったこと自体はよかったです。

## 2. やったことを全員で軽く読む(5分)
- 1.の延長でしたが、俯瞰してみて欲しい旨のアナウンスが挟めたのでよかったです。

## 3. わかったことを記載(10分〜15分)
- わかったことというネーミングではありつつも、どうしても問題点や至らない点の記載がありました。KPTを選択していないため、KPTでは出てこない「わかったこと」の内容がありましたので、大変学びになりました。
- 記載内容について「組織改善観点で記載してほしい」とお願いしましたが、個人の学びのようなものがちらほら混じっていました。（私も記載してしまいました）
    - ただ、その辺りを限定して大切な情報が出てこなくなることは避けたいので、今後も引き続き「わかったこと」へ記載する情報の制約は付けない予定です。

## 4. わかったことについて、記載した人が説明しつつ読む(15分)
- 個人反省のようなものが多いと、時間を食ってしまうなと感じました。とはいえ大切な情報ではあるかと思うので仕方ないなぁと思います。

## 5. 次やることを話し合いつつ考える(15〜25分)
- こちらの進め方に苦慮しました。
    - 今回は、私（司会）がその場で「わかったこと」の内容を勝手にグルーピングし、話した方が良さそうな論点を決めて話を進めました。
    - 今後YWTの振り返りを続ける場合は、「わかったこと」から「つぎやること」を導出する際に、どうやって進めていくことで抜け漏れのない改善点を作成できるのか？ について検討が必要だと考えています。

# その他感想など
- 実施してよかったと考えています。
    - メンバー全員が似たような問題意識を持っていることを確認でき、「今後どうチームをより良く改善していくか？」について同じ方向を向くきっかけとなったためです。
    - 通常の話し合いで「意見をください」と言っても、どうしても意見は出づらいかと思うので、引き続き継続して振り返りの取り組みを実施したいです。
- いろいろな役割の人に集まってもらって話せたことが良かったです。可能な範囲でステークホルダーを集めてお話しする方が、同じトピックについて様々な観点での意見が聞けるので、振り返りの質が向上するように感じました。
Manifold 2Gのセットアップ(opencvの導入から有効化まで)

## はじめに
現在、ドローンの活躍分野はますます拡大を見せており、ビジネス・学問の現場では設備保全であったり、生態調査であったりと様々な現場で利用されております。

ドローンの活用に欠かせない技術としてあげられるのが、画像認識や物体検出をはじめとした画像処理です。その画像処理に必要な様々な機能が実装されていて、BSDライセンスで配布されているため商用目的でも利用できるopencvはドローンにおける画像処理を行う第一段階として最適です。
今回はそのopencvの導入手順について説明します。世界のドローンメーカーのシェア率トップの「DJI」のドローンでの導入手順を説明します。

## DJI SDKとは
DJI Developerではドローンアプリ開発者むけに「DJI SDK」を提供してます。DJI SDKにはカスタマイズされたモバイルアプリを開発する「[Mobile SDK](https://developer.dji.com/mobile-sdk/)」、そのモバイルアプリのUI要素を提供することで、開発時間を短縮する「[UX SDK](https://developer.dji.com/ux-sdk/)」、低遅延、高周波センサーテレメトリ、航空機制御、およびビデオフィードにより、ソフトウェアおよびハードウェア機能を拡張する「[Onboard SDK](https://developer.dji.com/onboard-sdk/)」、ドローンの内部システムと通信できるようにする新しいプロトコルのセットである「[Payload SDK](https://developer.dji.com/payload-sdk/)」、カスタマイズされたアプリケーションを作成する「[Windows SDK](https://developer.dji.com/windows-sdk/)」があります。
その中でも**Onboard SDK(OSDK)**は、産業用に使われるドローンであるMatriceシリーズ用のアプリケーション開発時に使用され、そのOSDKに基づいてアプリケーションを開発することによってドローンを制御して自律飛行などの複雑な飛行タスクを実行することができます。

## ハードウェアについて
今回の導入に用いたハードウェアは以下のとおりです。
**Manifold 2G**: NVIDIA Jetson TX2、128GB SATA-SSDを搭載し、画像処理等の計算を行うのに適しています。
-  Ubuntu  16.04
-  CUDA 9
-  Cmake
-  GCC 7

## DJI Onboard SDK ROSの導入
以下を参照して、導入します。DJIの公式サイトは更新が遅いため、こちらのリンクを参照する方が確実です。
https://github.com/dji-sdk/Onboard-SDK-ROS

## OpenCVの導入
以下のリンクからopencv 3.3.1をダウンロードします。
- [OpenCv](https://opencv.org/releases/)
- [opencv contrib](https://github.com/opencv/opencv_contrib/releases)

以下のようなデイレクトり構造にします。

┌opencv-3.3.1/
└opencv_contrib-3.3.1/

build ディレクトリを作成ます。

```
cd opencv-3.3.1
mkdir -p build && cd build
```

以下のように設定します。

```
cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D WITH_CUDA=ON -D CUDA_ARCH_BIN="6.2" -D CUDA_ARCH_PTX="" -D WITH_CUBLAS=ON -D ENABLE_FAST_MATH=ON -D CUDA_FAST_MATH=ON -D ENABLE_NEON=ON -D WITH_LIBV4L=ON -D BUILD_TESTS=OFF -D BUILD_PERF_TESTS=OFF -D BUILD_EXAMPLES=OFF -D WITH_QT=ON -D WITH_OPENGL=ON -D WITH_TBB=ON -D ENABLE_PRECOMPILED_HEADERS=OFF -D ENABLE_CXX11=ON -D CUDA_NVCC_FLAGS=--expt-relaxed-constexpr -DBUILD_WEBP=ON -DOPENCV_EXTRA_MODULES_PATH=../../opencv_contrib-3.3.1/modules ..
```

ビルドし、インストールします。

```
make
make install
```

## Package ファイルの書き換え
前節で正常に動作しない場合は[`CMakeLists.txt`](https://github.com/dji-sdk/Onboard-SDK-ROS/blob/master/CMakeLists.txt)の3行目に以下を追加します。

```
set(OpenCV_DIR ~/opencv-3.3.1/build)
```

また、その下の行の`find_packages`に`cv_bridge`を追加します。
以上で、ROSのnodeでopencvを利用できるようになります。
@Published を監視する

```swift
struct Content: Hashable {
    let name: String
}

extension Content: Identifiable {
    var id: Content { self }
}

class ContentViewModel: ObservableObject {
    @Published var contents: [Content] = [.init(name: "piyo")]
}
```
上記のようなViewModelを実装した際に`contents`の更新を監視したい場合がある

### 解決策
```swift
viewModel.$contents
    .sink { contents in
        print(contents)
    }
```

もしくは

```swift
viewModel.objectWillChange
    .sink {
        print("willChange")
    }
```

これで値を購読することができる

注意するべきポイントとして、どちらも値更新前に呼ばれるのでsinkが呼ばれたタイミングでは値は更新されていない。
プロパティを直接購読する場合は**更新後の値が取れる**が、
objectWillChangeを購読する場合はObservableObjectに生えているプロパティそれぞれの更新タイミングを取得することができるが**更新後の値は取得できない**。

### 余談

ちなみに、ViewのinitializerなどでViewModelにあるPublishedObjectの更新前の値を参照したい場合に直接クロージャーで扱おうとすると`Escaping closure captures mutating 'self' parameter`と出てしまうので、値をコピーする必要がある。
コピーをするだけなのでクロージャー内で値を書き換えてもViewの保持するViewModelには何も影響は出ない。

```swift
viewModel.$contents
    .sink { [previousContents = viewModel.contents] _ in
        print(previousContents)
    }
```

```swift
typealias DisposeBag = Set<AnyCancellable>

struct ContentView: View {
    @ObservedObject var viewModel = ContentViewModel()
    private var disposeBag = DisposeBag()
    var body: some View {
        NavigationView {
            List {
                ForEach(viewModel.contents) { content in
                    NavigationLink(
                        destination: Text(content.name),
                        label: {
                            Text(content.name)
                        })
                }
            }
        }
    }
    init() {
        viewModel.$contents
            .sink { [previousContents = viewModel.contents] contents in
                print(contents)
                print(previousContents)
            }
            .store(in: &disposeBag)
    }
}
```
高速推論ライブラリtkDNN上で自前モデルで動かす方法

## 経緯
yolov4の推論を高速化させた推論ライブラリを使う機会があったのですが、自分で学習させたモデルを動かす際に少し詰まったので、手順を共有します。今回はdarknetの学習済みモデル(自前モデル)をtkDNNで使う方法を紹介します。

## tkDNNとは
[tkDNN](https://github.com/ceccocats/tkDNN)とは、yolo darknetを高速化できる推論ライブラリです。学習済みのv3またはv4のweightsファイルとconfigファイル、クラス名のファイルを用意するだけで使うことができます。**jetsonだと大体2倍~3倍高速化でき、量子化すると4倍以上速くなります**。ちなみにdarknet以外にもResNetやCenterNet、MobileNetなども高速化できます。
![Screenshot from 2020-11-26 19-15-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663246/9e152837-588c-dd4e-cd15-cd2ff810feef.png)

## 手順
### 1. tkDNNのビルド
下の手順でtkDNNをビルドします。環境作成などは[こちら](https://github.com/ceccocats/tkDNN)を参考にしてください。

```
git clone https://github.com/ceccocats/tkDNN
cd tkDNN
mkdir build
cd build
cmake .. 
make
rm yolo4_fp32.rt
./test_yolo4
```

### 2. weightsのexport
[こちら](https://git.hipert.unimore.it/fgatti/darknet)のリポジトリを使って、weightsファイルをexportします。

```
git clone https://git.hipert.unimore.it/fgatti/darknet.git
cd darknet
make
mkdir layers debug
./darknet export <path-to-cfg-file> <path-to-weights> layers
```
path-to-cfg-fileにdarknet学習時のconfigファイルのパス、path-to-weithsに学習済みモデルのパスを入れてください。これが無事に終わると、debugとlayersにbinファイルが作成されているはずです。debugとlayersフォルダをtkDNN/build/yolo4の中に入れてください。すでにdebugとlayersフォルダがある場合は入れ替えてください。

### 3. tkDNNのソースコードの変更
デフォルトのコードままでは、自前のモデルのクラスや設定を反映できないので、tkDNNのソースコードを編集します。下はデフォルトのままですが、cfg_pathとname_pathを自分のものに設定してください。namesファイルは学習したクラスを記入したものを自分で作成してください。

```tkDNN/tests/darknet/yolo4.cpp
int main() {
    std::string bin_path  = "yolo4";
    std::vector<std::string> input_bins = { 
        bin_path + "/layers/input.bin"
    };
    std::vector<std::string> output_bins = {
        bin_path + "/debug/layer139_out.bin",
        bin_path + "/debug/layer150_out.bin",
        bin_path + "/debug/layer161_out.bin"
    };
    std::string wgs_path  = bin_path + "/layers";
    std::string cfg_path  = std::string(TKDNN_PATH) + "/tests/darknet/cfg/yolo4.cfg";
    std::string name_path = std::string(TKDNN_PATH) + "/tests/darknet/names/coco.names";
    downloadWeightsifDoNotExist(input_bins[0], bin_path, "https://cloud.hipert.unimore.it/s/d97CFzYqCPCp5Hg/download");

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
}
```

### 4. tkdnnのビルド&weighsファイルをコンバート
下のコマンドを実行してください。fp16に量子化したい場合は、export TKDNN_MODE=FP16を実行すれば大丈夫です。

```
cd build
cmake ..
make
rm yolo4_fp32.rt
## (量子化)export TKDNN_MODE=FP16
./test_yolo4
```
完了すると、yolo4_fp32.rt(量子化した場合はyolo4_fp16.rt)というファイルが作成されていると思います。これで完了です。最後に、下のコマンドを実行すればデモ動画で試すことができます。

```
./demo yolo4_fp32.rt
```

## まとめ
tkDNNを作った人はすごい！リポジトリでのissueも結構答えてくれます。

**間違いや質問、ご意見等ありましたらお気軽にコメントください。頑張って答えますので(笑)。**
階段の三路スイッチ

階段の照明が二つのスイッチで入り切りができる電気工事士試験の定番の三路スイッチになっていて、以下のようにスイッチがありました。

![3RO1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/5452ef5d-c0a0-310a-1f96-7263ec90cd42.png)

階段上のスイッチは下で、階段下のスイッチが上になっていました。それぞれの階の照明のスイッチといっしょになっています。

ちょっと分かりにくいので、統一してみました。

![3RO2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/f00480ea-77a9-9679-29e6-17a51b61fe8b.png)

なれの問題かもしれませんが、私はこれの方が直感的に分かりやすい気がします。
OpenChain: spec v2.1 の紹介 第2回 / Commentary of spec v2.1 vol.2, §3.1.4-3.1.5

#OpenChain spec v2.1 の紹介 §3.1.4-3.1.5
本日は、OpenChain spec v2.1 の中身の紹介第2弾（1.4～1.5章）です。

1.4章は、OSSコンプライアンスプログラムの対象範囲に関する章です。OSSコンプライアンスプログラムは、組織全体を対象にしたり、一部のプロダクトラインのみを対象したりと、自由に対象範囲を選択することができます。

1.5章は、各OSSライセンスの組織内でのレビューに関する章です。組織はユースケースに応じてOSSライセンスの義務、制約、および権利についてレビューし、文書として記録するプロセスを定める必要があります。
1.5章のOSSライセンスのレビューは、組織にとって非常に重要な業務ですが、慣れていない組織にとっては難易度が高い業務です。
そこで、Japan WGのFAQサブグループでは「[**OSSライセンス関連でよくある誤解FAQ**](https://github.com/OpenChain-Project/OpenChain-JWG/tree/master/Education_Material/FAQ "OSSライセンス関連でよくある誤解FAQ")」を纏めて公開する活動を行っています。

明日はこのFAQ SGの活動を紹介します。

#Commentary of the OpenChain spec v2.1 §3.1.4-3.1.5
Today, we will introduce the contents of the OpenChain spec v2.1 (Chapter 1.4-1.5).

Chapter 1.4 is about the scope of the OSS Compliance Program. Th e OSS compliance program gives you the freedom to choose whether it covers your entire organization or just some product lines.

Chapter 1.5 is a chapter on reviewing each OSS license within your organization. Organizations should establish a process for reviewing and documenting OSS license obligations, restrictions, and rights for each use case.
Reviewing OSS licenses in Chapter 1.5 is a very important task for an organization, but a difficult task for an unfamiliar organization.
Therefore, the FAQ subgroup of the Japan WG is working to publish "[**common misunderstanding FAQs related to OSS licenses**](https://github.com/OpenChain-Project/OpenChain-JWG/tree/master/Education_Material/FAQ "common misunderstanding FAQs related to OSS licenses")" together.

Tomorrow we will introduce the activities of this FAQ subgroup.
CakePHPのアソシエーション


# はじめに
SQLのJOIN方法には、LEFT JOIN、RIGHT JOIN、INEER JOINがあるが、
cakephpでは標準でLEFT JOINしか準備していない。
LEFT JOINしかない代わりに、CakePHPでは「アソシエーション」という結合方法があり、
それによって多種多様な結合を実現している。

#joinを使うためのした準備
joinを使うコントローラで複数のモデルを利用するのを宣言する。

`public $uses = array('Board','Personal');`


#アソシエーションの紹介

##hasOne
**関係**　一対一

**例** ユーザーは１つのプロフィールを持っている

ユーザーモデル（主人）に設定する。
外部キーはプロフィールモデルに設定する。

##hasMany

**関係** １対多
**例** ユーザーは複数のレシピを持っている

基本的にhasOneと同様で少し設定が増える程度。
ユーザーモデルに（主人）に設定する。
外部キーはプロフィールモデルに設定する。

##belongsTo

**関係** 多対１
**例** レシピはユーザーに属している

hasManyと逆のイメージ。
hasOneが主人視点で定義したもので、belongsToが従者視点で定義しているようなイメージ。
外部キーはレシピモデルに定義する。

##hasAndBelongsToMany

**関係** 多対多
**例** 以下を参照
http://dim5.net/cakephp/hasandbelongstomany-configuration.html

#ダイナミックなバインド
モデルに定義したアソシエーションは、常に固定な関係だ。
一時的に、テーブルの結合設定を変えたい時は`bind`を使う。
`bind`で設定した結合関係は、`bind`直後のメソッドにのみ適応される。

モデルと結合する
`モデル->bindModel(結合設定の連想配列`

モデルの結合を解除する
`モデル->unbindModel(結合設定の連想配列`
Qiitaに記事を書く方法（markdown記法） 

初投稿するハードルの一つであったMarkdown記法についてまとめます。

## 目次

- Markdown記法とは
- 目次の作り方
- 見出し
- コードの記載
- リンクの貼り方

# Markdown記法とは

>Markdown（マークダウン）は、文書を記述するための軽量マークアップ言語のひとつである。本来はプレーンテキスト形式で手軽に書いた文書からHTMLを生成するために開発されたものである。しかし、現在ではHTMLのほかパワーポイント形式やLATEX形式のファイルへ変換するソフトウェア（コンバータ）も開発されている。各コンバータの開発者によって多様な拡張が施されるため、各種の方言が存在する。
https://ja.wikipedia.org/wiki/Markdown
(Wikipediaより引用）

要するにいい感じにテキストを見やすくしてくれる、手軽につかえる文法みたいなイメージですかね？そして、いろんな拡張ができるよーといった感じです。

# 見出し

見出し（この上のアンダーラインと太字表示）をするには、頭に#（シャープ）を付ければOKです。
何個つけるかによってサイズが変わります。
見出しをつけると、サイドに各見出しに飛ばしてくれる便利機能があるので、上手く使うと見やすくなると思います。

記述方法

```
# いっこ
## にこ
### さんこ
#### よんこ
##### ごこ
###### ろっこ
```

出力

# いっこ

## にこ

### さんこ

#### よんこ

##### ごこ

###### ろっこ

こんな感じです。

※ここの見出しのサンプルの関係で、サイドの見出しが少しおかしくなっています。

# 目次の作り方

このぺージの冒頭に作ったような目次です。

記述方法

```
- title1
- title2
- title3
- etc
```

出力

- title1
- title2
- title3
- etc
 
インデントを付ければ、入れ子構造も作れます。

- title1
    - title2
        - title3
- etc

# コードの記載

前項のように色をつけてコード等を見やすくする方法です。
バッククォート3つで囲めば大丈夫。

記述方法

    ```
    ここにコードをかく
    ```

出力

```
ここにコードをかく
```

たまに予期しない挙動をすることがありますが、スペースとか改行で
だいたい何とかなります。バックスラッシュもうまく使うといいです。

# リンクの貼り方

`[]`でリンクにしたい文字列を囲み、その後ろに`()`でURLを囲めばオッケーです。

記述方法

```
[google](http://google.com)
```

実際の表示

[google](http://google.com)

# まとめ

とりあえず、最低限ここまで覚えておけば記事は書けそうです。
あとは、細かい装飾や画像の貼付、表の挿入などありますが、やっていくうちに覚えられると思います。
また機会があれば、別で作ってアウトプットしてみます。

以下の記事を参考にさせて頂きました。
[Qiita記事作成方法　初心者の備忘録　＠U-MAさん](https://qiita.com/U-MA/items/996ae933ae94c5711883)
VisualStudio C# 便利ショートカットキー(頻繁に使うものだけ)

Qiita初投稿。
3DデザイナーがUnityを覚えるためにC#を勉強して早一か月。
便利だなと思ったものをメモとして書いてみた。

VisualStudio便利ショートカットキー
Ctrl+x　　　　　　　 行全て削除
Ctrl+d              行複製
Shift+↑、↓　　　     行選択
Shift+Tab           Tab戻し


C#
*/ 　文字   */      行をまたいでコメントアウトが出来る
//                  コメントアウト

C#分かりやすいHP
https://xr-hub.com/archives/15201

今後メモとしてQiitaを使い、メモが皆の技術共有になれば良いなあ。
よろしくお願いいたします。
モバイル新OSリリース前後の試験を考察する （iOS編）

iOS、AndroidのOSはほぼ毎年、メジャーバージョンアップが行われる。2020年を振り返るとAndroid11が9月8日に、iOS14が9月16日（日本時間9月17日）にリリースされたのだが、モバイルアプリ開発に携わっている者として、新OSへの対応は非常に頭の痛い課題である。
公開中のアプリの画面のレイアウトがおかしくなる、特定の機能が使えなくなる、最悪のケースではアプリが全く起動しない…といった事態も起こり得るため、事前の動作検証は必要不可欠である。

今回はiOS14に関して。Android11については後日。

## iOSのOSアップデートに関するユーザー動向

以下はとあるアプリのiOSプラットフォームごとのユーザー比率である。
（AppStoreConnect アクティブなデバイス数 を集計）
![ios14_user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531375/77240bbc-7a8c-4af1-782b-772939a25974.png)

- iOS14.0公開の翌日には5.6%
- iOS14.0公開の1週間後には20.0%
- iOS14.0公開の45日後に50%を突破
- 11月末時点では86.8%

となっていた。なんだ、翌日はたったの5.6%か…と思うかもしれないが、仮に10万ユーザーが利用するアプリなら5,600人。万が一、致命的な不具合が出てしまったら、ユーザーサポートへのクレーム電話（メール対応かもしれないが…）が殺到しかねない事態になる。マジでヤバい。

### じゃあいつテストをすべきか？

ということだが、iOS14の公開直後に不具合に気づいて即座に修正に取り掛かり、アプリのアップデート申請ができたとしても恐らく2～3日程度。だが、10万ユーザーが使うような商用アプリで、ここまで迅速な対応ができるモノは果たしてどれくらいあるだろうか？ もし、これくらいの対応は余裕だぜ！ と言えるプロジェクトに参画している方は、その対応の速さには誇リを持って良いだろう。

まぁ…1週間や10日、中にはアップデート申請の開発～社内承認には1ヶ月くらいかかるよ…というプロジェクトも当然あるはず。なので、とりあえず正式版の公開がされる（と予想される）1ヶ月程度前にベータ版でテストをしてアタリをつけておく…という方針が良いのではないかと思われる。なお、iOSの正式な公開日は、だいたい9月の中旬ごろであるが、直前まで情報が公開されないため、9月8日かな？ 15日かな？と想像して動くしか無い。

また、ベータ版、特に早期の段階ではOSの動作が不安定だったり、仕様が変わる可能性もあるので、待てる限り待つ、しかし対応が後手にならない線でテストをするのがベストである。

### iOS14のOSアップデートを振り返る

過去のiOS beta版の配信スケジュールは、@enomotok さんが以下にまとめてくれているので、そちらを参考にしていただきたい。（非常に重宝しました。ありがとうございます！）
https://qiita.com/enomotok/items/696b10866e33303ab3d4

- iOS13　GM版 2019/9/10　→　正式版 2019/9/24　（14日後）
- iOS12　GM版 2018/9/12　→　正式版 2018/9/17　（5日後）
- iOS11　GM版 2017/9/12　→　正式版 2017/9/19　（7日後）

オレたちは3日でアップデートをリリースできるぜ！ という稀有なプロジェクトなら、例年はGM版（最終版）で検証すればよいはずだったものの、iOS14はどうだったかというと…

- iOS14　GM版 2020/9/15　→　正式版 2020/9/16　（翌日）

はい、これは無理でした。何か起きていたら絶対に間に合いませんでした！
 （beta4の時点で、見切り発車しておいて正解でした）

<b>2020年の教訓：GM版を待つのはやめよう！</b>

来年のiOS15はどうなることやら…修羅場にならないよう早め早めに検証は実施しよう！
docker-composeでElasticsearchを起動する際に複数プラグインをインストールする

## 概要

docker-comopseでElasticsearchを起動する際に複数プラグインをインストールする

## docker-composeの書き方

```
version: "3.0"

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:x.x.x
    ...
    command:
      - /bin/sh
      - -c
      - "./bin/elasticsearch-plugin list | grep -q analysis-kuromoji
      || ./bin/elasticsearch-plugin install analysis-kuromoji;
      ./bin/elasticsearch-plugin list | grep -q analysis-icu
      || ./bin/elasticsearch-plugin install analysis-icu;
      /usr/local/bin/docker-entrypoint.sh"

```

## 参考
[Stackoverflow::How to install ElasticSeach plugins using docker compose](https://stackoverflow.com/questions/39691652/how-to-install-elasticseach-plugins-using-docker-compose)
MySQL 5.5から5.7へのバージョンアップと、libmysqlclient.so.18: cannot open shared object file: No such file or directoryの解消

#はじめに#
前回の記事 [Cloud9でRuby on Railsの環境構築 ~インストールから起動まで~](https://qiita.com/koguchi/items/0fb99a99b85da015928d) で「Yay! You’re on Rails!」を表示し、最低限の環境構築までは完了したが、MySQLのバージョンが古かったためバージョンアップをすることに。

その過程でいくつかエラーが発生したので、備忘録のためにカキカキしていきます。

#目標#
MySQL 5.5 からMySQL 5.7にアップデートし、「Yay! You’re on Rails!」を表示させる

#環境#
Amazon linux
ruby 2.6.3
Rails 6.0.3.4
MySql 5.5.62

#やっていきましょう#
###MySQLのバージョンアップ###
まずはバージョンを確認しておきます。

```
$ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.62-log MySQL Community Server (GPL)
～略～
```

そうしたら"yum"を使ってMySQL関連のモジュールをアンインストール。
その後使用するバージョンを指定して、MySQLのモジュールをインストールします。

```
$ yum remove mysql*
$ yum install mysql57 mysql57-devel mysql57-server
```

ここで一度バージョンを確認してみます。

```
$ mysql -u root -p
Enter password:
ERROR 2002 (HY000): Can't connect to local MySQL server through socket'/var/lib/mysql/mysql.sock' (2)
```

エラーが発生。前回の記事と同じ内容です。

socketファイルが無いためMySQLに接続できていないので、MySQLを再起動してsoketファイルを自動作成させます。
その後もう一度バージョンを確認。

```
$ sudo /etc/init.d/mysqld restart
$ mysql -u root -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 4
Server version: 5.7.31 MySQL Community Server (GPL)
```

これでうまく5.7.31がインストールできました。

###サーバー起動###

サーバーを起動して接続できるか確認します。

```
$ rails s
～略～
libmysqlclient.so.18: cannot open shared object file: No such file or directory
～略～
```

エラーです。
ディレクトリとかファイルがないから開けませんって言われています。

今回はDBにMySQLを使用するため、プロジェクト作成時に"-d mysql"オプションを追加しました（[前回の記事参照](https://qiita.com/koguchi/items/0fb99a99b85da015928d)）。
この時にmysql2というgemがインストールされたのですが、これを再インストールすれば解消されるっぽい。

そんなわけでmysql2をインストールしなおします。

```
$ gem uninstall mysql2
$ gem install mysql2
```

これで起動してみましょう。

```
$ rails s
Mysql2::Error::ConnectionError
Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
```

またsoketファイルか・・・
MySQLを再起動してから再びサーバーを起動。

```
$ sudo /etc/init.d/mysqld restart
$ rails s
```

![スクリーンショット 2020-11-26 184833.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/582824/b163a68a-535b-e960-5e5f-afa6295be851.png)

成功しました。
Google Chrome 開発ツールのwaring：'DevTools failed to load SourceMap' を非表示にする

Google chromeの開発ツールのコンソール画面でこのようなワーニング出た事ありませんか？

![スクリーンショット 2020-11-26 18.39.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322171/472db437-bb19-2466-6d2a-bd13db5c422a.png)

javascriptファイルをコンパイルして生成する時に、mapファイルというのも生成されるみたいですが、そのファイルがないとwarningが出るみたいです。

デバッグ時に邪魔なので、非表示にする方法を調べました。

## 非表示の仕方

1. f12で開発ツール起動
2. 歯車マーククリック
3. Sourcesの「Enable Javascript source map」のチェックを**外す**
![スクリーンショット 2020-11-26 18.52.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322171/0e37639e-8eac-7684-0659-1aacf508fc17.png)

これだけで、javascriptのmapファイルがない事によるwarningはなくなります。
Sourcetreeでスタッシュを適用して怒られたときの対処法

## はじめに
Sourcetree でスタッシュを適用したときに下記のように怒られたときの対処法です。

> Please, commit your changes or stash them before you can switch branches.

もちろん差分なんてなにもない。。。でも怒られる:scream:

## 対処法
とりあえずきれいにすればいい:sparkles:  
下記コマンドで追跡対象外のファイルとディレクトリを削除します。

```
$ git clean -n
$ git clean -df
```

これでもダメならいったん他のブランチに切り替えて上記コマンドを実行してみる（わたしはこれで復帰できました:tada:）。

## おわりに
今まではスタッシュに置いてるやつはちょっとした修正だけだったのであきらめてたけどこれで復帰できるようになりました:raised_hands:

Git はこの際ターミナルで扱うようにしてもいいかもしれない:thinking:  
ここ見ればだいたいできそう。  
[Gitコマンド早見表](https://qiita.com/kohga/items/dccf135b0af395f69144)

## 参考
* [git clean](https://qiita.com/k0uh0t/items/ae885bf2d5e05614b80f)
AutomatorでPython3を使う時にハマるポイント

##はじめに
Automatorを使用してPython3を動作しようとしている方がハマりやすいエラーを解説していきます。閲覧しているあなた様の助けになることをお祈りしております。ご質問等も歓迎です。

##初学者が必ずハマるエラーを紹介する
何も知識がないままAutomator開いていつものbashだと思い脳死状態でこう書きがちです。
![スクリーンショット 2020-11-26 10.44.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328076/18ca19c4-e689-99bc-2888-7572302c3463.png)
しかしながらこれでは実行できません。以下のエラーが発生します。
```アクション“シェルスクリプトを実行”でエラーが起きました: “-: python3.9: command not found”```
```-: python3.9: command not found```
![スクリーンショット 2020-11-26 10.44.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328076/d77867c3-0b34-1951-36a2-aa4c0975a5c4.png)
##原因
そもそもPythonのパスが``.bash_profile``にしか書いておらずAutomatorにあるbashは標準で/usr/binにあるコマンド以外を認識できないため。
##解決策
お好きな方をどうぞ。
####1.bash_profileを最初に読み込ませる
``source ~/.bash_profile``
![スクリーンショット 2020-11-26 11.37.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328076/dc15133b-1551-7bc1-ac9c-5fc1f7f43106.png)
####2.pythonの絶対パスを指定する
``which python3``で何処にPythonがあるのか分かるのでそのパスをC/Pして貼りましょう。
``/Library/Frameworks/Python.framework/Versions/3.9/bin/python3``
![スクリーンショット 2020-11-26 12.17.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328076/b2f6fccb-b23e-8ad2-ea76-80c44023f9a2.png)

##ニッチな人がハマるエラー
自分の運用しているdiscord.pyを使用したbotではsubprocessモジュールを使用しているのですが``source ~/.bash_profile``を忘れてしまい一部の機能が動かなくなると言う事例がありました。私の実際のコードを引用して解説します。

```subprocess_test.py
import subprocess
import discord
import key

TOKEN = key.TOKEN
client = discord.Client()

@client.event
async def on_ready():
    print('WakeUp...')
    subprocess.Popen(["sudo","/Library/Frameworks/Python.framework/Versions/3.7/bin/python3","example-a.py"])
    subprocess.Popen(["sudo","/Library/Frameworks/Python.framework/Versions/3.7/bin/python3","example-b.py"])
    
@client.event
async def on_message(message):
    if 'morning' in message.content:
        channel = client.get_channel(message.channel)
        subprocess.Popen(["python3","example-a.py"]
        await message.channel.send("<@0000000000000000000>"+"を起動しました")
    if 'evening' in message.content:
        channel = client.get_channel(message.channel)
        subprocess.Popen(["python3","example-b.py"])
        await message.channel.send("<@000000000000000001>"+"を起動しました")
        
client.run(TOKEN)

```

```example-a.py(discord.py公式ドキュメントから大半を引用)
import discord
client = discord.Client()

@client.event
async def on_ready():
    print("login!")

@client.event
async def on_message(message):
    if message.author.bot == True:
        return
    if message.content.startswith('$hello'):
        await message.channel.send('Hello!')
client.run('your token here')
```


```example-b.py
aとほぼ同じなので省略します
```

subprocess_test.pyを見てもらえると理解してもらえると思いますがpythonの絶対パスを指定せずにPopenしているので解決としては絶対パスで書くと適切に動きます。なぜか以前の環境では絶対パス無しで動作していました。なぜでしょう。

##終わりに
**そもそもAutomatorでBotを動かすな**
以上です。閲覧ありがとうございました。