OmniAICreator/Qiita-1.07M huggingface dataset:
node.js+Vue.jsアプリのWindowsサービス登録方法

#winserを使用してnode.js+Vue.jsアプリをWindowsサービスに登録する
node.jsアプリのWindowsサービス登録にはwinserモジュールが使えますが、vue-cliを使ったアプリをWindowsサービスに登録する場合にはwinserコマンドがそのまま使えませんでした。
winserがラッピングしているNSSMを使ってWindowsサービス登録ができたので、その方法を紹介します。

#手順
### 1. winserを導入
```dos
$ npm install winser
```
導入されると/node_modules/winserディレクトリができる
### 2. NSSMを起動
<アプリ名>にはWindowsサービスとして表示したいアプリケーション名称を入れる

```dos
$ C:\<アプリディレクトリ>\node_modules\winser\bin\nssm.exe install <アプリ名>
```
以下のような画面が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/b7b023b6-2b42-b61d-04b9-c8600edd43f2.png)

### 3. 必要な値を入力
* Path: <アプリディレクトリ>\node_modules\.bin\vue-cli-service.cmd を絶対パスで指定
* Startup: <アプリディレクトリ>を絶対パスで指定
* Arguments: アプリ起動コマンドを指定

Expressを使用していたため、ArgumentsにExpressのコマンドを指定した
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/1ee5cb04-a47b-1a2b-5672-27d76268539f.png)

### 4. "Install service"ボタンを押下
以下のような画面が表示されてWindowsサービスが登録される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248948/d454bfe3-5ba4-f951-a92e-58cc4cdbc89f.png)


これでWindowsサービスにアプリが登録され、起動・停止が可能になりました。
MySQL の全文検索を使った際にテストで困ったこと 


## TL;DR

* MySQL の全文検索では、変更を commit しなければ index が作成されない。
* これは、全文検索用の index を作成する処理は非常に重いので、内部では commit 後にバッチ処理を実行するため。
* そのために、unittest では rollback ができないので、必要なデータを全て消す方法を採用した。

## はじめに

MySQL の全文検索を用いた Web Application を作った際にテスト時にハマったことがありましたので、その原因と対処について記したいと思います。

## 概要

### 実行環境

- MySQL 5.7
  - Storage Engine は InnoDB を使っています
- Python 3.8
- SqlAlchemy 1.4.7

### やろうとしていたこと

* 検索機能を Web Application に作成する
  * MySQL の全文検索を用いた
* この箇所のテストコードは session を使ってテスト後に rollback をする設計になっていた

## 困ったこととその対処

MySQL 全文検索を用いた方法は正しく動きました。しかしながら、そのテストが正しく動きませんでした。詳しく説明すると、対象箇所の全文検索箇所には投入したはずのデータがなく、毎回テストが落ちる結果になっていました。テストコードを何度も見ましたが、特に問題はなさそうだったために、念のためにMySQL のドキュメントを細かく調べることにしました。するとこのように書かれていました。

https://dev.mysql.com/doc/refman/5.6/ja/innodb-fulltext-index.html より抜粋


> InnoDB による全文インデックスのトランザクション処理
> InnoDB の FULLTEXT インデックスには、そのキャッシュおよびバッチ処理の動作のために、特別なトランザクション処理の特性が備わっています。特に、FULLTEXT インデックス上の更新および挿入は、トランザクションのコミット時に処理されます。つまり、FULLTEXT 検索では、コミットされたデータのみを表示できます。次の例で、この動作を実演します。FULLTEXT 検索では、挿入された行がコミットされたあとにはじめて、結果が返されます。

```
mysql> CREATE TABLE opening_lines (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
opening_line TEXT(500),
author VARCHAR(200),
title VARCHAR(200),
FULLTEXT idx (opening_line)
) ENGINE=InnoDB;

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO opening_lines(opening_line,author,title) VALUES
('Call me Ishmael.','Herman Melville','Moby-Dick'),
('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'),
('I am an invisible man.','Ralph Ellison','Invisible Man'),
('Where now? Who now? When now?','Samuel Beckett','The Unnamable'),
('It was love at first sight.','Joseph Heller','Catch-22'),
('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'),
('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'),
('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451');
Query OK, 8 rows affected (0.00 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael');
+----------+
| COUNT(*) |
+----------+
|        0 |
+----------+
1 row in set (0.00 sec)

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line) AGAINST('Ishmael');
+----------+
| COUNT(*) |
+----------+
|        1 |
+----------+
1 row in set (0.00 sec)
```

ここで初めて知りましたが、InnoDB では FullText 用の Index を作成する際には、commit することが条件だったのです。

### テストコードの対処

今回のテストの設計では、DBを使った処理はテストの最後に確実に rollback がなされるような設計にしていました。しかしながら、これではこの方法では、FullText 用のインデックスを作成することができずに、正しくテストを行うことをできません。

苦肉の策ですが、FullText Index を用いる箇所のみデータを commit し、テスト後にはデータを全て削除するという方針に変更しました。もちろん、これが本当に良い方法であるかどうかわかりませんが、この方針で正しくテストが動くようになりました。

## まとめ

InnoDB において FullText 用のインデックスが作成されるのは、commit された後に実行される。そのために、テストの時にはこの点を留意して書かなければならない。
【Automation Anywhere】バージョン（ビルド）を確認する方法（Automation 360）

Automation Anywhere のAutomation 360（旧A2019）のBot開発に関して経験者やサポートに質問をすると、質問した相手から「ビルドは何ですか？」と聞かれる場面がままあります。

この記事では、Automation Anywhereのビルドの確認方法をお伝えします。

#バージョン（ビルド）確認の方法

やりかたは簡単。

Automation Anywhereにログインし、画面の左下あたりにある「？」のマークをクリックし、表示されるビルドの番号を確認するだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/8479d863-cfdd-a2de-f32c-ec6e6c88f7bf.png)

上記の場合、「10526」がビルドの番号です。

少し古いバージョンでは、「？」のマークは画面の右上にあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/f3312221-3560-1ea9-b16e-141310833fe6.png)

上記の場合、ビルドの番号は「8843」となります。

#エラーやトラブルの問い合わせをするときは、必ずビルドの番号を伝えよう

Automation Anywhere のBot作成中に、エラーやトラブルなどが出て質問するときは、必ずビルドの番号を伝えるように心がけるとよいです。
（必ず聞かれるので）

#エラーに関して人に質問するときは、他にもこんなことに気をつけよう

エラーに関する問い合わせをするときは、以下のような情報もできる限り、合わせて伝えるとよいでしょう。

- どういう処理をしようとしていてエラーになったのか
- エラーメッセージの内容
- エラーが出た画面のスクリーンショット
- 該当のエラーが出るのは特定のアクションだけなのか、他のアクションでも同様のエラーが出るのか
- 同じアクションを他のBotや他の環境で実施しても、同じエラーになるか

後半の２つは、少し面倒に感じるかもしれませんし、確認が難しい場合もあるかもしれません。

ですが、そういう確認をなるべく自力でやっておく方が、同じ質問をしても、各段に回答がスムーズにもらえるようになります。
確認をしているうちに、自分でエラーの原因に気づいたり、自分のBot開発の対応力も上がっていくので、なるべく心がけるといいと思います。
django アプリケーションテスト時のエラー

##ImportError##

```python:ターミナル
$ python manage.py test
```
上記を実行時に
`ImportError: 'tests' module incorrectly imported from`のエラーが発生。

###原因###
同じディレクトリ内に`「tests」`と`「tests.py」`の両方が存在している事が原因。


```
diary
    ├── tests
    │   └── test_views.py
    └── tests.py
```

###対処法###

既存の`tests.py`を削除することで解決。
「tests.py」についてはターミナルでstartupコマンドを実行した際に、自動的に作られてしまうので手動で削除する必要がある。

###RuntimeError
上記エラー解消後に発生。
`RuntimeError: Model class django.contrib.contenttypes.models.ContentType doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.`

```python
INSTALLED_APPS = [
    'django.contrib.contenttypes',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.sites',

    'diary.apps.DiaryConfig',
    'accounts.apps.AccountsConfig',

    'allauth',
    'allauth.account',
]
```
settingsにはエラーに書かれている`django.contrib.contenttypes`は書かれているので別のものが原因と思われる。

##原因＆対処法
[このページ](https://stackoverflow.com/questions/51676483/importerror-failed-to-import-test-module)のコメント欄に書かれている同じディレクトリ内の`__init__.py`を削除したところエラーが解消された。
新人教育について 心構え的な部分

# はじめに

技術分野において、新人に教育するってすごく難しいです。
はて、自分はどう教わって来たのだろう‥多分これ今では通用しない方法だよな‥と思うことが多々。
今まで自身が試行錯誤しながら指導してきてこうしたほうが良かったな、ここは大変だったなと思うことを記載しますので、育成に詰まっている方などの参考になればと思います。
ここではまずは心構え的なところから記載します。

一方自身がちゃんとできているかというと・・・反省すべき点はたくさんあります。
はっきりいって綺麗事で書いている部分もあります。
せめてこうしなきゃいけないと頭ではわかっている部分をアウトプットする次第です。

# これまでの指導対象

数年プログラミングをかじってきた若手
特にOJT的に教育は行われていなかった人物
など、完全な新人に対してというところではありません。

# 数人に教えて共通していた課題と対応

1.過程は考慮されない
2.努力家である
3.書かない

## 1.過程は考慮されない

機能実現（または課題など）そのものが終了すれば終わりと判断される。
何が問題かというと、例えばqiitaなどから「やりたいこと」に対する「答え」を「コピー」して片付けるケースが非常に多かった。
この時ある程度経験値を持っている技術者は「あ、これコピーだな」と気付けると思う。

対応→
「これコピーだろ！わかるからな！」と言いたくなるのをぐっとこらえ、「これってどういう意味かわからないから説明お願いできるかな？」といった具合にコントロールしてあげることで「過程を聞かれても大丈夫なようにしよう」と思って貰えるように指導。


## 2.努力家である

非常に真面目で努力家が多い。
真面目な事は素晴らしくいいこと。
ただ、この反面「わからないことがあったら聞いて」というのは全く通用しなかった。

対応→
あらかじめ「ここポイントだったと思うけど」という点は押さえておき、こちらからアプローチをかけていくことが必要。
欲を言えばガンガン相談して欲しいというのは願望だがそれは満たされないということは心掛けないといけない（もちろん個人差はある）

## 3.書かない

1に関係するがコピペして終わってしまう。
コピペ自体が完全悪とは言わないが、自分のものになかなかできず、いつまでも記事を探し回ってコーディングしてしまう。

対応→
コピーするにしてもせめて転写させます。
指で覚えさせてせめて自分で書けるようにしてもらいます。
また、参考にする記事は後追いでもなんでもいいから公式の記事と紐づけてもらいます。
公式以外の記事は効率的ですが、答えをコピーして終わりになる事が多いからです。


と、今時の開発事情からは少し古い考えが入っているかもしれませんが、育成に悩んでいる方の少しでも参考になればと思います。

次回はもう少し具体的なコーディングなどについて記載していきたいと思います。
Vue CliにTailwind CSSを読み込む方法

## Tailwind CSS ってなに？
https://Tailwindcss.com/


CSSフレームワークの一つで、いくつものclassを組み合わせることでコンポーネントが作成できます。
最大の特徴として、1つのクラスに対して1つプロパティのみが付与されていることです。
FLOCSSにおけるユーティリティクラスと同じ発想であり、インラインCSSを書くようにclassを付与していき、コンポーネントを作成していきます。

```html
<!-- 
  border: 1px solid #000;
  border-radius: 0.25rem;
  padding: 12px 24px;
  color: #fff;
  background: #3b82f6;
みたいボタンを作りたいときは以下のように書く
 -->
<button class="border border-solid border-black py-3 px-6 text-white bg-indigo-600">ボタン</button>
```


## まずはVue Cliをインストールしてプロジェクトフォルダを作る

vue3・vue-router（historyモード）を使用するので、マニュアルでプロジェクトを作成。

Vue Cliのインストールからプロジェクト作成までがわからない方はこの記事を参照にするといいかも。
https://qiita.com/ITmanbow/items/9ea7d3f5a9219d760d0c



## Tailwind CSSのインストール

Vue Cliではpluguinでインストールができます。
最新バージョンはvueでサポートがされてないので、[公式の記事](https://Tailwindcss.com/docs/installation#post-css-7-compatibility-build)を参照にして旧バージョンをインストールします。

```
npm install -D Tailwindcss@npm:@Tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9
```

次にconfigファイルを生成します。

```
npx Tailwindcss init -p
```

完了すると、Tailwind.config.jsが作成されるので、以下の内容を記述します。

```JavaScript:Tailwind.config.js
module.exports = {
  purge: [],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}
```

最後にpostcss.config.jsを手動で作成し、以下の内容を記述します。

```JavaScript:postcss.config.js
module.exports = {
  plugins: {
    Tailwindcss: {},
    autoprefixer: {},
  },
}
```

これでVue CliにおけるTailwind ＣSSのインストールは完了です。

## Tailwind CSSを読み込む
インストールが完了したら、使えるように読み込んでいきます。
まずは、任意の場所にCSSファイルを作成し、以下の内容を記述します。

```CSS:EX-/src/assets/css/Tailwind.css
@Tailwind base;
@Tailwind components;
@Tailwind utilities;
```

次にmain.jsにTailwind CSSを読み込む記述を追加します。

```JavaScript:main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

// tailewind css
import '@/assets/css/Tailwind.css';
```

これで準備完了です。Vue CliでTailwind CSSを使えるようになりました。
TypeORMで開発環境ごとにDB、設定を切り替える方法

#１・はじめに
NodeJSでORMを使用する際にTypeORMを使用していますが、環境ごとにDBを切り替える方法についてあまり情報がなかったため、今回紹介しようと思います。

###開発環境
OS・・・Ubuntu20.04LTS
TypeORM・・・0.2.32
Typescript・・・4.2.4
dotenv・・・8.2.0

#２・TypeORMで環境ごとにDBを切り替える
まず始めに今回の方法を簡単に説明すると、

**１・`package.json`と同じ階層に`ormconfig.js`ファイルを用意する**
　　　　　　　　　　　　　　↓
**２・if文または三項演算子を使用してNODE_ENVごとに設定情報を分岐させる**
　　　　　　　　　　　　　　↓
**３・`package.json`のスクリプトに環境情報を追加する**

です。それぞれ順を追って説明します。

##２−１　package.jsonと同じ階層に`ormconfig.js`ファイルを用意する
まずはプロジェクトの`package.json`と同じ階層に`ormconfig.js`ファイルを用意します。
通常の方法ですと`ormconfig.json`を使用する方法が一般的かと思いますが、

**・dotenvの環境変数`(process.env.~~)`を設定ファイル内に記述できる**
**・if文や三項演算子のようなJavascriptの文法が記述可能である**

以上のことから`ormconfig.json`ではなく`ormconfig.js`にTypeORMの設定を記述します。すでに`ormconfig.json`がプロジェクトにある方は`ormconfig.js`に置き換えて下さい。

また`ormconfig.ts`じゃあダメなの？と思う方がいらっしゃると思いますが、`.ts`形式にしてしまうと本番環境、言い換えれば**トランスパイル後のjsが設定ファイルを認識しなくなる**ため全環境に対応できるように`.js`形式にしています。

##２−２　if文または三項演算子を使用してNODE_ENVごとに設定情報を分岐させる

次はNODE_ENVごとに設定情報を分岐させます。
例では三項演算子を使用して分岐させていますがif文でも問題なく動作しますのでお好みで好きな方を選んで下さい。


````javascript:ormconfig.js
module.exports = {
	type: process.env.DATABASE_TYPE,
	username: process.env.DATABASE_USERNAME,
        //↓NODE_ENV==='production'で本番環境,'test'でテスト環境,設定しなければ開発環境になるよう設定
	host:
		process.env.NODE_ENV === 'production'
			? process.env.DATABASE_HOST_PRODUCTION
			: process.env.NODE_ENV === 'test'
			? process.env.DATABASE_HOST_TEST
			: process.env.DATABASE_HOST_DEVELOPMENT,
	port:
		process.env.NODE_ENV === 'production'
			? process.env.DATABASE_PORT_PRODUCTION
			: process.env.NODE_ENV === 'test'
			? process.env.DATABASE_PORT_TEST
			: process.env.DATABASE_PORT_DEVELOPMENT,
	password:
		process.env.NODE_ENV === 'production'
			? process.env.DATABASE_PASSWORD_PRODUCTION
			: process.env.NODE_ENV === 'test'
			? process.env.DATABASE_PASSWORD_TEST
			: process.env.DATABASE_PASSWORD_DEVELOPMENT,
	database:
		process.env.NODE_ENV === 'production'
			? process.env.DATABASE_NAME_PRODUCTION
			: process.env.NODE_ENV === 'test'
			? process.env.DATABASE_NAME_TEST
			: process.env.DATABASE_NAME_DEVELOPMENT,
        //↓開発時のみロギングをONにする
	logging: process.env.NODE_ENV === 'development' ? true : false,
        //↓テスト環境時のみsynchronizeをONにする
	synchronize: process.env.NODE_ENV === 'test' ? true : false,
        //↓テスト環境時のみ接続時DBをクリアにする
	dropSchema: process.env.NODE_ENV === 'test' ? true : false,
        //↓テスト環境時のみ「.ts」ファイルを参照する
	entities:
		process.env.NODE_ENV === 'test'
			? ['src/entities/**/*.ts']
			: ['dist/entities/**/*.js'],
	migrations: ['dist/migration/**/*.js']
	
};

````

このような感じです。
私は開発時もトランスパイルしたjsファイルを参照しているので、`entities`もテスト環境以外は`.js`ファイルを参照しています。
このように各人若干開発環境や手法が違う場合があると思うので、各人自分の開発環境、手法に置き換えて実装してみて下さい。

##２−３　`package.json`のスクリプトに環境情報を追加する

あとは切り替えたい環境によってpackage.jsonのスクリプトにNODE_ENV情報を追加すればOKです。

````json:package.json
"scripts": {
		"dev": "nodemon dist/index.js",
		"test": "NODE_ENV=test jest"//テスト環境の設定に切り替えられる
	}

````

`"dev"`のスクリプトには何も記述していませんが、今回の例では**NODE_ENV情報を設定しなければ開発環境になるように設定した**のでOKです。

#３・まとめ

`ormconfig.js`を使用してTypeORMの設定を記述すると、Javascriptの文法も使用できるため柔軟なDB環境の設定ができることがわかったと思います。
皆さんも開発時に試してみて下さい！
PHP classの継承（オーバーライド）について

#CakePHPを使用していて継承を使いたくなった時のメモ

参考記事：https://www.atmarkit.co.jp/ait/articles/1508/05/news021.html

##結論
オーバーライドは継承元のメソッドがpublicでもprotected でも可能

**検証例1**

```php
<?php 

 
class hoge {
    protected function A() {
        echo "hoge's Aを呼びます\n";
    }
//
public $i_ = 1;
}
//
class foo extends hoge {
    public function A() {
        echo "foo's Aを呼びます\n";
    }
//
public $i_ = 999;
}
 
// class fooを使う
$foo_obj = new foo();
$foo_obj->A();
var_dump($foo_obj);

結果
/*foo's Aを呼びます
object(foo)#1 (1) {
  ["i_"]=>
  int(999)
}*/
```
上記例では継承元hogeクラスのprotectedメソッド A()を子クラスfooでオーバーライドしている。

**検証例２**
親クラスのオーバーライドをした時に親クラスの元のメソッドも呼びたい場合
 ```parent::メソッド名（）```を使用する

```php
<?php 

 
class hoge {
    protected function A() {
        echo "hoge's Aを呼びます\n";
    }
}
//
class foo extends hoge {
    public function A() {
        echo "foo's Aを呼びます\n";
        parent::A();
    }
}
 
// class fooを使う
$foo_obj = new foo();
$foo_obj->A();

結果
/*
foo's Aを呼びます
hoge's Aを呼びます
*/
```
UbuntuでIPv6を無効にする

# 概要：
IPv4でしかネットワークを管理されていない場合はIPv6は無効にします。特にIPv4パケットしか監視していない場合はセキュリティのためにもIPv6を無効にした方がよいです。

# IPv6を無効にする手順
## アプリケーションでIPv6を無効にする
snmpなどアプリケーションでIPv6を利用している場合があります。それらのアプリケーションでIPv6を無効にしておかないとOSでIPv6を無効にした後にエラーになります。

### SNMPからIPv6を外す

1. snmp設定を変更<pre>sudo vi /etc/snmp/snmpd.conf</pre>修正前：agentAddress udp:161,udp6:[::1]:161<br/>修正後：agentAddress udp:161
1. snmpサービスを再起動<pre>sudo systemctl restart snmpd</pre>
1. 確認<pre>sudo systemctl status snmpd</pre>

## Ubuntu 20.04のIPv6を無効にする
### 一時的に無効にする
アプリケーションエラーが発生するか確認するために先ずは一時的にOSでIPv6を無効にします。

1. IPv6が利用されているか確認<pre>ip a</pre>inet6の設定があるか確認。ある場合はIPv6が有効。無い場合は既に無効である。
1. 次のコマンドを実行<pre>sudo sysctl -w net.ipv6.conf.all.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=1
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=1</pre>
3. 無効であることを確認<pre>ip a</pre>
4. アプリケーションが正常に利用できるか確認。エラーの場合はsudo rebootすると元に戻る。再起動できな場合は次のコマンドを実行<pre>sudo sysctl -w net.ipv6.conf.all.disable_ipv6=0
sudo sysctl -w net.ipv6.conf.default.disable_ipv6=0
sudo sysctl -w net.ipv6.conf.lo.disable_ipv6=0</pre>

### 再起動後もIPv6を無効にする
再起動後にIPv6を無効にする方法は2通ります。①sysctlを利用して無効にする、②GRUBで無効にする。
今回は直ぐに戻せるようにするためにsysctlを利用して無効にします。

#### sysctlで無効にする

1. sysctl用設定ファイルを新規作成<pre>sudo vi /etc/sysctl.d/60-ipv6-disable.conf</pre>
1. 次の内容を挿入<pre>net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1
net.ipv6.conf.lo.disable_ipv6=1</pre>
3. 設定を有効にする<pre>sudo systemctl restart procps</pre>
4. 起動時に設定を利用するようにする<pre>sudo vi /etc/rc.local</pre>
5. 次の内容を挿入<pre>#!/bin/bash
systemctl restart procps
exit 0</pre>
6. 実行可能にする<pre>sudo chmod 755 /etc/rc.local</pre>
7. 再起動してIPv6が無効であることを確認する<pre>sudo reboot</pre>

以上
Argument list too longの解決策

ポートフォリオ作成中にrailsとrubyのバージョンを変更したい為、環境構築しました。環境構築した際に、gemもbundle installでファイルの内容を変えました。その変更点をGitでコミットプッシュして、アプリ自体に反映させなければと思いました。

発生した経緯：環境構築する為にrubyのバージョンを変更し、railsを新しくインストロールしました。
　　　　　　内容反映させる為にギットでコミットプッシュしました。

エラーの内容：

```
（ターミナルでのエラー）/usr/local/bin/git-secrets: line 116: /Library/Developer/CommandLineTools/usr/libexec/git-core/git: Argument list too long　　（bundle install で取り込んだ大量のファイルなどを含めてコミットしようとした際に表示されるエラー文）
```
解決策：Gitでの場合
.gitignoreに、git対象から外したいファイルを記載します。(今回であればvendor)


```gitignore.
vendor/
```


次にGitのキャッシュから、対象ファイルを削除します。

```
git rm -r --cached vendor/
```


解説：bundle instalでインストールするファイル自体は、gemファイルにインストールすべきファイルが記載してある為、コミットに含める必要はないので外す必要があります。
ansible-playbook で limit (-l / --limit) を強制するタスク（指定がなければ実行終了）

# tl;dr

- ansible-playbook で --limit または -l を強制させたい
- [ansible-playbookでlimitオプションを強制する（無指定の場合失敗させる）](https://qiita.com/r_plus/items/81630c0c7ea84915489d)のように ungrouped を使うのは、ダイナミックインベントリ使用時や管理外の（でも対象になってしまう）インスタンスがある場合に不便
- 余計な制限を playbook 以外にかけたくない（playbookだけで完結したい）

# play

```limit.yaml
- name: limit
  hosts: all
  gather_facts: no

  pre_tasks:
  - name: force use limit
    fail:
      msg: "use -l or --limit option when run."
    when: ansible_limit is not defined
    run_once: True

  tasks:
  - name: ansible_limit
    debug:
      msg: "{{ ansible_limit }}"
```

こまけぇこたぁいいんだよ。

```bash
$ ansible-playbook playbooks/limit.yml

PLAY [limit] ************************************************************************************************************

TASK [force use limit] ************************************************************************************************************
fatal: [xxxxxxxxxx]: FAILED! => {"changed": false, "msg": "use -l or --limit option when run."}

NO MORE HOSTS LEFT ************************************************************************************************************

PLAY RECAP ************************************************************************************************************
xxxxxxxxxx           : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0


$ ansible-playbook playbooks/limit.yml -l localhost

PLAY [limit] *********************************************************************************************************

TASK [force use limit] *********************************************************************************************************
skipping: [localhost]

TASK [ansible_limit] *********************************************************************************************************
ok: [localhost] => {
    "msg": "localhost"
}

PLAY RECAP *********************************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0
```

# 蛇足

- pre_tasks にすることで早い段階で処理（もちろんどこにでも書けるのでいくつか処理してから止めるのもできる）
- -l に何も値を与えないと ansible がエラーにしてくれる
- -l に値を与えてターゲットホストがなくなっても ansible がエラーにしてくれる
- ansible_limit は 2.5 くらいからの機能 see [Special Variables](https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html)
「転生したらスライムだった件」の大賢者チャットボットを作ってみた件

チャットボットを制作していたのですが、ボットとの会話が味気ないなと感じ、思案した結果、転スラの大賢者風に話せてみようと作ってみました。

「転スラ」をご存じないという方はこちらを見てください。
https://www.ten-sura.com/

# 完成イメージ動画
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/71103894-6d76-acdd-cdf8-60b7a0c67ad3.gif"  width="300" height="200">

# 前回書いた記事
https://qiita.com/rakio/items/2690cf9b2d71d75bb5b4

# 環境
Windows10
Virtualbox v6
Docker
AWS CLI
Nginx
Botpress v12
PHP

# 参考リンク
https://botpress.io/

# Botpressインストール
今回はWindows10上にVirtualboxをセットアップしてCentos7をインストール、そのCentos7にDockerを入れてBotpressのコンテナを起動させています。
かなり複雑になってしまった。。。(;^ω^)

# Botpress設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/3e6ae84b-5e80-5123-d5e1-696a9c6ac525.png)

全体フロー図
段々とノードが増えていくにつれ、見にくくなっていくので対象のノードを探すのに困っています。このあたり何んとかならないものかな。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/a27e2568-724e-db46-2943-10d900fa7276.png)

# システムフロー

ユーザ→Bopress→API→コマンド実行

# FAQ
Emulatorをしばらく置いておくとセッションが切れてしまうので面倒でしたが↓で設定できることが分かりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115627/c48cdd79-a79a-19fc-2232-1ebbf81aed8f.png)

# 最後に

Botpressはチャットボットを自分で一からスクラッチ開発出来るので気に入っています。
今回はチャットボットの制作で力尽き、詳細をお伝えできませんがまたその内、更新したいと思います。
【#PowerApps】 Patch 関数 vs Collect 関数


#  概要

Power Apps のキャンバスアプリのでデータソースに対してデータを追加する時には Patch 関数と Collect 関数が使えます。このどちらを使えばいいのかを今回は解説します。
また、この情報は 2021/05/10 時点の日本環境でのものとなります。

# Collect 関数とは


公式より

```
Collect 関数は、データ ソースにレコードを追加します。
```

# Patch 関数とは

公式より

```
Collect 関数は、データ ソース 内で 1 つ以上の レコード を変更または作成するか、データ ソースの外部でレコードをマージします。
```

# 違い


Patch 関数には以下のメリット・デメリットがあります。

- 1件のデータを登録する時には結果が戻り値として帰ってくるので使いやすい
- Patch 内で起こったエラーを拾える
- 大量のデータを入れると時間がかかる or そもそもできない
- 公式のサンプルアプリでは Patch が使われている


Collect 関数には以下のメリット・デメリットがあります。

- 複数のデータを登録する時は高速
- 公式のサンプルアプリでは使われていない
- 戻り値が基本的にテーブル型で帰ってくるため、Firstなどの関数を使う必要がある
- エラーが拾いにくい

[こちらの記事により詳細な検証情報を載せています。](https://www.powerplatform.work/blog/2021/05/10/PowerApps_CollectFunc_vs_PatchFunc/)

# 結論

おそらくこの両者を実際に業務で使う場合以下の部分を検討し、選ぶ必要があります。

1. エラーを拾う必要があるようなアプリケーションか
2. データを大量に入れるかつ速度が必要か

1 の場合、Patch 関数を使うのが楽ですし、 2の場合は Patch の実行時間を考慮できるかという問題になります。
Collect を選ぶ場合は 1 の考慮をどのように行うのか、また、途中でエラーが起こった場合どのようにそのエラーを検知するのかといったことを検討して、使うべき関数を選びましょう。




# 参考

[公式ドキュメント Collect](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-clear-collect-clearcollect#collect)

[公式ドキュメント Patch](https://docs.microsoft.com/ja-jp/powerapps/maker/canvas-apps/functions/function-patch)


[Power Apps でデータを追加する時はCollect関数とPatch関数はどちらを使うべき？２つの関数の違いは？](https://www.powerplatform.work/blog/2021/05/10/PowerApps_CollectFunc_vs_PatchFunc/)
Webアプリケーション（2）

#Webアプリケーション（2）
[Webアプリケーション（1）](https://qiita.com/nekooosaka/items/cc39dab150f682be327d "Webアプリケーション（1）")の続きです。
XAMPPとVisual Studio Codeがインストール済みを前提としてすすめます。
##今回の内容（動画）
<iframe width="560" height="315" src="https://www.youtube.com/embed/I0vxrH8ggmY" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

##XAMPPの作業用フォルダを設定する

1. Visual Studio Codeで**フォルダを開く**を選択<img width="50%" alt="opend.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/f5cb88c2-269c-f9b4-120f-5b0f3318cf7c.jpeg">
    - Windosの場合　Cドライブ＞XAMPP＞htdocs　フォルダを選び、下の**フォルダーの選択**をクリック
    - Macの場合　移動＞アプリケーションXAMPP＞xamppfiles＞htdocs　フォルダを選び、下のフォルダーの選択をクリック
<img width="70%" alt="opend2.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/62b53a37-ab2c-0bf8-d18e-b40622ebff87.jpeg">
1. エクスプローラーにhtdocsの中が表示される
<img width="70%" alt="oopend3.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/9be5983d-82bd-8a24-4398-d95f1125a91e.jpeg">
1. 先ほど選択したフォルダの中がエクスプローラー（左）で見えていることを確認してください
<img width="70%" alt="oopend4.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221026/40053c04-2295-1004-e57f-a84bd3f1990b.jpeg">

##次はこちら
（次）
how to drop user in redshift 


## check schema

```
select
    nspname                      as schemaname
  , array_to_string(nspacl, ',') as acls
from
    pg_namespace
where
    nspacl is not null
and nspowner != 1
and array_to_string(nspacl, ',') like '%[username]%' -- REPLACE USERNAME
;
```

## check table 

```
select
    pg_namespace.nspname as schemaname
  , pg_class.relname as tablename
  , array_to_string(pg_class.relacl, ',') as acls
from pg_class
left join pg_namespace on pg_class.relnamespace = pg_namespace.oid
where
    pg_class.relacl is not null
and pg_namespace.nspname not in (
    'pg_catalog'
  , 'pg_toast'
  , 'information_schema'
)
and array_to_string(pg_class.relacl, ',') like '%[username]%' -- REPLACE USERNAME
order by
    pg_namespace.nspname
  , pg_class.relname
;

```

## drop user

```
drop user [username]
```

## reference

https://dba.stackexchange.com/questions/143938/drop-user-in-redshift-which-has-privilege-on-some-object
Mybatisで複数の引数を識別させる方法

<!-- タイトル:Mybatisで複数の引数を識別させる方法 -->

# はじめに
### 検索結果を取得する機能で、「入力フォームから取得した検索条件」と「事前に準備した非表示のリスト」という2つの引数で絞り込みを行いたい場面に遭遇した。そこで、2つの引数をMybatisに渡し、絞り込みを行なった結果を取得しようとした際に躓いた点についてまとめてみた。
<br>

# 実現したいこと
### Mybatisで二つ以上の引数を使用してSQLを実行する。
<br>

# 調査
### Mybatisでは複数の引数をただ渡すだけでは識別してくれない。@Paramアノテーションを用いることで、各引数に名前づけを行いMybatis側でその引数名が使用できる様子。
<br>

# 実装
```java
@Mapper
public interface SearchMapper {
    public List<ACCOUNT> searchAccount(@Param("searchForm") SearchForm searchForm,
            @Param("hideList") List<Integer> hideList);
}
```

```xml
<select id="searchAccount" resultType="com.example.matching.entity.ACCOUNT">
    SELECT *
    FROM ACCOUNT
    WHERE ID NOT IN 
    <foreach item="item" index="index" collection="hideList"
        open="(" separator="," close=")">
            #{item}
    </foreach>
    <if test="searchForm.AGE_LOWER != null and searchForm.AGE_UPPER != null"> 
        AND AGE BETWEEN CAST(#{searchForm.AGE_LOWER} as INTEGER) and CAST(#{searchForm.AGE_UPPER} as INTEGER)
    </if>
    ORDER BY CREATED DESC
</select>
```

# まとめ
> @Paramを付与しない場合、第一引数はparam1、第二引数はparam2のように「param+1からのインデックス」という変数になります。
### 以下、参考記事によると、@Paramを用いることなくMybatisで複数の引数を使用することは可能なようだが、基本的には@Paramの使用が推奨されている。

## 参考記事
https://qiita.com/Blueman81/items/72ca43681d16d44e21ad
【Javascript】try・catch・throw・finallyを試してみた

# 初めに
try...catchなどの例外処理について、学習した内容を纏めてみました。

※内容に間違いなどがある場合はご指摘をよろしくお願いします。

# エラーが出そうな関数の処理
例えば以下のような配列の特定の要素を出力する関数があるとします。

```javascript
 const fruits = ['apple', 'banana', 'mango', 'orange'];
    function getFruitName(num) {
      num += 1;
      document.write(fruits[num]);
    }
    getFruitName(3);
```
fruitsの4番目はないため、画面に何も表示されません。当たり前ですが、このような場合でもちゃんとエラーが表示するようにしたいことってありますね。

# throw
throwは意図的に例外を生成することができます。

```javascript
throw 'エラー発生';
```
コンソールには赤文字で以下のように表示されます。
![スクリーンショット 2021-05-10 7.51.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/82c887ca-0ac3-a963-5e91-67ba0cfdef78.png)
しかしこのようなやり方は非推奨で、errorオブジェクトそ生成してからthrowします。

```javascript
const err = new Error('エラー');
throw err;
```
![スクリーンショット 2021-05-10 8.01.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/cc481b84-9e47-1a6a-78ec-54fa77553f70.png)

先ほどの例に戻ってと意図的に例外を投げてみます。

```javascript
    const fruits = ['apple', 'banana', 'mango', 'orange'];
    function getFruitName(num) {
      num += 1;
      if (fruits[num] != null) {
        document.write(fruits[num]);
      } else {
        const err = new Error('エラー');
        throw err;
      }
    }
    getFruitName(3);
```
![スクリーンショット 2021-05-10 8.08.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/13ffc31b-ff4a-137f-1c43-baba7d8a300f.png)
このようにしてエラーが表示されない場合でも、意図的に表示させることができました。

# try...catch
エラーが予想される関数などを実行する場合に、そのエラーに対して何らかの処理をするために使われるのがtry...catch構文です。

```javascript
  try {
      getFruitName(3);
    }
    catch (e) {              //eにはエラーの内容が格納されている
      document.write(e);
    }
```
ブラウザーにはerrorの内容をcatchして画面に表示されます。
![スクリーンショット 2021-05-10 8.15.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/8f7d83c3-8dc3-6de2-fed1-a7eee353c783.png)
catchの引数にはthrow errの戻り値が格納されていて、エラーの内容が入っています。

# finally
例外が発生してもしなくても必ず処理したい命令などを扱う場合にはfinallyを使います。

```javascript
   try {
      getFruitName(3);
    }
    catch (e) {
      document.write(e);
    }
    finally {
      document.write('お疲れ様です')
    }
```
![スクリーンショット 2021-05-10 8.31.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/b557e1a2-dce1-197e-f54d-ae8da124d571.png)

#参考記事

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/try...catch
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Error
https://qiita.com/Tsuyoshi84/items/c50fbbf30a2af387efdf
Go ポインタとは~なぜ必要？

AWSのLambda関数を触っててGoのチュートリアルが読めなかったので、基礎的なところから勉強したことを記す。

#ポインタの概念
ポインタ=実体(インスタンス)が格納されたメモリのアドレス

```
package main

import "fmt"

func main() {

	var i int
    //int型の100という実体
	i = 100

    //int型のポインタ型変数pを定義
	var p *int
	p = &i

	fmt.Println(i) //100
	fmt.Println(p) //0xc00018c008
	fmt.Println(*p) //*をつけることでリテラル(数値や文字列を直接に記述した定数のこと)を参照できる
}

```

ここで疑問が湧いた。
ポインタってなぜ必要なのか？
それは、値渡しだけではなく参照渡しができるから。

## 値渡し
```
package main

import "fmt"

func main() {
	var i int
	i = 100

	fmt.Println(i) //100
	hoge(i)        //101
	fmt.Println(i) //100
}

func hoge(i int) {
	i += 1
	fmt.Println(i)
}

```
## 参照渡し
```
package main

import "fmt"

func main() {
	var i int
	i = 100
 
	fmt.Println(i) //100
	hoge(&i)       //101
	fmt.Println(i) //101
}

func hoge(i *int) {
	*i += 1
	fmt.Println(*i)
}
enebularで生HTTP

#概要

enebularで生HTTPが見たい。

#結果

headerは、見れた。

```
{
"host":"ev2-prod-node-red-3e84d49c-22c.herokuapp.com",
"connection":"close",
"sec-ch-ua":"\" Not A;Brand\";v=\"99\",
 \"Chromium\";v=\"90\",
 \"Google Chrome\";v=\"90\"",
"sec-ch-ua-mobile":"?0",
"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
"x-api-key":"test-api-key",
"content-type":"application/x-www-form-urlencoded",
"accept":"*/*",
"origin":"https://run.plnkr.co",
"sec-fetch-site":"cross-site",
"sec-fetch-mode":"cors",
"sec-fetch-dest":"empty",
"referer":"https://run.plnkr.co/",
"accept-encoding":"gzip, deflate, br",
"accept-language":"ja,en-US;q=0.9,en;q=0.8",
"x-request-id":"284c122c-6830-4cc0-b507-8639855478f5",
"x-forwarded-for":"133.209.208.14",
"x-forwarded-proto":"https",
"x-forwarded-port":"443",
"via":"1.1 vegur",
"connect-time":"0",
"x-request-start":"1620596366793",
"total-route-time":"0",
"content-length":"32"
}

```

#サンプルコード

```
msg.payload = msg.req.headers;
return msg;

```

以上。
Markdownでオシャレなスライドを作るSli.dev

Sli.dev は Beta Version。あらかじめ

> Slidev is still under heavy development. API and usages are not set in stone yet.

らしいので注意。しかしこれまで Markdown でスライド作るなら日本製 [fusuma](https://hiroppy.github.io/fusuma/) あるいは [Marp](https://qiita.com/msp0310/items/0e54f69457f81bc64754) かなと思っていたが、`npm init slidev` したら爆速でMarkdownでスライドのガワが `http://localhost:3030/` にできた。(以下gifの日本語は筆者が入れた)

![slidev.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/81da2091-53c4-9795-3f58-9f53ee1987c1.gif)

以降は

`npm run dev`
`npm run build`
`npm run export` 


## sli.dev

https://sli.dev/

使い方

```
C:\workspaces\nodejs\slidev>npm init slidev
npx: installed 22 in 6.101s

  ●■▲
  Slidev Creator  v0.6.2

? Project name: » slidev
```




...以上。プレゼンターモードというのもあって右上に時間が表示されている。
`http://localhost:3030/presenter/1`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/5e18cbb4-4b7f-66d6-ef9a-f32e4666ec15.png)


slide.md ファイル、結局シンプルに以下だけ。

```md
---
layout: cover
background: https://generative-placeholders.glitch.me/image?width=600&height=300&style=triangles&gap=100
---

# Slidev をお試し。

Presentation Slides for Developers

---

# Page 2

- 📄 Write slides in a single Markdown file
- 🌈 Themes, code blocks, interactive components
- 😎 Read the docs to learn more!|

```

### Theme

https://sli.dev/themes/gallery.html

### Showcases

https://sli.dev/showcases.html

### VSCode拡張

https://marketplace.visualstudio.com/items?itemName=antfu.slidev

### PDFにExport

https://sli.dev/guide/exporting.html

`npm install playwright-chromium`
を行って、
`npx slidev export`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/ce0a55a1-2aa4-906b-025c-09bf27b3702e.png)


## 参考

これまでMarkdownでスライドを作るに以下辺りを参考にしていたがまた選択肢が増えたようだ...。

https://qiita.com/moomooya/items/45398e06f189d4a26227

https://qiita.com/unbabel/items/bf5d7e9e847190ddb0ee

https://notepm.jp/blog/5994

同じく紹介記事 :smiley: 

https://zenn.dev/ryo_kawamata/articles/introduce-slidev

https://qiita.com/loftkun/items/2fbeddc9449eb5d85dfd

簡単ながら以上、参考になればさいわいです。
enebularでherokupostgres その3

#概要

enebularでherokupostgresに繋いでみた。

#参考にしたページ。

https://qiita.com/uhidekita/items/3e64413f1822b32d7bb7

#写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e91ac4ae-6903-958b-259e-ffd0dcf9f0fc.png)

#setup

```
msg.payload = "CREATE TABLE sensordata_tbl(id SERIAL PRIMARY KEY, temperature numeric NOT NULL, roomname text, ts bigint NOT NULL);";
return msg;

```

#select

```
msg.payload = "select * from sensordata_tbl;";
return msg;
```

#insert

```
msg.payload = "insert into sensordata_tbl(roomname, temperature, ts) values ('living', 22.5, " + Date.now() + ");";
return msg;
```

#drop

```
msg.payload = "drop table sensordata_tbl;";
return msg;
```

以上。
react-test-rendererがpeer dependency依存関係エラーでインストールできないときの対処法

# 始めに
npm 7が公開されました。
古いバージョンのnpmとの違いはいくつかありますが、大きな点はpeer dependencyへの対処法です。
React Nativeでjestを用いてテストを記載しようとしたところ、peer dependencyの依存関係が解決できず、いろいろ調べたのでまとめました。

# 状況
npm installをしていると以下のようなエラーが出ることがあります。
![スクリーンショット 2021-05-03 11.33.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980953/422afe22-ca64-adf5-7871-041496826be5.png)

# エラーの理由
一言で言うと、「同じモジュールを違うバージョンでインストールしようとしている」ためです。
そもそもpeer dependencyとは、簡単にいうと「依存関係はあるけど、バージョン指定はインストールする人が自分のプロジェクトに適切なものを選んでね」というものです。
以下の記事に詳しく載っています。
[Understanding Peer Dependencies in JavaScript](https://blog.bitsrc.io/understanding-peer-dependencies-in-javascript-dbdb4ab5a7be)


私たちが、モジュールをインストールする際、npmはそのモジュールを動かすために必要なモジュールも一緒にインストールしてくれます（依存関係の解消）。
しかし、いくつかモジュールをインストールしていると、Aモジュールで使うCモジュール、Bモジュールで使うCモジュール、、、と言うように別々のモジュールが同じモジュールを依存関係に持つことがあります。

Cモジュールがpeer dependencyである、すなわち、インストール者にバージョン管理が任されている場合、Aモジュールで使用しているCモジュールのバージョンと、これからインストールしようとするCモジュールのバージョンが異なると、npmは上記のようなエラーを表示することがあります。

エラーを表示することがある、と言うのは、これがnpm 7からの仕様であるためです。古いバージョンのnpmですと、デフォルトでpeer dependencyによる不適当な依存関係を無視してしまいます。

# 解決策
無理やり解決したい場合は、--forceや--legacy-peer-depsオプションを使用することで可能です。

--forceは、コンフリクトを無視して強制インストールをさせるオプション。
----legacy-peer-depsは、peer dependencyを完全に無視してインストールさせるオプション。
npm4~6の挙動と同じです。

しかしこれでは依存関係を正しく処理できてはいません。
面倒ですが、手動でモジュールのバージョンを揃えることが推奨されています。

上記だと、root projectのreactはバージョン16.13.1であるのに対し、インストールしようとしているreact-test-rendererが使用するreactは17.0.2であるため、エラーとなっています。
私の場合、以下のようにバージョンを指定してインストールすることで解決しました。
![スクリーンショット 2021-05-03 11.49.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980953/dbe38c3e-36c9-c5be-2f9a-a927b440c000.png)

react-test-renderer@16.13.1というバージョンに指定したのは、エラー文面を見る限りreact-test-rendererと、そのサブモジュールであるreactのバージョンが等しかったためです。そのため、react-test-rendererのバージョンをroot projectのreactとバージョンを一致させてインストールしました。
![スクリーンショット 2021-05-03 11.59.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/980953/535c32ef-afee-ef13-ba05-2efe27977119.png)


# 参考
[npm 7 is now generally available!](https://github.blog/2021-02-02-npm-7-is-now-generally-available/#peer-dependencies)
[npm-install](https://docs.npmjs.com/cli/v7/commands/npm-install)
点群を法線方向でフィルターにかける

### はじめに

ある点群から特定の法線方向の点群のみ抽出したいと思い調べたところ、```jsk_pcl_ros```の```NormalDirectionFilter```でそのような処理ができることがわかりました。

https://jsk-docs.readthedocs.io/projects/jsk_recognition/en/latest/jsk_pcl_ros/nodes/normal_direction_filter.html

### 使ってみる

以下のパッケージで簡単に```jsk_pcl_ros```の```NormalDirectionFilter```を試すことができます。

https://github.com/hoshianaaa/jsk_pcl_ros_samples

```bash:install
sudo apt-get install -y ros-melodic-jsk-pcl-ros
sudo apt-get install -y ros-melodic-jsk-visualization
git clone https://github.com/hoshianaaa/jsk_pcl_ros_samples.git
cd ~/catkin_ws

catkin build 
または
catkin make

source ~/catkin_ws/devel/setup.bash
```

```bash:実行
roslaunch jsk_pcl_ros_samples normal_direction_filter.launch
```

作成したlaunchは次のようになっていて赤枠部分のnodeletに法線点群を入力します。またパラメータとして```use_imu=false```,```eps_angle```,```direction```を指定します。

![Screenshot from 2021-05-10 02-55-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/9f61ba18-e4e8-4474-e365-2e4ca07c403c.png)

```xml:launch
<launch>
  <arg name="gui" default="true"/>

  <include file="$(find jsk_pcl_ros_samples)/launch/normal_estimation_omp.launch">
    <arg name="file_name" value="$(find jsk_pcl_ros_samples)/pcd/bunny.pcd"/>
    <arg name="gui" default="false"/>
  </include>

  <node name="normal_direction_filter"
        pkg="nodelet" type="nodelet"
        args="standalone jsk_pcl/NormalDirectionFilter">
    <remap from="~input" to="normal_estimation_omp/output"/>
    <rosparam>
      use_imu: false
      eps_angle: 0.2
      direction: [0, 0, 1]
    </rosparam>
  </node>

  <group if="$(arg gui)">
    <node name="extract_indices_normal_filtered"
          pkg="nodelet" type="nodelet"
          args="standalone jsk_pcl/ExtractIndices">
      <remap from="~input" to="normal_estimation_omp/output_with_xyz"/>
      <remap from="~indices" to="normal_direction_filter/output"/>
      <rosparam>
        keep_organized: true
      </rosparam>
    </node>

    <node name="rviz"
          pkg="rviz" type="rviz"
          args="-d $(find jsk_pcl_ros_samples)/rviz/normal_direction_filter.rviz"/>
  </group>
</launch>
```

### 結果

下の写真のように特定の方向の点群のみ抽出することができました。

![Screenshot from 2021-05-10 02-53-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/0786546f-7bc0-442a-0b3f-a7ea5baa6a96.png)
rails new〜gitコミットまで必要コマンドまとめ(初学者向け)


☆railsチュートリアル初学者向け
rails newでアプリ作成〜コミットまで、チュートリアルの反復学習用に纏めています。
注意点を含めて、個人的に忘れそうな部分を所々追記していきます。


<h2>コミット対象の新規アプリケーションを作成</h2>

```
$ rails _4.0.5_ new アプリケーション名
```
新規作成したいアプリケーション名が「sample_app」の場合は、
`$ rails _4.0.5_ new sample_app` と入力。`_4.0.5_` はバージョン指定 (省略可)。

<h2>リポジトリの初期化</h2>

```
$ git init 
```
現在のディレクトリに対して、新しいリポジトリを新規作成する。
コマンド実行後、配下に`.git`という名前でサブディレクトリが作成される。`ls -a`コマンドで確認。


<h2>コミット対象のファイルを指定</h2>
```
$ git add -A
```
ファイルをコミットする為に、ステージングエリアと呼ばれる待機リポジトリに置く。
エリアに置かれたファイルはコミット待ち状態になる。
`-A`は「全てのファイル」を指定するオプション。`$ git add README.md` のように直接ファイル指定も可能。

<h2>ファイルのコミット</h2>
```
$ git commit -m "メッセージ"
```
ステージングエリアに存在するファイルをコミットする。
ファイルの変更のたびgit addをするのが面倒な場合は、`-a`オプションによって、`git add`コマンドを省略可能。
（`-a`は変更された全ファイルを一括でコミットする）

```
$ git commit -a -m "メッセージ"
```
OSqlEditからAutonomousDB(ATP)に接続(tnsnames.ora使用しない版)

ふとしたきっかけで、tnsnames.oraの接続記述子側（＝の右辺側）でwalletフォルダを指定する方法があることを知りました。
ということはsqlnet.oraのWALLET_LOCATIONの指定も省略できて、OSqlEditのTNSの欄に接続記述子をにぶちこめば、tnsnames.oraの接続識別子（＝の左辺側）を使う必要もなく、接続できるのでは、と思い試してみました。
結果成功したのでここにやり方を載せます。
AutonomousDBになってsqlnet.ora書き換えるとか、tnsadminのパス設定とかめんどくさい。簡易接続ネーミング・メソッドみたいにOSqlEditの接続設定を一回書くだけで済ましたい、という人向けの記事になります。

# 前提条件
* 接続先のAutonomousDBとしては、VPNの外にあるパターンを扱います。AutonomousDBのタイプとしては、ATP(Autonomous Transaction Processing)で試していますがADWでも同じです。
* Oracle Clientはすでに導入済みを想定
* OsqlEditはVersion 10.1.3.2
* Oracle ClientはVersion 19.10.0
* ATPは19c(Always Free環境)

# 手順サマリ
1. OCIコンソールのDB接続からクライアント資格証明(ウォレット)のダウンロードもしくは管理者に共有してもらって自分のローカルPCのフォルダに置く
1. そのフォルダのtnsnames.oraを開いてMY_WALLET_DIRECTORYの句を追加した接続記述子を作る。
1. OSqlEditの接続設定。TNSの欄に上記手順で作った接続記述子を入力

# 手順詳細
### OCIコンソールのDB接続からクライアント資格証明(ウォレット)のダウンロード、もしくは管理者に共有してもらって自分のローカルPCのフォルダに置く

こちらの手順と同一のため省略します

https://qiita.com/ketsuji1/items/8a666bb8b1bb01d3c309#oci%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%AEdb%E6%8E%A5%E7%B6%9A%E3%81%8B%E3%82%89%E3%82%AF%E3%83%A9%E3%82%A4%E3%82%A2%E3%83%B3%E3%83%88%E8%B3%87%E6%A0%BC%E8%A8%BC%E6%98%8E%E3%82%A6%E3%82%A9%E3%83%AC%E3%83%83%E3%83%88%E3%81%AE%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89

### そのフォルダのtnsnames.oraを開いてMY_WALLET_DIRECTORYの句を追加した接続記述子を作る。

tnsnamaes.oraを開いたときの記載は下記のようになっています。
（一部マスクと、見やすさのため改行をいれています。実際は一行に全部記載されています）

```
atpfree_high = (description= (retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=xxxxxx.oraclecloud.com))
(connect_data=(service_name=xxxxxx_atpfree_high.adb.oraclecloud.com))
(security=(ssl_server_cert_dn="CN=xxxxxx.oraclecloud.com,OU=Oracle ADB TOKYO,O=Oracle Corporation,L=Redwood City,ST=California,C=US")))
```

ここにMY_WALLET_DIRECTORYの句を追記して前の手順でダウンロードしたフォルダを配置した場所を記載します。自分の場合はC:\OracleClient\tns_admin。
他にも環境に応じて(https_proxy)(https_proxy_port)といったプロキシ設定を加えます。
見やすさのため改行を加えています。

```
(description= (retry_count=20)(retry_delay=3)
(address=(https_proxy=www-proxy.xxxxx.com)(https_proxy_port=80)(protocol=tcps)(port=1522)(host=xxxxxx.oraclecloud.com))
(connect_data(service_name=xxxxxx_atpfree_high.adb.oraclecloud.com))
(security=(ssl_server_cert_dn="CN=xxxxxx.oraclecloud.com,OU=Oracle ADB TOKYO,O=Oracle Corporation,L=Redwood City,ST=California,C=US")
(MY_WALLET_DIRECTORY=C:\OracleClient\tns_admin)))
```
### OSqlEditの接続設定。TNSの欄に上記手順で作った接続記述子を入力

先ほど作った接続記述子をTNSの欄（下記）に入力します。欄は小さいですがかまわず入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/85051/ec26f47d-b3af-a7e8-952c-ce818866a7a9.png)

接続を確認できたら成功です
TPS視点でオブジェクトを射出する

# 目的
以下のようなTPS視点でオブジェクトを射出する動作を作りたい

![shoot_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408723/2c1b2016-9e8e-be05-ee73-13c246090f72.gif)



# 必要な処理
1. キャラクターを作る
1. カメラの設定
1. オブジェクトを作る
1. オブジェクトを生成、動かす

# 1.キャラクターを作る

以下を参照しました
https://xr-hub.com/archives/13135

# 2.カメラの設定
以下を参照しました
https://qiita.com/K_phantom/items/d5d92955043137a59d8f

# 3.オブジェクトを作る
なんでもよいので、キューブオブジェクト等を作成します
そしてプレハブ化させておきます

#4.オブジェクトを生成、動かす
ボタンを押されたときにオブジェクトが生成されるようにスクリプトを記載します
キャラクター（ユニティちゃん）にアタッチしておきます

```UnityChanController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class UnityChanController : MonoBehaviour
{

    //ユニティちゃんを格納する変数
    public GameObject player;
    //プレハブ名
    public GameObject BindCube;
    //ポジション
    private Vector3 playerpos;
    private Vector3 bindcubepos;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {

        if (Input.GetKeyDown(KeyCode.X))
        {
            
            playerpos = this.transform.position;
            bindcubepos = new Vector3(playerpos.x, playerpos.y + 2, playerpos.z);
            bindcubepos += transform.forward * 2;
            Instantiate(BindCube, bindcubepos, player.gameObject.transform.rotation);
            
        }
    }
}

```

前に生成されるように

```.cs

bindcubepos += transform.forward * 2;

```

としています
プレハブはインスペクターで設定します

そして、射出したいプレハブ化したオブジェクトに
以下のスクリプトをアタッチします。

```BindCubeController.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BindCubeController : MonoBehaviour
{

    //オブジェクトの速度
    public float speed = 0.05f;
    //オブジェクトの横移動の最大距離
    public float max_alive = 10.0f;
    //プレハブ
    public GameObject BindCube;
    //ユニティちゃんを格納する変数
    public GameObject player;


    // Start is called before the first frame update
    void Start()
    {

        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        Vector3 worldDir = ray.direction;
        GetComponent<BindCubeController>().Shoot(worldDir * 700);
    }

    // Update is called once per frame
    void Update()
    {



        //オブジェクトが生き残る時間
        if (max_alive < 0)
        {
            Destroy(this.gameObject);
        }



        max_alive -= Time.deltaTime;
    }

    public void Shoot(Vector3 dir)
    {
        GetComponent<Rigidbody>().AddForce(dir);
    }

}

```

カメラ⇒マウスカーソルの位置へ射出されるようにしています

# まとめ
基本的な処理過ぎて探しても載っていなかったためまとめました。
参考になれば幸いです。
zsh on MacOSでcompinitがエラーを吐く

## 現象
zshにログインした時に、以下のようなエラー（警告？）が出る

```
zsh compinit: insecure files, run compaudit for list.
Ignore insecure files and continue [y] or abort compinit [n]?
```

## 原因
パーミッション周りが悪いらしい。
compinit は、セキュリティ上の問題から、補完に関連するファイルで所有者の違うものを見つけるとそれを読み込まないらしい。
そのあたりについてはググれば GitHub や StackOverflow のページがいくらでも見つかるだろう。

## 解決
zsh-users GitHub 上の [issue につけられているコメント](https://github.com/zsh-users/zsh-completions/issues/433#issuecomment-390600994) で分かる通り、権限と所有者を変更すればかんたんに解決する。Macの場合は以下のようになる。

1. `compaudit` を実行すると、問題のあるディレクトリが表示される
2. 表示された各ディレクトリに対して `sudo chown -R root:staff target_directory` を実行する
3. 同様に `sudo chmod -R 755 target_directory` を実行する

または、以下のコマンドでも解決する場合があるらしい。

```
$ compaudit | xargs g-w
```

反応や別のページを見る限り、多くの場合はこれで解消するらしいのだが、私はこれだけでは解決しなかった。

`compaudit` で表示されたディレクトリを調べると、 `/usr/local/share/zsh/site-functions/` 以下にあるファイルがシンボリックリンクになっており、 `-R` オプションによる再帰的な適用が効かなかったようである。

そのため、以下のようにして解決した。

```
for i in $(compaudit | xargs readlink -f)
do
    sudo chown root:staff $i
    sudo chmod 755 $i
done
```

※実際には手作業で行ったが、同等の効果が得られるはずである。

## まとめ
compinit が権限周りで吐くエラーを解消した。

同じようにシンボリックリンクが問題を起こしている場合のページが軽く調べた中には見つからなかったため、記録として残しておく。
【algorithm】シェルソート、クイックソート

#はじめに
今回はシェルソートとクイックソートを紹介したいと思います！

#シェルソート
間隔を空けて挿入ソートを行い、その間隔をだんだん狭めていく方法
特徴は
・少ないデータであればソートは高速になる
・大雑把でも順番に並んでいる部分が多いと挿入ソートは高速にソートできる
考え方として、
・グループ分けの間隔を半分にしていく繰り返しを行う
・その中で各グループに対して挿入ソートを行う

```swift
var nums = [5, 3, 14, 15, 7, 9, 13, 1, 2, 4, 12, 11, 8, 6, 10]
var step = Int(nums.count / 2)
while step > 0 {
    for i in step..<nums.count {
        let t = nums[i]
        var j = i
        while j >= step {
            if nums[j-step] > t {
                nums[j] = nums[j-step]
                j -= step
            } else {
                break
            }
        }
        nums[j] = t
    }
    step = Int(step / 2)
}
print("ソート後:", nums)
// ソート後: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
```

#クイックソート
少し難しいです。
配列の中の小さいデータを左に集め、大きいデータを右に集め、大小二つのグループに分けます。それぞれのグループで同様に左に小さい、右に大きいデータを集め、二つのグループに分ける。これを繰り返していくと、最終的にソートされた配列が完成します。
・真ん中にある値を基準にしてデータを大小二つのグループに分割する
・分割したグループのそれぞれに同じ処理を繰り返す。
・交換回数を減らすために交換する必要があるものだけで交換を行う
・アルゴリズムをシンプルにするために、再帰を使う
ちなみに、基準となる値をピボットと言います。
「再帰」とは、自分で自分自身を呼び出すアルゴリズムです。
今回は分割した部分に対してさらに分割して同じような処理をしていくという階層的な繰り返しになっているので、このような回想的な繰り返しには再帰を使います。

```swift
var nums = [5, 3, 14, 15, 7, 9, 13, 1, 2, 4, 12, 11, 8, 6, 10]
func quickSort(startID: Int, endID: Int) {
    let pivot = nums[Int((startID + endID) / 2)]
    var left = startID
    var right = endID
    while true {
        while nums[left] < pivot {
            left += 1
        }
        while pivot < nums[right] {
            right -= 1
        }
        if right <= left {
            break
        }
        let t = nums[left]
        nums[left] = nums[right]
        nums[right] = t
        left += 1
        right -= 1
    }
    if startID < left - 1 {
        quickSort(startID: startID, endID: left - 1)
    }
    if right + 1 < endID {
        quickSort(startID: right + 1, endID: endID)
    }
}
quickSort(startID: 0, endID: nums.count - 1)
print("ソート後:", nums)
// ソート後: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
```


#おわりに
次回から応用的なアルゴリズムをみていきます！
【algorithm】単純交換法、単純選択法、単純挿入法

#はじめに
今回は整列(ソート)アルゴリズムについてまとめていこうと思います！

#単純交換法(バブルソート)
全ての隣り合った値を比べていき、小さい方が前に移動するように交換する方法
総当たりてきなアルゴリズムなので、大量データには向かない

```swift
var nums = [5, 3, 7, 9, 1, 2, 4, 8, 6]
for i in 0..<nums.count  {
    for j in stride(from: nums.count-1, to: i, by: -1) {
        if nums[j] < nums[j-1] {
            let t = nums[j]
            nums[j] = nums[j-1]
            nums[j-1] = t
        }
    }
}
print("ソート後:", nums)
// ソート後: [1, 2, 3, 4, 5, 6, 7, 8, 9]
```
まず、前からソート済みを省いた要素にアクセスするためfor文と後ろから二つを比較して行くためのfor文の二つのfor文が必要です。
`stride(from: nums.count-1, to: i, by: -1)`で配列を逆順でアクセスできます。
あとは、二つを比較していき、左の方が大きい場合は交換のアルゴリズムを使って交換します。[交換のアルゴリズム](https://qiita.com/REON/items/debba5a41f03b689fb76#%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E4%BA%A4%E6%8F%9B)


#単純選択法(選択ソート)
最小値を探して先頭から順番に並べていく方法
最小値をを入れる位置を「選択」し、最小値と交換していくので、選択ソートという
最小値と交換のアルゴリズムを使います。[最小値のアルゴリズム](https://qiita.com/REON/items/debba5a41f03b689fb76#%E6%9C%80%E5%A4%A7%E5%80%A4%E3%81%A8%E6%9C%80%E5%B0%8F%E5%80%A4), [交換のアルトリズム](https://qiita.com/REON/items/debba5a41f03b689fb76#%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E4%BA%A4%E6%8F%9B)

```swift
var nums = [5, 3, 7, 9, 1, 2, 4, 8, 6]
for i in 0..<nums.count {
    var min = nums[i]
    var k = i
    for j in (i+1)..<nums.count {
        if min > nums[j] {
            min = nums[j]
            k = j
        }
    }
    let t = nums[i]
    nums[i] = nums[k]
    nums[k] = t
}
print("ソート後:", nums)
// ソート後: [1, 2, 3, 4, 5, 6, 7, 8, 9]
```

ポイントは、最小値の位置を表す変数も用意してその位置を保存しておくことです。


#単純挿入法(挿入ソート)
データを抜き出して正しい位置に挿入していく方法
・整列していない部分から挿入する値を順番に一つずつ取り出す繰り返しをする
・その中で取り出した整列した部分のどこに挿入すればよいかをみていく繰り返しをする

```swift
var nums = [5, 3, 14, 15, 7, 9, 13, 1, 2, 4, 12, 11, 8, 6, 10]
for i in 1..<nums.count {
    let t = nums[i]
    var insert = 0
    for j in stride(from: i-1, through: 0, by: -1) {
        if nums[j] > t {
            nums[j+1] = nums[j]
        } else {
            insert = j + 1
            break
        }
    }
    nums[insert] = t
}
print("ソート後:", nums)
// ソート後: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
```


#おわりに
今回は単純なソート方法を紹介しました！次回は少し難しいシェルソートとクイックソートについてまとめていこうと思います！