OmniAICreator/Qiita-1.07M huggingface dataset:
プログラミング超初心者がNode.jsについて理解しようとした

JavaScript関連の分野について学習をしていると Node.jsというものがどうしても目に入ってくるのですが、プログラミング初学者の私にとっては、わかりやすく解説しようとしてくれている記事を10本調べてみても結局Node.jsがなんなのかわかりませんでした。

もしかして同じような初心者の人いるのでは？と思い、理解が進んだ説明を書き留めておきます。
Node.js ってなんなん？ていつまで経っても解決しない方はぜひご覧ください。

### クライアントサイド JavaScript

Webクライアント（Webブラウザ）で動作するJavaScript。
ユーザーの目に見える場所（フロントエンド）の挙動にあれこれ指示を出す言語。
マウスオーバーするとポップアップが出る、webサイト上に画像のスライダーの挙動を実現させる、など。

Webサーバーとの情報のやり取りをしてくれる、言語のような使い方ができるというもの。
↓
本来webページには、登録された情報を引っ張ってくる指示が出されてからサーバーに情報を取りに行って表示されるというプロセスがある。

### サーバサイド JavaScript ： Node.js

Webサーバーは、Webクライアントからの要求に応じて、データベースに入っている情報を取得したり格納したり、いわゆるユーザーの目に見えない（バックエンド）処理を担当する。
このとき、Webサーバ側でもプログラムが動作しており、Webサーバ側で動作するように作られた JavaScript言語の実行エンジン（JavaScriptインタプリタ）が Node.js である。
Node.js は、Webサーバだけでなく、JavaScript言語で書かれたスタンドアロンアプリケーションを動かすこともできる。

### 非同期処理、非同期通信

データベースに登録されたユーザー情報などをサーバーに連携して取り出してきて表示、、、
というように、情報取得の要求(ユーザーから) 
→ サーバーへ情報を探しに行く
→ 該当情報を返して表示
という一連の流れに時間がかかりすぎると、ちょっとサービスによってはユーザーの要求するイベントに対してタイムラグが発生し、(LINEのやり取りや決済サービスなど)サービス的にイケてないものになってしまいそうな時に使われるものらしい。

特徴：

* webサイトやサービス上で、
* 入力された情報などをリアルタイムでサーバーに保存し反映し続ける(常時接続)

LINEがなんか挙動が止まって数秒経ってからようやくメッセージ送れるみたいな状態だと結構ストレス溜まりますよね。
そうならないようにするための実装方法、という解釈ができました。

JavaScript言語は、非同期処理や非同期通信を行うプログラムを作るのに向いている言語です。

### 参考

参考にさせていただいたサイト：
https://eng-entrance.com/what-is-nodejs
Ruby variable and method



# 概要

Ruby における変数及び関数のまとめ


# Ruby における変数

Ruby における変数は、python のように型を宣言する必要がなく以下のように扱う

```ruby
name = 'Rudy'
```


# Ruby における関数

Ruby における関数(method)は、以下のように扱う。method においては、0個以上の引数を取るものとする。

```ruby
def hello name
puts "Hello #{name}."
end

name =ARGV[0]
hello(name)
```



------
 - **source** ~/grad_members_20f/members/FumiyaToyoda/variable_method.org
M1のMACでtensorflow + opencv

# はじめに
<!-- 発端や概要を記載 -->
M1のMACでtensorflowとopencvを同時に利用したかったのですが、中々上手くいかなかったので記事にまとめます。
注意：浅学エンジニアですので、もっといい方法はあると思います・・・

# 環境

- マシン：MacBookAir M1
- Python：3.8.2（デフォルトで入っていた）

# 導入方法

- Anacondaをインストール　[ここ参照](https://sukkiri.jp/technologies/ides/anaconda-mac_install.html)
- Rosettaでターミナルを起動⇦たぶん大事
- Anacondaでpython3.7環境を構築⇦超大事
    - `conda create -n py37_opencv python=3.7 anaconda`
- opencvをインストール
    - `pip install opencv-python-headless`
    - ↑GPU非対応版
- tensorflowをインストール
    - `conda install tensorflow`
   
# 実行！
[この記事](https://qiita.com/Kazuhito/items/f8f21956436dc410f8d2)の03_face_detection_demo.pyソースを実行しました。
※01や02は`AttributeError: module 'tensorflow_core.keras.applications' has no attribute 'EfficientNetB0'`というエラーを吐いて動きませんでした。。。
Ruby variable and method



# 概要

ruby における変数及び関数のまとめ


# Ruby における変数

Ruby における変数は、python のように型を宣言する必要がなく以下のように扱う

```ruby
name = 'Rudy'
```


# Ruby における関数

Ruby における関数(method)は、以下のように扱う。method においては、0個以上の引数を取るものとする。

```ruby
def hello name
puts "Hello #{name}."
end

name =ARGV[0]
hello(name)
```



------
 - **source** ~/grad_members_20f/members/FumiyaToyoda/variable_method.org
ruby puts



# 概要

ruby における変数及び関数のまとめ


# Ruby における変数

Ruby における変数は、python のように型を宣言する必要がなく以下のように扱う

```ruby
name = 'Rudy'
```


# ruby における関数

Ruby における関数(method)は、以下のように扱う。method においては、0個以上の引数を取るものとする。

```ruby
def hello name
puts "Hello #{name}."
end

name =ARGV[0]
hello(name)
```



------
 - **source** ~/grad_members_20f/members/FumiyaToyoda/variable_method.org
RaspberryPIでAE-VL53LX1（測距センサ）を使用して距離測定

# やったこと
「AE-VL53LX1」センサモジュールとPythonライブラリを使用して、RaspberryPiで距離を測定してみました。

# 使った物
- Raspberry Pi4(4GB)
- [AE-VL53LX1](https://akizukidenshi.com/catalog/g/gM-14249/)
    - 測距センサモジュール（リンク先は秋月電子の商品ページです）

# 簡易回路図
![AE-VL531X1_ec.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197227/7fe7be23-2a81-c1cc-59c7-ee96b9f79c8a.jpeg)


# 環境
- python3.7.3
- venv

## OS
```bash:os
(VL53L1X) pi@raspberrypi:~/WorkSpace/Python/VL53L1X $ uname -a
Linux raspberrypi 5.4.51-v7l+ #1327 SMP Thu Jul 23 11:04:39 BST 2020 armv7l GNU/Linux
```

# ライブラリ
- smbus
- vl53l1x
    - [pimoroni/vl53l1x-python](https://github.com/pimoroni/vl53l1x-python)

```bash:install
(VL53L1X) pi@raspberrypi:~/WorkSpace/Python/VL53L1X $ python -m pip install smbus vl53l1x
```

# pip list

```bash:list
(VL53L1X) pi@raspberrypi:~/WorkSpace/Python/VL53L1X $ pip list
Package       Version
------------- -------
pip           18.1   
pkg-resources 0.0.0  
setuptools    40.8.0 
smbus2        0.4.0  
VL53L1X       0.0.5  
```

# サンプルプログラム

`pimoroni/vl53l1x-python`の[距離をバーで表示するプログラム](https://github.com/pimoroni/vl53l1x-python/blob/master/examples/graph.py)をそのまま実行した結果です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197227/3c94e210-6faa-51fc-dcb7-bd9b5defb24b.png)

# 今後
カメラなのでbitmapなどで表示できると思っているのですが、どうすれば良いかよくわかっていないので調べていこうと思います。
DynamoDBを構築してみよう

## 概要

1. DynamoDBを構築
2. テーブルにデータを追加
3. データの削除

今回は、 [AWSのチュートリアル](https://aws.amazon.com/jp/getting-started/hands-on/create-nosql-table/) を参考に進めて行きます。

## 1. DynamoDBを構築

- テーブルの作成

コンソール > DynamoDB > テーブル へ移動して、テーブルの作成を行います

![DynamoDB · AWS Console 2020-12-28 23-54-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/0194a569-0f83-e0e1-95ae-30ac5903cd95.png)


- DynamoDB テーブルの作成

テーブル名 : qiita-test-2020
プライマリキー : ID
デフォルト設定の使用 : チェック入れる

![DynamoDB · AWS Console 2020-12-28 23-55-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/e934b805-fe65-df9f-2458-2347e6dca8cc.png)


- テーブルの完成

保存すると、テーブルができました

![DynamoDB · AWS Console 2020-12-28 23-57-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/63df7487-1275-0d5d-7b04-4be096022dff.png)



## 2. テーブルにデータを追加

- 項目の作成

qiita-test-2020をクリックすると詳細が出ます。
詳細 > 項目 > 項目の作成 でデータを入れることができます。

![DynamoDB · AWS Console 2020-12-29 00-00-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/176c4eed-e868-8de1-30fa-2f329e17fdf3.png)


- データの追加

追加するデータを記載し、保存します。

![DynamoDB · AWS Console 2020-12-29 00-01-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/91027cb8-17b7-1877-7a5a-756bef96412b.png)


すると、ID 1 が保存されました。

![DynamoDB · AWS Console 2020-12-29 00-02-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/660c4a2b-cf8f-e6d5-8d17-e4c1e8ca11fd.png)




## 3. データの削除

- いくつかデータを入れてみました

![DynamoDB · AWS Console 2020-12-29 00-14-12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/4dc1923a-a957-1042-70b0-ecd43cb5b5d2.png)


- 2 のデータを削除してみます

2 にチェックを入れて、アクション > 削除 を行うことで、データの削除ができます

![DynamoDB · AWS Console 2020-12-29 00-18-16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/2a8ddc75-c5dd-ce5e-7747-29c09981ed3e.png)


2 がなくなっていました

![DynamoDB · AWS Console 2020-12-29 00-19-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/6e1d81fb-95c8-e5be-0d5a-e2c56c079cca.png)


### 勉強後のイメージ

基本的にはaws cli から実行することが多いのかな・・？
まぁ普通はコンソールからしないよね。。
一旦どうやって作るかくらいは試してみたかったの。
M1のMACのtensorflowでzsh illegal hardwareが出る話 2020/12

# はじめに
<!-- 発端や概要を記載 -->
M1のMACでAppleが最適化した[tensorflow環境](https://qiita.com/tomoyaeibu/items/46f2f3384a370df71d5e)を利用せず、Rosettaでターミナルを起動した状態でtensorflowを利用したい（普通にpip install tensorflowでインストールしたい）場合、`import tensorflow`を実行すると`zsh illegal hardware`と怒られてインタプリンタが落ちます。
理由は分かりません・・・


# 解決策
<!-- タイトルとアンカー名を編集 -->
- Rosettaでターミナルを起動
- Anaconda経由でtensorflowをインストール
    - `conda install tensorflow`

何でApple謹製のtensorflowを使わないのかというと、opencvも使いたいからです。
前の記事でも書きましたが、opencvとtensorflowを同時に使おうとするとどうしてもAnacondaを経由するしか私には解決できませんでした。
簡単！Migration Fileを一気にdownする方法

※この記事はプログラミング初心者が書いたものです。間違っている所があればどんどん指摘してください。

マイグレーションファイルを一気にダウンする方法。

```
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20201030063444  Create posts
   up     20201031040328  Devise create users
   up     20201031085240  Add user id to posts
   up     20201103054933  Create likes
   up     20201105073301  Add details to users
   up     20201109035610  Add gender to users
   up     20201109055919  Remove time from posts
   up     20201109062656  Remove week from posts
   up     20201112060702  Create comments
   up     20201210062454  Add url to posts
```
最初の方に作成したモデルに入っているカラムを変更したいときは、該当するマイグレーションファイルのStatusをdownにしなければなりません。
例えばMigration NameがCreate postsの場合はrails db:rollbackを10回行わなければなりません。
正直めんどくさいです。。。
<br>
そこで登場するコマンドが

```
$ rails db:rollback STEP=n　
```
です！
nはロールバックしたいファイルの数を代入するのです。


これで開発効率あげれるぞ～

<h1>参考にさせていただいたサイト</h1>
https://pikawaka.com/rails/migration
PowerShell　vue : このシステムではスクリプトの実行が無効になっているため～　エラーの対処法

##はじめに
vueコマンドを実行したら以下のエラーが起きたときの自分ができた解決方法を記載します。（ぼくではできましたレベルの記事なので、ご参考程度に）

##エラー内容
vue : このシステムではスクリプトの実行が無効になっているため、ファイル C:\Users\~~~~
を読み込むことができません。詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170
) を参照してください。
発生場所 行:1 文字:1
+ vue
+ ~~~
    + CategoryInfo          : セキュリティ エラー: (: ) []、PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess

要するに、「このPowerShellではスクリプトの実行を禁止していますよ」ということ

##解決策
以下の命令を実行

Set-ExecutionPolicy RemoteSigned -Scope Process

一時的にスクリプトを実行可能にする

vueコマンドが使えるようになった。

##参考記事
http://www.curict.com/item/d1/d1c4a3e.html
アドベントカレンダー27日目：SREを読んでみた「時系列データからの実践的なアラート」編②

Borgmanは、Borgのモニタリングを行うシステムです。
Borgmanでは、データフォーマットを統一していました。これにより、システム間のオーバーヘッドをなくし、大量のデータを捌くことができるようになりました。
今日からデータの扱い方について、学んでいきます。

## エクスポートされたデータの収集
Borgmanは決められた間隔で/varzからフェッチを行います。収集は他のターゲットの収集と足並みをそろえて、行われるわけではありません。
Borgmanは以下のターゲットに対して「合成」変数も記録します。

> * **名前がホスト名とポート番号に解決されたか**
* **ターゲットが収集に対してレスポンスを返したか。**
* **ターゲットがヘルスチェックに対してレスポンスを返したか。**
* **収集が完了した時刻**<sup>1</sup>

これらの変数によって、対象のタスクが利用不可になっていることを検出するルールを簡単に作成できます。

## 時系列のアリーナにおけるストレージ
Borgmonは全てのデータをインラインメモリデータベースに保存し、定期的にディスクへの書き込みが行われます。
データポイントは（timestamp, value）の形式で行われます。ホストごとに時系列データとして、保管されます。また、それぞれのデータはname=valueの形式でユニークなラベルが付けられます。これは、時系列アリーナと呼ばれる固定サイズのメモリになっていて、アリーナがいっぱいになるとガベージコレクタが古いエントリから削除します。最新と最古のエントリの時間差はホライゾンと呼ばれます。１つのデータポイントに必要なメモリは約24バイトで100万個のユニークな時系列データを1分間隔で12時間保存するのに必要なRAMは、17GB弱になります。実際には、メモリ内のデータは定期的なアーカイブが行われます。

## ラベルとベクタ
時系列データの並びはベクタと呼ばれます。時系列データの名前はkey=valueというペアで表されるラベルの集合です。時系列データには最低でも、次のラベルを持つ必要があります。

var（変数名）、job（モニタリングの対象となるサーバーの種類の名前。）、service（緩やかに定義された、ユーザーに対してサービスを提供するジョブの集合。ユーザーは内部の場合も外部の場合もある）、zone（この変数の収集を行ったBorgmonの場所（通常はデータセンター）を指すGoogleでの表現）

これらの変数は、変数式と呼ばれる以下のような形式をまとめられます。

```
{var=http_rquests,job=webserver,instancd=host:80,zone=us-west}
```

時系列データへのクエリは、すべてのラベルを指定する必要はなく、ラベルセットに対して、検索すると、マッチするすべての時系列データが返されます。


#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　116-120
Python パッケージ（ライブラリ）のpipコマンドを使ったインストール方法　Mac環境

こんにちは、かをるです。

今回は、GUIツールである【PyCharm】をつかってPythonの環境構築を行なっていきます。

PyCharmとは、Pythonの統合開発環境です。

コマンドラインによる環境開発よりもこういったツールを使いこなすことで、より効率的に開発を進めることができます。

有償と無償とありますが、今回は無償のインストール方法を紹介していきます。

ブログに投稿しました。

https://kaworublog.com/pycharm-python/
GitHub Actions/Cache "Unable to reserve cache with key {KEY}, another job may be creating this cache." エラー

ググってもすぐに原因がわらなかったので備忘録

## 結論
エラー内容そのまんまなんですが

`Unable to reserve cache with key {KEY}, another job may be creating this cache.`

というエラーが出たらそのキーはもう使えないので、新しいキーにしましょう。

## 原因

GitHub Actions/Cache の Post で下記のようなエラーが出た。

```:キャッシュ作成(post)時のエラー
> Post job cleanup.
Unable to reserve cache with key Linux-2.6.6-cache-c0304304e, another job may be creating this cache.
```

原因は同じキャッシュキーを使ってキャッシュを初めて作った際に、アクセス権限などの理由でキャッシュがうまく作れなかったこと。

```:キャッシュ作成に失敗した例
/bin/tar: {PATH}: Cannot open: Permission denied
/bin/tar: Exiting with failure status due to previous errors
Warning: Tar failed with error: The process '/bin/tar' failed with exit code 2
```

なので、利用しているキーはもう汚染されて使えない（少なくとも2週間ぐらい？）。
CircleCI などと違いGitHub Actions/Cacheは一度作られたキーのキャッシュを上書きしないので、汚染されるとそのキーの記録が残ってる限り使えないため。

## エラーの分かりづらさ

このエラーの分かりづらいのは、キャッシュダウンロード時は

```
> Run actions/cache@v2
Cache not found for input keys: {KEY}, {RESTORE_KEYS}
```

と表示されて、キーがまだ使われてないかのように表示されるところ。
また、このエラーが出てもworkflowは成功してしまうところ。

## 対応策

エラーが出てしまって汚染されたらもう仕方がないので、根本的な対応策は結構難しい。

キャッシュ固有のバージョン番号のようなものを用意し、それをキャッシュキーに含めるようにするし、いつでもキーを変更し過去のキャッシュの使用をやめることができるのでそのようにすると良い。

```yaml:ci.yaml
job-name:
  env:
    GEM_CACHE_TAG: project:0.0.1
  {...}

  steps:
  {...}
  - name: Cache bundle gems
    id: cache-bundle-gems
    uses: actions/cache@v2
    with:
      path: ${{ env.GEMS_ARCHIVE_DIR }}
      key: "${{ runner.os }}-${{ matrix.ruby }}-${{ env.GEM_CACHE_TAG }}-${{ hashFiles('Gemfile.lock') }}"
      restore-keys: |
        ${{ runner.os }}-${{ matrix.ruby }}-${{ env.GEM_CACHE_TAG }}-
```
[Unity]ShaderGraphをとりあえず一回使ってみたい方用の手順紹介

# 概要
とりあえずShaderGraphを触ってみたいなぁと思った方向けに簡単なものを一回作ってみる為の記事です。
# 本文
①UnityHubでURPの新規ファイルを作成
![スクリーンショット (1488).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/740c1a1c-9bb1-e527-f2fa-b3b8380f8c4a.png)
②ShaderGraphは自動でインポートされています
![スクリーンショット (1487).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/5281dc5c-a92d-b2b7-3694-53c51885f907.png)
③Create > Shader Graph > URP > Unlit Shader Graphでシェーダーを作成
![スクリーンショット 2022-12-18 14.48.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/b25b76bc-325c-03a5-19a2-77f07f82c317.png)

④作成したシェーダーのアイコンの上で右クリック。Create > Material
シェーダーが設定されたMaterialが作成されます。シェーダーを反映させたい3DオブジェクトにこのMaterialをドラッグ&ドロップで適用させます。
⑤今回は画像テクスチャを貼り付けるシェーダーを作ることにしました。
シェーダーをダブルクリックするとShaderGraphの画面が表示されます。
画像ファイルをShaderGraph画面へドラッグアンドドロップするとノードが作成されます。
作成されたノードのRGBA(4)をFragmentのBaseColorへつなぐ
![スクリーンショット (1492).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/807c0de0-e58c-0963-006f-ed816a6f79d9.png)
⑥ShaderGraph画面左上のSaveAssetを押す(自分でセーブをしないとShaderGraphの変更が反映されません。)
![スクリーンショット 2022-12-18 14.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/8b45db48-0248-9fe1-d065-36bd5346811d.png)

テクスチャが貼られただけで他の効果が一切無いシンプルなマテリアルが適用されました
![スクリーンショット (1491).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/ee746b93-3c2b-ffb9-73c9-f29ad487138a.png)
Ruby3.0.0をソースからビルドしてみた

2020/12/25にリリースされたRuby3.0.0をWindowsのWSLを使い、まっさらなUbuntu上でbuildしてみました。

# 環境
●ハードウェア環境
- Lenovo ThinkPad T460s

●ソフトウェア環境
- Windows 10 Home (バージョン20H2 OSビルド19042.685)
- Ubuntu 20.04 LTS(WSL上)

# 所要時間(ざっくり)
- WSL環境構築(Ubuntuアプリ取得とアカウント設定含む)：約10分
- Ubuntu初期設定：約10分
- Rubyソース ダウンロード：約5分
- Rubyソース ビルド：約90分

# 手順
## WSL環境構築(Ubuntuアプリ取得とアカウント設定含む)
Microsoftのドキュメントに従って構築しました。
[WSLドキュメント > クイックスタート > WSL をインストールし、WSL 2 に更新する](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)

## Ubuntu初期設定
ビルドに必要なツールだけインストールしました。
`$ sudo apt update`
`$ sudo apt install -y build-essential`

## Rubyソース ダウンロード
公式サイトからダウンロードし、解凍しました。
[Ruby 3.0.0](https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gz)
`$ curl -O https://cache.ruby-lang.org/pub/ruby/3.0/ruby-3.0.0.tar.gz`
`$ tar -xvzf ruby-3.0.0.tar.gz`

## Rubyソース ビルド
makeに80分くらい、make installに20分くらいかかりました。
`$ cd ruby-3.0.0`
`$ configure`
`$ make`
`$ make install`

# まとめ
makeは予想以上に時間がかかりました。。
N + 1 問題を解決する

# はじめに
N + 1 問題とは何なのかと、解決した方法を**個人的な解釈で**メモしていきます。
間違いがありましたら、ご指摘いただけますと幸いです。

今回は
"ユーザー（usersテーブル）" と "商品（itemsテーブル）"があり、
アソシエーションが設定されているという状況で、実際に起きた問題です。

問題が発生した際の
作業目的は、「ユーザーが出品した商品一覧をトップページに表示する」です。


---
# 前提

usersテーブル

id   | name   |
---- | ------ |
1    | 田中さん |
2    | 佐藤さん |
3    | 山田さん |
4    | 原田さん |


itemsテーブル

id   |	product    | user_id       |           
---- | ------------| ------------- |
1    |	スニーカー   |  4           |
2    |   香水　　　　|  5            |
3    |	 本        |  6            |

---
アソシエーション

```user.rb
class User < ApplicationRecord

has_many :items
end
```

```item.rb
class Item < ApplicationRecord

  belongs_to :user
end
```

---

コントローラー

```items_controller.rb
class ItemsController < ApplicationController

def index
  @items = Item.all
end
# 省略

def item_params
    params.require(:item).permit(:product).merge(user_id: current_user.id)
  end
end

```
---
ビュー

```index.html.erb
<% @items.each do |item| %>
  <li class='list'>
    <%= link_to item_path(item.id) do %>
      <div class='item-img-content'>
        <%= image_tag item.image, class: "item-img" %>
# 省略
```

# N + 1 問題とは
結論：
**データベースからデータを取り出す際に、大量のSQLが実行されて動作が重くなる**という問題です。

具体的に言うと、
`@items = Item.all`でitemsテーブルのデータを全て取り出して
それを一つずつ表示させようとしていますが、アソシエーションの関係で、
取り出す際にuser_idを１回１回探しに行っちゃうので、SQLが大量に実行されて動作が重くなります。

イメージ的には、
「パンと牛乳とiTunesカード 買ってきてー」って頼んだら一個ずつ買ってくる
みたいな感じです。効率悪すぎですね（笑）

# 解決方法
結論： こちらです

```items_controller.rb
def index
  @items = Item.includes(:user)
end
```

.all →　.includes(:user) としました。

解説：
includesとは**アソシエーションの関連付けを事前に取得してくれる**メソッドです。
`モデル名.includes(:関連名)` # アソシエーションで定義した関連名
belongs_to :user　←　このuserです。

includesは allの役割も持っているので、同じく全てのデータを取得できています。

includesの引数にuserモデルを指定してあげることで、usersテーブルから参照して
いるuser_idは、１回１回ではなく、itemsテーブルのデータを取ってくるときに、自動
で取得してくれるようになる。

以上で解決した、と私は理解しております。

---
今回は下記の記事を参考させていただきました。
https://pikawaka.com/rails/n1#includes%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89
kintoneおみくじアプリ作ってみました！！（動作原理について）

[こちら](https://note.com/tarimo34/n/n152c6d1bb732)で動作原理についても知りたいのことでしたのでQiitaに書こうかと。

kintoneおみくじアプリ作ってみました！！の動作原理説明編です。
なんのことはなく、参照先のアプリからデータを取ってきてランダムで抽選をかけて、おみくじの結果レコードを作成してるだけ、です。

どんな感じで動作しているかは以下をご覧ください！
[kintoneおみくじアプリ2021　使用例](https://www.youtube.com/watch?v=VNYQ2PE-0xg)

```javascript:app55.js
/**
 * おみくじアプリ
 * AUTHOR S.Morita(AntbearCreates)
 */
(function () {
    "use strict";

    /**
     * カスタムビューで表示した時＆カスタムビューに配置した#post_btnをクリック時の処理
     */
    kintone.events.on(['app.record.index.show'], function (event)
    {    
        /* カスタムビューの処理　特にカスタムビューのIDなど指定していないけど・・・ */
        jQuery('#post_btn').click(function() 
        {  
           const add_appId = kintone.app.getId();//追加先のアプリID（自アプリ）

           const master_appId = kintone.app.getLookupTargetAppId("おみくじid");//おみくじマスターアプリのID
           
            //おみくじマスタから最大500件まで取得して抽選！

            let param = {
                app: master_appId,
                query: 'limit 500',
                fields: ['$id','おみくじ結果'],
                totalCount: true,
                isGuest: false
            };
            
            //kintoneUtility廃止される前のモジュールなんでご勘弁
            kintoneUtility.rest.getRecords(param).then(function(resp) {
                
                // 成功時の処理

                //抽選結果を確定
                let random = Math.floor( Math.random() * resp.records.length );
                
                //結果に貼り付けるためのログインユーザー情報
                let user = kintone.getLoginUser();

                //結果レコードを追加
                let add_record = {
                    'おみくじid'  :  { value: resp.records[random]["$id"].value },
                    "ユーザー"    :  { value: [{"code": user.code }]}
                };
                let add_param = {
                    app: add_appId,
                    record: add_record,
                    isGuest: false
                };
                
                kintoneUtility.rest.postRecord(add_param).then(function(add_resp) {
                    // 成功時の処理を記載する
                    console.dir(add_resp);

                    //作ったおみくじ結果のレコードに移動しましょう！
                    location.href="/k/"+ add_appId +"/show#record="+add_resp.id;

                    return event;

                }).catch(function(error) {
                    // エラー時の処理を記載する・・・とりあえず省略
                    console.log(error.message);
                });

            }).catch(function(error) {
               // エラー時の処理を記載する・・・とりあえず省略
               console.log(error.message);
            });
        });
        
        return event; 
    });


 })();
```
ちょっと一癖あるRSpecを使ったモデルの単体テストコード　〜ユーザー登録

#はじめに
　完全に自分用です。モデルの単体テスト（ユーザー登録）の一癖あるコードを残しておきます。

##

###メールアドレス

```ruby:user_spec.rb
it 'メールアドレスは、@を含む必要があること' do
  @user.email.delete!('@')
  @user.valid?
  expect(@user.errors.full_messages).to include("メールアドレスは不正な値です")
end
```
###パスワード

```ruby:user_spec.rb
it 'パスワードは、6文字以上での入力が必須であること' do
  @user.password = '12345'
  @user.password_confirmation = @user.password
  @user.valid?
  expect(@user.errors.full_messages).to include("パスワードは6文字以上で入力してください")
end
```

```ruby:user_spec.rb
it 'パスワードは、半角英字がないとでの入力が必須であること' do
  @user.password = '123456'
  @user.password_confirmation = @user.password
  @user.valid?
  expect(@user.errors.full_messages).to include("パスワードは不正な値です")
end
```

```ruby:user_spec.rb
it 'パスワードは、半角数字がないとでの入力が必須であること' do
  @user.password = 'abcdef'
  @user.password_confirmation = @user.password
  @user.valid?
  expect(@user.errors.full_messages).to include("パスワードは不正な値です")
end
```

```ruby:user_spec.rb
it 'パスワードは全角数字では登録できないこと' do
  @user.password = '１２３４５a'
  @user.password_confirmation = @user.password
  @user.valid?
  expect(@user.errors.full_messages).to include("パスワードは不正な値です")
end
```

```ruby:user_spec.rb
it 'パスワードとパスワード（かくにん）、値の一致が必須であること' do
  @user.password = '12345a'
  @user.password_confirmation = '12345b'
  @user.valid?
  expect(@user.errors.full_messages).to include("パスワード（かくにん）とパスワードの入力が一致しません")
end
```
assert_equalを作って簡単にテストを書けるようにする

\![macOS-11.1](<https://img.shields.io/badge/macOS-11.1-brightgreen>) \![ruby-2.7.2p137](<https://img.shields.io/badge/ruby-2.7.2p137-brightgreen>) 


# Preface (はじめに)

テスト駆動型開発(TDD)では簡易的なテストを何度も繰り返し開発を進めることが基本です.

本記事では, ある式や値が想定のものと同じかどうかを確かめる関数assert\_equalを作り, それを用いて簡単なテストコードを作ろうと思います. 


# Assert


## Equal

まずは`expected`と`result`の値が等しいか確かめる

```ruby:assert_equal.rb
def assert_equal(expected, result)
  return expected == result
end

p assert_equal(1, 1)
```

```
> ruby assert_equal.rb
-> true
```

次に視覚的に分かりやすくするため`colorize`ライブラリを用いて出力に色をつけます. 

```ruby:assert_equal.rb
require 'colorize'

def assert_equal(expected, result)
  if expected == result
    puts 'true'.green
  else
    puts 'false'.red
  end
end

assert_equal(1, 1)
assert_equal(1, 2)
```

結果は一つ目は緑のtrue, 二つ目は赤のfalseとなるはずです. 

少し改良を加えます. 

-   引数のexpectedとresultの値を出力
-   先ほどのassert\_equalの処理を以下のように変更
    -   **true**: print "succeeded in assert\_equal.\n".green
    -   **false**: print "failed in assert\_equal.\n".red

```ruby:assert_equal.rb
require 'colorize'

def puts_vals(expected, result)
  puts "expected :: #{expected}"
  puts "result   :: #{result}"
end
def assert_equal(expected, result)
  puts_vals(expected, result)
  print  case expected == result
     when true  ; "succeeded in #{__method__}.\n".green
     when false ; "failed in #{__method__}.\n".red
     end
end

assert_equal(1, 1)
assert_equal(1, 2)
```

出力は

```
> ruby assert_equal.rb
```

```
expected :: 1
result   :: 1
succeeded in assert_equal.
expected :: 1
result   :: 2
failed in assert_equal.
```

となります. (Qiita上では色は変わっていません.)


## Not Equal

今度は`expected`と`result`が等しければfalse, 異なればtrueを返すassert\_not\_equal関数を作ります. 

```ruby:assert_equal.rb
require 'colorize'

def puts_vals(expected, result)
  puts "expected :: #{expected}"
  puts "result   :: #{result}"
end
def assert_not_equal(expected, result)
  puts_vals(expected, result)
  print expected != result ?
  "succeeded in #{__method__}.\n".green :
    "failed in #{__method__}.\n".red
end
def assert_equal(expected, result)
  puts_vals(expected, result)
  print  case expected == result
     when true  ; "succeeded in #{__method__}.\n".green
     when false ; "failed in #{__method__}.\n".red
     end
end

assert_equal(1, 1)
assert_equal(1, 2)
assert_not_equal(1, 2)
assert_not_equal(1, 1)
```

出力は

```
> ruby assert_equal.rb
```

```
expected :: 1
result   :: 1
succeeded in assert_equal.
expected :: 1
result   :: 2
failed in assert_equal.
expected :: 1
result   :: 2
succeeded in assert_not_equal.
expected :: 1
result   :: 1
failed in assert_not_equal.
```

このassert\_equalやassert\_not\_equalは便利なので他のコードにも使いたいです. しかしこのままでは, コード内のテストも実行されてしまうので,

```ruby:assert_equal.rb
if $PROGRAM_NAME == __FILE__
  assert_equal(1, 1)
  assert_equal(1, 2)
  assert_not_equal(1, 2)
  assert_not_equal(1, 1)
end
```

というようにテスト部分を変えます.
このように書くことでcodeが書いてあるファイル名(＿FILE＿)とPROGRAMが動いているファイル名($PROGRAM\_FILE)とが一致したら, 中身を実行するようにできます. 


# 参考資料

[チャート式ruby-IV(assert\_equal)](https://qiita.com/daddygongon/items/f6cea87314ee26e130ea)
Batch Normalizationの学習用や推論用のmeanやstdについて

Deep Learning with PyTorchを読んでいて、Batch Normalizationの学習用や推論用のmeanやstandard deviationについて、下記の内容があります。（p223）

> Just as for dropout, **batch normalization needs to behave differently during training and inference**. In fact, at inference time, we want to **avoid having the output for a specific input depend on the statistics of the other inputs** we’re presenting to the model. As such, we need a way to **still normalize, but this time fixing the normalization parameters once and for all**.
As minibatches are processed, **in addition to estimating the mean and standard deviation for the current minibatch**, PyTorch **also updates the running estimates for mean and standard deviation that are representative of the whole dataset**, as an approximation. This way, when the user specifies **`model.eval()`** and the model contains a batch normalization module, **the running estimates are frozen** and used for normalization. To **unfreeze running estimates and return to using the minibatch statistics**, we call **`model.train()`** , just as we did for dropout.


- 推論時もnormalizationが必要です。batch normalizationで学習したモデルだから。
- 推論時のnormalizationはサンプル１つ１つに対してやる。
- 推論時normalization用のmeanやstandard deviationは、学習時推定した。
- `model.eval()`が呼び出されたら、全体データの近似meanやstdは更新できない状態。
- `model.train()`が呼び出されたら、更新できる状態。
JavaScript　ClickイベントとFunction（関数）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654025/7533369e-2ef6-9b36-2243-819d852dc5dc.png" width="300">

#:white_check_mark:目標
>**JavaScriptでClickイベントを作る**

#HTMLファイル

```html:index.html
    <!DOCTYPE html>
    <html lang="ja">

    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>DOM</title>
        <style>
            .red {
                background: red;
                color: white;
                text-transform: uppercase;
                font-size: 2rem;
            }

            .blue {
                backgroun:white_check_mark:d: blue;
                color: white;
                text-transform: capitalize;
                letter-spacing: 10px;
            }

            .btn {
                background: #f15025;
                color: white;
                font-size: 1.2rem;
                border: none;
            }
        </style>
    </head>

    <body>

        <h2>events in javascript</h2>
        <button class="btn">click me</button>
        <!-- JavaScript -->
        <script src="main.js"></script>
    </body>

    </html>
```

#JavaScriptファイル
>ボタンをクリックすると表示が切り替わります！


```javascript:app.js
// Step1: select element
// Step2: addEventListener()
// Step3: what event, what todo

const btn = document.querySelector('.btn');
const heading = document.querySelector('h2');

function changeColors() {
    let hasClass = heading.classList.contains('red');
    console.log(hasClass);
    if (hasClass) {
        heading.classList.remove('red');
    } else {
        heading.classList.add('blue');
    }
}

btn.addEventListener('click', changeColors);
```
Docker環境でのLaravel×Nuxt.js開発時のDB接続とCORS問題を解決

# はじめに
Docker環境を用いて、Laravel（APIサーバー）、Nuxt.js（フロント）の環境を構築しました。
その際`コンテナ名関連のエラー`が2つほど出たのでその点について記載します。

## 本記事で扱わないもの
- Docker環境の構築方法
- LaravelをAPIサーバーとして利用する方法
- Nuxt.jsでのAPIリクエスト方法

# 概要
- LaravelをAPIサーバー、Nuxt.jsをフロントとして利用
- axiosを用いてLaravelにAPIをリクエスト

## DB接続問題

LaravelでDBへアクセスしたら下記エラーが発生しました。

![スクリーンショット 2020-12-29 22.29.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378711/a92030e0-106b-6dcd-364a-c8a5926e7d05.png)

調べたところDockerの場合、`.env`の変更が必要になるとのことで修正。

（変更前）

```:.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
```

（変更後）

```:.env
DB_CONNECTION=mysql
DB_HOST=db #ここをデータベースのコンテナ名にする
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=root
DB_PASSWORD=
```

無事jsonを取得できることが確認できました！
![スクリーンショット 2020-12-29 22.43.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378711/21015f5e-a5ec-2108-fcb8-c21305fd9a85.png)

## CORS問題
Nuxt.jsからはaxiosを用いてLaravelへjsonを取りにいきます。
![スクリーンショット 2020-12-29 22.47.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378711/a6ba48a6-5f7d-ab62-442f-2a84ca64f91b.png)
![スクリーンショット 2020-12-29 22.47.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378711/6455f93d-43d9-b533-69af-cc46e51701a1.png)
プロキシ関連でエラーが出ましたので対応します。

### プロキシ設定
モジュールを追加します。

```
$ yarn add @nuxtjs/proxy
```

nuxt側では`/api`でLaravelにアクセスします。

`web`がコンテナ名、`80`がコンテナのポートになります。（ここを最初localhost:8000にしていたので少しつまずきました）

```js:nuxt.config.js
  modules: [
    "@nuxtjs/axios",
    "@nuxtjs/proxy" //追加
  ],
  axios: {
    proxy: true //追加
  },
  proxy: {
    "/api": "http://web:80" //追加
  },
```

無事データ取得できました！
![スクリーンショット 2020-12-29 22.49.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378711/7ed048ba-9568-addf-d246-ac31330d468e.png)

# おわりに
LaravelをAPIサーバーとしてDocker環境で開発する際などは上記以外にも必要となる部分が出てくるかと思いますが、その辺りは検索したら割とすぐ出てくるのでそこにあまり載っていなかったものに関して今回記載しました。
Twitter、Google、メールでのログインを実装しよう。

これらの技術を使えば、簡単に実装できます。

## 自前で実装(Twitter,Google)

PHPでTwitterログインを実装しよう
https://dotinstall.com/lessons/tw_connect_php_v3#!lessons

GoogleでログインするWebサービスを作ろう
https://dotinstall.com/lessons/google_connect_php_v2

## BaaS/MBaaS環境を使う。

Firebase
https://firebase.google.com/?hl=ja

## Ruby on Railsを使う

【Rails】ログイン機能を実装する
https://qiita.com/d0ne1s/items/7c4d2be3f53e34a9dec7

## シンプルなPHPでのログイン実装

phpで作る簡素なログイン機能
https://qiita.com/qwertyuiopngsdfg/items/597da67387723a5aedad

PHP5.6でログイン機能を実装しよう
https://dotinstall.com/lessons/sns_php_v3

## 「パスワードを忘れた時」のメール送信

PHPでメール送信するための方法を解説【初めてでもわかりやすく】
https://techplay.jp/column/550

## アイコンの画像設定

Python(CGI)で画像アップローダーを作ってみた
https://masublog.net/python/pythoncgiimageuploader/

Python, Pillowで画像を一括リサイズ（拡大・縮小）
https://note.nkmk.me/python-pillow-image-resize/
cygwin で tcsh

いまさらだけど、cygwin をインストールした。で、tcsh もインストールした。しかし、login shell は bash のままだ。むかしはバッチファイルを書き換えていたが、どうやら、mkpasswd で /etc/passwd を作るのが正しそう(情報求む)。

```
mkpasswd > /etc/passwd
```

おそらく、cygwin をインストールするまえに user の id と group が Windows から与えられている。なので、後から mkpasswd で /etc/passwd をつくるというほうしきみたいだ。(う～ん。インストール時に作ればいい気もするが)

そこで passwd 内の bash を tcsh に変えれば、見事、tcsh が立ち上がるようになります。はい。本当に正しい方式を知っている人は教えてほしい。バッチファイルを書き直したり、.bashrc を書き直す、、、ってのはいまいちな気がするぞ。

Linux Sub System に移行してしまえばこんな苦労は必要ない気もする。
VSCodeで、ローカルのcodeコマンドと、RemoteSSH時のcodeコマンドを共存させる方法

# 何を言ってるんだ？
タイトルが何を言ってるかわからないと思うので、まずは環境の説明。

私は自宅のマシン（macOS）をモリモリスペックにして自宅ではそのマシンを、外出先ではノーパソからRemoteSSHを使って作業をしています。
作業環境を引き継げたり、外出先でコンパイルしてもバッテリー消費しなくて済むなどメリットがいろいろあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265811/10f535cf-ff13-4a04-17b0-8cb6de6057a8.png)

そしてVSCodeには`code`というCLIからVSCodeを開けるコマンドがあるのですが、これが実は２種類存在します。

|  path | 説明 |
|---|---|
| ローカルのcodeコマンド<br/>（`/usr/local/bin/code`） | ローカル環境で使うためのcodeコマンド。多くの人はこれ使ってるはず![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265811/f9ac31dd-a5be-a975-2e89-d37011a2e1b0.png) |
| RemoteSSH時のcodeコマンド<br/>（`~/.vscode-server/bin/<hash>/bin/code`） | リモート接続時に使うためのcodeコマンド。RemoteSSH時に使うことで、クライアントPCのVSCodeでワークスペースを開いてくれる。<br/>（https://code.visualstudio.com/docs/remote/ssh#_opening-a-terminal-on-a-remote-host） |

# 何が問題なの？
で何が問題なのかというと、ローカルの`code`コマンドをインストールしてしまうと、`/user/local/bin/`配下にインストールされるためエイリアスが上書きされます。
そうするとRemoteSSHで接続中にcodeコマンドを実行してもローカルのcodeコマンドが実行されてしまい、クライアントにしているノーパソのVSCodeには何も表示されません。

RemoteSSHは、サーバー（ワークステーションなど）のワークスペースを直接編集したりするのが一般的な使い方なんだと思います。
しかし私の場合はデスクトップマシンなので、リモート環境がローカル環境にもなり得るちょっと複雑な環境です。

**デスクトップPCを直接使っているときは`ローカルのcodeコマンド`を、RemoteSSHしているときは`リモート用のcodeコマンド`を実行してほしい！**

というのが今回の問題です。

# 解決策

ローカルで使う`code`コマンドはアンインストールして、`.zshrc`や`.bashrc`などに以下のコードを追加するだけ。

```
# codeコマンドがRemote SSHと競合しないように、`/usr/local/bin/`にはインストールせず、環境分岐させる
if [ -z "$VSCODE_IPC_HOOK_CLI" ]; then
  # ※macOSの場合↓↓↓
  alias code='/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code'
fi
```
`/Applications/Visual\ Studio\ Code.app/Contents/Resources/app/bin/code` は、ローカルで実行するcodeコマンドのオリジナルです。

RemoteSSH時に使われる環境変数 `$VSCODE_IPC_HOOK_CLI` が存在しない場合、すなわちローカルで実行するときは、アプリケーション内にある`code`コマンドを直接実行します。

こうすることで`/user/local/bin/`にcodeコマンドを置く必要がなくなり、エイリアスが上書きされるのを防げます。

### 終わり
実にニッチな要望だと思うのですが、備忘録として残しておきます。

次はiTermみたいなターミナルからcodeコマンド使いたい。昔からGithubとかで議論されているけど、良さげな方法が見つかっておらず……。
Rails「Not Null制約」と「バリデーション(presence: true)」 メモ

勉強していて、2つの動きに違いがあることに気が付き
更に同様の内容について、調べられているQiitaの記事も見つけたため
自分のローカルでも動作を確認しながらメモ程度にまとめてみたいと思います

## まずは、投稿用の簡易アプリを作成する

```rb:app/controller/posts.controller.rb
class PostsController < ApplicationController
  def index
    @posts = Post.where(user_id: @user.id)
  end

  def new
    @posts = Post.new
  end

  def crate
    @posts = Post.create(
      title: params[:post][:title],
      contents: params[:post][:contents],
      user_id: @user.id
    )

    if @posts.save
      redirect_to posts_index_path
    else
      render :new
    end
  end
end
```

マイグレーションファイル

```rb:db/migrate/☓☓☓_create_posts.rb
class CreatePosts < ActiveRecord::Migration[5.2]
  def change
    create_table :posts do |t|
      t.string :title, null: false
      t.text :contents
      t.string :user_id

      t.timestamps
    end
  end
end
```


テーブル ※わかりやすいように※をつけてます

```
sqlite> .schema posts

CREATE TABLE IF NOT EXISTS "posts" (
"id" integer NOT NULL PRIMARY KEY, 
"title" varchar NOT NULL, 
"contents" text DEFAULT NULL, 
"user_id" integer DEFAULT NULL, 
"created_at" datetime NOT NULL, 
"updated_at" datetime NOT NULL);
```

タイトル(title)には、「**NOT NULL**」制約をつけました
タイトルを空にして投稿してみる

```コンソール
~/environment/rails/sample_app
❯ rails c
Running via Spring preloader in process 23513
Loading development environment (Rails 5.2.4.4)
[1] pry(main)> Post.all
  Post Load (1.1ms)  SELECT "posts".* FROM "posts"
=> []
```

中身がはいっていないことを確認する

```rb:app/views/posts/new.html.erb
<h1>投稿新規作成画面</h1>

<%= form_with(model: @posts, url: posts_crate_path, local: true) do |f| %>
  <%= f.text_field :title %>
  <%= f.text_area :contents %>

  <%= f.submit '確認画面へ' %>
<% end %>
```

###タイトルが空のまま入力してみる
空のまま入力してみて、コンソールを確認すると

```コンソール
~/environment/rails/sample_app
❯ rails c
[2] pry(main)> Post.all
  Post Load (1.6ms)  SELECT "posts".* FROM "posts"
=> [#<Post:0x00007f956380e990
  id: 1,
  title: "",
  contents: "テスト contents",
  user_id: 1,
  created_at: Mon, 28 Dec 2020 07:43:20 UTC +00:00,
  updated_at: Mon, 28 Dec 2020 07:43:20 UTC +00:00,
  posted_date: nil>]
```

保存されていることがわかった

###「NOT NULL制約では」…
「空文字（"")」を拒否することが出来ない
なので、今回のように保存されてしまう

「null」と「空文字("")」は全くの別もの

##「null」と「空文字("")」の違い
Rubyにおける「null」つまり「nil」は…
・`false`と同じように「**偽**」として扱われる
・**NilClass**のインスタンス
・器も中身も**何もない状態**

「空文字("")」は…
・""は、**空白が存在**する

##空文字を拒否したければ…
モデルにバリデーションを付与する

```rb:app/models/user.rb
class Post < ApplicationRecord
  belongs_to :user

  # 空文字を拒否する
  validates :title, presence: true
end
```
上記を設定すれば、フォームに何も入力しなくても(空文字)
データに反映されることはない


##参考記事
https://qiita.com/wonder_meet/items/fa804f0d436a29c97460
https://qiita.com/tsuchinoko_run/items/c9214379a1f2878ec4ee
tnsnames.oraを探すスクリプト

# はじめに

職場のOracleクライアントがインストールされているPCで、「どこにtnsnames.oraがあるか分からない」ということが何度かありました。
Oracleのバージョンによって、あるいはインストール時に指定したフォルダによってtnsnames.oraがあるフォルダパスが異なるため、tnsnames.oraを探すスクリプトを作ってみました。

# 着眼点

[こちらのページ](https://docs.oracle.com/cd/E16338_01/install.112/b58879/post_install.htm)を見ると、以下のように「ORACLE_HOMEいかに作られる」と書かれています。
しかし、コマンドプロンプトの`SET`コマンドで探しても`ORACLE_HOME`という環境変数がないため、別の方法でtnsnames.oraを探すことにしました。

> 次の場所にtnsnames.oraファイルが作成されます。
> ORACLE_HOME\network\admin\tnsnames.ora

次に[こちらのページ](https://w.atwiki.jp/tak_is/pages/72.html)を見てみると、`tnsping`というコマンドを実行した際に返されるパス上にtnsnames.oraがあると書かれていました。
実際に試してみると以下の結果が返されて、実際に`C:\app\NKOJIMA\product\11.2.0\client_1\network\admin\`上にtnsnames.oraが存在していました。
そこで`tnsping`コマンドの結果を使って、tnsnames.oraがどこにあるのかを探すスクリプトを作ってみました。

```dosbatch:tnspingの結果
C:\Users\NKOJIMA>tnsping aaa

TNS Ping Utility for 32-bit Windows: Version 11.2.0.4.0 - Production on 29-12月-2020 19:45:28

Copyright (c) 1997, 2013, Oracle.  All rights reserved.

パラメータ・ファイルを使用しました:
C:\app\NKOJIMA\product\11.2.0\client_1\network\admin\sqlnet.ora

TNS-03505: 名前の解決に失敗しました。
```

# 作成したスクリプト

* 最初に`tnsping`コマンドの存在を確認して、`tnsping`コマンドがなければ処理をOracleクライアントがインストールされていないとみなして、処理を中断します。
* 次に`tnsping`コマンドの結果からsqlnet.oraのフォルダパスを取得して、そのフォルダパス上にtnsnames.oraがあるかどうかを調べています。
  * tnsname.oraが見つかった時は、そのファイルパスをコンソールに出力します。 
  * このフォルダにtnsnames.oraが無い時は、処理を中断しています。

```powershell:find_tnsnames_ora.ps1
# ------------------------------------------------------------------------------
# tnsnames.oraの保管場所を探すスクリプト
# ------------------------------------------------------------------------------

Write-Host 'tnsnames.oraの保管場所を探索します...'

try {
    # 1. tnspingコマンドの存在（＝Oracleクライアントの存在）を確認する。
    #    tnspingコマンドが無い場合はエラーとなるため、catch句に飛ばされる。
    #    ※「-ErrorAction "Stop"」を付けることで、終了しないエラー（Non-terminating Errors）をcatch句で補足できるようにしている。
    $tnsPing = Get-Command tnsping -ErrorAction "Stop"
}
catch
{
    Write-Host 'Oracleクライアントがインストールされているか確認してください。'
    exit
}

# 2. tnspingコマンドの実行結果から、sqlnet.oraのパスを取得する。
$pingResult = tnsping aaa
$pingResultArray = $pingResult.Split("`r`n")

$existsTnsnames = $false

foreach ($row in $pingResultArray)
{
    if ( $row -like '*sqlnet.ora')
    {
        # 3. sqlnet.oraの保管フォルダにtnsnames.oraがあるかを確認する。
        $tnsnamesPath = Join-Path (Split-Path -Parent $row) tnsnames.ora

        if (Test-Path $tnsnamesPath)
        {
            Write-Host 'tnsnames.oraは以下の場所にありました。'
            Write-Host $tnsnamesPath
            $existsTnsnames = $true
        }
    }
}

# 4. sqlnet.oraの保管フォルダにtnsnames.oraが見つからない時は、tnsnames.oraの探索を終了する。
if (!$existsTnsnames)
{
    Write-Host 'tnsnames.oraは見つかりませんでした。'
}

Read-Host "処理が完了しました..."
```

```dos:実行結果
tnsnames.oraの保管場所を探索します...
tnsnames.oraは以下の場所にありました。
C:\app\NKOJIMA\product\11.2.0\client_1\network\admin\tnsnames.ora
処理が完了しました...:
```

# 参考URL

* [Oracle Database Clientのインストール後の作業](https://docs.oracle.com/cd/E16338_01/install.112/b58879/post_install.htm)
* [tnsnames.oraの場所を探す](https://w.atwiki.jp/tak_is/pages/72.html)
Please tell me who you are.

# 事象 : Git Guiで[コミット]ボタン押したらエラー
- 環境
    - CentOS Linux release 7.9.2009 (Core)
    - git-2.31.1

原因は、下の事象と同じでユーザー情報を設定いないから
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/2b499455-73a2-d604-a7fa-df40c5f4e433.png)


## 対応 : Git Guiでユーザー情報を設定する
Gitコマンドでやってもいいけど、Git Guiの使い方を覚えるためにメニューからやってみる。
参考 : [Windows: Git GUIを使う準備 - すたらブログ](http://sutara79.hatenablog.com/entry/2015/07/06/113431)
初めてオプションダイアログを見たが、いろんな設定ができることを知った。

1. [編集] > [オプション・・・]でダイアログを表示
1. [大域(全てのリポジトリ)]にある[ユーザ名][電子メールアドレス]を設定する
    - リポジトリ毎にユーザー情報を変えたければ[xxxリポジトリ]のところ
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159761/37b21e6e-e753-fa83-3e4b-7803637f1169.png)
1. [保存]ボタンでダイアログを閉じる
1. 今一度[コミット]ボタンでコミットする


# 事象 : pullしたら怒られた
- 環境
    - macOS Big Sur バージョン11.1
    - git version 2.28.0

```zsh
% git pull origin master --allow-unrelated-histories
#...省略...
*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: empty ident name (for <>) not allowed
```

## 対応 : ユーザー情報を設定する
```zsh:リポジトリ用のユーザー情報を設定する場合
# ユーザー名を設定する
% git config user.name "{ユーザ名}"
# メールアドレスを設定する
% git config user.email "{メールアドレス}"
# configに追記された
% cat .git/config | grep -A 3 user
[user]
    name = {ユーザ名}
    email = {メールアドレス}
```

```zsh:グローバルのユーザー情報を設定する場合
# そういえばグローバルの.gitconfigはまだなかった
$ find ~ -type f | grep gitconfig
$

# メールアドレスを設定する
$ git config --global user.email "{メールアドレス}"
# ユーザー名を設定する
$ git config --global user.name "{ユーザ名}"

# グローバルの.gitconfigができる
$ find ~ -type f | grep gitconfig
/home/ponsuke/.gitconfig
```
DockerでPytorchの実行環境

# はじめに

Pytorchが使えるJupyter Notebook環境を構築します。

お手軽にPytorch使える環境が欲しいと思ったのと、Dockerfileやymlファイルの内容、オプションとかよく忘れちゃうので備忘のために記事にしました。

※ Dockerはインストールしておいて下さい。

# Dockerイメージをつくる

ベースイメージは [jupyter/datascience-notebook](https://hub.docker.com/r/jupyter/datascience-notebook/) を使います。

今回はこれに加えてpytorchをインストールします。
pipコマンドは [ここ](https://pytorch.org/get-started/locally/) で確認します。
下図のように選択しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536019/5cc83555-50bc-948d-be23-f0c23490929a.png)

続いて、Dockerfileからコンテナイメージ作成します。
Dockerfileはこんな感じ

```dockerfile
FROM jupyter/datascience-notebook

USER root

RUN pip install torch torchvision

USER jovyan
WORKDIR /home/jovyan
```

- イメージビルド（Docker build） 

```
docker build -t 好きなイメージ名 .
```

- コンテナ作成（Docker run）

```
docker run -p 80:8888 -v ./:/home/jovyan/work イメージ名
```

- pオプションでポートを指定します。
    - ホスト側は空いてるポートを指定する
    - -p 「コンテナ側」：「ホスト側」
- vオプションでホスト側のディレクトリをマウントします。
    - -v 「ホスト側」：「コンテナ側」
    - 「ホスト側」のディレクトリにソースコード置いてください。

docker runを実行したら、`http://localhost:8888` でjupyter notebookが表示されるようになります。

ただ、このままだと `Docker run`の度に色んなオプションを指定する必要がありめんどくさいので、`docker-compose`でパラメータもまとめて実行出来るようにする。

# docker-composeで実行

`docker-compose.yml`をこんな感じで作成して、

```yml
version: "3"
services:
  jupyterlab:
    build:
      context: .
    user: root
    ports:
      - "80:8888"
    volumes:
      - "./:/home/jovyan/work"
    environment:
      GRANT_SUDO: "yes"
    command: start-notebook.sh --NotebookApp.token=""
```

`docker-compose up --build`を実行でコンテナの作成・起動をします。

- `build` でDockerfileを使ってコンテナ作成できます。
    - 今回は`context: .`なのでカレントディレクトリにある`Dockerfile`を使ってます
- `ports` でポートを指定します。
    - 「コンテナ側」：「ホスト側」
- `volumes` でマウントするディレクトリを指定します
    - 「ホスト側」：「コンテナ側」
- `command` でコンテナ起動時のコマンドを指定します
    - jupyter notebookの起動に`start-notebook.sh`を使います
    - オプション`--NotebookApp.token=""`をつけるとアクセス時のTokenの確認がなくなります

これで、`http://localhost:8888`にアクセスするとjupyter notebookが使えるようになると思います。

後はpytorchで色んなモデルを実装していきましょう。

以上です。
【Laravel】Form Requestで　「~ dose not exist」のエラー

##背景
LaravelとVue.jsで自作WEBサービスのレビュー機能を作成。

フォームに入力したレビュー情報をFormRequestでバリデーションしようとしたところ、
`Class App\\Http\\Requests\\ReviewPost does not exist`のエラー


####FormRequest

```php:ReviewPost.php
namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class ReviewPost extends FormRequest
{
    /**
     * Determine if the user is authorized to make this request.
     *
     * @return bool
     */
    public function authorize()
    {
        return true;
    }

    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'rate' => ['required', 'integer', 'between:1,5'];
            'summary' => ['required', 'string', 'max:100'];
            'detail' => ['required', 'string', 'max:500'];
        ];
    }
}
```

####コントローラー

```php:ReviewController.php
namespace App\Http\Controllers\Ajax;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Requests\ReviewPost;

class ReviewController extends Controller
{
    public function postReview(ReviewPost $request)
    {
        
    }
}
```

##原因
シンタックスエラーが原因

`ReviewPost`が存在しないとのことで、コントローラーに`use App\Http\Requests\ReviewPost;`とちゃんと書いたんだけどな〜？？と思いながらコードを見直していると、FormRequest（ReviewPost.php)の`rule()`内で「`,`」とするべきところを「`;`」としているミスを発見。
直したところ、エラーは解消した。

文法ミスでも`class dose not exist`となってしまうようなので注意。
【Java ~配列~】勉強メモ4

Java学習中。
復習に見返せるようにメモしていきます。
ほぼ自分の勉強メモです。
過度な期待はしないでください。


配列
-
配列とは、変数のセットのようなもの。
変数が1つしか値を扱えないのに対し、配列は<b>複数の値をまとめていれておくこと</b>が出来る。
配列に入っているそれぞれの値のことを<b>要素</b>と呼ぶ。
<br>

- 配列の変数定義

配列を扱う場合には、配列型の変数に配列を代入します。
配列型は、「int型の要素を持つ配列型」と「String型の要素を持つ配列型」という風に指定する必要がある。
int型の要素を持つ配列は<font color="Red">int[]</font>、
String型の要素を持つ配列は<font color="Red">String[]</font>と記述する。
<br>

- 配列の作り方

配列は{　}の中に、コンマ（,）で区切りながら値を書くことでつくることが出来る。
[]と{}を混同しないように注意。
配列の最後にもセミコロン(;)が必要なので注意

```.java:配列の作り方
// int型の要素を持つ配列
int[] numbers = {"3", "6", "9"};

// String型の要素を持つ配列
String[] names = {"Aki", "John", "Bob"};
```
<br>

- インデックス番号

配列の要素は、前から順に「0, 1, 2・・・」と数字が割り振られています。
これをインデックス番号といい、インデックス番号は0から始まる点に注意。
<br>

- 要素の取得

配列の各要素は、配列名[インデックス番号]とすることで取得することが出来る。

```.java:配列の作り方
String[] names = {"Aki", "John", "Bob"};

// インデックス番号が2の要素を出力
System.out.println(names[2]);
```

```.text:出力結果
Bob
```
<br>

- 配列の要素を上書き

特定の要素に値を代入することで、要素を上書きすることが可能。

```.java:配列の作り方
String[] names = {"Aki", "John", "Bob"};

System.out.println(names[1]); //①
// 配列の要素を上書き
names[1] = "Taro";
System.out.println(names[1]); //②
```

```.text:出力結果
① John

② Taro
```
<br>

配列と繰り返し
-

- 配列とfor文

配列の要素を全て出力する為に、for文を使えば簡単に一覧表示出来る。

```.java:配列の作り方
String[] names = {"Aki", "John", "Bob"};

for(int i=0; i<0; i+=1){
  System.out.println("私の名前は、" + names[i] + "です。"); // iが「０,１,２」の間だけ繰り返される
}
```

```.text:出力結果
私の名前は、Akiです。
私の名前は、Johnです。
私の名前は、Bobです。
```
<br>

- length

配列には、要素の数を数えるlengthという機能が備わっている。
lengthは、`「配列.length」`のようにドット（.）でつないで用います。
lengthを用いれば、先ほどのfor文の条件式「i < 3」を書き換えることができ、
配列の要素数を気にする必要がなくなる。

```.java:配列の作り方
String[] names = {"Aki", "John", "Bob"};

for(int i=0; i<names.length; i+=1){
  System.out.println("私の名前は、" + names[i] + "です。");
}
```
<br>

- 配列用のfor文

for文は配列用に特別な構文（拡張for文）がある。
これを使えば、先ほどのfor文をよりシンプルに書くことが出来ます。

```.java:書き方
for(データの型 変数名:配列名){
  //繰り返し処理内容;
}
```


```.java:配列の作り方
String[] names = {"Aki", "John", "Bob"};

for(String name: names){
  System.out.println("私の名前は、" + name + "です。");
}
```

```.text:出力結果
私の名前は、Akiです。
私の名前は、Johnです。
私の名前は、Bobです。
```
<br>




<br>
過去投稿記事
-
[【Java~変数の定義、型変換について~】勉強メモ](https://qiita.com/k-yasuhiro/items/43ef789c8be7b669046a)
[【Java ~真偽値~】勉強メモ2](https://qiita.com/k-yasuhiro/items/5a75e6130552abd03934)
[【Java ~条件分岐・繰り返し処理~】勉強メモ3](https://qiita.com/k-yasuhiro/items/cc7ceb00bc795d1ea33c)
自作キーボード8 ケース自作

前回Elecrowから2重に支払いがされてしまった関係でメールをやり取りし、昨日言いたいことがなんとか伝わったようで
一応返金するとの回答があった。返金を待つ

右側の基板はんだ付けはスイッチ数が多くて飽きてきて今、完全に途中。
![IMG_20201229_222855.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/fcf3da4f-534b-e46c-d91e-62ef9e18b302.jpeg)


# というわけでケースづくりを頑張る
YoutubeでCADソフトの使い方を学び、なんとかできた。

## 左側ケース全体像
![hidari.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/1412b458-1273-8cf6-7c88-dd0b09c9d1e8.png)

## 右側ケース全体像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/d2b7bbd4-a7a5-09b2-18b3-34976d0a4448.png)

出来上がった3Dプリントデータをアップしておく。
https://github.com/kirin123kirin/keyboard/tree/main/case

## ケース自作でいくらかかるのかが気になる
3Dプリンタを持っていないしノウハウもないし、印刷に失敗しそうなので
3Dプリントサービスを使ってプロに頼むことにする。

## DMM.make 3Dプリントサービス
オンラインで見積ができ送料が無料のDMM.makeが検索で引っかかった。
見積もってみたところ左右のケースを一番安い素材でも合計すると
**¥44,993**もする！？

|STLデータ|素材|金額|
|:---|:---|---:|
|左ケース底面|	PA12　ナチュラル（MJF）|¥10,959|
|左ケース上面|	PA12　ナチュラル（MJF）|¥3,069|
|左トッププレート|PA12　ナチュラル（MJF）|¥3,654|
|右ケース底面|	PA12　ナチュラル（MJF）|¥17,085|
|右ケース上面|	PA12　ナチュラル（MJF）|¥4,385|
|右トッププレート|PA12　ナチュラル（MJF）|¥5,841|
||合計|¥44,993|


おいおい3Dプリンターが買えるじゃないか、、
[ANYCUBIC MEGA X 3D](https://amzn.to/3hCHDPj)
が欲しいんですけど、、

品質良いのだろうけど、試作品にとてもじゃないがこんな金額出せない。

## 相見積もり
みんな大好きElecrowのサイトをよく見ると3D Printing Serviceという文字があるので早速見積を依頼してみた。

早速メールが帰ってきて、
細かい内訳はないがElecrowの回答は

|STLデータ|素材|金額|
|:---|:---|---:|
|PLA|全部合わせて|$96|
||送料|$17|
||合計|$113|

や、安い！、いや財布には痛い金額だが、
国内サービスの料金に比べると、5分の1 ~ 3分の1　ぐらいの圧倒的破格。

英語でやり取りするのがつらいが、比較すると金額が魅力的すぎる。。
3Dプリンタを買っても良いが、年明けはそれほど時間を費やす暇がない。。

もう少し、設計を見直したりしてメールをやり取りしておそらくElecrowに発注するか、、、


<br><br>
<td><font size="6">
※Amazon商品へのリンクは「Amazon.co.jpアソシエイト」を使用しています。
「Amazon.co.jpアソシエイト」とは、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。
</font>
</td>
Mockarooの使い方

ポートフォリオを作成していて、データベースに挿入するレコードの作成が面倒だと思ったので調べたところ、自動でinsert文を作成するツールを見つけたので備忘録として残しておきます。


残念ながら日本語版はありませんが使い方はそんなに難しくないのでぱっと見てわかると思います
[Mockaroo](https://www.mockaroo.com/)

![スクリーンショット 2020-12-29 22.19.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637360/4d4384cb-65af-12d0-ebd9-9eac5e4a91ae.png)

画面はいたってシンプルで、こんな感じです。

ここでは簡単に使い方を例を挙げながら説明していきます。

1. こんな感のuserテーブルがあり、このテーブルに100レコード挿入したいたします![スクリーンショット 2020-12-29 22.21.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637360/1b243e36-f460-3af8-140e-6c67ef1394a4.png)

2. テーブル名を画面の下の方にある、「Table Name」に入力
3. カラム名を「Field Name」に入力
4. カラムのデータ型にあった挿入データを「Type」から選択。IDなどの連番の主キーであれば、「Row Number」、ユーザ名であれば、「User Name」などテーブルのデータに必要な最も基本的なところはありますが、細かいところまではカバーしていません
5. 「Options」でnullの発生率の調整などが可能
6. 画面下の「Rows」で必要なレコード数である「１００」を入力(Max1000)
7. [Download]ボタンをしたら、sqlファイルがDLできるので、それをテキストエディタで開いて編集し、SQL実行

これで大量のテストデータもぱっと作成できますね