OmniAICreator/Qiita-1.07M huggingface dataset:
【Ruby】簡単なAPIを叩いてみる（郵便番号検索API）

# 環境
macOS: Big Sur Ver11.2.2
Ruby: 2.6.5

# 記事の背景
「Webアプリの開発で外部APIを使わないことはほぼない！」ということを聞いて慌ててAPIについて勉強し始めました。第一歩として、郵便番号を検索する簡単なAPIでプログラムを実装。
調べていくと「Faraday」というGemがリクエストとレスポンスを比較的シンプルに書けるらしく、このGemを使った方法でも実装してみました。
どちらもRubyのファイルを単独で生成して、そこに記述してターミナル上で実行しています。

# 実装①
#### Rubyの外部ライブラリをrequireして最も基本的な形で実装
上記のGemを使わず、基本に則ったやり方で実装。

```ruby:potal_code.rb
# このプログラムで使うメソッドが組み込みライブラリではないので必要なライブラリを読み込む必要がある
# この2つは基本となるのでrequireする
require 'uri'
require 'net/http'
# レスポンスがJson形式で返ってくるので、それをRubyのオブジェクトに変換するのに必要な外部ライブラリ
require "json"

def get_address(zip_code)
  # 引数を使って postal_code=1111111 のような形をつくる
  query = URI.encode_www_form(zipcode: zip_code)
  # リクエストを送るURIを生成
  uri = URI.parse("https://zipcloud.ibsnet.co.jp/api/search?#{query}")
  # 上記のURIに実際にリクエストを送り、返ってくるレスポンスをresponseに格納
  response = Net::HTTP.get_response(uri)
  # 返ってきたresponseのbody部分をJSONからRubyのハッシュに変換
  result = JSON.parse(response.body)
  # 上記までで返ってきたレスポンスがブラウザに表示されているのと同じ状態になっている。あとは返ってきた情報を使うだけ。
  postal_code = result["results"][0]["zipcode"]
  prefecture = result["results"][0]["address1"]
  city = result["results"][0]["address2"]
  region = result["results"][0]["address3"]

  puts "郵便番号は#{postal_code}、住所は#{prefecture}#{city}#{region}です"
end

# 上で作成したメソッドを実行
get_address(ハイフン無しの郵便番号を半角で入力)
```

#### 解説
流れとしては、
①リクエストと送るURLを定義し、URL末尾に渡すクエリパラメーターも定義する。
　クエリパラメータの生成には、*URI.encode_www_formメソッド*を使う。
　このメソッドは外部ライブラリを読み込んでいるから使えるようになっている！

②リクエストを送り、レスポンスを得る。
　①で定義したURLに*Net::HTTP.get_response*メソッドでリクエストを送る（これも外部ライブラリのおかげ）。
　返ってくるレスポンスを変数responseに格納。

③返ってきたレスポンスはJson形式なので、*JSON.parseメソッド*でRubyのオブジェクトに変換が必要

④最後にハッシュ形式になっているデータから使いたいデータを取り出し、利用します。

**返ってくるデータは以下を参照**
[郵便番号検索API](http://zipcloud.ibsnet.co.jp/doc/api)

# 実装②
#### Gem「Faraday」を使ってもう少し簡単に実装

基本的な流れは一緒ですが、こちらのやり方は少し記述量が減ります！
まず準備として[公式ドキュメント](https://lostisland.github.io/faraday/)に掲載されている通り、ターミナルでGemをインストールします。

```terminal
 % gem install faraday
 % gem install faraday_middleware
```

あとはドキュメントを見ながら実装してみました。

```ruby
# ターミナルで「gem install faraday」コマンドを打ってから
require 'faraday'
# ターミナルで「gem install faraday_middleware」コマンドを打ってから
require 'faraday_middleware'
# 外部ライブラリをrequire
require "json"

def get_address(zip_code)
  url = 'https://zipcloud.ibsnet.co.jp/api/search'
  response = Faraday.get(url, {zipcode: zip_code}, {'Accept' => 'application/json'})
  # 返ってくるJson形式のレスポンスをRubyのオブジェクトに変換
  result = JSON.parse(response.body)

  postal_code = result["results"][0]["zipcode"]
  prefecture = result["results"][0]["address1"]
  city = result["results"][0]["address2"]
  region = result["results"][0]["address3"]

  puts "郵便番号は#{postal_code}、住所は#{prefecture}#{city}#{region}です"
end

get_address(ハイフン無しの郵便番号を半角で入力)
```

違うのは前半のリクエストURLを生成してレスポンスを送るまでのところですね。
ちなみにJSON.parseとしてRubyハッシュに変換するのは必須みたい。これやらないとデータを受け取れませんでした。

# 最後に
今回使用したFaradayはRubyのGemの[公式サイト](https://rubygems.org/)ではかなりダウンロード数も多く、実務でも使われているのではという印象。
次はYouTubeあたりのAPIを叩きたい...

以上。
Ruby on Rails のルーティングエラー

##1.はじめに
今回は私が体験したエラーについての原因や解説を書いています
参考になるかどうか話わかりませんがよろしくお願いします。

##2.エラー内容
```php:
Routing Error

No route matches [POST] "/tweets/search"
```


今回はツイートアプリにて投稿したツイートを検索しようとして起こったエラーです。

##3.エラー解説
まず一行目の**Routing Error**ですがこれが出たらルーティングが正しく設定できているかどうか
**rails routes**を使い確認します![スクリーンショット 2021-03-29 19.04.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208326/ca7a1777-1fa7-345a-b2ff-e100af0d4ee6.png)

この中から**"/tweets/search/"**のパスを探してみると
sarch_tweetsの隣のHTTPメソッドが**GET**になっています。しかし今回は検索結果を表記したいのでHTTPメソッドはGETで正しいです

このことから今回のエラーは**間違ったHTTPメソッドを定義しているのではないか**、**間違ったリクエストを送信してしまっているのではないか**という仮説が立てれます。


##4.エラー解決

それでは実際にコードを見てみましょう。
リクエストが送られるときは検索ボタンを押したときなのでtweetsフォルダのindex.html.erbに着目したいと思います。

```php:views/tweets/index.html.erb
<%= form_with(url: search_tweets_path, local: true, method: :post, class: "search-form") do |form| %>
```
HTTPメソッドを定義しているところをみてもらうと**method: :post**となっています。
先ほども確認した通り、今回は検索結果を表記したいので指定するHTTPメソッドはGETのはずです

つまり今回は**間違ったリクエストを送ってしまっていた**ということになります。

```php:views/tweets/index.html.erb
<%= form_with(url: search_tweets_path, local: true, method: :get, class: "search-form") do |form| %>
```
このように今回のエラーはHTTPメソッドをgetにすることで解消できます。
プログラミング超入門(８)〜GO言語〜

#switch文
switch文は、変数の値を「case」で始まる文で評価して条件が満たされれば特定の処理を行います。一度でも条件が満たされれば再び評価はしません。条件が満たされなかった場合は何もせずに終わります。複数の「case文」を用いて場合分けをし、値を示させます。switch文の後に変数名を記述し、どの変数の値について「スイッチ」させるか決めます。

```switch.go
package main

import "fmt"

func main() {

	pushs := []string{"S", "N", "R", "C", "E"}

	for i := 0; i < len(pushs); i++ {
		switch pushs[i] {
		case "R":
			fmt.Printf("[%s] 実行します。 \n", pushs[i])
		case "S":
			fmt.Printf("[%s] ファイルを保存します。 \n", pushs[i])
		case "N":
			fmt.Printf("[%s] 次に進みます。 \n", pushs[i])
		case "E":
			fmt.Printf("[%s] 終了します \n", pushs[i])
		default:
			fmt.Printf("[%s] 最初からやり直して下さい。 \n", pushs[i])

		}
	}
}
```
###実行結果
```
[S] ファイルを保存します。 
[N] 次に進みます。 
[R] 実行します。 
[C] 最初からやり直して下さい。 
[E] 終了します
```
case文は値を示すだけです。switch文は全体を{　}で囲みますが、case文は囲む必要ありません。case文はいくらでも書くことができますが、default文を持って終了します。
##式の値で場合分け
case文で数値の大小関係を評価してみましょう。スライスを用いて病院内で感染してしまった患者さんを年齢別に集計するプログラムを作成してみます。

```cluster.go
package main

import "fmt"

func main() {

	age := []int{19, 21, 23, 48, 36, 26, 33, 39, 67, 31, 55}
	clus := [4]int{}
	patient := true

	for i := 0; i < len(age); i++ {
		switch patient {
		case age[i] > 59:
			clus[3]++
		case age[i] > 49:
			clus[2]++
		case age[i] > 29:
			clus[1]++
		default:
			clus[0]++
		}
	}

	fmt.Printf("院内感染者%d名のうち : \n", len(age))
	fmt.Printf("60代以上は%d名\n", clus[3])
	fmt.Printf("50-60代は%d名\n", clus[2])
	fmt.Printf("30-40代以は%d名\n", clus[1])
	fmt.Printf("30代以下は%d名\n", clus[0])
}
```
###実行結果
```
院内感染者11名のうち : 
60代以上は1名
50-60代は1名
30-40代以は5名
30代以下は4名
```
switch文で評価する変数patientにブール型である固定値trueが代入してあります。clusが見ている配列から要素を取り出してswitch文を評価する度、case文の内容が変わります。GO言語のswitch文は、前に書いてある条件に合致して処理されたら、次の条件に合致しても無視されるので、式の値がtrueかfalseかで場合分けする場合はpatientのような変数を以下のように省略して書きます。

```
switch {
    case age[i] > 59:
    case age[i] > 49:
    case age[i] > 29:
    default:
}
```
配列clusを作成して、値が整数0である要素を4つ自動で作成しています。この配列からは、要素clus[0],clus[1],clus[2],clus[3]の値を操作できます。それぞれの要素を「６０歳以上の人数」「５０歳以上の人数」「３０歳以上の人数」「それ以外の年代の人数」として、for文の中のswitch文が書かれています。
#for文とswitch文を組合せコードを綺麗に
caseの条件に当てはまらなければ何もせず次の繰り返しに進むことができるのでそれを利用し、コードをすっきりまとめ上げます。

```forswitch.go
package main

import "fmt"

func main() {
	then := 6789

	fmt.Println(then)
	for n := 0; n < then; n++ {
		switch {
		case n == 0:
		case n == 1:
		case then%n == 0:
			then /= n
			fmt.Printf("を%dで割ると、 %d\n", n, then)
		default:
		}
	}
}
```
###実行結果
```
6789
を3で割ると、 2263
を31で割ると、 73
```
nが0と1のときは何もせず、ただnを増やすだけなので、0で除算するリスクを避け条件の書き方を簡単にします。

[←前回の記事](https://qiita.com/ume-bar/items/25b8b85529d2c3a27969)　[次の記事へ→](https://qiita.com/ume-bar/items/eaba7bc53f39e8d7deba)
ECSにデプロイしたコンテナが一定時間ごとに落ちる？

# 背景

ECSにデプロイしたAPIサーバの役割を果たすタスクが一定時間ごとに落ちて毎回ECS agentによって立ち上げられるという事象を観測した。大元の原因を特定するのに手間取ったため、メモとして残しておく。

# 状況整理

ECSはALBのターゲットとして登録してしていたので、ALBによるヘルスチェックが行われている。また、ECSのタスク定義でコンテナヘルスチェックも行なっている。

このような場合、以下のような現象が観測される。

- ALBのヘルスチェックが失敗している
- ECSのコンテナヘルスチェックが失敗している
- サーバプロセスがexitしている

これらの現象は相互に影響を与え合う。例えば、サーバプロセスがexitするとECSのコンテナヘルスチェックやALBのヘルスチェックが失敗する。また、ネットワークの設定ミスがあった場合、サーバプロセスは動いているのにALBによるヘルスチェックが失敗して、ALBがECS agentにコンテナを落とすことを命令し、サーバプロセスがSIGTERMを受け取ってexitするかもしれない。さらに、ECSのコンテナヘルスチェックの設定ミスで、サーバプロセスは動いているのにコンテナヘルスチェックが失敗して、サーバプロセスにSIGTERMが送られるかもしれない。
すなわち、大元の原因を突き止めるにはちょっとした工夫が必要である。

# 絞り込み1

まず重要なヒントは、コンテナが起動されて落ちるまでの時間が毎回一定かどうか、ということである。

一定でなければ、サーバプロセスが自らexitしている可能性が高い。その場合は、コンテナからCloudWatch logsなどにログを送信してエラーがおきていないかを確認する必要がある。これは比較的わかりやすい。
コンテナが起動されて落ちるまでの時間が毎回一定である場合は、さらに絞り込みを行う。

# 絞り込み2

コンテナが起動されて落ちるまでの時間が毎回一定であれば、(サーバプロセスは正常であるが)ネットワークやヘルスチェックの設定にミスがある可能性が大きい。

最初にやるべきことは、サーバプログラムへのリクエストのログをCloudWatch logsなどに送信してログを見れる状態にすることである。このリクエストログにはUser-Agentが含まれていなければならない。

User-Agentを含むリクエストログが見れる状態にできたら、タスクを再実行してみる。
ECSに設定したヘルスチェックコマンドがcurlを使ったものであれば、User-Agentの部分がcurlであるログが存在するはずである。
同じようにALBによるヘルスチェックが正しく行われていれば、リクエストログのUser-Agentが"ELB-HealthChecker"となっているログが存在するはずである。両方のヘルスチェックが設定されていた場合は、それぞれに対して以下の検証を行う。

もし、設定したヘルスチェックコマンドに対応するUser-Agent値がログに含まれていれば、ネットワークの設定は正しいがヘルスチェックの設定ミスが原因でサーバプロセスにSIGTERMが送られている可能性が高い。この場合、ヘルスチェックコマンドの設定は正しいことが保証されている。ヘルスチェックの設定にはコマンド以外にも、タイムアウトやインターバルやリトライ回数といったパラメータがある。ここでは、それらのパラメータ設定が間違っていることを疑う。ここで大事なのは、各ヘルスチェックの設定において、最短でUnhealthyになるまでの時間を求めることである。例えば、ECSのコンテナヘルスチェックでタイムアウトが20s、インターバルが100s, リトライが3回、スタートピリオドが30sという設定がなされていたとき、最短でUnhealthyになるのはインターバル100sのヘルスチェックが3回連続失敗する場合なので、(100 * (3 - 1)) + 20 + 30で250sである。もし、ECSのコンテナヘルスチェクとALBのヘルスチェックの設定が異っていれば、コンテナが起動して落ちるまでの時間と比較することで、どちらのヘルスチェックの設定を直すべきかがわかる。ここまでわかれば解決は容易いだろう。

一方、設定したヘルスチェックコマンドに対応するUser-Agent値がログに含まれていなければ、さらに絞り込みを行う。

# 絞り込み3

ヘルスチェックがなされた痕跡がリクエストログに残っていない場合、2つの可能性がある。

1. ネットワークの設定ミスで、ヘルスチェックのリクエストがコンテナまで到達していない
1. ネットワークの設定は正しいが、ヘルスチェックコマンドの設定が間違っている。

2の場合は、大抵の場合、以下のいずれかに該当するであろう。

1. リクエストが送られるパスに対する応答が200以外のコードを返す。
1. リクエストが送られるポート番号が間違っている。
1. ECSのヘルスチェックコマンドでcurlを使っているが、curlがコンテナにインストールされていない。(alpineにはcurlが含まれていない。)
1. ECSのヘルスチェックコマンドの設定形式が間違っている。

4のケースはデバックがしづらいが[AWS::ECS::TaskDefinition HealthCheck](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-ecs-taskdefinition-healthcheck.html)や[Docker公式ドキュメント CreateContainer](https://docs.docker.com/engine/api/v1.35/#operation/ContainerCreate)を慎重に読み込むことでミスを見つけることは可能である。

これらに当てはまらない場合は、1.ネットワークの設定ミス、を疑う。ネットワークの設定ミスには、SubnetのNetworkACL設定や、ECS ServiceのSecurity group設定、タスク定義のport mapping設定など、様々な設定値が関係してくるので、一つ一つの設定を慎重に疑う必要がある。また、ネットワーク設定のデバッグは、踏み台サーバからリクエストを送ってみるなどの手段が有効である。

# まとめ

上記の流れで大抵のケースは捕捉できると思う。
Refresh Gladle projectで、JREバージョンがリセットされた問題の解決

#現象
Gladle + Eclipseの環境で、
WorkspaceのJREバージョン、プロジェクトのJRE Versionを変更した場合、
Refresh Gladle Projectを実行することで、
変更前のJRE versionに戻ってしまった。

#設定（失敗したところ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189220/8b153092-c7d8-07fb-efef-27053adbc0d4.png)
Refresh Gradle Projectを実行することで、前の設定に戻ってしまった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189220/b0f89e77-7ce9-780e-f860-49b64b4573ac.png)

#解決案
Gladle の workspace settingのJavahomeを手動で設定します。
Refresh Gladle Projectが正しく実行できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189220/a08e7377-1559-3aaa-d4d5-3ef5b29ba719.png)


#結論（原因不明）

手動でGladleの目標環境を設定することで解決できましたが、
根本的な原因はまだわかりませんでした。

#その他情報
ここでいろいろ状態の確認ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1189220/f74ac787-fdbf-7c66-bcdb-5ffac8080aea.png)
【メモ】gitでプロキシ設定をする

* 製造業出身のデータサイエンティストがお送りする記事
* 今回はメモとして、Gitでプロキシ設定する方法を整理しておきます。

##Gitのプロキシ設定方法
下記コマンドで簡単に設定できます。

```php
git config --global http.proxy http://proxy.hogehoge.com:8080
git config --global https.proxy http://proxy.hogehoge.com:8080
```

下記コマンドでプロキシが設定できたか確認できます。

```php
git cohnfig --global --list | grep proxy
```
cron による Minecraft サーバのプロセス自動再起動設定


# 概要
- systemd サービスユニットファイルを作成して、Minecraft サーバをサービス化
- cron で定期的に systemctl コマンドを発行するシェルスクリプトを実行し、サービスの状態をチェック
- サービスがダウンしていた場合、再起動

# Minecraft サーバの設定方法
[Linux(CentOS7)で、Minecraftマルチサーバを立ち上げる手順](https://qiita.com/t-morisoba/items/51d2463d41055768eabe)

# 環境
- CentOS 7

# シェルスクリプト作成
作業ディレクトリに移動し、シェルスクリプトを編集する。

```
# cd /var/minecraft
# vi auto_restart.sh
```

シェルスクリプトの内容は以下の通り。

```shell:auto_restart.sh
#!/bin/bash

systemctl is-active minecraft_server.service >/dev/null 2>&1

if [ $? != 0 ]; then
    systemctl start minecraft_server.service
fi

exit
```

`systemctl is-active` は、サービス実行中は 0 を、そうでない場合は 0 以外の値を返す。詳しくは `man systemctl` で参照できる。

# cron 設定
以下のコマンドを実行する。

```
# echo "*/10 * * * * root /var/minecraft/auto_restart.sh" > /etc/cron.d/minecraft_auto_restart
```
上記は、毎時 0 分, 10 分, 20 分, 30 分, 40 分, 50 分に　auto_restart.sh に実行する設定なので、必要に応じて実行間隔を調整する。
LightSail(LAMP/Bitnami)でImagickを利用したときにハマった

EC-CUBE4 を利用する中で、カスタマイズした際にImagickを利用した処理を追加。

環境は、LightSailのLAMP環境(Bitnami)。

これをステージング環境にデプロイした際、以下のエラーが発生。

```
no decode delegate for this image format `JPEG'
```

Imagick は、以下で有効済み。


https://docs.bitnami.com/aws/infrastructure/lamp/configuration/install-modules-php/#imagick

で、コマンドで ImageMagick を確認。

```
$ php -i | grep ImageMagick
Imagick compiled with ImageMagick version => ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org
Imagick using ImageMagick library version => ImageMagick 6.9.10-23 Q16 x86_64 20190101 https://imagemagick.org
ImageMagick copyright => © 1999-2019 ImageMagick Studio LLC
ImageMagick release date => 20190101
ImageMagick number of supported formats:  => 242
ImageMagick supported formats => 3FR, 3G2, 3GP, AAI, AI, ART, ARW, AVI, AVS, BGR, BGRA, BGRO, BIE, BMP, BMP2, BMP3, BRF, CAL, CALS, CANVAS, CAPTION, CIN, CIP, CLIP, CMYK, CMYKA, CR2, CRW, CUR, CUT, DATA, DCM, DCR, DCX, DDS, DFONT, DJVU, DNG, DOT, DPX, DXT1, DXT5, EPDF, EPI, EPS, EPS2, EPS3, EPSF, EPSI, EPT, EPT2, EPT3, ERF, EXR, FAX, FILE, FITS, FRACTAL, FTP, FTS, G3, G4, GIF, GIF87, GRADIENT, GRAY, GRAYA, GROUP4, GV, H, HALD, HDR, HEIC, HISTOGRAM, HRZ, HTM, HTML, HTTP, HTTPS, ICB, ICO, ICON, IIQ, INFO, INLINE, IPL, ISOBRL, ISOBRL6, J2C, J2K, JBG, JBIG, JNG, JNX, JP2, JPC, JPE, JPEG, JPG, JPM, JPS, JPT, JSON, K25, KDC, LABEL, M2V, M4V, MAC, MAGICK, MAP, MASK, MAT, MATTE, MEF, MIFF, MKV, MNG, MONO, MOV, MP4, MPC, MPEG, MPG, MRW, MSL, MSVG, MTV, MVG, NEF, NRW, NULL, ORF, OTB, OTF, PAL, PALM, PAM, PANGO, PATTERN, PBM, PCD, PCDS, PCL, PCT, PCX, PDB, PDF, PDFA, PEF, PES, PFA, PFB, PFM, PGM, PGX, PICON, PICT, PIX, PJPEG, PLASMA, PNG, PNG00, PNG24, PNG32, PNG48, PNG64, PNG8, PNM, PPM, PREVIEW, PS, PS2, PS3, PSB, PSD, PTIF, PWP, RADIAL-GRADIENT, RAF, RAS, RAW, RGB, RGBA, RGBO, RGF, RLA, RLE, RMF, RW2, SCR, SCT, SFW, SGI, SHTML, SIX, SIXEL, SPARSE-COLOR, SR2, SRF, STEGANO, SUN, SVG, SVGZ, TEXT, TGA, THUMBNAIL, TIFF, TIFF64, TILE, TIM, TTC, TTF, TXT, UBRL, UBRL6, UIL, UYVY, VDA, VICAR, VID, VIFF, VIPS, VST, WBMP, WEBP, WMF, WMV, WMZ, WPG, X, X3F, XBM, XC, XCF, XPM, XPS, XV, XWD, YCbCr, YCbCrA, YUV
```

特に問題なさそう。

で、管理画面側で改めて `phpinfo()` を確認すると `ImageMagick number of supported formats: 0 ` に。
`ImageMagick supported formats` も `no value` 。

![phpinfo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28494/c96f6b8c-68da-465a-8aff-f860fcab6d16.png)

コマンドと、php-fpm が実行している php のバージョンとかが違うのかなぁと思ったけど、そうでもない。

で、数時間悩んだ挙げ句、他の人にチェックしてもらったら、以下が設定されていないよーという指摘。

```
$_SERVER['MAGICK_HOME']
$_SERVER['MAGICK_CODER_MODULE_PATH']
$_SERVER['MAGICK_CONFIGURE_PATH']
```

はい、これが原因でした。

これに対応するために、以下に変更。

```/opt/bitnami/php/etc/environment.conf

env[MAGICK_HOME] = /usr/lib/x86_64-linux-gnu/ImageMagick-6.9.10/
env[MAGICK_CONFIGURE_PATH] = /etc/ImageMagick/
env[MAGICK_CODER_MODULE_PATH] = /usr/lib/x86_64-linux-gnu/ImageMagick-6.9.10/modules-Q16/coders

```


で `ImageMagick supported formats` も正常になりました。
めでたし、めでたし。
職場でのメンタルトラブルの対応

プログラムとは直接関係のない記事なのでこちらに移動しました。

[職場でのメンタルトラブル対応の備忘録](https://plussum.hatenablog.com/entry/2021/06/06/171900?_ga=2.200609069.2086076410.1622962263-1594190019.1614326990)
【Swift】SlideshowAppで学んだこと

#はじめに
SlideshowAppを作成しましたので、そこで学んだことの備忘録です。

#GitHub
https://github.com/0429oonishi/SlideshowApp

#学んだこと
グラデーションの扱いです。

```Swift
let width = self.view.frame.size.width
let height = self.view.frame.size.height
let gradientLayer = CAGradientLayer()
gradientLayer.frame = CGRect(x: 0, y: 0, width: width, height: height)
gradientLayer.colors = [UIColor(red: 0.8, green: 0.0, blue: 0.73, alpha: 1).cgColor,
                        UIColor(red: 0.1, green: 0.0, blue: 0.40, alpha: 1).cgColor]
gradientLayer.startPoint = CGPoint.init(x: 0, y: 0.5)
gradientLayer.endPoint = CGPoint.init(x: 1, y: 0.5)
self.view.layer.insertSublayer(gradientLayer, at: 0)
```
このようにすることで、背景色がグラデーションでいい感じになってくれます。
公式ドキュメント: [CAGradientLayer](https://developer.apple.com/documentation/quartzcore/cagradientlayer)
スニペットなどに登録しておくことをお勧めします！

#おわりに　
おわりです。
DockerイメージのMySQL5.6と5.7はタイムゾーン設定が異なる


MySQL5.6から5.7に移行するにあたって、開発環境を整理していたらDockerイメージのデフォルトのタイムゾーンが変わっていることに気付いた。

## MySQL 5.6のタイムゾーン設定

5.6のデフォルトのタイムゾーンは以下の通り設定されていた。


```
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | UTC    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)
```

そのため、Dockerfileで以下のコマンドを実行して、タイムゾーンを変更していた。

```
RUN cp -p /usr/share/zoneinfo/Japan /etc/localtime
```

## MySQL 5.7のタイムゾーン設定

5.7のデフォルトのタイムゾーンは以下の通りだった。


```
mysql> show variables like '%time_zone%';
+------------------+--------+
| Variable_name    | Value  |
+------------------+--------+
| system_time_zone | JST    |
| time_zone        | SYSTEM |
+------------------+--------+
2 rows in set (0.00 sec)

```

system_time_zoneがロケールの時間帯を採用するように変更されたらしい。
これによって最初から日本時間で処理されるようになった。
Nuxt.js の SSG で環境ごとにパスを変える

例えば社内確認用サーバと本番サーバで API の向き先が違う場合、
どちらも Nuxt.js の SSG でファイルを書き出すとしたら
環境変数はどうやって切り替えるんだっけ？と少し手が止まってしまったので
その忘備録です。

Nuxt.js のバージョンは 2.15.3 です。

## 構成
env ファイルと nuxt.config.js の構成は下記です。

```
/
 ├ env
 │ ├ .env.local
 │ ├ .env.development
 │ └ .env.production
 │
 └ nuxt.config.js
```

```.env.local
ENV="local"
URL="http://localhost:3000/"
```

```.env.development
ENV="development"
URL="https://dev.dummy.com"
```

```.env.production
ENV="production"
URL="https://dummy.com"
```

## 結論

```$ nuxt generate ``` では process.env.NODE_ENV が **production** に固定されます。
しかし、nuxt.js に内蔵されている dotenv の向き先だけを
環境ごとに変えれば、静的ビルド時の環境変数を変えることができます。

 ```--dotenv ``` というオプションがあり、これを使います。


```package.json
  "scripts": {
    "dev": "nuxt",
    "build": "nuxt build",
    "start": "nuxt start",
    "generate": "nuxt generate --dotenv ./env/.env.production",
    "generate:local": "nuxt generate --dotenv ./env/.env.local",
    "generate:development": "nuxt generate --dotenv ./env/.env.development"
  },
```

nuxt.config.js の env を追加。

```nuxt.config.js
const { ENV, URL } = process.env;

export default {
  env :{
    ENV,
    URL,
  },
}
```
CentOSにインストールしたmunin-updateが自動起動されないときの対処方法

対象OS: CentOS 7.x以降

munin-updateは、パッケージインストール時にデフォルトで5分間隔で自動起動するよう設定されるはずだと思います。
パッケージのバグなのか仕様なのかわかりませんが、パッケージインストール時に自動起動設定されなかった場合の対処方を説明します。

私がこの現象に遭遇したのは、CentOS 8, munin-2.0.66-1です。

## munin-updateはsystemd.timerが起動する

systemd配下で起動するサービスは、cronを使わずにsystemd.timerを使って自動起動させるものが多くなっています。
muninのパッケージに含まれている /usr/lib/systemd/system/munin.timer がその定義ファイルです。

```/usr/lib/systemd/system/munin.timer
[Unit]
Description=Munin server to collect data from nodes
Documentation=man:munin-cron(8)

[Timer]
OnCalendar=*:00/5

[Install]
WantedBy=timers.target
```

## /etc/cron.d/muninを作成するのは余り良くない

/etc/crond.d/muninを作成し自動起動設定すると説明している記事がありますが、muninのパッケージが正しくsystemd.timerの設定を行うようになったら、munin-updateが二重起動するようになってしまいます。

## 自動起動設定
systemd.timerにmuninパッケージが提供する設定ファイルを登録します。

```bash
# cd /etc/systemd/system/timers.target.wants
# ln -s /usr/lib/systemd/system/munin.timer .
# systemctl start munin.timer
# systemctl enable munin.timer
```
正しく設定できたかどうかを確認します。

```bash
# systemctl status munin.timer
● munin.timer - Munin server to collect data from nodes
   Loaded: loaded (/usr/lib/systemd/system/munin.timer; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2021-03-29 17:25:55 JST; 24min ago
  Trigger: n/a
     Docs: man:munin-cron(8)

 3月 29 17:25:55 hoge systemd[1]: Started Munin server to collect data from nodes.
```
system.timerの状態でも確認できます。

```bash
# systemctl -t timer
UNIT                         LOAD   ACTIVE SUB     DESCRIPTION
dnf-makecache.timer          loaded active waiting dnf makecache --timer
munin.timer                  loaded active waiting Munin server to collect data from nodes
systemd-tmpfiles-clean.timer loaded active waiting Daily Cleanup of Temporary Directories
unbound-anchor.timer         loaded active waiting daily update of the root trust anchor for DNSSEC

LOAD   = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state, i.e. generalization of SUB.
SUB    = The low-level unit activation state, values depend on unit type.

4 loaded units listed. Pass --all to see loaded but inactive units, too.
To show all installed unit files use 'systemctl list-unit-files'.
```
以上です。
【Swift】Extensionまとめ(基礎)

#はじめに
Extensionの基礎的な扱い方をまとめました。

#Extensionとは？
Extensionキーワードを使うことで既存の型に方を構成する要素（プロパティやメソッドやイニシャライザ）を追加する事ができます。
具体例を見ていきましょう。

#メソッドでの利用
以下のようにすることで、`plusOne`メソッドをIntに追加できます。
`self`はこのメソッドの呼び出し元(今回は5)を表しています。（詳細は後述します）

```swift
extension Int {
    func plusOne() -> Int {
        return self + 1
    }
}
print(5.plusOne()) // 6
```

#プロパティでの利用
extensionはストアドプロパティは追加できませんが、コンピューテッドプロパティを追加する事ができます。

```Swift 
extension Int {
    var minus10: Int {
        return self - 10
    }
}
print(100.minus10) // 90
```

#イニシャライザでの利用
イニシャライザを追加してみます。

```swift 
enum BloodType {
    case A
    case B
    case O
    case AB
    var title: String {
        return "あなたの血液型は"
    }
    var message: String {
        switch self {
        case .A: return "Aです"
        case .B: return "Bです"
        case .O: return "Oです"
        case .AB: return "ABです"
        }
    }
}

extension UIAlertController {
    convenience init(blood: BloodType) {
        self.init(title: blood.title,
                  message: blood.message,
                  preferredStyle: .alert)
    }
}

let blood = BloodType.AB
let alert = UIAlertController(blood: blood)
```

#プロトコルでの利用
プロトコルをエクステンションすることもできます。

```Swift 
protocol Book {
    var name: String { get }
    var price: Int { get }
}

extension Book {
    func printName() {
        print(name)
    }
    func printPrice() {
        print(price)
    }
    func printSelf() {
        print(self)
    }
    func printMyType() {
        print(type(of: self))
    }
}

struct MyBook: Book {
    var name: String
    var price: Int
}

let myBook = MyBook(name: "マイブック", price: 1000)
myBook.printPrice() // 1000
myBook.printSelf() // MyBook(name: "マイブック", price: 1000)
myBook.printMyType() // MyBook
```
これで`Book`プロトコルを採用した型は`extension Book`内のメソッドを扱う事ができます。

#制約の追加
プロトコルエクステンションは型による制約をつけることができ、この条件を満たすもののみプロトコルエクステンションを有効にできます。

```swift
extension Collection where Element == Int {
    var total: Int {
        return self.reduce(0) { $0 + $1 }
    }
}

let intArray = [1, 2, 3, 4, 5]
print(intArray.total) // 15
let stringArray = ["a", "b", "c"]
print(stringArray.total) // error
```

条件は`Collection`の要素`Element`が`Int`であると言う意味です。ですので、`intArray`の要素は`Int`なので`total`プロパティを扱う事ができますが、`stringArray`は要素が`String`なので`total`プロパティにアクセスしようとするとエラーになります。

#おわりに
エクステンションの基礎的な使い方を紹介しました。以上です。
windowsでiverilog その97

# 概要　

windowsでiverilogやってみた。
vcdを、生成してみた。

# 写真

![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/1f5af703-00e1-226e-fbfa-1a28d23457d5.jpeg)


# 生成されたvcd

GTKwaveで表示。
```
$date
  Mon, 29 Mar 2021 08:27:31 GMT
$end
$version
  plunker
$end
$timescale
  1s
$end
$scope module test $end
$var reg 1 ! a $end
$upscope $end
$enddefinitions $end
#0
$dumpvars
x!
$end
#1
0!
#2
1!
#3
0!
#4
1!
#5
0!
#6
1!
#7
0!
#8
1!
#9
0!
#10
1!
#11
0!
#12
1!
#13
0!
#14
1!
#15
0!
#16
1!
#17
0!
#18
0!
#19
0!
#20
0!
#21
0!
#22
0!
#23
0!
#24
1!
#25
0!
#26
1!
#27
0!
#28
1!
#29
0!
#30
1!
#31
0!
#32
1!
#33
0!
#34
1!
#35
0!
#36
1!
#37
0!
#38
1!
#39
0!
#40
0!
#41
0!
#42
0!
#43
0!
#44
0!
#45
0!
#46
1!
#47
0!
#48
1!
#49
0!
#50
1!
#51
0!
#52
1!
#53
0!
#54
1!
#55
0!
#56
1!
#57
0!
#58
1!
#59
0!
#60
1!
#61
0!
#62
0!
#63
0!
#64
0!
#65
0!
#66
0!

```

# 成果物

https://embed.plnkr.co/plunk/UeQ9YXXynIiKHv4e


以上。
SplunkのForwarder機能を駆使してデータの複製/切出し転送にトライ

はじめに
---
- SplunkのForwarder使ってデータを複製して、メイン機とは異なる別のSplunkに二重転送したり
- 必要なデータソースだけ切出して特定のIDXに転送したり 等
- データをマルチパスに制御して送りたいという要件がでてくることがままあります
- そんなときにシンプルな複製から、ちょっと込み入った切出し転送方法をいくつかまとめて紹介します


大別するとこんな感じ
---
- **複製編**
    - 全データまるごと複製
    - 特定のソースタイプのみ複製

- **切出して転送編**
    - 特定hostを含むデータのみ別IDXに転送
    - 特定の監視対象ファイルのみ別IDXに転送


#(複製編)How to

全データまるごと複製
---
- 以下マニュアルより抜粋
    - https://docs.splunk.com/Documentation/Forwarder/8.1.3/Forwarder/Configureforwardingwithoutputs.conf#Configure_data_cloning_on_a_universal_forwarder_with_outputs.conf
- cloned_group1とcloned_group2を定義して、それぞれにindexerのserverをセットするだけで、全データの複製が可能

**設定例:**

```:outputs.conf
[tcpout]
defaultGroup=cloned_group1,cloned_group2

[tcpout:cloned_group1]
server=10.10.10.1:9997, 10.10.10.2:9997, 10.10.10.3:9997

[tcpout:cloned_group2]
server=10.1.1.197:9997, 10.1.1.198:9997, 10.1.1.199:9997, 10.1.1.200:9997
```


特定のソースタイプのみ複製
---
- 参考記事：
    - https://splunkonbigdata.com/2018/09/12/clone-data-to-2-different-groups-of-indexers-in-splunk/

**設定例:**
- sourcetypeがWinEventLog://Microsoft-Windows-Sysmon/Operationalのデータを2つの_TCP_ROUTING先に転送（カンマで区切る）

```:inputs.conf
[WinEventLog://Microsoft-Windows-Sysmon/Operational]
_TCP_ROUTING = basic_indexer,mss_indexer
```

- _TCP_ROUTING先はoutputs.confにて指定

```:outputs.conf
[tcpout:basic_indexer]
server = 13.xx.xx.138:9997

[tcpout:mss_indexer]
server = 192.xx.xx.191:9997
```


##(切出して転送編)How to

特定hostを含むデータのみ別IDXに転送
---
- **1つのログファイルの中に、複数のhostが出てくる場合に、特定hostのデータのみメインIDXとは異なる別のIDXにだけ転送したいシーンにお勧め**
- 参考マニュアル
    - https://docs.splunk.com/Documentation/SplunkCloud/8.1.2101/Forwarding/Forwarddatatothird-partysystemsd#Forward_a_subset_of_data

**設定例:**

- まずpropsにて、別転送用のポリシー(otherRouting)を定義。この時、hostフィール名にipxxx.us-west-1.compute.internalが含まれるデータが対象となる

```:props.conf
[host::ipxxx.us-west-1.compute.internal] 
TRANSFORMS-routing = otherRouting
```
- 次にREGEXで対象データがマッチングする条件を定義。この場合、なんでもマッチするようにしている。DEST_KEYをセット。ポイントはFORMATにてoutputs.confで読み込む定義名を揃える必要あり

```:transforms.conf.conf
[otherRouting]
REGEX = .* 
DEST_KEY=_TCP_ROUTING 
FORMAT=other
```

- 最後にoutputsにてtransformで定義したotherという名称でtcpoutスタンザを定義

```:outputs.conf
[tcpout]
defaultGroup = default-autolb-group 

[tcpout:default-autolb-group]
server = xxx.xxx.xxx.97:9997

[tcpout:other]
server = xxx.xxx.xxx.18:9997 
```


特定の監視対象ファイルのみ別IDXに転送
---
- HF上で複数のファイルを監視対象にしている際に、特定ファイルのログだけ別のIDXに転送したい場合にお勧め

**設定例:**

- InterSafe_http.logを送る先としてiswf_routingポリシーを定義。同様にsecureログ送る先としてlinux_routingポリシーを定義

```:inputs.conf
[monitor:///usr/local/intersafe/logs/InterSafe_http.log] 
_TCP_ROUTING = iswf_routing
sourcetype = intersafe_http

[monitor:///var/log/secure] 
_TCP_ROUTING = linux_routing 
sourcetype = linux_secure
```

- tcpoutにてそれぞれのポリシーをセットして、転送したいIDXのserverを設定するだけ

```:outputs.conf
[tcpout:default-autolb-group] 
server = 54.xxx.xxx.50:9997

[tcpout:iswf_routing]
server = 13.xxx.xxx.97:9997

[tcpout:linux_routing]
server = 54.xxx.xxx.44:9997
```


最後に
---
- 実はまだやり方が見つかってないのですが、全データをIDX-Aに転送しつつ、特定の文字列を含むデータをIDX-Bにも転送するというハイブリッドなやり方が分かってません。
- ご存知の方いたらコメントにて教えてほしいです
【ServiceNow】sys_idの取得方法のまとめ

# 概要
　ServiceNowには、Sys ID[sys_id]と呼ばれる一意の32文字の羅列が存在します。この羅列によりインスタンス内の各レコードを識別することができるので、ビジネスルールやクライアントスクリプト等のスクリプト、参照型フィールドへの参照等、全てのレコードを一意に特定することができる。
　また、Sys IDは世界中の全てのインスタンス、全てのテーブルで作成された全てのレコードにおいて一意に割り振られるため、Sys IDは以下の注意点を除き、被ることはありません。

この記事では、Sys IDを取得するための実用的な方法を紹介します。
##注意点
- データベースレベルでNowプラットフォームの外でコピーされてレコード
- 更新セット、XMLでコピーされたレコード。
 - インスタンス間で同様なレコードを用意するための手段として使用されます。

# sys_idを取得する方法
- 右クリックによるsys_idのコピー
- URLからの特定
- XML出力による特定
- Easy Importによる特定
- スクリプトによる取得

## 右クリックによるsys_idのコピー
・フォーム画面：ヘッダーを右クリック
・リスト画面：レコードを右クリック
　[sys_idをコピー]でsys_idをコピーできます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425100/bea717ff-c7ce-005e-4bac-438c63751699.png)

## URLからの特定
フォーム画面にいる時のURLにsys_idは表示されています。
 **sys_id%~%**で囲まれた部分がsys_idです。

https://<instance_name>.service-now.com/nav_to.do?uri=%2Fincident.do%3F **sys_id%3D552c48888c033300964f4932b03eb092** %26sysparm_view%3Dess%26sysparm_record_target%3Dincident%26sysparm_record_row%3D1%26sysparm_record_rows%3D66%26sysparm_record_list%3DORDERBYDESCnumber

## XML出力による特定
・フォーム画面：ヘッダー右クリック
・リスト画面：フィールラベル横のハンバーガーアイコンをクリック 
　[XML表示]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425100/53d9c7db-ceba-69a8-2429-90bd4be52980.png)

ポップウィンドウにXML形式で表示されたレコード内の<sys_id>を確認する。

## Easy Importによる特定
Easy Importを利用して複数のレコードのsys_idを取得することもできる。

1. Sys IDを取得したいレコードのみになるようフィルターをかける。
2. ハンバーガーアイコンから[インポート]をクリック
3. 以下の画像のように設定し、[Excelテンプレートを作成]でExcelをダウンロード。
　　[全てのフィールドをテンプレートに含めますか]にチェックを入れることで、ファイルにsys_idのカラムを追加できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425100/5240578f-1be7-0fa8-d006-e32c46f0403b.png)



## スクリプトによる取得
###Server サイド
```
var sysID = current.getValue('sys_id'); //APIによる取得
                 or
var sysID = current.sys_id; //ドットウォークによる取得
```
###Client サイド
```
var sysID = g_form.getUniqueValue(); //APIによる取得
```
# 結論
sys_idを取得する方法は様々だが、個人的に普段使いできるものをまとめると以下になる。

| 取得数 | 手段 |
|:-:|:-:|
| 単体  | 右クリック  |
| 複数  | Easy import  |
| スクリプト  | API  |

ありがとうございました。
jetsonで深層学習をする環境を整える


#はじめに
* jetsonはarmアーキテクチャなので環境構築が面倒くさい
* nvidia公式のjetson用深層学習イメージがある　[nvidia NGC](https://www.nvidia.com/ja-jp/gpu-cloud/)
* vscodeを使って快適に開発を行いたい

#流れ
* vscodeのインストール
* vscodeにdocker extentionをインストール
* dockerhubからimageをpullする
* コンテナを立ち上げる
* vscodeでコンテナにアタッチする

#vscodeのインストール
[ここ](https://code.visualstudio.com/#alt-downloads)からダウンロードしてインストールできます.
![Screenshot from 2021-03-29 17-01-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322641/25978bf6-4953-57d9-58fe-c378576b1095.png)
jetsonはarmアーキテクチャなのでARM64を選択してください

#docker extentionのインストール
vscodeの拡張機能から[docker](https://marketplace.visualstudio.com/items?itemName=ms-azuretools.vscode-docker)をインストールします.
![Screenshot from 2021-03-29 17-14-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322641/c6c222b4-1155-65e4-d407-073d26ae826e.png)

#imageをpullする
[nvidia NGC](https://www.nvidia.com/ja-jp/gpu-cloud/)からjetson用のimageをpullします.今回はpytorchを使いたいので[これ](https://ngc.nvidia.com/catalog/containers/nvidia:l4t-pytorch)を使います.
jetpackのバージョンに合わせないといけないのでjetpackのバーションを確認します

```bash
> dpkg-query --show nvidia-l4t-core
nvidia-l4t-core	32.4.4-20201016123640
```

このバージョンにあったものをpullします

```bash
docker pull nvcr.io/nvidia/l4t-pytorch:r32.4.4-pth1.6-py3
```

#コンテナを立ち上げる
ターミナルから

```bash
docker run --rm --runtime nvidia --network host -v /home/user/project:/location/in/container nvcr.io/nvidia/l4t-pytorch:r32.4.4-pth1.6-py3
```

と入力するとコンテナが立ち上がります
--rm はコンテナ終了時に自動的にコンテナを削除するコマンド (削除したくない場合は--rmコマンドをつけない)
--runtime nvidia これをつけるとjetsonのcuda環境をdockerに提供することができる
-v : 左がマウントしたいホストのファイルパス(絶対パスでないといけないらしい)。右がコンテナ内のファイルの置き場。

![Screenshot from 2021-03-18 19-14-19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322641/76ceb57f-a510-55c4-c71c-bca3b9e61092.png)

docker extentionからもコンテナが立ち上がっていることが確認できる.

#vscodeでコンテナにアタッチする
vscodeのdocker extensionからcontainersの起動中のコンテナ上で右クリックしattach visual studio code を選択
![Screenshot from 2021-03-18 19-35-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322641/f4610fc0-d658-1294-41eb-1ea9db3a41d1.png)

vscodeで開発する環境が整いました

#実際に動くかの確認
GPUが認識されているか確認しましょう

```python
import torch
# GPUの確認
use_cuda = torch.cuda.is_available()
print('Use CUDA:', use_cuda)
```

実行結果は以下のようになります

```python
Use CUDA: True
```

dockerコンテナでGPUを使った深層学習の開発ができます.
collection_check_boxes を用いた中間テーブルのコールバック

collection_check_boxes を用いて中間テーブルを削除した際に、中間モデルの after_destroy のコールバックを実行したかったが上手くいきませんでした。

## モデル

```ruby:
class Route < ApplicationRecord
  belongs_to :user
  has_many :route_spots, dependent: :destroy
  has_many :spots, through: :route_spots
end

class Spot < ApplicationRecord
  belongs_to :user
  has_many :route_spots, dependent: :destroy
  has_many :routes, through: :route_spots
end

class RouteSpot < ApplicationRecord
  belongs_to :route
  belongs_to :spot
  after_destroy :align_sequence

  private
    def align_sequence
      self.route.route_spots.order(sequence: "ASC").each_with_index{ |object, index|
        object.sequence = index + 1
        object.save
      }
    end
end
```

## コントローラ

```ruby:routes_controller.rb
class RoutesController < ApplicationController
  before_action :authenticate_user!
  before_action :set_id, only: %i[edit destroy update show]

  ...省略

  def edit
    @my_spots = current_user.spots
  end

  def update
    if @route.update(route_params)
      redirect_to routes_path(anchor: "id_#{@route.id}"), notice: "「#{@route.name}」を編集しました"
    else
      render :edit
    end
  end

  ...省略

  private
  def route_params
    params.require(:route).permit(:id, :name, :memo, :sequence, spot_ids:[])
  end

  def set_id
    @route = Route.find(params[:id])
  end
end
```
## view

```slim:views/routes/edit.html.slim
= form_with model: route, local:true, id:"route_form" do |f|
  = f.label :name
  = f.text_field :name, id: 'route_name'
  = f.label :memo
  = f.text_area :memo, id: 'route_memo'
  = f.collection_check_boxes(:spot_ids, @my_spots, :id, :name)
  = f.submit '登録する' , class:'button-primary'

```

## やりたかったこと
動作自体は、Route の edit 時に、has_may な Spots の登録/登録解除を、collection_check_boxes で簡単に実装しただけのなんてことのないもの。
やりたかったのは、collection_check_boxes でチェックを外して route を update (routeのupdate と同時に route.route_spots が destroy）した際に、RouteSpotモデルの after_destroy で メソッドalign_sequence を実行したかった。

しかし、after_destroy、before_destroy、どちらでも動作せず、ただ RouteSpot の destroy が完了するだけでした。

- 下記の記事を辿ると、どうにも Rails が持っているバグとのこと。
  - https://stackoverflow.com/questions/54471258/rails-collection-check-boxes-not-triggering-callbacks-on-join-model
- githubのissueを見ると、どうも放置されて close しているっぽいです。状況が限定的すぎだからでしょうか。
  - https://github.com/rails/rails/issues/27567
- RouteSpot の after_destroy、before_destroyは動作しなかったが、試しにafter_createを書いてみたら、そちらは問題なく動いたので、やはりコールバック全てが動作しない訳ではなく、destroy関連のみが動かないようです。

## 結論
あまり良いとは言えないかもしれないですが、RouteSpot のコールバック(after_destroy)ではなく、Route のコールバック(after_update)ので処理することにしました。
もともと、route.route_spots に対し一括で連番を振り直すというものだったので、ひとまずやりたいことは問題なく動作しますので、今回はこれで妥協します。

仕様と言われたら納得いきますが、バグ、しかも長期にわたって放置されているものとだと思うとちょっと微妙な気持ちです。
【Laravel】ルーティングの状態をファイルで見やすく確認する小技

## 環境
|バージョン等|
|-|
|Laravel 6.20.19|
|MacOS 10.15.7 Catarina|

## ①普通にルーティングを確認してみる
Laravelの通常のWebページとしてのルーティングは`Routes/web.php`にいろいろと記載していますが、
prefixとかgroupeなどを記述していると、実際にどうなっているか分からなくなったりしますよね。

これを確認する時に使うのが、

```sh:ターミナル
$ php artisan route:list
```
というコマンド。

なのですが、これがずら〜と表示されてちょっと分かりづらい。
## 現状
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675596/dc4da604-7b48-1dbf-19b2-1149fbfa720f.png)

## ②見やすくルーティングを表示する
ということでこれをファイルとして保存して見やすく表示してみましょう。
`route:list`コマンドに` > .route`を追加すればOKです。

```sh:ターミナル
$ php artisan route:list > .route
```
これでプロジェクトの直下に.routeというファイルが保存されました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675596/494eeee9-5393-d851-466f-fbc20fd41f15.png" width="400px">
## After
中身を表示するとこんな感じで見やすく表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675596/1a38a090-cecc-0cef-5244-acd3d52ef814.png)
作成してしまえばその後はコマンドを実行せずに確認できるのも嬉しいですね。
なおルーティングにもし変更があれば、再度同じコマンドを実行すれば上書きされます。

また作成した.routeファイルは、チームで共有する必要はないと思いますので.gitignoreに追加すると良いです。

```sh:.gitignore
.route #追記
```
<br>
最後までお読みいただきありがとうございます〜！
AppleとAndroid審査時グラフィック関連のまとめ

# アイコンについて
## Android
[Adaptive Icon](https://developer.android.com/guide/practices/ui_guidelines/icon_design_adaptive?hl=ja)になっている。<br>用意する画像が一点のみで、Android Studioで設定すれば、<br>丸アイコン、丸角アイコン、Google Play アイコンなどが自動で生成される。

- [Image Asset Studio を使用してアプリアイコンを作成する](https://developer.android.com/studio/write/image-asset-studio?hl=ja)方法

### 用意する画像
- Radiusが0である四角
- サイズについては公式サイドで108.00dpで書いてあり、一番解像度が高いxxxhdpiと合わせて、432.00px（xxxhdpi @ 108.00dp = 432.00px）になると思う
- safe zoneは真ん中の66dpなので、アイコンの載せる画像と文言を66dp超えないように
![android-icon.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419712/f09cc6b0-a988-3bb2-4c74-ab24606968ff.png)

 
#### Google Play アイコンの要件に関する補足
- 32 ビット PNG（アルファ付き）
- サイズ: 512 ピクセル x 512 ピクセル
- ファイルの最大サイズ: 1024 KB

## iOS
[公式サイト](https://developer.apple.com/design/human-interface-guidelines/watchos/visual/app-icon/)でよくまとめている

# スクリーンショットについて
## iOS
以下の２種類が必要

- 6.5 インチ iPhone XS Max
- 5.5 インチデバイス (iPhone 6s Plus、iPhone 7 Plus、iPhone 8 Plus)

[公式サイト](https://help.apple.com/app-store-connect/#/devd1093d90d)

## Android
以下の3種類が必要

- スマートフォン
- ７インチタブレット
- 10インチタブレット

[公式サイト](https://support.google.com/googleplay/android-developer/answer/9866151?hl=ja#zippy=,スクリーンショット)

# Android固有
## フィーチャーグラフィック
要件

- JPEG または 24 ビット PNG（アルファなし）
- サイズ: 1024 ピクセル x 500 ピクセル

[公式サイト](https://developer.android.com/distribute/best-practices/launch/feature-graphic?hl=ja)
PHP if文とcount()の混合条件の作成

#はじめに
今回は基本的な投稿システムが完了したので少しこだわりを入れて備忘録として投稿いたします。これを利用してlaravelに組み込みます。


#今回の条件
1. １件以上のコメントがある場合は現在〇〇件コメント数という風に表示
1. コメントが0件の場合は現在〇〇件コメント数を非表示にする

これらの条件を使用するにはif文とcount()の両方を使用することになります。以下にサンプルを掲載します。

###if文の構文

```if.php

$value1 = 200;
$value2 = 100;

if ($value1 > $value2){
  echo 'value1はvalue2より大きい';
  $value2 = $value1;
}
```

###countの構文

```count.php

$collection = collect(['鈴木', '佐藤', '田中']);
echo $collection->count();  // 3
```

#上記の条件を纏めたコード

```sample.php

@if ($post->comments->count() >= 1)
<p>
  <span class="badge badge-primary">
    現在のコメント数　{{ $post->comments->count() }}件
  </span>
</p>
@endif
```

![“スクリーンショット” 2021-03-29 17.29.14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/03c66b86-f382-ef19-86a0-051b64a9082a.jpeg)

#解説
今回は各々が投稿した投稿内容の詳細にコメントを掲載するようになっています。
$postは投稿の変数になります。`comments`はPost.modelのcommentsを表しています。
`>= 1`で１件以上のコメントがある場合は不等号を使用して表示させる様にしています。

```Post.php

    public function comments()
    {
        // 投稿は複数のコメントを持つ
        return $this->hasMany('App\Models\Comment');
    }
```
[React Next.js] Consoleに[Fast Refresh] rebuildingが表示されたままコンテナが落ちる問題

## 環境

Dockerで
- Next.js & GraphQL
- Rails
- MySQL DB
のDevServerを立てていて
VSCodeのRemoteContainerでComponentを編集している状態

## 問題

ブラウザでページを表示（こちらは大丈夫）
Reactのファイルを編集し、ブラウザが自動的にfast refreshを始める
そしてそのままエラーでコンテナが落ちる
以下がそのエラー

```console:コンテナのログ
client_1 | wait - compiling...
client_1 | Killed
client_1 | error Command failed with exit code 137.
client_1 | info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
```

## 解決策

error 137　はメモリ不足のエラーなのでコンテナの割り当てメモリを増やせばOK
MacのDockerであれば`右上の歯車→Resources→ADVANCED`で設定できる

## 最後に

エラーコードはちゃんと読みましょう（戒め)
Python用日本語文字列変換ライブラリjaconv 0.3の説明

ちゃお……†

久しぶりにまいおり……†

ネオ東京文京区からやってきてPython用日本語文字列変換ライブラリjaconvを0.3にアップデートをしました。変更点は下記の通りです。

- バグ修正
- ひらがなからJuliusの音素表現への変換に対応

バグはアルファベットからひらがなに変換する `alphabet2kana` 関数の修正です。使ってる人多分少なそうだからあんまり影響ないかも。

そして新機能！ひらがなから[音声認識システムJulius](https://julius.osdn.jp/)の音素表現に変換する `hiragana2julius` 関数です！

どんなものかというと以下のようにちょっと気の利いた処理をしつつJuliusの音素表現に変換するのです。

```python
>>> import jaconv
>>> print(jaconv.hiragana2julius('てんきすごくいいいいいい'))
t e N k i s u g o k u i:
```

"いいいいいい" の部分を長音扱いにします。

ただし実装が細かくないので以下のような問題も起こります……。

```python
>>> print(jaconv.hiragana2julius('てんきいい'))
t e N k i:
```

"てんき" の "き" の母音 "i" と "いい (ii)" がくっついて "てんきー" となってしまうのです……。

これを解決するにはMeCab等の形態素解析器を使いましょう。具体的には、形態素ごとに `hiragana2julius` で変換するのです。これでだいぶ問題が減るはず。それでもだめなときはある (特に固有名詞でありそう) ので、そこは自分の目で**確かみてみろ！**なんでも機械だけに頼っていてはだめです。あくまでもサポート役と考えましょう。

わかっていてあえて実装しないのは、jaconvはミニマルなライブラリという位置づけでいたいので外部ライブラリを使いたくないからです。半角⇔全角の変換しか使わない人にまでMeCabをインストールさせるのは気が重いし……。

そういえばJuliusって「ジュリウス」って呼ぶ人と「ジュリアス」って呼ぶ人と「ユリウス」って呼ぶ人にこれまで出会ってきたけど、[開発チーム内では「ジュリアス」と呼ぶそうです](https://julius.osdn.jp/juliusbook/ja/pr01.html)。豆知識💡ジュリアナっぽいやつと覚えれば良さそうですね💃🕺

ところで終電大丈夫？じゃあね。Bye.
AWS Amplifyの認証情報を他のAWSサービスのSDKで流用した[Swift Storyboard]

AWS Amplifyを使うとモバイルアプリで簡単に認証機能を搭載できますが、Amplifyの対応していないAWSサービスを使わなければならない場面があったのでメモ。
AWS歴半年の初学者の備忘録ですので、誤り等あればご指摘いただけると幸いです。

# 前提
- Amplify CLIでプロジェクトに認証機能を追加している（[参考:AWS AmplifyによるiOSアプリ開発入門（Part1）](https://qiita.com/papi_tokei/items/55d48a1a9a9e56d7cbd4)）
- 対応するIDプールのIAMロールに必要なポリシーをアタッチしている  
具体的には *amplify-xxxx-yyyy-zzzz-authRole-idp* のようなロール名です

# 実装
認証が必要なSDKの直前で以下を追記

```swift
let credentialsProvider = AWSMobileClient.default().getCredentialsProvider()
let configuration = AWSServiceConfiguration(region:.APNortheast1, credentialsProvider:credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
```

# 動かないときは
- IDプールに対応するIAMロールで実行したいアクションが許可されているかを確認する。
- `AWSMobileClient.sharedInstance()~`としている箇所があれば`AWSMobileClient.default()~`と変更する。  
前者のメソッドは今後は後者に移行されていくようです。
Google Apps ScriptのWeb AppsをURLを変えずに最新のスクリプトでデプロイしたい

# 概要
この投稿ではGoogle Apps ScriptのWeb Appsについて、URLを変えずに最新のスクリプトを反映させる方法を紹介させていただきます。ここでは新しいIDEを使って説明します。

2021年3月15日からGoogle Apps Script projectでは複数のdeployment IDを使用することが可能になりました。[Ref](https://developers.google.com/apps-script/releases/#march_15_2021) これよにり、例えばWeb Appsでは、これまで最新のスクリプトをWeb Appsへ反映させるために新たなバージョンとして再デプロイすることで使用してきましたが、今ではこれまでのようにWeb Appsを再デプロイすると、deployment IDが変化するためにURL (デプロイする都度、`https://script.google.com/macros/s/###/exec`の`###`が毎回変化してしまう。) そのものが変化してしまいます。

最近、このような問題に関する問い合わせ、すなわち、URLを変えずに最新のスクリプトをWeb Appsに反映させたいといった内容の問い合わせが増えてきましたので、こちらでもその回避策について紹介させていただきます。

# 流れ
URLを変えずに最新のスクリプトをWeb Appsに反映させるための流れは下記の通りです。

1. 新しいGoogle Apps Script projectを作成する。この場合、standalone type, container-bound script typeの両方を使用することができます。作成したGASプロジェクトのスクリプトエディタへ下記のスクリプトをコピーペーストし、保存します。

    ```javascript
    function doGet() {
      return ContentService.createTextOutput("sample1");
    }
    ```

2. Web Appsを下記条件でデプロイします。ここでWeb AppsのURLをコピーしておきます。
  - `Execute as: Me`
  - `Who has access: Anyone`

    ![20210329a-fig1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133383/50d8a93b-a2d7-bcbc-4ac0-1d1c079e5295.png)

3. デプロイしたWeb Appsへcurlコマンドを使って動作テストします。デプロイ時にコピーしたURLを使用します。

	```bash
	$ curl -L "https://script.google.com/macros/s/###/exec"
	```
  - `sample1`が返されると動作確認完了です。

4. 次に、Web Appsのスクリプトを下記のように変更します。

	```javascript
	function doGet() {
	  return ContentService.createTextOutput("sample2");
	}
	```

5. 下記の図のようにWeb Appsをアップデートします。

    ![20210329a-fig2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/133383/2282d408-640f-5d31-132e-f1fbd6646111.png)


	1. スクリプトエディタから"Deploy" -> "Manage deployments"で"New deployment"ダイアログを開きます。
	2. 最初にデプロイしたバージョンを開きます。その状況下で、鉛筆マークをクリックして編集状態にします。
	3. "version"を"New version"として設定します。(ここがポイントです。) "description"を変更する場合はここで変更できます。
	4. "Deploy"ボタンを押します。これにより変更が保存されます。

6. 再度、curlコマンドを使ってテストします。この時のコマンドは、上記のものと同一のコマンドで行います。
	- `sample2`が返されます。すなわち、Web AppsのURLを変更することなく（deployment IDを変更することなく）、最新のスクリプトをWeb Appsへ反映させることができました。

英語版は[こちら](https://tanaikech.github.io/2021/03/29/redeploying-web-apps-without-changing-url-of-web-apps-for-new-ide/)です。

## 参考
- [Create and manage deployments](https://developers.google.com/apps-script/concepts/deployments)
- [Web Apps](https://developers.google.com/apps-script/guides/web#test_a_web_app_deployment)
確率的言語モデル　北研二先生　東京大学出版会

```{r}


#反復スケーリング法　p.162

library(dplyr)

x=c(1,2,3,2,4,5,6)

y=c(3,4,9,8,7,9,8)

C_x_y=data.frame(x=x,y=y)%>%group_by(x,y)%>%summarise(n=n())

x=C_x_y$x;y=C_x_y$y;p=C_x_y$n/sum(C_x_y$n)

f1=function(X,Y){

return(exp(-X*Y))

}

f2=function(X,Y){

return(X*Y)

}

lam=rep(1,2)

ite=100

for(l in 1:ite){

f1_vec=f1(x,y)

f2_vec=f2(x,y)

P=exp(cbind(f1_vec,f2_vec)%*%lam)/sum(exp(cbind(f1_vec,f2_vec)%*%lam))

f_sharp=f1_vec+f2_vec

print(sum(p*log(P)))

#Newton Algorithm

f=function(z){

f1_val=sum(P*f1_vec*exp(z[1]*f_sharp))-sum(p*f1_vec)

f2_val=sum(P*f2_vec*exp(z[2]*f_sharp))-sum(p*f2_vec)

return(c(f1_val,f2_val))

}

del=rep(1,2)

eta=0.0001

h=0.01

while(sum(abs(f(del)))>10^(-5))({

df=(f(del+h)-f(del))/h

del=del-eta*f(del)/df

#print(sum(abs(f(del))))

})

lam=lam+del

}


```
Ruby on Railsのビューに関するエラー

##1.はじめに
この記事では私が実際に体験したエラーとその原因と解決方法について書いてます
参考になるかどうかわかりませんがよろしくお願いします。

##2.エラー内容
![エラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208326/f813b83f-a5b6-072c-03f1-a2beebb73138.png)
今回のエラーはツイートアプリにて新規投稿した際に
発生したエラーになります。

##3.エラー解説
まずは一番上の文の**No templete for interactive request**について解説していきます。

No templateとは訳すと**ビューファイルが見つからないよ**ということになります

じゃあなんのビューファイルが見つからないかというとその下の分をみてもらうと
**TweetsController#new is missing a template for request formats: text/html**
と書いてあります。
**Tweetsコントローラーのnewアクションに対応するビューファイルが見つからないよということ**

このことからビューファイルになんらかの問題があるという仮説が立てられます。


##4.エラー解決
そしてビューフォルダのツイートフォルダをみてもらうと
<img src= "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1208326/4f07d507-d53b-b41b-74a5-e01381d3ee5b.gif" width=30%>
本来はnew.html.erbのところが**nwe.html.erb**になってしまっています。

これを正しい表記、**new.html.erb**にしてあげるとエラーが
解消します。


##5.あとがき
今回のエラーはビューファイルの表記ミスでしたが今一度MVCのコントローラーとビューについて復習してみると
**コントローラー内のアクションはレスポンスとしてブラウザに返す見た目をビューフォルダの中から見つけ出す役割があります。**
例をいうとコントローラー内で

```php:tweets_controller.rb
def index　　　　　　
 @tweet = Tweet.all   
end
```
と記述していてもビューフォルダでそのコントローラー内のアクションに対応しているビューファイルがないとコントローラはレスポンスとしてブラウザに返すことができない。
そのため今回のようなエラーが起こりました。
GDevelop v5.0.0-beta108 がリリースされました。

Gdevelop v5.0.0-beta 106 がリリースされる前に 107 が発表されて、んじゃ 107 の記事を書くか～っと思っていたら 108 がリリースされたでござる😅
しかも、リリースに間に合うほど爆速で翻訳してくださった [YU-TANG](https://twitter.com/yu_tang_) さんのおかげで、初めから新機能も日本語で利用できますぞー🙌
ということで今回は、GDevelop v5.0.0-beta 106 から 108 までの気になった変更点を、まとめてピックアップしました❗
##✨ 新機能
###・配列変数と真偽値変数が追加
全ての変数（グローバル、シーン、オブジェクト）で、従来の数値、文字列、構造体に加えて、配列と真偽値のタイプ（型）が利用できるようになりました。
![2021-03-29 104545.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224830/2eff7a73-78ef-fcaa-497c-1217f44e5fed.png)
真偽値は ON、OFF などに、配列は子変数の数が決まっていないデータや、増減するデータを持たせる事ができるので、とても便利です。
もちろん、配列と構造体は他のタイプを入れ子で持つことができるので、配列の子が構造体、なんてことも可能です。

特に配列は、個人的に待ち望んでいた機能なので、嬉しいです😊
ただし、現状は繰り返しイベントがシーン変数にしか対応していない点が残念です。
グローバル変数やオブジェクト変数を繰り返し処理したい場合は、シーン変数へコピーするか Javascript コードを使用する必要があります😥
###・トップダウン移動ビヘイビアを改善
「スティックコントロールをシミュレートする」アクションや「移動角度オフセット」プロパティが追加されて、より便利になったようです😆（よく分かってないｗ）
###・オーディオに立体音響とプリロードの機能が追加
立体音響は距離による音量の減衰だけでなく、音がどの方向から鳴っているかを再現することができるようになります。（3D なので上下前後左右なのだとは思いますが、特に左右が分かりやすいです）
ただし、なぜか位置を逆距離モデルという謎の割合で設定する必要があり、かなり使いにくい仕様となっています😥

[Wiki の Spatial-sound ページ（英語）](http://wiki.compilgames.net/doku.php/gdevelop5/all-features/spatial-sound/reference)

あと、プリロードされていないサウンドには効果がなかったり、再生前に位置を設定しようとすると落ちるバグが有るようです……😞
今後の改善に期待です。

プリロードの方は、読み込みが完了しているかを確認するすべは無いものの、使い方はアクションを追加するだけなので、簡単に利用できます。
あとアンロードもできます👍
###・グリッドに等角投影（Isometric）を追加
ストラテジーゲーム制作などで便利な、斜めグリッドが可能になりました。
![斜めグリッド](https://user-images.githubusercontent.com/1280130/112768282-4c12a200-9013-11eb-921e-4dd9d3f80dd4.png)
最近のトップダウン移動ビヘイビアへの熱心な改善といい、等角投影派の貢献が止まりませんね👍
##💝 改善点
###・シーンエディターでインスタンスを Shift + 矢印キーで素早く移動
矢印キーだけだと 1px ごとの移動ですが、Shift + 矢印キーで 5px ごとに移動できるようになりました。
なんで 10px じゃないのかは謎ですｗ
###・AAC オーディオファイルが利用可能に
選択できるようになったらしいです。
###・動画オブジェクトを正式採用
実験的なオブジェクトから昇格しました。
###・アセットストアがさらに充実
これはバージョンアップ前から利用できていましたが、色々増えてます👍
##🐛 バグの修正
###・Center ポイントが初期値ではないスプライトの、当たり判定がズレる問題を修正
やっと直してもらえましたｗ🙌
[[Fixed] Sprites with modified points do not collide correctly](https://forum.gdevelop-app.com/t/fixed-sprites-with-modified-points-do-not-collide-correctly/24785)
###・数学的ツールに正規化（normalize）を追加
beta 105 で追加されたのに、使えなかった式が使えるようになりました。
###・変数の繰り返しイベント（For each child variable）で、構造体の子が指定できない問題を修正
入れ子になっている構造体も繰り返しの対象にすることができるようになりました。
##🧐 まとめ
今回の目玉はやはり、配列変数の追加ですね。
今までは配列の拡張機能とか作っていたので、標準で対応してくれたのは助かります。
ただ、現状は末尾追加と削除しかアクションがないので、もう少し色々なアクションが追加されることを期待したいです。

あと手前味噌ですが、Mouse Pointer Lock という拡張機能が、拡張機能の検索に掲載されるようになりました🎉
JS の [Pointer Lock API](https://developer.mozilla.org/ja/docs/Web/API/Pointer_Lock_API) が利用できるようになるという、かなりニッチな拡張機能ですが、マウスカーソルの移動量を得たりもできるので、PC 向けゲーム制作の際などにお役立てくださいませ😊

ここで紹介した点以外にも、色々と改善されているので、詳しくは [GitHub の GDevelop Releases ページ](https://github.com/4ian/GDevelop/releases)をチェック！

**※ この投稿は「[GDevelop 無料ゲーム制作ツールを使い倒す Blog](https://gdevelop-jp.blogspot.com/2021/03/v500-beta108.html)」からの移植＆改訂版です。**