OmniAICreator/Qiita-1.07M huggingface dataset:
アドミニストレーター認定の準備: 設定とオブジェクト ⇒ 標準オブジェクトとカスタムオブジェクトの確認

１．「標準オブジェクトとカスタムオブジェクト」セクションは、アドミニストレーター認定試験の何パーセントを占めていますか?
２．アドミニストレーター認定試験の「標準オブジェクトとカスタムオブジェクト」セクションの主なトピックはどれですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/e5e6adef-474c-f679-6267-8ad231c933cc.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/b06a2dad-f5f7-27f5-11c1-79e881f575ec.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/952ac815-8727-da30-0a2a-d7950d112ea8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/803d67d9-d987-0ab4-9fca-38b3183da3b9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/e0c79919-c039-5889-2bdd-ca2dbe5d41ba.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/0ad48d64-3263-ff7e-2e11-2fe9b6300aa5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/cb96b19e-5dec-22d8-9617-a8eaa0951226.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/95ebc20d-22e7-a503-81ee-e171fd366745.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/33f9eeb0-d385-7f0b-b341-ad8c28801435.png)
Java16をjenvに追加 (Mac)

ステップ

1. Download https://jdk.java.net/16/
1. `sudo mv ~/Downloads/openjdk-16_osx-x64_bin.tar.gz /Library/Java/JavaVirtualMachines/`
1. `cd /Library/Java/JavaVirtualMachines/`
1. `sudo tar -xzf openjdk-16_osx-x64_bin.tar.gz`
1.  `sudo rm openjdk-16_osx-x64_bin.tar.gz`

1. jenvに追加

    ```
    jenv add /Library/Java/JavaVirtualMachines/jdk-16.jdk/Contents/Home
    ```

1. jenvに出てきた

    ```bash
     jenv versions                                                      
    * system (set by /Users/masato-naka/.jenv/version)
      11
      11.0
      11.0.2
      16
      openjdk64-11.0.2
      openjdk64-16
    ```
Unity IPointerイベント実行順メモー

###実行イベント
    public interface IPointerDUEEHandle : IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler, IPointerExitHandler
    {
    }

    public class TapTest : MonoBehaviour, IPointerDUEEHandle
    {
        public void OnPointerDown(PointerEventData eventData)
        {
            Debug.LogError(name + " : down");
        }

        public void OnPointerEnter(PointerEventData eventData)
        {
            Debug.LogError(name + " : enter");
        }

        public void OnPointerExit(PointerEventData eventData)
        {
            Debug.LogError(name + " : exit");
        }

        public void OnPointerUp(PointerEventData eventData)
        {
            Debug.LogError(name + " : up");
        }
    }
####参考図
![111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159490/15185b1a-3a60-bb11-1169-442dbf44893f.png)
###実行手順
1. Image1クリック。
1. Image1を押したまま、Image2の上で指を離す。
1. Image1を押したまま、Image2を通り指を離す。

####エディター上結果(通常の場合
1. **Image1 : enter -> Image1 : down -> Image1 : up**
1. **Image1 : enter -> Image1 : down -> Image1 : exit -> Image2 : enter -> Image1 : up**
1. **Image1 : enter -> Image1 : down -> Image1 : exit -> Image2 : enter -> Image2 : exit -> Image1 : up**

####端末上結果
1. **Image1 : enter -> Image1 : down -> Image1 : up -> Image1 : exit**
1. **Image1 : enter -> Image1 : down -> Image1 : exit -> Image2 : enter -> Image1 : up -> Image2 : exit**
1. **Image1 : enter -> Image1 : down -> Image1 : exit -> Image2 : enter -> Image2 : exit -> Image1 : up**
cakephp4のインストール方法

#ローカル環境構築
参考：[cakeドキュメント](https://book.cakephp.org/4/ja/installation.html)

php７.２以上のバージョンを設定する。
この時Macローカル環境で開発の場合、PHPの読み込みのパスがMAMPとなっていないので注意。
環境変数（パスを通す）を設定する必要がある。

```
$ which php
/usr/bin/php
```
上記コマンドでデフォルトの環境変数の設定が確認出来る。

MAMPに設定した場合は

```
$ which php
/Applications/MAMP/bin/php/php7.4.12/bin/php
```

のようになる。

変更方法は以下の記事を参考にした。
[PHPの環境構築（パスを通すとは）](https://qiita.com/tetsu-upstr/items/7fa800488dc29228d7fd)

基本的には```.bash_profile```の変更を行っていく。
.bash_profileがない場合は自分でファイルを作成する。



#インストール

MAMP環境の場合htdocs内にcakephpのアプリを作りたいフォルダを作成する（今回は「cakephp」フォルダを作成）
ターミナルでcakephpフォルダへ移動し
[Composerの公式サイトよりダウンロードする](https://getcomposer.org/download/)
Compoeserをダウンロード後、以下のコマンドを実行


```terminal
mv composer.phar /usr/local/bin/composer
php composer.phar create-project --prefer-dist cakephp/app:4.* my_app_name //my_app_nameの部分は任意でアプリのフォルダ名をつける
```

これでインストールが出来る。
Windows10にVB6アプリを移行する際の問題点とまとめ

#はじめに
始めまして、タイトル通り、Windows10にVB6アプリを移行する際に起きた問題点をまとめたいと思います。

本来であれば既にレガシーとなっているシステムではありますが、世の中でまだ利用者が多いと思われるVB6アプリをWindows7（32bit版）から、Windows10(64bit版)に延命の為
移行する事となり、その時起きた問題を中心に内容を記載しました。



#環境情報
* 移行元：
    * 　 Windows 7 Professional
    * 　 メモリ　8GB
    * 　 CPU   intel core i5




* 移行先：
    * 　 Windows10 pro 64bit版
    * 　 メモリ　8GB
    * 　 CPU　intel core i7


#発生した問題
自社アプリのインストーラーを使用しインストール後、アプリを起動した所、以下メッセージが発生しました。

![WS000013.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311365/4a094bab-3001-6fb2-a460-5ffc5dada29b.jpeg)

#原因
自社アプリの仕様となりますが、会社で持っているoralcedbに接続して処理を行うアプリであり、流れとしては以下の形で行っておりました。


![WS000012.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311365/601e2047-9484-bb42-6831-c1cc26211b09.jpeg)



調べた所、Windowsアプリケーションでoralcle接続を行う際に、使用するミドルウェアが存在し、
それが「oo4o（Oracle Objects for OLE）」となっております。
oracleを扱う際はoracle clientのインストールが必要なのですがoo4oの提供が行われているのが11gまでとなっておりました。
また、oracle client11gには　32bit版、64bit版の2種類があり、最初はPCの環境に合わせて64bit版を入れたのですが
Vb自体は32bit版にしか対応していない為、そちらをインストールしていなかったのも原因でした。
※アプリによってはODBCを使った接続方法もあるかと思いますが今回は、oo4oを使用していた場合の解消方法を記載させていただきます。


oracleサポート概要：

|oracle client ver  |サポート内容 |
|---|---|
|oracle client 11g以前  |・oo4o(Windows用アプリケーション向けにOracleが提供しているデータベースへ接続するミドルウエア)を提供  |
|oracle client 12c以降  |・oo4oの提供が終了  |


#解決方法
oracle　client11g 32bit版をインストールしその後、oracle clientの「Admin」フォルダ内に「tnsnames.ora」（各DBへの接続情報がまとまったファイル）を格納し、cmdを立ち上げ「tnsping ●●」※●●は自社で持っているDB名を記載
コマンド実行し、tnsnames.oraファイルまでのパスが通っている事を確認、その後自社アプリを実行すると問題なく立ち上げる事ができました。


![WS000003.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311365/7ab074f7-b98b-5cf6-955a-5904357c22a0.jpeg)

↑「oracle client 11gのsetup.exe」をクリック

![WS000005.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311365/9ed5c168-f13b-a8d3-4359-9260d54a010a.jpeg)
↑インストールタイプを選ぶ時は「管理者」を選択、※oracle clientに詳しい人はカスタムで必要なものだけを選択してインストールでも問題ないかと思います。

![bakファイル.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311365/4f748ea1-a85c-5b10-43be-db3675d1f85a.jpeg)

↑インストールが終わったら、DB接続情報が記載されている「tnsnames.ora」ファイルを格納


![WS000007.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311365/b28bed14-6feb-1053-b1f1-eede6937cac4.jpeg)

↑インストール完了後はcmdを立ち上げ「tnsping ●●」※自社で設定しているデータベース名を入力

![WS000008.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311365/a5e7cd71-c5a0-ae3d-dfcb-31402716125d.jpeg)
↑特に問題なければ、上記画像のような表示になります。

その後、アプリを立ち上げると問題なく起動し、oracledbへ接続する処理に関しても問題なく行えました。

#最後に
上記、DB接続が絡んだ場合はoracle clientのverとbit数に気を付けないといけないという事を知りました。
ただ、システム自体が古いので、今後はリプレイスを行いVBアプリを使用しない形にもっていきたいです。
PHP  変数の存在を確認する

# 目的

- 変数の存在を確認する関数の振る舞いをメモ的にまとめる

# 情報

- 下記のサービスを用いて動作を確認した。
    -  [https://paiza.io/ja](https://paiza.io/ja)

# 紹介

- `isset()`関数を用いることで変数の存在を確認することができる。
- 下記に例を記載する。下記を実行すると「$strは存在しています。」が出力される。

    ```php
    $str = 'ああああ';

    if(isset($str)) {
        echo '$strは存在しています。';
    }else{
        echo '$strは存在していません。';        
    }
    ```

- `isset(変数)`は変数が存在している時にtrueを返す。存在していない時にfalseを返す。
- なので、下記を実行すると「$strは存在していません。」が出力される。

    ```php
    if(isset($str)) {
        echo '$strは存在しています。';
    }else{
        echo '$strは存在していません。';        
    }
    ```

# 参考文献

- [https://www.php.net/manual/ja/function.isset.php](https://www.php.net/manual/ja/function.isset.php)
K8sクラスターの統合管理ソリューションとしてのAzure Arcを調査

#背景
- コンテナプラットフォーム（K8sやOCP）がいろんなところに散らばってできたときに統合管理するソリューションを調査
- Red Hat ACMが統合管理ソリューションとして最初にあてはまるが、極論すると「コンテナプラットフォームをECS/EKSに限定してしまえばAWS Management Consoleでも統合管理できる」
- そうすると、各社粒度は違えど統合管理サービスを持っていることになり、比較をする価値はあるかも
- まずは直近出てきたAzure Arcが気になる





#調査開始！
##まずはニュースサイトから
https://codezine.jp/article/detail/13654

- Azure以外のサーバー・K8sなどをAzure Portalから統合管理する
- Managed DBのK8sへのデプロイや、様々な環境のSQL Server/Machine Learningの統合管理はパブリックプレビュー
- Azure ArcエンドポイントへのHTTPS接続（Proxy接続可）が必要とのことで、管理対象からインターネットアウトバウンドができれば管理対象にぶら下がれるらしい
    - (2021/04/21追記)HTTPS接続なのでExpress Routeを接続してルーティング設定すればクラスターからインターネットに接続しなくても専用線内で完結
- (2021/04/21追記)費用はAzure外のK8sを利用する際に発生する様子。
    - "Azure外部のKubernetesクラスタに対して最初の6vCPUは無料だが、vCPUコア毎に月々$2の料金が発生する"（上記記事より引用）
    - 公式の料金表が分かりやすい
    - コントロールプレーンは無料、Azure外のクラスターのみ課金対象
        - https://azure.microsoft.com/ja-jp/pricing/details/azure-arc/


https://tech-blog.cloud-config.jp/2019-12-24-azure-arc/

- K8sではなくVMの管理だがGCP, OracleのVMを管理したりポリシー適用したりされている事例
- まぁ特に問題なく管理できている印象


https://www.softbanktech.co.jp/special/blog/cloud_blog/2020/0077/

- AKSを登録して管理されている事例
- ノード数・K8s Versionなどは見れている
- 監視は個別にAKSから見られている（EKSを管理対象にしたらAWS Management Consoleから見ないといけないかも？）


##我らが公式
https://docs.microsoft.com/ja-jp/azure/azure-arc/kubernetes/overview

> すべての Cloud Native Computing Foundation (CNCF) 認定 Kubernetes クラスターで動作します

- なるほど


https://docs.microsoft.com/ja-jp/azure/azure-arc/overview

> Arc 対応 Kubernetes で使用されるすべての Azure サービス (Azure Security Center、Azure Monitor など) は、そのサービスの価格で請求されます。 

- なるほど


https://azure.microsoft.com/ja-jp/global-infrastructure/services/?products=azure-arc&regions=all

- Japanでは未提供（プレビューでもなく提供予定アイコンもない）





#感想
- なかなか使えそう
- 概ね無償なのは良心的
    - Azureに管理コンソールを統一させる狙いがある分、撒き餌的な価格設定か
    - 対抗馬になりそうなRed Hat ACMやVMware Tanzu Mission Controlあたりが有償と考えるとAzure Arcに心が動く・・・
Bitly v4のURL短縮をPerlで実装

## Bitly v4のURL短縮をPerlで実装

昨年の4月にBitlyからAPIをバージョン3を使える時期を、パンデミックの影響もありしばらく延期するというお知らせメールが届いたのですが、私のほうはとくにパンデミックで忙しくなったわけではないので、Perlスクリプトで使用していたバージョン3をバージョン4に更新しようと思い、作りました。
あれから1年が経ったんだなぁ、という感慨とともに、備忘録を兼ねて書いておきます。
おそらく現在はバージョン3は使えなくなったのではないかと思いますが、私の認識が間違っているようでしたら、教えてください。

#### Bitly Developerへの登録
もしBitlyのアカウントをお持ちでない場合は登録を行ってください。
私は通常のメールアドレスによる登録を行いました。
すでにアカウントをお持ちの方は予めログインしておいてください。
続いて以下のURLへ行き、
[Introduction | Bitly Developer](https://dev.bitly.com/)
Generate an access token.のリンクをクリックしてください。
Bitlyコンソール画面にジャンプし、GENERATE ACCESS TOKENという画面が開きますので、Bitlyアカウントのパスワードを入力してください。
GENERATE TOKENボタンを押すとアクセストークンが生成されます。
これを覚えておいてください。他の方には見せないでくださいね。

#### Perlスクリプトを作成

以下のようなPerlスクリプトファイルを作成してください。

```perl
#!/usr/bin/env perl

use strict;
use diagnostics;

use HTTP::Headers;
use HTTP::Request;
use LWP::UserAgent;
use JSON;

my $token = '先程作成したアクセストークン';
my $bearer = "Bearer $token";
# Bitly api v4 のURL短縮URLはこちらです。
my $base_url = 'https://api-ssl.bitly.com/v4/shorten';
my $header = HTTP::Headers->new('Authorization' => $bearer, 'Content-Type' => 'application/json');
my $request = HTTP::Request->new('POST', $base_url, $header);

my $long_url = 'https://qiita.com/bontaro_1';
print "このURLを縮めます => $long_url\n";
my $json = "{ \"long_url\" : \"$long_url\" }";
$request->content($json);
my $ua = LWP::UserAgent->new;
my $response = $ua->request($request);
my $content = $response->content;
print "JSON文字列 => $content\n";
my $response_content = JSON::decode_json($content);
my $short_link = $response_content->{'link'};

if ($short_link) {
  print "短縮URL => $short_link\n";
} else {
  print "短縮URL作成失敗.\n";
}
```
HTTP::Headers, HTTP::Request, LWP::UserAgent, JSONのライブラリはもしまだインストールされていないようでしたらCPAN等でインストールしてください。

#### Perlスクリプトを実行

上記perlスクリプトを実行すると以下のような出力となります。

```
このURLを縮めます => https://qiita.com/bontaro_1
JSON文字列 => {
  "created_at":"2021-04-20T05:45:22+0000",
  "id":"bit.ly/*******",
  "link":"https://bit.ly/*******",
  "custom_bitlinks":[],
  "long_url":"https://qiita.com/bontaro_1",
  "archived":false,
  "tags":[],
  "deeplinks":[],
  "references":{
    "group":"https://api-ssl.bitly.com/v4/groups/***********"
  }
}
短縮URL => https://bit.ly/*******
```
知られてはならない部分は*で伏せており、JSON文字列は見やすいように編集しましたが、以上のような出力になります。
JSON連想配列の link という要素に目的の短縮URLが入っています。
私のアカウントで実行した時は以下のような短縮URLが作成されました。
https://bit.ly/3syK5dt

送信するパラメータは **long_url** だけが必須です。他に **domain** **group_guid** というパラメータもありますが、私のような無料アカウント利用者は省略可能のようです。

以下に公式の詳しい説明がありますので、ご覧ください。
[Bitly API Reference](https://dev.bitly.com/api-reference)
2021年4月20日現在ではshorten APIが一番上に書かれていますね。

**domain** は'bit.ly'がデフォルトのようです。
**group_guid** は実はよくわかっておりませんが、アカウントでグループを利用する時などに必要なのではないか？と思っております。間違っているようでしたコメントをお寄せください。
下記画像はWebブラウザのアドレスバーですが、無料アカウントの方はBitlyにログインして最初に出てくるURLの赤枠の部分を指定すれば良さそうです。
![bitlink_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31696/e30a0a63-2fe8-4d87-4b3d-c86d5c50e6da.png)
いずれにせよ、グループに関する操作をしていない場合は、特に指定する必要はなさそうです。
NetApp ONTAPの Ansible Modulesを Python venvと一緒に使う

素の Debianとかに Ansibleを Installしようとしたときに

「あー、でもaptで入れるとちょっと古いしなー」
「pip3で入れてもいいんだけど、なんか環境が汚れる感じするしなー」

と思います（個人の感想です）。

そして

「そうだ venvで入れよう」

となります。が、

venv 環境下で `pip3 install ansible netapp-lib` で入れても ontapの ansible moduleは素直に動きません……。

その解決方法についてです。

## 結論から

pythonの依存パッケージ不足です。
venv環境で使うなら 以下の様に依存パッケージもあわせてインストールしましょう。

```bash
python3 -m venv ansible-ontap
. ansible-ontap/bin/activate
pip3 install ansible netapp-lib six requests solidfire-sdk-python
```

six と requests が システムに入っている場合は `python3 -m venv --system-site-packages` でもOKです。

## 理由

venvではデフォルトだと、`/usr/lib/python3/dist-packages` は有効じゃないために
OSデフォルトで入っているパッケージが不足するケースがあります。

netapp.ontap の collectionを入れた後で `netapp/ontap/requirements.txt` を確認すると
必要なパッケージが書いてありますので、最新版使う場合は

```bash
ansible-galaxy collection install netapp.ontap
pip3 install -r ~/.ansible/collections/ansible_collections/netapp/ontap/requirements.txt
```

でも良いと思います。

ちなみに公式ドキュメントは、モジュール追加が非常に頻繁な事もあって、徐々に修正されているものの
若干ここら辺の記載が不足している点があります。

そういう意味では collection を install して requirements.txt を 使うのが良いのかもしれません。

最近 requests は記載されるようになったようなのですが、sixは まだ書かれていないようです[^1]。
sixは pypiの netapp-lib 側が使っている物なので そっちで依存関係解決する話だからだと思います[^2]。

[^1]: すいません
[^2]: 重ね重ね、本当にすいません

## おまけ:Ansible/ONTAPモジュール テスト環境作成用スクリプト

```bash
{
  INSTALL_DIR=ansible-ontap
  python3 -m venv ${INSTALL_DIR}
  . ${INSTALL_DIR}/bin/activate

  INSTALL_PATH=$(cd $INSTALL_DIR; pwd)

  pip3 install ansible netapp-lib six requests solidfire-sdk-python

  # 最新版の collectionを インストール ~/.ansible/collections
  # ansible-galaxy collection install netapp.ontap
  # バージョンを更新したい場合
  # ansible-galaxy collection install --force-with-deps netapp.ontap

  # inventory.yaml のテンプレートファイル
  cat <<EOF > ${INSTALL_PATH}/inventory_template.yaml
cluster:
  hosts:
    ontap:
  children:
    svms:
      hosts:
        svm01:
        svm02:
    nodes:
      hosts:
        ontap-01:
        ontap-02:
  vars:
    ansible_python_interpreter: ${INSTALL_PATH}/bin/python3
    ansible_host: localhost
    ansible_connection: local
    ontap_hostname: "xxx.xxx.xxx.xxx"
    ontap_username: "admin"
    ontap_password: "SuperSecretPassword"
    ontap_cert_filepath: ${INSTALL_PATH}/ontapsim_admin.cert
    ontap_key_filepath: ${INSTALL_PATH}/ontapsim_admin.key
    ontap_https: true
    ontap_validate_certs: false    
EOF
  deactivate

  # 情報表示
  echo "----"
  echo "ansible用 venv の activateは以下を実行"
  echo "source ${INSTALL_PATH}/bin/activate"
}
```

## 余談

ところで、solidfire-sdk-python て ontapなのになんで？って思われた方がいるかも知れません。

na_ontap_snapmirror のモジュールで solidfire モジュールを使っているようで
solidfire-sdk-python が必要になります。na_ontap_snapmirror使わないなら 多分不要です。

SolidFire というか Element OS は ONTAPとの間で SnapMirror 使えるので参照しているのでしょう。

## 余談２

Ansible Collectionを書く場合、こういった外部依存 Libraryの管理どうするのが正解なんだろう？と思って
Googleで検索してみたのですが、Documentに書いておいて ユーザ側に どうするかは任せろと出てきました。
kintoneのルックアップを便利にするキーを作るカスタマイズ

今回はルックアップで値を取得するのに便利な方法です。
自動採番を用いず、重複禁止の文字列(1行)に重複しない値を自動的に入力するカスタマイズです。
マスタアプリを作るときに便利！かもしれません。

# アプリの準備

今回は別のアプリからルックアップで呼び出す、「お気に入りの曲マスタ」を作ります。

必要なフィールド

| フィールド種類| フィールドコード | 備考 |
|:-:|:-:|:-:|
| 文字列(1行)  |  曲名 | 必須  |
| 文字列(1行)  |  作曲者 |   |
| 文字列(1行)  |  曲メモ |   |
| 文字列(1行)  | キー  | 重複禁止＆必須  |

※その他のフィールドはお好みで♪

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/9946239a-4990-c7c5-10ba-2811913ee833.png" width=600>

重複しないキーとして、
「曲名」「作曲者」「曲メモ」の３つを半角スペースを挟んでつなげた文字列
を使いたいと思います。
（同じ作曲者が同じタイトルの作品内で同じ曲名の曲を作ることはないだろうという考え）

# JavaScript
「キー」というフィールドは手入力できないようにして
「曲名 + 作曲者 + 曲メモ 」の値を自動的に値をセットする

というカスタマイズをします。

```js
(() => {
  "use strict";

  // キーフィールドは手で編集できないようにする。
  kintone.events.on(
    ["app.record.create.show", "app.record.edit.show"],
    (event) => {
      event.record.キー.disabled = true;
      return event;
    }
  );

  // 保存前にキーを設定する
  kintone.events.on(
    ["app.record.create.submit", "app.record.edit.submit"],
    (event) => {
      event.record.キー.value = event.record.曲名.value + " " + event.record.作曲者.value + " " + event.record.曲メモ.value;
      return event;
    }
  );
})();

```

# 動作確認

例えば・・・↓のように入力して保存すると
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/44fb6ab8-1249-1b29-674b-cf65665ef156.png" width=600>

↓のようにキーが設定されて保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/643c78ba-a181-065d-c1a6-dcb5f0f45606.png)


# ルックアップする側の設定

他のアプリのルックアップで「コピー元のフィールド」に「キー」を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/fc96d36c-003b-734c-3d24-56c8a306a3b1.png)

半角スペースで区切られたキーを使うことで、
曲名だけでなく、作曲者名や曲のメモの入力でもルックアップ取得することができます。
![adfads.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/ba72f9f1-e21c-8e8f-8a01-15718c15cf21.gif)

# まとめ
今回はルックアップを便利にするキーを自動的につくるカスタマイズでした。

※アプリ間の連携カスタマイズをしたいという場合は自動採番のプラグインなど、キーが連番になるようなカスタマイズをしたほうが良いと思います（＞＜）

いろいろ試してみてくださいね✨では！
ServiceNow - Easy Importでadmin以外でもテーブルデータをエクスポートできるようにする

#概要
デフォルトではEasy Importはadmin権限が必要です。データをインポートするにはadmin権限が必要ですが、admin権限以外のロールが付与されたユーザもテーブルデータをエクスポートできるようにできます。

注意：データをエクスポートすることは可能になりますが、Easy ImportでExcelデータをインポートすることはadmin権限が必要です。

#手順
1. アプリケーションナビゲータから「UI Context」を検索して「UI Context Menus」を選択。<br/>![easy_import_non-admin_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/7c54848d-5bd3-341e-4efe-c19d9da770ef.png)
2. ConditionにEasy Importを可能にするロールを条件に追加します。<br/>例：ロールeasy_exportが付与されているユーザもインポートからExcelファイルをダウンロードできるようにするには次のようにConditionを変更します。<pre>(gs.hasRole('easy_export') || gs.hasRole('admin'))</pre>![easy_import_non-admin_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/e3decb23-69f8-3bce-fb0e-47e468fb649b.png)
3.権限を付与したユーザでログインするとコンテキストメニューから「Import」を選択することが可能になる。<br/>![easy_import_non-admin_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/60c63881-9dbd-5a86-013d-b30932e21c43.png)
4. 「Create Excel template」ボタンを押下すると列名が記載されたExcelファイルをダウンロードできます。また、「Update」を選択した後に「Create Excel template」を選択するとテーブルデータがダウンロードされます。<br/>![easy_import_non-admin_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698027/6f858203-7109-8234-7455-0ddc4fa54ddd.png)

以上
GPT-3を試してみた

#はじめに
近年、Deep Learningの自然言語処理分野への応用もかなり活発になっていますが、その中で特に話題となっているOpen AIのGPT-3を試してみました。前回の記事[「GPT-3 APIの利用申請から承認まで」](https://qiita.com/nissan_lab/items/8d0a887b6d32881d6d80)からの続きで、今回は実際にGPT-3を試した結果を紹介したいと思います。

（理解不足により記述に誤りが含まれる場合はご容赦ください）

#Open AI のAPIサイト
https://beta.openai.com/
ログインすると、次のようなページがまず出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177012/45f05a12-ecd8-a96f-15af-9216d1ea230c.png)

左上にDocumentation, Playground, Examples, Resourcesとメニューが並びますが、PlaygroundでGPT-3の実際の動きを手軽に試すことができます。試す前にDocumentationで簡単にAPIの説明を読んでおくと、PlaygroundでのGPT-3の挙動が理解しやすくなります。

#Documentation
Documentationには、APIの使い方や注意事項が載っています。Key conceptsでAPIの基本的な概念が以下のように書かれています。APIは、入力および出力ともにテキスト（文章）であり、"Prompt"という入力テキストの続きを推論した結果を"Completion"という出力テキストとして得る仕組みになっています。要はユーザーが入れた文章の続きをそれらしく推定して出力してくれるという感じです。

他、PythonなどによるAPIの使い方が簡単なコード例とともに掲載されています。本記事では、APIを直接動かすのではなく、次に説明するPlaygroundで試した結果を紹介したいと思います。

# Playground
Playgroundには、以下のようにプリセットとして十数種類の応用例が用意され、ブラウザ上でインタラクティブに試せるようになっています。実際に裏でAPIを動かしているようですので、プログラミング抜きでGPT-3の性能を試すのに向いています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177012/3cf6e4f2-b270-d943-a213-b90d64aca1ab.png)

#Chatの例
Chatは、いわゆるスマートスピーカー(SiriやAlexaなど)のようにユーザーとおしゃべり(チャット)する機能です。
![図1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177012/b279a5d3-f15a-c025-a077-078e59cf9f42.png)
（注：このキャプチャは3月頃のGUIバージョンなので最新のものと若干違います。次のキャプチャも同様。）

チャット機能の実現方法は、一行目の"The following is a conversation with an AI assistant to support a driver in a car. The assistant is helpful, creative, clever, and very friendly."という文でチャットボットの性格付けやシチュエーションを設定し、さらに対話パートを1, 2ターン書くだけです。要約など他の機能も同様で、入力の一部として用途を表す文章を書けば、機能が実現できるようになっています。汎用性が高いですね。

この例は、鎌倉にドライブしに行き、周辺の観光スポットなどを聞くシチュエーションで実際に自動生成させた例です。2つ目のHumanパートまでを入力し、"Submit"ボタンを押してチャットをスタートし、以降はインタラクティブにやり取りした結果です。AIパートは自動生成された文章で、的確に受け答えし、鎌倉の観光スポットも間違えずに提案していることに驚かされます。

#Chat（日本語）の例
さらに日本語もできるかを試してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177012/978b8807-5c7e-a58b-f9dd-2ddc5b8e5eb5.png)

一行目に日本語も流ちょうに話せると書き加え、設定シチュエーションは英語の例と同じにしました。こちらもかなりうまくいっています。

#失敗例
実は、上の２つの例はうまくいった例で、Chatの場合は大体４ターン目ぐらいで少しおかしなことを言い始めます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1177012/a68309ef-f891-3454-8aaa-388df8b40458.png)
この例だと５ターン目から怪しくなり、６ターン目から突然ハワイの洞窟の話を始めてしまいました。人間同士のおしゃべりでも話題が飛ぶこともあるので、ある意味人間らしいのかもしれません。

#おわりに
最新NLPの一つであるGPT-3を試してみました。自動で生成される文章はかなり自然で意味もある内容なことが多く、試すのも面白くて飽きませんでした。一方で、時折完全に間違ったことを（自信満々に）出力するので、自分が良く知らない分野に関する内容は、嘘か本当かを見極めるのは難しいと感じました。悪用されては危険ですのでAPIの試用を許可制にして、さらに５人以上に対するアプリ開発に事前レビューを設けているのもうなずけます。

(written by Teraguchi)
Railsのdeviseのエラーで詰まったこと忘備録【超初心者】

何回も使っているのに何回もエラーに悩まされてるので忘備録。。。

##最初のセットアップを忘れない

```console:console
 $ rails g devise:install
```

を忘れてコントローラーとかを作ったら大変
```ActionController::UnknownFormat in Admins```が永遠に出てどうにもこうにもならなくなってしまった･･･
最初からやり直しすることになりました、皆さんはお気をつけて･･･(´;ω;｀)

##deviseの関与するmigrateファイルを消す時はrouteを確認
一回やり直そうと思い、```rails:db:rollback```を試みましたがエラーが出て出来ずオロオロ･･･
routeの```devise_for~~```を消したら直りました。

##pathを指定するときにredirect_toは不要
application_controllerやadmins/sessions_controllerに記載する時はredirect_toは不要！
 
```rb:admins/sessions_controller.rb
  protected

  def after_sign_in_path_for(resource)
    admins_workbooks_path
  end
```

こうやって書くときはbefore_actionとかも記入不要！
まじでこれよくやってるから気を付けるのだ、私。

---

class AdminsのAdminsは定数だからconst_getのエラーが出るというのは知れて良かったですが、deviseは適当にやらないように気を付けようね私っ！！！
【Mac】git add / commit / push 手順

index.htmlをgit add/ commit / pushする手順をご紹介します。


①更新したファイルに対してgit addを実行し、エラーなどが表示されないことを確認する。

```
$ git add /Users/user_name/clone/www.domain_name.jp/index.html
```

② git commit -m を実行し、エラーなどが表示されないことを確認する。

```
$ git commit -m "/Users/user_name/clone/www.domain_name.jp/index.html”
```

③秘密鍵を登録する。

```
$ ssh-add -K ~/.ssh/codecommit_rsa
```

④git pushする。

```
$ git push
```

以上。
テックキャンプを受講した感想

#はじめに
私はテックキャンプに通い、プログラミング未経験から学習、及び転職活動を始め、10社様から内定をいただきました。

本記事ではテックキャンプを受講した感想について、記事にしております。

これから、エンジニア転職を検討されている方、プログラミングスクールに通うか検討されている方、プログラミング学習・転職活動をされている方のご参考になればと思い本記事を作成しました。

#目次
・総括
・テックキャンプでは人とのつながりの大切さも学べる
・テックキャンプは自走力が身に付く環境
・プログラミング未経験からエンジニア転職するハードルの高さ
・他力本願はやめる
・あらゆる才能より、続けることの重要さ
・プログラミングスクールでの学習方法について
・転職活動するなら、就活テクニックもある程度必要
・これからプログラミング学習を始めようとしている方へエールを！


#総括
テックキャンプでは**プログラミング学習を挫折せず、楽しく勉強できる仕組み、転職活動支援**などがあります。

また、カリキュラムにはありませんが、エンジニアリング以外の**ビジネスマンや人としてのスキル、マインドも同時に学べる**場でもありました。

人とのつながりの大切さを学べ、私は通ってよかったと思っております。

プログラミング未経験からエンジニアを目指すことは本当に難しく、決して楽な道ではありませんでした。

ただ、**テックキャンプのサービスを十二分に自分のスキルにし、体現できれば、転職活動の難易度は下がる**と思います。

スクールで学んだことは、これからのエンジニアもしくはビジネスマンとしての人生の基盤になります。

これから際なる飛躍ができるよう、入社後も日々精進して参ります！！

#テックキャンプでは人とのつながりの大切さも学べる
テックキャンプでは様々な人との関わり合いがあります。
以下の方々とともに、学習ができ、支援もいただけます。

・同じ目標がある同士がいるので切磋琢磨できる
・モチベーション高く学習するために支えてくださるライフコーチがおり、独りよがりにならない
転職活動支援をしてくださるキャリアアドバイザーがおり、転職活動の相談、職務経歴書・面接等のアドバイスを受けられる
・プログラミングスキルをご教示くださるメンターがおり、質問形式で正しい知識得られ、プログラミング学習の疑問点を解消できる

おそらく、私は皆さんのお力添えがなければプログラミング学習、転職活動を挫折していたかもしれません。
上記の方々とは**密なコミュニケーションをとり、刺激や勇気、支援、情報提供**などいただけました。

**人との縁の大切さが、私はさらに大きな人間**になったと言えます。

ただ、相手の支援をただ待つだけでなく、自分から行動し周りを巻き込むことが重要になると思いました。

#テックキャンプは自走力が身に付く環境
テックキャンプでは、学習は講義形式ではなく、カリキュラムを自分で進めて、わからない箇所、疑問点などをメンターに質問するという形式です。

なので、**能動的に自身で行動する必要がある環境**です。
言い換えれば、学習が身についきやすい環境であり、自走した分だけ成長できる場です。

私はメンター利用を100回以上していました。

その多くは質問だけでなく**「自身の理解のアウトプット」**という形で、自分の学んだことをメンターに説明しておりました。
自分の誤認だけでなく、理解の定着にも繋がりまりました。

自走した中で、質問やアウトプットで**表現力・論理的思考能力**が培え、**能動的な思考**がつきました。

相乗効果で成長できる環境がありました。

成長できたと言えど、まだまだ未経験エンジニアであり、エンジニア転職するハードルの高さは凄まじいものでありました。

#プログラミング未経験からエンジニア転職するハードルの高さ
以下私の活動経歴となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/dcaeae5a-affc-44eb-5890-f33917702cc6.png)

応募数に対しての内定率は約5%でした。

多くのお見送り理由は経験不足等で、未経験エンジニアの需要の低さが私の活動経歴からもわかります。

しかし、**諦めなければ未経験ながらも内定**をいただけます。
そのためにはマインドが一番重要になってくると思います。

#他力本願はやめる
マインドの１つに他力本願をやめることを挙げます。
スクールに通ったから内定をいただけるという他力本願はやめるということです。

スクールに通うと求人案件の紹介もあり、スクールがなんとかしてくれるという気持ちで面接に挑めば落ちてしまいます。

企業からしても未経験よりも経験者を雇う方が、利益にもなります。
しかし、未経験エンジニアにも求人があります。

その理由を考え、**内定という目標から逆算し考え、就活対策**をすることが転職活動を成功させると思っています。

そのためには諦めず継続することが必要不可欠です。

#あらゆる才能より、続けることの重要さ
才能による効率は大抵２~3倍異なると言われていますが、**人よりも続けることで10倍以上の効率**を生み出すそうです。

なので、転職活動をしていてお見送りになっても、めげずに挑戦し続けることが内定につながってくると思います。

これは転職活動だけでなく、今後のエンジニアリングにも同様のことが言えます。

マインドも重要ですが、もちろん学習方法も大切になってきます。

#プログラミングスクールでの学習方法について
私は、テックキャンプに通う中で、勉強方法を工夫したことが、内定にもつながったかと思います。

というのも学習の質が高ければ、**より質の高いポートフォリオ**を作成できるからです。

勉強方法については以下より、ご確認いただけます。

http://yumekalog.com/

学習も重要ですが、就活テクニックで選考で自分を魅せることも重要になりました。

#学習も重要だが、就活テクニックもある程度必要
以下に、就活で工夫したことを記事にしておりますので、よろしければご覧ください。

http://yumekalog.com/

#これからプログラミング学習を始めようとしている方へエールを！
エンジニアを目指して日々転職活動をされている方、学習されている方は本当に素晴らしいと思っています。
特に未経験からチャレンジされている方は、それほど決断力があって今も努力されていることはとても素晴らしいことですし、誰しもできることではないです。

皆さんは素晴らしですし、これからエンジニアとして活躍していくことが目標かと思いますので、諦めないことが一番大切かと思います！！

諦めずに納得いく就職活動をしていきましょう！！

以上です。
クラスメンバ変数の有無を見て存在する場合は値を反映したい

## やりたいことの概要

- C++ テンプレートでクラスのメンバ変数(bool型想定)の有無をチェックして処理を切り替えたい。
- さらに、メンバ変数が存在するときは値を反映したい。
- C++17を使えない環境のためにconstexpr if禁止縛り

※完全に私個人にとっての課題で、あくまで情報共有が目的です。
※きっともっと他にいい方法があります。

## モチベーション

私の書くコードでは、@akinomyoga さんの記事[^1]でいうところのPolicy(テンプレートを使ったコンポジション・包含みたいなもの)をする機会が多いのですが、包み込まれる方のサブクラスによって処理を切り替えたいことがあります。そもそもサブクラス側に定義されているメンバ関数の処理内容は違わけですが、包含(ラップ)している側の処理を切り替えたいという状況が今回のターゲットです。こんなとき、テンプレートの特殊化で解決することもできます。しかし、科学技術計算では非常に長く込み入ったコードが実際に有り得て、その中でたった一部だけに違いを入れたい場合、特殊化では関数丸ごとコピペに近い状態となり、保守の観点ではあまり好ましくありません。

そこで、包み込まれる方のサブクラスにフラグ(例として変数`bool need_special`)としてメンバ変数を持たせ、それを見て処理を切り替える。

1. need_special=trueの場合はフラグが立っている
2. need_special=falseの場合はフラグが立っている
3. メンバ変数`need_special`を持っていないクラスの場合は、自動的にフラグが立っていないもの(false)とみなす

ここで、3つ目の条件を設けることで「わざわざ不必要なクラスにメンバ変数を追加しなくてよい」という利点があります。歴史の長いコードやチームで作っているコードだとこの点は非常に重要です。

## 方法とサンプル

今回のサンプルは下記のようなコードになります。

```c++
#include <iostream>
#include <type_traits>

class PotentialA{
public:
static const bool need_special = true;
public:
void Force(){};
};

class PotentialB{
public:
static const bool need_special = false;
public:
void Force(){};
};

class PotentialC{
public:
void Force(){};
};

template<class P>
class WrapPotential{
    template <typename X>
    static std::integral_constant<bool, X::need_special> check_special(X*);
    static std::false_type check_special(...);
    static constexpr bool is_special = decltype(check_special((P*)nullptr))::value;
public:    
    void Call(){
        P p; 
        p.Force();
        /****************
        ここにめちゃくちゃ長い処理があるとする
        *****************/
        if(is_special){
            printf("Force with special routine\n");
        }else{
            printf("Force without special routine\n");
        }
        /*****************
         ここにもめちゃくちゃ長い処理があるかもしれない
         *****************/
    }
};

int main(void){
    WrapPotential<PotentialA> pa;
    pa.Call();
    WrapPotential<PotentialB> pb;
    pb.Call();
    WrapPotential<PotentialC> pc;
    pc.Call();
}
```

実行結果

```
Force with special routine
Force without special routine
Force without special routine
```

包含されるサブクラスは`PotentialA`, `PotentialB`, `PotentialC`になります。メンバ変数`need_special`の有無から、これらのサブクラスがそれぞれ先の条件1,2,3に対応しています。包含している側の`WrapPotential`クラスではフラグが立っているかどうかを`is_special`として持たせ、長い処理の途中において一部のみの処理の切り替えをしています。

メンバ変数`need_special`の存在確認は`check_special`のテンプレート宣言文の中の`X::need_special`で行っています。`PotentialC`の場合はこのメンバ変数が存在しないので失敗し、次に定義された`std::false_type check_special(...);`が選ばれます。

`PotentialA`および`PotentialB`の場合は失敗しないので、続いて`std::integral_constant<bool, X::need_special>`が展開され、`X::need_special=true`の場合は`std::true_type`に、`X::need_special=false`の場合は`std::false_type`になります。

## 感想

HPCというべきか科学技術計算というべきなのか、私はgccを使うことは少なく、規格の新しい構文に関してはベンダー毎にコンパイラの対応が遅いことがよくあります。構文に対応していても最適化を早々にあきらめるコンパイラもあります。そういう状況もあって、実務でのテンプレートの多用はなかなか悩ましいですね。でも、新しい規格や初めて使う規格で頭を悩ますのは楽しいですよね。

以下参考にした記事
[特定のメンバ関数有無で、呼び出す関数を変えたい](https://qiita.com/terukazu/items/e257c05a7b191d32c577)


[^1]: [C++ Traits/Policies/Strategies/Concepts/Contracts の関係](https://qiita.com/akinomyoga/items/506bd1fe47046bd636ae)
scikit-learnのパイプラインを使ってみる


まずは、普通のRandomForestClassifierから。

<pre>
import matplotlib.pyplot as plt
import sklearn.datasets
import sklearn.ensemble
import sklearn.model_selection

iris = sklearn.datasets.load_iris()
features = iris.data[:, [0, 2]]

train_x, test_x, train_y, test_y = sklearn.model_selection.train_test_split(features, iris.target, test_size=0.3)

rf = sklearn.ensemble.RandomForestClassifier()
rf.fit(train_x, train_y)

accuracy = rf.score(test_x, test_y)
print('accuracy {0:.2%}'.format(accuracy))
</pre>

accuracy 93.33%

パイプラインを使うとこうなる。

<pre>
from sklearn.pipeline import Pipeline
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestClassifier
from sklearn import datasets
iris = datasets.load_iris()
X, y = iris.data, iris.target

steps = [('pca', PCA()),('rf', RandomForestClassifier())]

pipeline = Pipeline(steps=steps)

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.33, random_state=42)
pipeline.fit(X_train, y_train)
y_pred = pipeline.predict(X_test)

from sklearn.metrics import accuracy_score
accuracy_score(y_test, y_pred)
</pre>

accuracy 98%

つまり、

<pre>
steps = [('pca', PCA()),('rf', RandomForestClassifier())]
</pre>

によって、RandomForestClassifierの前にPCAをかましている。

https://github.com/RuoAndo/time-series-analysis-with-Python/blob/master/pipeline/1.ipynb
skickaの使い方

skickaというGoogle Drive APIを便利に使うためのコマンドラインツールがあります。
使えるようになるために一苦労あったので方法をメモ。

# go環境構築
skickaはgoで動くので実験用にdockerでgolangの環境を作ります。

```
docker pull golang
docker run -itd golang
docker attach {コンテナ名}
```

これでgo環境ができました。

# Google Drive API用のOAuth認証情報の作成
* GCPコンソールで適当なプロジェクト作成(既存があればそれでよし)
* Google Drive APIを有効化
* (なければ)OAuth同意画面を設定(スコープはGoogle Driveの./auth/docs, ./auth/driveがあれば十分だった)
* OAuth Clientの認証情報を新規作成(種類：テレビと入力が限られたデバイス)
* 作成したクライアントIDとシークレットはあとの手順で使います

# skickaインストールと認証
```
go get github.com/google/skicka
skicka init
apt-get update
apt-get install vim
vim /root/.skicka.config
# skicka.configに生成されたクライアントIDとシークレットを追記し、コメントインする。
skicka -no-browser-auth df
# URLが表示されるのでブラウザにペーストし、Google Driveへのアクセスを許可する
# ブラウザに表示された認証コードをskickaのコンソールにペースト
```

dfの結果が以下のように表示されればOKです

```
Capacity    15.00 GiB
Trash           0 B       0.00%
Drive      209.70 MiB     1.37%
Gmail        2.47 GiB    16.47%
Photos     598.67 MiB     3.90%
Free space  11.74 GiB    78.27%
```

# Github actionでGoogle driveにファイルをアップロードする
Github actionsでGoogle driveにファイルをアップロードするには[Interact with Google Drive](https://github.com/marketplace/actions/interact-with-google-drive)というactionを使用します。

認証情報として `skicka-tokencache-json` に 上記の認証手順で `/root/.skicka.tokencache.json` の文字列を指定します。
またOauthの情報として `google-client-id` と `google-client-secret` も指定します。

正しく認証情報が指定されていれば以下のようなコマンドでファイル/ディレクトリをアップロードすることができます。

```
- name: Upload to Google Drive
  uses: satackey/action-google-drive@v1
  with:
    skicka-tokencache-json: ${{ secrets.SKICKA_TOKENCACHE_JSON }}
    upload-from: ./
    upload-to: /path/to/upload

    # For those who set up Google Drive API client ID and secret themselves
    google-client-id: ${{ secrets.GOOGLE_CLIENT_ID }}
    google-client-secret: ${{ secrets.GOOGLE_CLIENT_SECRET }}
```
【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その4


全部で4記事です。
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その1](https://qiita.com/h_koya/items/efeed0af267298a66cee)
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その2](https://qiita.com/h_koya/items/c90c8e0c6a2ef8ce0de0)
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その3](https://qiita.com/h_koya/items/bcaf82c5e36f3fb1c06c)
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その4](https://qiita.com/h_koya/items/b5a6f4bdb43608982f2a)

前回
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その3](https://qiita.com/h_koya/items/bcaf82c5e36f3fb1c06c)
# サウンドにリバーブ効果を追加
AudioMixerウィンドウを開く
 Groups > Master の上で右クリック Add child group を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/b487e0b2-5c43-fa8f-7075-8dde2f0da47d.png)

追加したグループの Addをクリック > SFX Reverb を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/0971b74f-3973-9011-a953-a963e59acb28.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/06bfb268-4798-854b-fb4b-2559c70205a7.png)
Inspector から SFX Reverb の設定を変更
DryLevel を最小
Room を 最大
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/ba24ce4c-dd45-82de-52fc-21a48b473d35.png)
Quad に RoomEffectSendLevelコンポーネントを追加
Hierarchy > Quad > AddComponent("RoomEffectSendLevel")
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/0b30a202-e9ed-780a-736e-f8002b003e0f.png)
RoomEffectsendLevelプロパティを 約-30Dbに変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/b1866d6c-d41c-bfea-7c2a-c632cfb5b7f6.png)

Project からSpatializeOnOff を開いてコメントアウトを解除
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/40b54321-8b70-f32d-7666-193cf7fcb6e5.png)

Hierarchy > Quad を選択して Inspector > SpatializeOnOff を開く
RoomEffectGroup ､ MasterGroupプロパティに AudioMixer をセット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/e320683e-80f3-5521-83cb-db3f5c4ba26c.png)
# 動作確認
File > Build Settings > Build
適切なフォルダを選択してビルド
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/605aa780-edd2-a934-db16-7fc586aac739.png)

音にリバーブ効果が追加されているか確認しましょう。
お疲れさまでした。
【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その3

全部で4記事です。
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その1](https://qiita.com/h_koya/items/efeed0af267298a66cee)
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その2](https://qiita.com/h_koya/items/c90c8e0c6a2ef8ce0de0)
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その3](https://qiita.com/h_koya/items/bcaf82c5e36f3fb1c06c)
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その4](https://qiita.com/h_koya/items/b5a6f4bdb43608982f2a)

前回
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その2](https://qiita.com/h_koya/items/c90c8e0c6a2ef8ce0de0)
# ボタンに立体音響の切り替え機能を追加
Project で右クリック Create > C#Script
名前を SpatializeOnOff に変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/b1277822-2086-596d-1590-a51174703f23.png)
下のコードを貼り付け、保存

``` C#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Audio;

[RequireComponent(typeof(AudioSource))]
public class SpatializeOnOff : MonoBehaviour
{
    public GameObject ButtonTextObject;
    //public AudioMixerGroup RoomEffectGroup;
    //public AudioMixerGroup MasterGroup;

    private AudioSource m_SourceObject;
    private bool m_IsSpatialized;
    private TMPro.TextMeshPro m_TextMeshPro;

    public void Start()
    {
        m_SourceObject = gameObject.GetComponent<AudioSource>();
        m_TextMeshPro = ButtonTextObject.GetComponent<TMPro.TextMeshPro>();
        SetSpatialized();
    }

    public void SwapSpatialization()
    {
        if (m_IsSpatialized)
        {
            SetStereo();
        }
        else
        {
            SetSpatialized();
        }
    }

    private void SetSpatialized()
    {
        m_IsSpatialized = true;
        m_SourceObject.spatialBlend = 1;
        m_TextMeshPro.SetText("Set Stereo");
        //m_SourceObject.outputAudioMixerGroup = RoomEffectGroup;
    }

    private void SetStereo()
    {
        m_IsSpatialized = false;
        m_SourceObject.spatialBlend = 0;
        m_TextMeshPro.SetText("Set Spatialized");
        //m_SourceObject.outputAudioMixerGroup = MasterGroup;
    }

}
```
Quad に SpatializeOnOffコンポーネントを追加
Hierarchy > Quad > AddComponent("SpatializeOnOff")
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/046bedb5-d75d-2b18-7a7a-70fda4b62a00.png)
SpatializeOnOff の Button Text Object に "PressableButtonHoloLens2" をセット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/c1c4c5e3-1b5e-cede-35c7-4f27877482da.png)
Hierarchy > PressableButtonHoloLens2 > Intractable を開く
Events OnClick() の+アイコンをクリックしてイベントを追加
追加したイベントのオブジェクトに Quad をセット
関数に SpatializeOnOff > SwapSpatialization() をセット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/f4bc24b7-aafc-b333-d0ae-ec141b20350d.png)
# 動作確認
File > Build Settings > Build
適切なフォルダを選択してビルド
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1264045/605aa780-edd2-a934-db16-7fc586aac739.png)

続き
[【MRTK】HoloLens2 空間オーディオのチュートリアルのやり方 その4](https://qiita.com/h_koya/items/b5a6f4bdb43608982f2a)
Railsチュートリアルまとめ 第2章

# 第2章について
第2章ではscaffoldを使ってユーザーモデルとマイクロポストモデルを作成し、投稿機能、投稿者と投稿の関連付けができるアプリケーションを作成する。

# 目次
[1. scaffoldについて](#1-scaffoldについて)
[2. scaffoldの欠点](#2-scaffoldの欠点)
[3. RESTアーキテクチャ](#3-RESTアーキテクチャ)
[4. 継承](#4-継承)
[5. 命名規則](#5-命名規則)
[6. 関連付け](#6-関連付け)
[7. エラー](#7-エラー)
[8. 参考文献](#8-参考文献)

#1 scaffoldについて
Railsには大量の機能を自動生成する`scaffold`というコマンドがある。
`rails generate scaffold モデル名 カラム:型`というようにコマンドを実行すると、簡単にRESTfulな（HTTPリクエストによって作成、取得、更新、削除の操作を振り分けて行うことができる）アプリケーションを作成することができる。

* モデル
* コントローラ
* ビュー

scaffoldは上記のようなRailsアプリケーションに必要なMVCを構築するためのファイルを自動作成してくれるので、後は`rails db:migrate`コマンドでデータベースをマイグレートすることで動くアプリケーションを作成することができる。

#2 scaffoldの欠点
scaffoldは便利ではあるが、以下のような欠点がある。

* データの検証が行われていない(Validationが書かれていない)
* ユーザー認証が行われていない
* テストが書かれていない
* レイアウトやスタイルが整っていない
* コードが難解

特にコードが難解で理解が難しいので、Railsのコマンドを学習するためにも初学者はscaffoldを使うべきではないのかもしれない。

#3 RESTアーキテクチャ
Wikipediaより以下引用。
> Representational State Transfer (REST) は、ウェブAPIの定義に使用されるアーキテクチャスタイルであり、同時にウェブのような分散ハイパーメディアシステムのためのソフトウェアアーキテクチャのスタイルのひとつでもある。

簡単に言ってしまえば、RESTfulなスタイルというのはHTTPリクエストメソッド（POST/GET/PATCH/DELETE）によってデータベースの作成/取得/更新/削除操作を行えるということ。
以下の記事がRESTについて分かりやすくまとめていたので参照。
[REST入門基礎知識](https://qiita.com/TakahiRoyte/items/949f4e88caecb02119aa)

#4 継承
モデルやコントローラでRubyのコードが書けるのはRailsにおいてMVCのModelの部分を提供するActiveRecordが提供するActiveRecord::baseという基本クラスをApplicationRecordが継承しているから。
> app/models/user.rb
> class User < ApplicationRecord
> ...
> end

#5 命令規則（単数形？複数形？）
基本的に`rails generate`コマンドを実行するとき、モデルを作成するなら先頭大文字で単数形、コントローラを作成するなら複数形にする。
以下参考。
[Railsの命名規則【単数形・複数形】](https://www.y-hakopro.com/entry/2019/06/25/235943)

ちなみにユーザーモデルとマイクロポストモデルの関連付けを行う際にhas_manyとbelongs_toをモデルに記載するがその時、has_manyであれば対象のモデルを複数形、belongs_toであれば単数形で記載する。

#6 関連付け
投稿者(User)１人に対してが投稿内容(Micropost)が複数になっている場合において関連付けをすることでUser側からMicropostを操作することができる。関連付けを行うためにはUserの方にはモデルに`has_many :microposts(*複数形であることに注意)`、Micropostの方はモデルに`belongs_to :user`というように記載する。
こうすることで例えば、
`@user = User.first`
`@user.micropost.create`
というようなコードでidが１のUserのMicropost(投稿)を新規作成することができる。

#7 エラー
herokuでマイグレートを実行しようとした際、エラーが発生した。原因はアプリケーションのpostgresqlへのアドオンが設定されていなかったから。
下記コマンド実行で接続完了。(おそらくコマンドじゃなくてもherokuのwebページでも設定できる)
`heroku addons:create heroku-postgresql`

#8 参考文献
[【Ruby on Rails】Herokuへデプロイして、heroku run db:migreteにて...](https://amaino.me/blog/development/heroku%E3%81%B8%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%97%E3%81%A6%E3%80%81heroku-run-dbmigrate%E3%81%AB%E3%81%A6%E3%82%A8%E3%83%A9%E3%83%BC%EF%BC%9Apgconnectionbad-could-not-connect-to-server/)
[Representational State Transfer](https://ja.wikipedia.org/wiki/Representational_State_Transfer#%E5%8E%9F%E5%89%87)
[REST入門基礎知識](https://qiita.com/TakahiRoyte/items/949f4e88caecb02119aa)
[Railsガイド 2.1命名ルール](https://railsguides.jp/active_record_basics.html#%E5%91%BD%E5%90%8D%E3%83%AB%E3%83%BC%E3%83%AB)
[Railsの命名規則【単数形・複数形】](https://www.y-hakopro.com/entry/2019/06/25/235943)
dockerでコンテナ外部にファイル保存

ボリュームを利用してdockerのコンテナ外にファイルを保存する方法。
例としてwordpressのdockerコンテナで記載する。

# 元のdocker-compose (wordpress)

[docker hub参考](https://hub.docker.com/_/wordpress)

```docker-compose.yml
version: '3.1'

services:

  wordpress:
    container_name: wp-trial
    image: wordpress
    restart: always
    ports:
      - 55555:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_USER: exampleuser
      WORDPRESS_DB_PASSWORD: examplepass
      WORDPRESS_DB_NAME: exampledb
    volumes:
      - wordpress:/var/www/html

  db:
    container_name: wp-db
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_DATABASE: exampledb
      MYSQL_USER: exampleuser
      MYSQL_PASSWORD: examplepass
      MYSQL_RANDOM_ROOT_PASSWORD: '1'
    volumes:
      - db:/var/lib/mysql

volumes:
  wordpress
  db:
```

# ディレクトリを直接指定

`C:\wordpress\html`をボリュームとして設定する場合はこんな感じ。
ただ、このままサーバでは使えないので環境変数の方がいい。

```docker-compose.yml
version: '3.1'

services:

  wordpress:
# (省略)
    volumes:
      - /C/wordpress/html:/var/www/html

# (省略)
volumes:
# (wordpressは削除)
  db:
```

# 環境変数で指定

WORDPRESS_HTML_PATHという環境変数を設定する場合はこんな感じ。
※環境変数は開発環境やサーバ環境で設定すればOK

```docker-compose.yml
version: '3.1'

services:

  wordpress:
# (省略)
    volumes:
      - ${WORDPRESS_HTML_PATH}:/var/www/html

# (省略)
volumes:
# (wordpressは削除)
  db:
```

# 参考記事

* [Docker、ボリューム(Volume)について真面目に調べた](https://qiita.com/gounx2/items/23b0dc8b8b95cc629f32)
* [docker for windowsでのdocker-composeのvolumes](https://qiita.com/tettsu__/items/c50c17b4eef3c960e9b8)
* [Docker Composeでボリューム作成](https://qiita.com/reflet/items/5c0a488494c7d6904084)
React で `<T>(v: T) => v` と書くとエラーになる理由

## はじめに

Dwango でニコニコ生放送のフロント開発を担当している @misuken です。

React で開発中、すごく単純な Generics を持つ関数を書いたらエラーになってビルドが通らないといった経験をしたことはないでしょうか？

それも、常に通らないのではなくて、通るときもある。。。というような不思議な現象。

今回は最初に遭遇したときは確実に戸惑うこの現象について解説します。

## エラーになる例

例えば、これくらい単純なコードでもエラーになります。
構文的には間違ってなさそうなんですけどね。

```tsx
const F1 = <T>(v: T) => v;
```

[playground で確認する](https://www.typescriptlang.org/play?#code/MYewdgzgLgBAYgRhgXhgHgCoD4AUA3ALhgwEoUsY8BuAKCA)

## エラーにならない例

次にエラーにならない例を紹介します。(といってもコードは変わってないんですが)

```ts
const F1 = <T>(v: T) => v;
```

[playground で確認する](https://www.typescriptlang.org/play?jsx=0#code/MYewdgzgLgBAYgRhgXhgHgCoD4AUA3ALhgwEoUsY8BuAKCA)

## 二つの例の違い

エラーになる例と、エラーにならない例の違いは、構文を JSX として認識するかどうかの違いです。
playground の設定で言うところの以下。 

### エラーになる時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41058/a206abc6-cf07-52b9-bef3-5f15955dbb80.png)


### エラーにならない時
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41058/aab13978-723d-1cc0-4fa5-da0aa3a34241.png)

## tsx と ts の違いに注意

つまり問題のコードは tsx なら `<T>` の部分が JSX と認識されるので、その後の記述が不適切なため構文エラーになりますが、 ts なら JSX とは認識されないので構文エラーになりません。

## 対処法

原因はわからなくとも、エラーを無くすために以下のように書き換えている方もいるのではないでしょうか。

```tsx
const F1 = <T extends any>(v: T) => v;
```
[playground で確認する](https://www.typescriptlang.org/play?#code/MYewdgzgLgBAYgRhgXhgHgCowKYA8rZgAmEMAhmAJ4B8AFAG4BcMGAlCtTPQNwBQQA)

これにはもっと簡単な解決策があり、カンマを足してやれば良いのです。

```tsx
const F1 = <T,>(v: T) => v;
```
[playground で確認する](https://www.typescriptlang.org/play?#code/MYewdgzgLgBAYgRhgXhgHgCoBoB8AKANwC4YMBKFHGAgbgCgg)

理屈を知らないとわかりにくいものの、コード自体に意味合いを持たせないという意味ではこれが適切かもしれませんね。

自分は TypeScript の issue を眺めているときにこの書き方を知りました。
初学者のプログラミング　ActiveHashの実装

##ActiveHashを実装する目的
特に入力せず、選択方式で保存したいデータに対し、ActiveHashを導入しようと考えた。それにより、UIの向上を目指す。
##手順①Gemの導入
``` ruby
gem 'active_hash'
```
上記を`Gemfile`に記述し、ターミナル上で`bundle install`を実行する。
##手順②モデルを作成する
```ruby
class Term < ActiveHash::Base
  self.data = [
    { id: 1, name: '学期を選択' },
    { id: 2, name: '1学期' },
    { id: 3, name: '2学期' },
    { id: 4, name: '3学期' },
    { id: 5, name: '前期中間'},
    { id: 6, name: '前期期末'},
    { id: 7, name: '後期中間'},
    { id: 8, name: '後期期末'},
  ]
  include ActiveHash::Associations
  has_many :scores
end
```
モデルはmodelディレクトリ内に、マグレーションファイルが不要なため、手動で作成する。ActiveHashではIdで保存されるため、それぞれに紐づく情報を`name: '情報'`という形で記述する。また、ScoreモデルにもActiveHashを有効にするため下記のように記述をする。

```ruby
 belongs_to_active_hash :term
```


##手順③カラムを設定する
ActiveHashのデータを保存するテーブルにActiveHashを保存するためにカラムを設定する。

```ruby
class CreateScores < ActiveRecord::Migration[6.0]
  def change
    create_table :scores do |t|
      t.integer :term_id, null: false #<=idで設定している
      t.integer :grade_id, null: false #<=これもActiveHash
      t.integer :user_id, null: false
      
      #省略#

      t.timestamps
    end
  end
end
```

##手順④コントローラーを記述
```ruby
def score_params
  params.require(:score).permit(:grade_id, :term_id, ...省略).merge(user_id: current_user.id)
end
```
ストロングパラメーターを設定し、ActiveHashのIdを受け付けられるように設定する。

##手順⑤ビューを設定
```erb
    <div>学期
      <%= f.collection_select(:term_id, Term.all, :id, :name, {}) %>
    </div>
```
collection_selectを使用することでプルダウンメニューのように表示することが可能。

##エラーへの対応：ActiveRecord::NotNullViolation in ScoresController#create　Mysql2::Error: Field 'term_id' doesn't have a default value
上記のエラーは"term_idがnullになっているためエラーが出ています"というような内容。つまり、term_idが受け取れていない、もしくは遅れていないことが原因。今回はモデルのhas＿manyの記述に誤りがあった

```ruby
 has_many :score <=単数系は誤り
 has_many :scores <=複数形に訂正
```

##unknown attribute 'user_id' for Score.
"Scoreモデルにuser_idが保存できません"というような内容。カラムを修正。

```ruby
class CreateScores < ActiveRecord::Migration[6.0]
  def change
    create_table :scores do |t|
      t.integer :term_id, null: false
      t.integer :grade_id, null: false
      t.integer :user_id, null: false #<=追記
      
      t.integer :japanese, default: "0"
      t.integer :mathematics, default: "0"
      t.integer :english, default: "0"
      t.integer :social_studies, default: "0"
      t.integer :science, default: "0"

      t.timestamps
    end
  end
end
```

##その他エラー
スペルミスによるものが多いと考えられる。他にも、ビューファイルの絡む指定にスペルミスがあるなど、チェックすべき点は多い。

##まとめ
ActiveHashはコスパいいな！簡単に実装できる割に機能的だと思った。選択方式で保存したい内容についてはどんどん使ってみようと思う。

## さいごに
プログラミングの初学者です。その日に学んだことを学習の一環としてアウトプットしています。より深く学習していきたいと考えておりますので、内容に誤りがございまいたらご指摘等いただけますと幸いです。

参考図書：パーフェクト Ruby on Rails【増補改訂版】すがわらまさのり/前島真一/橋立友宏/後藤優一/五十嵐邦明
ディレクトリに含まれているファイル（ハイフンから始まる）に連番を付けて一括で名前変更する

# やりたいこと

```
DIR
|
L A
| L ---foo---.jpg
| L ---hoge---.jpg
| L ...以下略   
|
L B
  L ---foo--.jpg
  L ---hoge--.jpg
  L ...以下略
```

のような状態のファイル構造のデータに対して、以下のような状態にしたいです

```
DIR
|
L A_01.jpg
L A_02.jpg
L ...以下略   
L B_01.jpg
L B_02.jpg
L ...以下略
```

## 要件など

- 何らかのコマンドで手数をあまりかけず実行する（手動実行より明らかに楽になればOK）
- サブディレクトリを使わず、ディレクトリ直下で管理する（DIR直下に全ファイルを置く）
- 名前による並び順はサブディレクトリの名前順、サブディレクトリ以下のファイル名の名前順を維持する
- サブディレクトリ以下のファイルは、サブディレクトリ名＋数字＋拡張子とする
- サブディレクトリ内のファイル数は１０を超える（数字に対してゼロ埋めが必要）
- （オプション）-などのメタ文字から始まるファイルに対しても対応できるようにする


# やったこと

以下のcpup.shをAやBなどのディレクトリ内か、第１引数に指定して実行する

`sh cpup.sh A`

```shell

if [ $# != '0' ]; then
  cd $1
fi

cur_dir=`pwd`
lst=${cur_dir//\// }
for prefix in ${lst[@]};
do
  :
done

i=1
for f in `ls`
do
  s=`printf %02d $i`
  e=${f##*.}
  g="../_${prefix}_${s}.${e}"
  cp "${f}" $g
  let i++
done

```

# ポイント
- ファイル内の一括返還のためにforを使用（リストアップ「ls部分」は適宜変更
- ゼロ埋め制御のために、printfを利用
- 連番化するために変数iを設け、ループ毎に１ずつ増やす