OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS8にJavaをインストールする

本ページではCentOSにJavaをインストールする手順についてまとめていきます。
yumでインストールしました。

#前提条件
ホストOS:Windows10
ゲストOS:CentOS8
今回インストール：Java8　~~JRE,~~JDK
以下JREをインストールする手順も含んでいますが、JDKにJREが含まれているので、必要ありません。


#インストール手順

###yumリポジトリ対象パッケージ検索(確認)
```
yum search java-1.8.0-openjdk
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1620534/8fa66e56-7291-8bb8-f3a8-34233cfd0849.png)
メタデータを取得しているのでしょうか…？必要そうな手順です。(飛ばしてもできそう)

###Java8 JDK開発環境インストール
```
sudo yum install java-1.8.0-openjdk-devel
```
こちらも上記同様に、
「これでよろしいですか？(y/N)」と聞かれるので、yで進めます。
「完了しました！」と表示されれば成功です。

####確認
インストールが完了しているかはバージョンが*1.8*になっているかで確認できます。

```
java -version
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1620534/d06f5a4a-4ec1-eb2e-ed9d-391b9d78e1d3.png)

#####所感
yumでのインストールは表示に圧倒されるところは少しあるものの、かなり簡単そうでした。

他の方法、rpmファイルからインストール、バイナリファイルから、というのもあるそうです。

###alternativesコマンド
alternativesというのを時々目にしました。
バージョンの違うプログラムを複数扱いたい場合に、それぞれ別名を付けておくコマンドのようです。
プロジェクトごとや同じ環境でバージョンを切り替えたい場合に使用するそうです。

####JREとJDKの違い
JRE：Java Runtime Environment Javaアプリケーションを実行するためだけに必要**だった**
JDK：Java Development Kit　おなじみJavaの開発をするなら絶対必要、JREも含んでいる

Java開発はプログラムを
コンパイル→実行
JREはコンパイルできないが実行はできる、
JDKはコンパイルも実行もできる
→JDKのみでOK

>~~Java8 JRE実行環境インストール~~
sudo yum install java-1.8.0-openjdk
いろいろサイズ等表示され、
「これでよろしいですか？(y/N)」と聞かれるので、yで進めます。
「完了しました！」と表示されれば成功です。

#参考文献

####CentOS 7 に Java 8 (OpenJDK) を yum インストールする手順
大変参考にさせていただきました。CentOS7でも8でもほとんど違いは無さそうです。
https://weblabo.oscasierra.net/installing-openjdk8-on-centos7/

####CentOS7へのOpenJDKインストールあれこれ
前述所感の項目で述べた、今回のyumインストールとその他の方法も大変参考になりそうです。
https://qiita.com/yuuman/items/a9e89d7d4899cbdaed44
pip installしたライブラリをLambda layerする

lambda環境で実行するとpython3.8環境のsys.pathは以下でした。

```
[
  '/var/task', 
  '/opt/python/lib/python3.8/site-packages', 
  '/opt/python', // ここ
  '/var/runtime', 
  '/var/lang/lib/python38.zip', 
  '/var/lang/lib/python3.8', 
  '/var/lang/lib/python3.8/lib-dynload', 
  '/var/lang/lib/python3.8/site-packages', 
  '/opt/python/lib/python3.8/site-packages'
]
```

layerはopt以下に展開されるので、解凍して `python/モジュール` という構成になるzipを作ればよいです。
なので次のようにpythonディレクトリ以下にpipでライブラリをインストールすれば、layerで複数Lambda関数から利用できるようになります。

`pip install pytz -t python`
初めてのAppストア申請でリジェクトされた

# Appleを舐めてた
App Storeを見ると、ゴミアプリもあるため、自分がとりあえず作ったアプリも公開できるだろうと思い込み、申請。
見事にリジェクトされ、僕がとりあえず作ったアプリは、ゴミ以下だと認定されました。

## 申請したアプリの概要
飲んだお酒の量や体重を打ち込むと、大雑把な血中アルコール濃度や呼気アルコール濃度を計算してくれるアプリ。
早い人なら1日Swiftを学べば作れるレベルのアプリで、とりあえず、公開方法を知るために公開したかった。

## リジェクト理由
>Guideline 1.4 - Physical Harm
Your app is marketed as a blood alcohol content calculator but does not have associated hardware to perform these calculations accurately. To ensure users’ safety, we only allow blood alcohol content calculator apps that pair with hardware capable of offering accurate blood alcohol content measurements on the App Store. Apps that rely solely on software, Widmark formulas, or other mechanisms to calculate blood alcohol content are not appropriate for the App Store.

要約すると、「アルコール濃度を計算するアプリを出したいなら、アルコール濃度を正確に検知できるハードウェアとセットで提供してください」とのことでした。

そのときは血中アルコール濃度や呼気アルコール濃度が表示されるようになっていたので、それを消して、酒酔い運転になるのか、酒気帯び運転になるのかだけ表示させて再申請しましたが、再びリジェクト。
「いくら表示を消しても、裏で計算しているなら計算機として扱うため、ハードウェアとセットで提供する、もしくはアプリにコンセプトを変えてください」とのこと。
とりあえずで作ったアプリで、ハードウェアまで準備できるわけもなく、公開を断念。
別のまだちゃんとしたアプリを作っているため、そちらを公開予定。

## 結論
とりあえず、アプリの公開方法は理解できたので、よかったということで。
僕がアプリ公開のために参考にした記事は以下に貼っておきます！

## アプリ公開申請時に参考にした記事
[【2020年度版】 iOSアプリをApp Storeに公開する手順を簡潔に解説](https://qiita.com/Labi/items/3b71b8f5ef065904c1de)
[（2021年版）iOSアプリをAppStoreで公開する手順まとめ](https://zenn.dev/moutend/articles/feebf0120dce6e6426fa)
[個人開発アプリのプライバシーポリシーを参考にしてみる](http://buchio.ever.jp/how-privacy-policy/)
[App Store提出用のスクリーンショットを無料で自作する](https://yaba-blog.com/app-store-screenshot/)
SwiftプロジェクトにStub環境を入れる

## 背景
ほとんどのアプリはサーバーAPIを連携して動くのが一般的ですね。
もし、サーバー側の開発が終わってない時はWebAPIがないまま開発することになる。これはよくあるパターンですが、APIがないまま開発するのは限界があるのでこんな時にスタブ環境構築しておけばとりあえずAPI連動開発もしやすくなります。
サーバー側からAPIが準備できなくても大体はインターペース定義書ぐらいはあるはずなのでそれを元にスタブを作り、ローカルでもテストができます。

今回、やりたいのは、

- Requestがあった場合、事前に定義したjsonファイルを読み込み、そのデータをResponseにしたい。
- 特定な`Host`や`Path`で判定し、スタブで実行するかどうかを設定できるようにしたい。

## ライブラリー導入
ネットで調べると[OHHTTPStubs](https://github.com/AliSoftware/OHHTTPStubs)がよく使われているらしいです。
Swiftでも使えるので問題なし。
使い方は上記のリンクで細かく説明がありますのでご参考を。

### ます、入れましょう。

`podfile`へpod追加します。

```
pod 'OHHTTPStubs/Swift'
```
そして、`pod install`

### Response用Jsonファイル追加
Responseに連携したいプロジェクトにリソースとして追加します。

例） hoge.json

```json
{
    "args": {
        "foo1": "bar1",
        "foo2": "bar2"
    }
}
```

### コードを書く

#### ライブラリーインポート
```
import OHHTTPStubs
```

#### 初期化処理のメソッド

```swift
private let stubHost = "test.hoge.com"
private let stubReponseDelay = 0.5  // Response遅延時間設定

private func initializeStubConfiguration() {
    HTTPStubs.setEnabled(true)    // StubをOnにする
    
    // MARK: Add stub endpoint.
    stubEndpoint(path: "/test/hoge", file: "hoge.json")
    
}
```

#### 登録用メソッド
エンドポイントをjsonファイルとマッピングするメソッド。特定の`Host`, `Path`によりJSONファイルを制御するようにします。

```swift
private func stubEndpoint(path: String,
                          file: String,
                          status: Int32 = 200,
                          headers: [String: String]? = ["Content-Type": "application/json"]) {
    
    /*
    // Pathだけで判定してstub環境に切り替えならこれでいい。
    stub(condition: isPath(path)) { _ in
        let stubPath = OHPathForFile(file, type(of: self))
        return fixture(filePath: stubPath!, status: status, headers: headers)
            .requestTime(self.stubReponseDelay, responseTime:OHHTTPStubsDownloadSpeedWifi)
    }
    */
    
    stub { [weak self]  (request) -> Bool in
        
        guard let `self` = self else { return false }
        
        return request.url?.path == path && request.url?.host == self.stubHost
        
    } response: { _ -> HTTPStubsResponse in
        
        let stubPath = OHPathForFile(file, type(of: self))
        let response = HTTPStubsResponse(fileAtPath: stubPath!, statusCode: status, headers: headers)
        response.requestTime = self.stubReponseDelay
        response.responseTime = OHHTTPStubsDownloadSpeedWifi
        return response
    }
}
```

## 切り替え設定（おまけ）
`Build Target`、`Build Setting`値でスタブ環境の切り替えを行いたいので下記の様に設定しておく。

`Build Setting->Add User-Defined Setting`を選択
`STUB_ENABLED`を追加、値は`YES`に入力

`info.plist`に`Build Setting`に定義してある設定をしておく(Key追加)
`StubEnabled -> ${STUB_ENABLED}`

#### コードで読み込み

```swift
// NOTE: Stub設定がtrueの場合のみ実行
if let stubEnabled = Bundle.main.object(forInfoDictionaryKey: "StubEnabled") as? String, stubEnabled == "YES" {
    initializeStubConfiguration()
}
```

以上
【BizRobo!】計算されたキー(Calculated Key)の設定方法

# はじめに
現在、RAPを実務で行っていますが、まだまだまだまだ経験が浅く、日々勉強中です。
本記事については、自身の備忘録も含め同じ様な所で頭を抱えている方に対して、
少しでもヒントになり、先に進める力となれれば良いなと思い記事にしましたーー！

## 今回のTips
今回の内容は、DAで何かのステップを作成する際の一つとして実装されている「計算されたキー(Calculated Key)」について、ご紹介します。

knowledgeからの抜粋ですが、計算されたキー(Calculated Key)とは以下になります。
>「キー プレス（Press Key） ステップ」は、キーボードのキーを入力する操作をロボットに実行させるステップです。「キー プレス ステップ」を追加すると「標準キー（Standard Keys）」の中から入力したいキーを選択できるようになります。
「標準キー」には無いキー入力（"Print Screenキー"、"Deleteキー"、"テンキー側のエンターキー"等）や3つ以上のキーを同時に押す操作をロボットに実行させる場合は、「キー」項目を「計算されたキー（Calculated Key）」に設定し、キーコードを入力します。
「標準キー」が正常に動作しない場合にも「計算されたキー」を設定してください。

通常であれば、下半分に表示されている画面からクリックステップなどを作成しますが、
計算されたキー(Calculated Key)を使用すると、仮想キーを使用した処理が作成できます。
どんな時に有効かというと、Windows系のキーボードショートカットで、3つ以上のキーを同時押ししたい場合などは、通常の設定だと「Ctrl + A」など2つまでしかキー押下できませんので、計算されたキー(Calculated Key)が有効になります。

## Tips概要
詳しい内容は、以下のknowledgeをご覧ください。
[▼キーコードで操作する](https://knowledge.bizrobo.com/hc/ja/articles/360027502651-Calculated-Key%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%96%B9%E6%B3%95)

また、計算されたキー(Calculated Key)で使用する仮想キーについては、以下のknowledgeをご覧下さい。
[▼代表的な仮想キーコード一覧](https://knowledge.bizrobo.com/hc/ja/articles/360037912092?source=search)

また、通常のキー設定で上手くクリック出来ない場合も、計算されたキー(Calculated Key)の設定は有効ですので、試してみるのもありです！
Firebaseの様々な機能

# Firebaseの様々な機能
チュートリアルの延長線でFirebaseを使うことが多いですが、
Authentication,Cloud Firestore, Cloud Storageぐらいしか使ったことがありません。
Firebaseに他にどんな機能があるのか気になり、その他の機能についても調べてみました。
「もっとこんな便利な使い方があるよ」「それならこっちのサービス使ったほうがいい」などあればコメントで教えてください！

## Authentication
Authenticationは、新規ユーザー登録やログインのような認証システムを簡単に実装できる機能です。
認証方法には、一般的なメールアドレスとパスワードで認証する方法から、
Twitter, Google, Facebook, GitHubなどのアカウント認証があります。
また、カスタム認証システムも提供されており、それを利用することで他のSNSアカウント認証を作ることもできます。

## Cloud Firestore
Cloud FirestoreモバイルアプリやWebアプリのデータを保存したり、持ってきたりすることが簡単にできるNoSQLデータベースです。
メンテナンスなしで、容易にスケールできるサーバーレスのドキュメントデータベースのため、
初めてデータベースを使うモバイルアプリを作るときに使うことが多いと思います。
初心者向けのチュートリアルを見ていると、だいたいはFirebaseを使っています(かなり主観)。

## Realtime Database
Realtime Databaseは、クラウドホスト型のNoSQLデータベースで、JSON形式で保存されます。
正直、 Cloud Firestoreがあると、Realtime Databaseを使う必要があるのかわかりません。
コメント欄で、あえてRealtime Databaseを使う理由があれば初心者にもわかるように教えてほしいです。

## Cloud Storage
Cloud Storageは、ユーザーが作成した写真や動画をアップロードやダウンロードできる機能です。
アップロードした写真や動画などはバイナリーデータなどで保存されます。
Cloud Storage、オートスケールに対応しているため、コンテンツの参照が増えた場合に、手動でスケールする必要はありません。

## Analytics
Analytics、アプリでのユーザーの行動を分析できる機能です。
年齢、性別、端末などの属性別のユーザー分析、Googleアナリティクスでも実装されているコホート分析
プッシュ通知の分析、広告やイベントのアトリビュート分析などが簡単にできるように提供されています。

## Crashlytics
Crashlyticsは、アプリがクラッシュしたときに検知してくれたり、その原因を調査する手助けをしてくれたりする機能です。
クラッシュの原因や事前の出来事だけではなく、クラッシュの優先順位を把握できます。
また、リアルタイムアラートを設定しておくと、クラッシュをすぐに検知でき、見逃さないようにできます。
クラッシュレポートは解析画面で見れるため、Analyticsの一部かなと思います。

## Hosting
Hostingは、シングルページのWebアプリやモバイルアプリのランディングページを簡単にデプロイできる機能です。
サーバーの構築や、レンタルサーバーの契約などが必要なく、シンプルなWebページであれば簡単にデプロイできます。
個人的には、GitHub Pagesの方が使うんだろうなと思います。

## Cloud Messaging
Cloud Messagingは、アプリでメッセージや通知を送受信できる機能です。
Cloud Messagingを使うと、特定のセグメントに対して、メッセージを送るようなことができます。
また、メッセージをタイムゾーン別にスケジュール配信することもできます。
[JavaScript] class取得した値にaddEventListenerは使えない

##はじめに
JavaScriptでclassを取得してaddEventListener使ったら、エラーが出たので、自分なりに原因を突き止めてみました。
間違いや、補足知識などあればガンガンコメントしていただけると幸いです！
よろしくお願いします！

##前提として

今回、簡略化しわかりやすく説明するために、一部分のコードしか載せておりません。
しっかりと説明できるよう努めますのでよろしくお願いします。

問題が発生したコードの記述がこちらです↓

```JavaScript
const studentName =document.getElementsByClassName("student_name");

studentName.addEventListener("click", function() {
  // 以下省略
});
```

これは取得したclass名の要素をクリックしたら、イベント発火するように意図した記述となります。ちなみにこのclassで取得した要素は複数あります。

もちろん私は複数の要素全てにaddEventLisnerでイベント発火させたくてこの記述をしました。
しかし、うまく動きませんでした。。。

##原因と対策①
この原因はどうやらaddEventListenerは一つの要素にしかかけられないようです。
もし、複数の要素に対して、全てにこの効果を適応したい場合（今回のように定数に複数要素が格納されている場合）は繰り返し処理を行って、一つづつ要素を取り出して、一つづつ丁寧にaddEventListenerをかけてやります！

**forEach**を使って繰り返し処理を加えました↓

```JavaScript
const studentName =document.getElementsByClassName("student_name");

studentName.forEach(function(student_name) {
  student_name.addEventListener("click", function() {
  // 以下省略
});
```

よし、これで全ての要素に対してイベント発火できる！と思ったのですが、また全然動きませんでした。一体どうして欲しいんだ。。。

##原因と対策②
原因としては、forEachメソッドは「HTMLCollection」に使えないことです。

どういうことかというと、getElementsByClassNameで所得した複数の値は、**HTMLCollection**というものなのです。
そしてforEachはHTMLCollectionには使えないので、何も反応がなかったのです。

試しにブラウザ上でconsole.logでgetElementsByClassNameで所得した値を出力してみれば、HTMLCollectionと出てきます。

forEachは配列に対しては仕事をしてくれるらしいので力技でこいつを配列に変えます。

```JavaScript
const studentName =document.getElementsByClassName("student_name");
const studentNames = Array.from(studentName);

studentNames.forEach(function(student_name) {
  student_name.addEventListener("click", function() {
  // 以下省略
});
```

2行目の記述でHTMLCollectionを配列に変えて、新しい定数studentNamesに代入しています。forEachを使う定数もstudentNamesに変更しました。

これで取得してきたすべての要素に対してaddEventListenerがイベント発火できるようになりました。

##おまけ
今回、getElementsByClassNameで取得してきた値はHTMLCollectionで返されていることを学びました。そしてforEachメソッドはそれに対しては使えません。

では同じようにclass名から要素を取得する方法として、**querySelectorAll**がありますが、この場合どうなるのでしょうか。

実際試してみました！
これが面白いことに、わざわざ配列に変更しなくても、addEventListenerを使うことができたのです。

調べたところ、querySelectorAllで取得すると、**NodeList**というもので返ってきます。
NodeListもHTMLCollectionと同様、複数の要素を格納しているようですが、配列とは別の存在です。だけど！NodeListにはforEachは使えました 笑

つまり、はじめからquerySelectorAllで取得すれば、「原因と対策②」で紹介したような、配列に直す作業はしなくて済みます。
こちらでclass名から取得する方法はgetElementsClassNameとは少し違いがありますのでお気をつけください。
↓こちらの記事を参照していただければと思います
[ HTMLを取得するメソッド三種](https://qiita.com/minhee/items/786c04e1259c04209b47)

##終わりに
今回このエラーにハマって、新しく得られた学びがたくさんあってとても有意義な時間を過ごせました！そして、また、こうしてまとめて発信できる環境もあって本当にこの時代は恵まれているなーと感じます。
laravel から vue.jsへの値の受け渡し

vue.jsの勉強を始めて二週間くらいです。今までやったことといえばvueのチュートリアルくらい
そんな僕がvueをとりあえず実践で使ってみようとlaravel bladeの中で使ってみたら思いのほか躓いたという話です。


###やりたいこと

```laravel.blade.php
<div id="test">
   @foreach( $informations as $information )
     <example-vue information_id="{{$information['id']}}"><example-vue>
   @endforeach
</div>
```

こんな感じでbladeの中でforeachで取り出した値をなんとかしてvueで使いたいなあ…と考えていました。
が、やり方が分からない。
これで一夜「laravel vue 値 受け渡し」みたいな単語で何度も検索していました。

#全然簡単だった件

なんとかできるようになりました
が、終わってみると全然簡単でした。

propsなるものがあるそうで

```vue.js
<script>
Vue.component('example-vue',{
  props: ['information_id'],
  template: '<p>@{{information_id}}</p>'
})

new Vue({ el: '#test' })
</script>
```

こんな感じでpropsでカスタムプロパティーにセットした値を受け取れます。


###終


なんだ！めっちゃ簡単じゃんｗｗｗ
てかチュートリアルにもあったはずなのになんで忘れてしまうん・・・
[Android]This version of Android Studio cannot open this project, please retry with Android Studio (hogehoge_version) or newerになった時の解消法

#解決策
cloneした時に、そのリポジトリのgradleのプラグインバージョンが手持ちのバージョンより最新であるとこのようなエラーが表示されます。
要は、「更新」が必要ってことですな。
でも、更新をしなくても、逆更新（笑）、つまりバージョンを下げれば解決します。

####Help -> About
でAndroidStudioのバージョンを確認します。
そして、gradleファイルのclasspathを確認したバージョンにします。

#追記：飽くまでも最終手段です！
ちゃんとダウンロードしましょう。
【M1チップ/Docker/Rails6/MySQL5】デプロイ済みアプリをHEROKU環境でDocker構築するまでの道程

### やりたいこと
既存アプリに対してHEROKUでのdocker導入

### 環境
Ruby 2.6.5
rails 6.0
MySQL 5.6
M1チップ搭載MacOS

### 目次
[1.導入手順](#1-導入手順)
[2.発生したエラー](#2-発生したエラー)
[3.まとめ](#3-まとめ)



###1.導入手順

```
% heroku login
% heroku container:login
% heroku container:push web -a <アプリ名>
% heroku container:release web -a <アプリ名>
% heroku run rails db:migrate
```

###2. 遭遇したエラー

```
Error: Exec format error
```
heroku run rails db:migrate実行したとき
（heroku run consoleやrails c実行時も同様）

heroku logs --tailでエラーログ確認するもわからず、

[M1 MacでHeroku containerにデプロイしたらExec format errorと出て困った話](https://zenn.dev/daku10/articles/m1-heroku-container-trouble-exec-format-error)
⬆こちらの記事を参照させていただきました。  

```
% docker buildx build . --platform linux/amd64 -t <ユーザー名>/<アプリ名>:latest
```

上記コマンド実行時、またしてもエラー発生!


```
ERROR [10/12] RUN bundle exec rails webpacker:install
Errno::ENOSYS: Function not implemented - Failed to initialize inotify
```

　　
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">config/environments/development.rb の config.file_watcherを<br>config.file_watcher = ActiveSupport::FileUpdateChecker<br>に変更(ポーリングで検知するやつ)したらいけた。やっぱそうなのか。</p>&mdash; caffepocari (@caffepocari) <a href="https://twitter.com/caffepocari/status/1357962311059734530?ref_src=twsrc%5Etfw">February 6, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

⬆こちらの方のツイートを参照させていただきました。　　　　



```
- config.file_watcher = ActiveSupport::EventedFileUpdateChecker
＋　config.file_watcher = ActiveSupport::FileUpdateChecker
```
config/enviroments/development.rbを書き換えます。

```
% docker tag <ユーザー名>/<アプリ名> registry.heroku.com/<アプリ名>/web
% docker push registry.heroku.com/<アプリ名>/web
% heroku container:release web -a <アプリ名>
% heroku run rails db:migrate
%　　heroku open
```
あとはイメージをプッシュし、リリース


###3. まとめ
これで無事HEROKU上でDockerコンテナが起動できました。

ローカル環境のDockerイメージをビルドして本番環境に直接アップしました。


前回の記事はこちら➡[【M1チップ/Docker/Rails6/MySQL5】既存アプリをローカルでDocker環境を構築する道程で遭遇したエラー
](https://qiita.com/yunyun_engineer/items/a94e28a1cf5eb2c0ffdc)
ローカルで動かしたものを本番環境でも同様に動かすことができました。
Visual Studio Code  エディタとターミナル切り替え(Mac,Windows)

#結論
<details><summary>keybindings.jsonに設定を組み込む</summary><div>
「cmd+j」でターミナルとエディタの移動するサンプルです。

```
[
    {
        "key": "cmd+j",            "command": "workbench.action.terminal.focus",
                                    "when": "editorTextFocus"
    },
    {
        "key": "cmd+j",            "command": "workbench.action.focusFirstEditorGroup",
                                    "when": "terminalFocus"
    }
]
```

○keybindings.jsonの配置先
 Windowsの場合 C:\Users\(ユーザー名)\AppData\Roaming\Code\User
 Macの場合     $HOME/Library/Application Support/Code/User

</div></details>
iOS内蔵メールリーダーで、メール添付の日本語ファイル名の名前の後半が化ける(RFC2231形式の長いファイル名)

#はじめに

電子メール添付の日本語ファイル名の名前の後半が化ける現象が確認されました。

ファイル名の後半が化けます。前半は正常です。

確認するとiOS内蔵のメールリーダーで受信したときに化けるようです。（機材の都合でiPadOSで動作確認してます。）

送信メールリーダー(JISで送信):
Sylpheed 3.7.0 (Windows10)
DeepMail (Webメール。バージョン不明。)

受信メールリーダー:
iOS内蔵メール (iPadOS 14.6)

ファイル名の例
正常に表示:
「一二三四五.docx」

文字化けする例:
「一二三四五六.docx」
「一二三四五六七.docx」
「一二三四五六七八.docx」
「算算算算算算算算算算算算算算算算算算.docx」

日本語の6文字目(付近)から化けるようです。(DeepMailはだいたい6文字が限界。Sylpeedは6文字以上行ける場合が多い。)

なお、Mew6.8で送信すると化けません。

補足: Mewは拡張子がtxtだと属性がinlineになりiOS内蔵メールでは引用形式で表示されるためファイル名が見えないので、Mewで送信を試す時はMS-Word(拡張子docx)とかにしてください。属性がattachmentになります。

```
テキスト(txt)の時。
Content-Type: Text/Plain; charset=iso-2022-jp;
 name="xxxxx.txt"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="xxxxx.txt"
```


```
MS-Word(docx)の時。
Content-Type: Application/Vnd.openxmlformats-Officedocument.wordprocessingml.document;
 name="xxxxx.docx"
Content-Transfer-Encoding: base64
Content-Disposition: attachment; filename="xxxxx.docx"
```

#どんな感じで化けるか
どうも６文字目(付近)以降のJIS相当のASCIIコードが見えるようです。

サンプルファイル名「算算算算算算算算算算算算算算算算算算.docx」としますが、こんな感じ「算算算算算;;;;(一部省略);;;;.doc」になります。

なお、「算」はJISコードが「;;」です。

#原因(AppleMailのバグ)
試行錯誤した範囲ですが、おそらくこれが原因です。

ファイル名「算算算算算算算算算算算算算算算算算算.docx」はRFC2231形式にのっとり以下のようにASCIIコードに変換されます。

```MultiPartのヘッダ部分()
Content-Disposition: attachment;
 filename*0*=ISO-2022-JP''%1B%24B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B;
 filename*1*=%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B;
 filename*2*=%3B%3B%1B%28B.docx
```

ここで改行が入ったところから化けるようです。AppleMail(iOS)のバグです。

Mew6.8は化けません。何故かと調べたら、Mewは改行してませんでした。

```
Content-Disposition: attachment;
filename*=iso-2022-jp''%1B%24B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%3B%1B%28B%2Edocx
```

偶然Mewはバグを回避していたにすぎないです。

しかし、Mewの挙動に驚いたのですが、長さ制限とかないのでしょうか？

追記: 最大998文字だそうだ。ただし78文字が推奨。
 http://www.t-net.ne.jp/~cyfis/rfc/mail/rfc2822_ja-1.html#INDEX_2_1_1

追記2: 冒頭で「DeepMailはだいたい6文字が限界。Sylpeedは6文字以上行ける場合が多い。」と述べたがRFC2231形式に変換する規則の違いです。DeepMailはアルファベットも含めて16進数(%nn)に変換します。Sylpeedはアルファベットはそのままになります。記号のみ16進数(%nn)に変換します。そのため若干短くなり、改行(文字化け)するまで余裕が出ます。

追記3: ファイル名がRFC2231ではなくBエンコーディングの場合はファイル名(filename="=?ISO-2022-JP?B?....")が長くても改行しないのが正しい。
http://www.emaillab.org/essay/japanese-filename.html

#参考文献
https://www.atmarkit.co.jp/ait/articles/0104/10/news002.html
https://www.mew.org/~kazu/doc/newsletter/3.html
http://www.emaillab.org/essay/japanese-filename.html#rfc2231

#追記: JISコードのエスケープシーケンス

JISコードの開始エスケープは「ESC $ B」です。RFC2231だと「%1B%24%42」もしくは、Bはそのままにして「%1B%24B」です。
終了エスケープは「ESC ( B」です。RFC2231だと「%1B%28%42」もしくは「%1B%28B」です。

参考文献
http://x0213.org/wiki/wiki.cgi?page=%A5%A8%A5%B9%A5%B1%A1%BC%A5%D7%A5%B7%A1%BC%A5%B1%A5%F3%A5%B9

以上です。
httpd (pid ####) already running で apache が起動しない場合の対処

# 事象

VMのCentOS7を電源オフで落とした後、起動すると apache が起動失敗する。


```sh
[root@localhost ~]# systemctl restart httpd24-httpd
Job for httpd24-httpd.service failed. See "systemctl status httpd24-httpd.service" and "journalctl -xe" for details.
```

statusを確認すると`httpd (pid 1033) already running`と出力されている。

```sh
[root@localhost ~]# systemctl status httpd24-httpd.service
● httpd24-httpd.service - The Apache HTTP Server
   Loaded: loaded (/usr/lib/systemd/system/httpd24-httpd.service; enabled; vendor preset: disabled)
   Active: failed (Result: protocol) since 木 2021-06-24 11:25:56 JST; 21min ago
  Process: 1687 ExecStart=/opt/rh/httpd24/root/usr/sbin/httpd-scl-wrapper $OPTIONS -DFOREGROUND (code=exited, status=0/SUCCESS)
 Main PID: 1687 (code=exited, status=0/SUCCESS)
   Status: "Reading configuration..."

 6月 24 11:25:55 localhost.localdomain systemd[1]: Starting The Apache HTTP Server...
 6月 24 11:25:56 localhost.localdomain httpd-scl-wrapper[1687]: AH00558: httpd: Could not reliably determine the server's...sage
 6月 24 11:25:56 localhost.localdomain httpd-scl-wrapper[1687]: httpd (pid 1033) already running
 6月 24 11:25:56 localhost.localdomain systemd[1]: Failed to start The Apache HTTP Server.
 6月 24 11:25:56 localhost.localdomain systemd[1]: Unit httpd24-httpd.service entered failed state.
 6月 24 11:25:56 localhost.localdomain systemd[1]: httpd24-httpd.service failed.
```

# 原因
前回終了時のhttpdのPIDファイルが残っている。

# 対応

PIDファイルを削除。

```sh
[root@localhost ~]# find / -name httpd.pid
/opt/rh/httpd24/root/var/run/httpd/httpd.pid

[root@localhost ~]# mv /opt/rh/httpd24/root/var/run/httpd/httpd.pid /opt/rh/httpd24/root/var/run/httpd/httpd.pid.bk
[root@localhost ~]# systemctl restart httpd24-httpd
[root@localhost ~]# rm /opt/rh/httpd24/root/var/run/httpd/httpd.pid.bk
```

# 参考URL
https://piyolian.blogspot.com/2012/06/apache-httpd-pid-already-running.html
https://unix.stackexchange.com/questions/548776/how-to-avoid-systemd-pid-conflict-after-crash
【ビジネスマン必見】最低限抑えておきたいPCアプリ・サービス

# 業務効率に欠かせないアプリ
世の中には便利なアプリがたくさんあるので、それらを使って業務をより効率化させていきましょう。
特に難しいことはなく、導入するだけです。

## OSアプリ(Windows)
### clcl

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/83a28431-8790-57b8-2ad1-ff48a199a7f9.png)

業務効率化必須アプリ
直近コピーしたテキストを保存することができる(最大30個)
Alt+c でリストを出すことができる
また定型文など保存しておくこともでき非常に便利
※Macの場合はClipy

https://forest.watch.impress.co.jp/library/software/clcl/


## Chromeアプリ(拡張機能)
### AwesomeScreen

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/a2039312-466c-d321-58d8-ab363f9f937a.png)


スクショ&動画撮影ができるアプリ
微調整もつけやすく使い勝手の良いアプリ

https://chrome.google.com/webstore/detail/awesome-screenshot-screen/nlipoenfbbikpbjkfpfillcgkoblgpmj?hl=ja&


### Gyazo

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/3101a5f0-ddbd-c7b8-0aa7-925a6af789cd.png)

画像をURL化することのできるアプリ
SlackやChatWorkで共有する際に便利

こんな感じで画像にURLをもたせることができ、
楽に共有できます。

https://chrome.google.com/webstore/detail/gyazo/ffdaeeijbbijklfcpahbghahojgfgebo?hl=ja&

### RemoteDesktop


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/20590fda-95d6-6a9e-7f05-81e3dab953cf.png)

あまり使用頻度はないかもしれないが、
パスコードを発行→入力することで遠隔で他のユーザーのPCを外から操作することのできる神アプリ
エクセルだったりコーディングの際非常に便利

https://chrome.google.com/webstore/detail/chrome-remote-desktop/inomeogfingihgjfjlpeplalcfajhgai?hl=ja&

### LINE

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/b89b31f7-3fd9-73c1-9e89-26a4ccb16853.png)

通常アプリだとデバイスに依存するがChromeアプリだと同じGoogleアカウントで入ればどのデバイスからも使える為入れておくのが吉

https://chrome.google.com/webstore/detail/line/ophjlpahpchlmihnnnihgmmeilfjmjjc?hl=ja&

## おすすめWEBサイト
### bitly(URL短縮サービス)


![URL Shortener - .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/783feeac-3197-3f0b-deb7-284066056860.png)

GoogleのURL短縮アプリがなくなった今代用し得るサービス
長いURLも簡単に短縮することができる

https://bitly.com/

### Canva


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/ffd8edfb-c5c8-ecf1-6e7b-ec67318acd91.png)

パワーポイントやGoogleスライドでは作れないようなスライドが作成可能
またYoutubeサムネやブログのアイキャッチ画像なども簡単に作成可能

https://www.canva.com/

### iLoveIMG


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/2d342017-a1da-e988-4ec0-2b141c334b60.png)

画像の圧縮・画像サイズ変更など便利なツールが一括で使えるサービス
基本的に未ログインで無料で使うことができる

https://www.iloveimg.com/ja

# まとめ
他良さそうなアプリが出てくれば随時追加していきます。
無駄な工数を省けるアプリがたくさんあるのでどんどん活用していきましょう。
Elastic Search入門

###### Index
- 作成
  curl -X PUT localhost:9200/index
- 表示
  curl localhost:9200/index
- 削除
  curl -X DELETE localhost:9200/index

###### DocData
- 追加
  - curl -X POST localhost:9200/index/_doc/ -H "Content-Type: application/json" -d data
- id指定
  - curl -X POST localhost:9200/index/_doc/id -H "Content-Type: application/json" -d data
- 表示
  - curl localhost:9200/index/_doc/id
  - curl localhost:9200/index/_search
- 修正
  - curl -X POST localhost:9200/index/_doc/id -H "Content-Type: application/json" -d data
  - curl -X POST localhost:9200/index/_doc/ -H "Content-Type: application/json" -d "{¥"doc¥":{filedname:value}}" 
- 削除
  - curl localhost:9200/index/_doc/id

###### 検索
- curl localhost:9200/index/_search?q=filed:value
- curl localhost:9200/index/_search -H "Conten-Type: application/json" -d {query:{match:{filed:name}}}
- curl localhost:9200/index/_search -H "Conten-Type: application/json" -d {query:{match_all:{},from:0,size:10}}
- curl localhost:9200/index/_search -H "Conten-Type: application/json" -d {query:{match_all:{},from:0,size:10},_source:[filed:name],sort:{filed:{order:asc/desc}}}

###### 複数条件検索
- and {query:{bool:{must:[{match:{filed:name}}]}}}
- or {query:bool:{should:[{match:{filed:name},{match:{filed:name}}}]}}

##### 完全一致
- {query:{match_phrase:{filed:name}}}

###### higtlight
- {query:{match_phrase:{filed:name}},highlight:{fileds:{filed:{}}}}

###### mapping
Laravelでviewに共通の変数を渡す（ただし処理は一回で）

Laravel歴１ヶ月のど素人です。

DBから取得した結果をviewに共通の変数として渡したいって時にどうしたらいいのか、
公式を参考に作ってみました。


## とりあえず公式を参考に作ってみる

Laravel公式はこちら
https://readouble.com/laravel/8.x/ja/views.html


```php:ComposerServiceProvider
namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{

    public function register()
    {
    }

    public function boot()
    {
        View::composer(
            '*', 'App\Http\View\Composers\CategoryComposer'
         );
    }
}
```

```php:自前で作ったComposerクラス
namespace App\Http\View\Composers;

use App\Repositories\Category\CategoryRepository;
use Illuminate\View\View;


class CategoryComposer
{
    protected CategoryRepository $category;

    public function __construct(CategoryRepository $category)
    {
        $this->category = $category;
    }

    public function compose(View $view)
    {
        // DBからデータを取得してビューに渡す
        $view->with('category_groups', $this->category->getCategoryGroupList());
    }
}
```

## このままサイトを表示すると・・・


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143303/092363e2-2243-c23a-04e9-ba9b265392df.png)

N+1を検知するライブラリを仕込んでいたので、全ページで上記のアラートが出るように。。。
おそらくサイト全体のviewをパーツ化し読み込んでいるので、そのパーツをレンダリングするたびにSQLが実行されてしまっているようでした。

https://github.com/beyondcode/laravel-query-detector


また、以下のQiitaを参考に実装をしてみましたが、「middlewareの仕事じゃない！」とコードレビューで指摘を受けてしまい。。。。

https://qiita.com/kazuhei/items/7de36d5aab440b3f5928


## シングルトンにすることでSQL実行を一回に

こんな感じにすることで、同じ処理が何度も呼ばれることは無くなりました。


```php:ComposerServiceProviderを修正
namespace App\Providers;

use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;

class ComposerServiceProvider extends ServiceProvider
{

    public function register()
    {
        //　自前で作ったCategoryComposerをシングルトンに登録する
        $this->app->singleton(\App\Http\View\Composers\CategoryComposer::class);
    }

    public function boot()
    {
        View::composer(
            '*', 'App\Http\View\Composers\CategoryComposer'
         );
    }
}
```


```php:自前で作ったComposerクラスをすこし改良
namespace App\Http\View\Composers;

use App\Repositories\Category\CategoryRepository;
use Illuminate\View\View;


class CategoryComposer
{

    protected $category_group;

    public function __construct(CategoryRepository $category)
    {
        // DBから取得した結果をプライベート変数に保存しておく
        $this->category_group = $category->getCategoryGroupList();
    }

    public function compose(View $view)
    {
        // 何度呼ばれてもコンストラクタで取得しておいた結果を返すようにする
        $view->with('category_groups', $this->category_group);
    }
}
```

## おわり

ググり方が悪かったのか、なかなか解決できなかったのでqiita記事にしてみました。
別の方法が何かあればコメントもらえると嬉しいです。
Ubuntu20.04の環境構築

# はじめに
職場の廃却予定のPCをもらってきてUbuntu20.04を導入しました。
そのときインストールしたものをメモしておきます。

* 日本語入力
* Google Chrome
* Slack
* VScode
* Vim
* Curl
* Docker
* Python
* Node.js

# 日本語入力
```bash
sudo apt install ibus-mozc
sudo apt install mozc-data mozc-server
sudo apt-get install mozc-utils-gui fcitx-config-gtk
reboot

# このあと、toolの設定を行い、半角キーにてIMEを有効化設定を行う
```
https://www.ultra-noob.com/blog/2020/2020-07-04-Ubuntu(Linux)%E3%81%AE%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E8%A8%AD%E5%AE%9A%E3%82%92%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%81%AB%E5%A4%89%E3%81%88%E3%81%A6%E3%80%8C%E5%8D%8A%E8%A7%92_%E5%85%A8%E8%A7%92%E3%80%8D%E3%81%A7%E3%81%B2%E3%82%89%E3%81%8C%E3%81%AA%E3%81%AB%E3%80%8C%E7%84%A1%E5%A4%89%E6%8F%9B%E3%80%8D%E3%81%A7%E8%8B%B1%E6%95%B0%E5%AD%97%E3%81%AB%E5%A4%89%E3%81%88%E3%82%8B%E6%96%B9%E6%B3%95/


# Google Chrome
```bash
# ここからダウンロード
https://www.google.co.jp/chrome/

# インストール
cd Downloads/
sudo apt install -y ./google-chrome-stable_current_amd64.deb
```
https://inab818.site/ubuntu-desktop/ubuntu-desktop-20-04-lts-google-chrome-download-aptinstall/

# Slack
```bash
sudo apt install snapd
sudo snap install slack --classic
```
https://tutorialcrawler.com/ubuntu-debian/ubuntu20-04%E3%81%ABslack%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/

# VScode
```bash
sudo apt update
sudo apt install software-properties-common apt-transport-https wget
wget -q https://packages.microsoft.com/keys/microsoft.asc -O- | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://packages.microsoft.com/repos/vscode stable main"
sudo apt install code
```
https://home.hirosaki-u.ac.jp/heroic-2020/1489/


# Vim
```bash
sudo apt install vim
```

# Curl
```bash
sudo apt install curl
```

# Docker
https://docs.docker.com/engine/install/ubuntu/

# Python
## pyenv
```bash
# 依存を下記まとめてインストール
sudo apt install -y \
build-essential \
libffi-dev \
libssl-dev \
zlib1g-dev \
liblzma-dev \
libbz2-dev \
libreadline-dev \
libsqlite3-dev \
git

# pyenv本体のダウンロードとインストール
git clone https://github.com/pyenv/pyenv.git ~/.pyenv

# .bashrcの更新(shimsを追加)
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc 
echo 'export PATH="$PYENV_ROOT/shims:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
source ~/.bashrc

pyenv -v
```
https://www.kkaneko.jp/tools/ubuntu/ubuntu_pyenv.html

https://qiita.com/neruoneru/items/1107bcdca7fa43de673d

https://qiita.com/mckyhrs/items/94a2db3506287df0420e


## Python 3.9.5
```bash
# インストール
pyenv install 3.9.5
pyenv versions

# グローバル環境で適用
pyenv global 3.9.5
```

# Node.js
## nodebrew
```bash
curl -L git.io/nodebrew | perl - setup
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
```
https://mongpa.hatenablog.com/entry/nodejs-install

## node 14.17.0
```bash
nodebrew ls-remote
nodebrew install v14.17.0
nodebrew use v14.17.0
```

## yarn
```bash
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add -
echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list
sudo apt-get update && sudo apt-get install yarn
yarn -v
```
https://loumo.jp/archives/23123
【第2回】Railsのjoinsとleft_outer_joinsの挙動と違いをまとめた

前回はN+1問題が発生する状況とタイミングについて解説しました。
→[【第1回】RailsのN+1問題と解決するためのメソッド完全版](https://qiita.com/kurokawa516/items/6c6e895843e199c52ac2)
もしまだご覧になっていなければ、一読していただけると理解がスムーズになります。

##本記事の内容
今回はN+1問題を解決するメソッドを5つ紹介していきます。

1. joins
2. left_outer_joins <=（本記事ではここまで）
3. eager_load
4. preload
5. includes

##joinsメソッド
SQLの``INNER JOIN句``が発行されます。（内部結合）
内部結合とは、指定したそれぞれのテーブルのカラムの値が一致するデータだけを取得する方法のことです。
内部結合についてはこちらを参考にすると理解しやすいです。
[内部結合を行う(INNER JOIN句)](https://www.dbonline.jp/mysql/join/index1.html)

###使い方

```ruby:例1
モデル名.joins(:関連モデル)
```

軸となるモデルに対してjoinsメソッドを呼び出し、引数で関連モデルを指定します。

```ruby:例2
モデル名.joins(:関連モデル)
```

**joinsメソッドは、関連モデルにあるカラムで絞り込みたい場合に使います。**

```ruby:例3
User.joins(:post).where('post.title = ?','ruby')
```

例3では、UserモデルとPostモデルを結合したうえで、whereメソッド（WHERE句）を使いPostモデルのtitleカラムがrubyの投稿を取得しています。
このように、joinsメソッドは、関連モデルにあるカラムで絞り込みたい場合に使います。

##left_outer_joinsメソッド
SQLの``LEFT_OUTER_JOIN句``が発行される。
参考：SQLでは``OUTER``を省略し、``LEFT JOIN``と書くこともできる。

###使い方

```ruby:例1
モデル名.left_outer_joins(:関連モデル)
```

軸となるモデルに対してleft_outer_joinsメソッドを呼び出し、引数で関連モデルを指定します。

```ruby:例2
User.left_outer_joins(:post)
```

**left_outer_joinsメソッドは、軸となるモデル(ここでいうところの``Userモデル``)の全レコードと、関連モデル（Postモデル）の指定した条件にマッチするレコードを取得します。**

下記の記事がわかりやすくまとめてあります。
*参考:[LEFT (OUTER) JOIN （左外部結合）を使ってデータを取得する](https://sql55.com/t-sql/t-sql-join-3.php)*

```ruby:例3
User.left_outer_joins(:post).where('post.title = ?','ruby')
```

``joinsメソッド``との大きな違いは、軸となるモデルの全レコードを取得することです。
必要に応じて使い分けるのがよいでしょう。

##まとめ
* ``joins``は、内部結合をおこない、指定したそれぞれのテーブルのカラムの値が一致するデータだけを取得する。
* ``left_outer_joins``は、軸となるモデルの全レコードを取得し、関連テーブルの条件にマッチしたレコードを取得する。
* ``joinsメソッド``と``left_outer_joins``の違いは、軸となるモデルの全レコードを取得すること。

5つのメソッドすべてを紹介しようと思いましたが、長くなりそうだったためここまでとします。
eager_load以降のメソッドは、joinsやleft_outer_joinsとはまた挙動が変わってくるので、ちょうどいいかなと思います。
それではまた次回、よろしくお願いします！
UIImageのメモリ上のサイズを取得する

**Swift 5:**

```Swift
let image = UIImage(named: "test")
if let cgImage = image?.cgImage {
    let size = cgImage.height * cgImage.bytesPerRow;
    print(size)
}
```

参考にした記事
https://stackoverflow.com/questions/25483931/ios-get-uiimage-memory-size
Stringのenumの配列に優先順位をつけて優先度が一番高いものを取得する方法(Comparable使う)

Comparable使えば良いよ

```Swift
public enum Emoji: String, Comparable {
    
    case neko = "😺"
    case inu = "🐶"
    case usi = "🐮"
    
    var priority: Int {
        switch self {
        case .neko:
            return 0
        case .inu:
            return 1
        case .usi:
            return 2
        }
    }
    
    public static func <(_ lhs: Emoji, _ rhs: Emoji) -> Bool {
        return lhs.priority < rhs.priority
    }
}
let emojis: [Emoji] = [.neko, .inu, .usi, .inu]
let topPriorityEmoji = emojis.max()
topPriorityEmoji?.rawValue //"🐮"
```

Comparable使えば別にStringでなくてもいいし、enumでなくてもよい
メモ限定公開

```

/** @jsx jsx */
import React, { useState } from 'react';
import { jsx, css } from '@emotion/core';

const or = "OR" 
const and ="AND";

export const Matchitem: React.FC = (props) => {
    const [selected, setselect] = useState(or);
        return (
            <div className="App">
            <button css=
            {selected === "OR" ? 
                css` border: 1px solid #5e81f4;
                font-weight: 600;
                color:#5e81f4;
                background-color: #bdccfb;`: undefined} //参考演算子
                onClick={() => setselect("OR")}>OR</button>
                <button
                    css= {selected === "AND" ? css` font-weight: 600;
                    color:#5e81f4;
                    background-color: #bdccfb;`: undefined} //参考演算子
                    onClick={() => setselect("AND")}>AND</button>
            </div>
        );
    }
export default Matchitem;

```
【M1チップ/Docker/Rails6/MySQL5】既存アプリをローカルでDocker環境を構築する道程で遭遇したエラー

### やりたいこと
既存アプリに対してローカル環境でのdocker導入

### 環境
Ruby 2.6.5
rails 6.0
MySQL 5.6
M1チップ搭載MacOS

### 遭遇したエラー
[1.ERROR RUN bundle install](#1-ERROR RUN bundle install)
[2.error Integrity check failed](#2-error Integrity check failed)
[3.ActiveRecord::NoDatabaseError](#3-ActiveRecord：：NoDatabaseError)
[4.Aws::Sigv4::Errors::MissingCredentialsError in items#index](#4-Aws::Sigv4::Errors::MissingCredentialsError in items#index)

###1.ERROR RUN bundle install

##### 発生したエラー

```
Could not locate Gemfile
bundle update --bundler
gem install bundler:2.1.4
```
Dockerfileとdocker-compose.ymlを書いて、docker-compose up　--buildを実行したとき

#####　解決方法
```Dockerfile
ENV BUNDLER_VERSION 2.1.4
RUN gem update --system \
    && gem install bundler -v $BUNDLER_VERSION \
    && bundle install -j 4
```

###2.error Integrity check failed
##### 発生したエラー

```
Your Yarn packages are out of date!
web_1  |   Please run `yarn install --check-files` to update.
```
docker-compose up　-dを実行したとき


#####　解決方法

```config/webpacker.yml
 - check_yarn_integrity: true
 + check_yarn_integrity: false
```
trueをfalseに変更


### 3.ActiveRecord::NoDatabaseError
##### 発生したエラー

```
Unknown database 'fridge_app_development'
```
docker-compose up　-dを実行してサーバーにアクセスして表示されないとき

#####　解決方法

```
% docker-compose exec web rails db:create
% docker-compose exec web rails db:migrate
% docker-compose exec web rails db:seed
```
ターミナルでコマンド実行。単純にDBを作るだけ

### ４.Aws::Sigv4::Errors::MissingCredentialsError in items#index
##### 発生したエラー

```
Cannot load `Rails.config.active_storage.service`: 
missing credentials, provide credentials with one of the following options:
 - :access_key_id and :secret_access_key
 - :credentials
 - :credentials_provider
```
docker-compose up　-dを実行してサーバーにアクセスして表示されないとき

#####　解決方法

```Dockerfile
environment:
      AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
      AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY

```
.envファイルで環境変数を宣言して、Dockerfileで展開するように追記

### まとめ

その他、細かいエラー等ありましたが、なんとかローカル環境でDocker導入できました。[次回はHeorkuでのDocker環境構築の記事を備忘録として書き留めます。](https://qiita.com/yunyun_engineer/items/7b7583750f8824554808)
React > 親から子のメソッドを呼ぶ


子の中にある`getAlert`メソッドを親から呼びたい時のサンプル

修正：`RefForwardingComponent`は`deprecated`だったので、`ForwardRefRenderFunction`に変更

```
/**
 * @deprecated Use ForwardRefRenderFunction. forwardRef doesn't accept a
 *             "real" component.
 */
interface RefForwardingComponent <T, P = {}> extends ForwardRefRenderFunction<T, P> {}
```


## PropsにInterfaceを使わない場合

子 (Child.tsx)

```Child.tsx
import React, { forwardRef, useImperativeHandle } from "react";

// 公開したいメソッドの定義
export interface ChildHandles {
  getAlert(): void;
}

// コンポーネントを `forwardRef` でラップする必要があります。
export const Child = forwardRef<ChildHandles>((props, ref) => {
  // コンポーネントのインスタンスが拡張されます
  // 第2引数として渡されたコールバックから返されたもので拡張されます
  useImperativeHandle(ref, () => ({
    getAlert() {
      alert("getAlert from Child");
    }
  }));

  return <h1>Hi</h1>;
});
```


親 (Parent.tsx)

```Parent.tsx
import React, { useRef } from "react";
import { Child, ChildHandles } from "./Child";

export const Parent = () => {
  // 子コンポーネントのインスタンスにアクセスするためには、`ref` に割り当てる必要があります。
  const childRef = useRef<ChildHandles>(null);

  const onClick = () => {
    childRef.current?.getAlert();
  };

  return (
    <div>
      <Child ref={childRef} />
      <button onClick={onClick}>Click</button>
    </div>
  );
};
```

codesandboxにサンプルをあげてます

https://codesandbox.io/s/parent-child-method-ok425


## PropsにInterfaceを指定したい場合


子 (Child.tsx)

```Child.tsx
import React, {
  forwardRef,
  useImperativeHandle,
  ForwardRefRenderFunction
} from "react";

// 公開したいメソッドの定義
export interface ChildHandles {
  getAlert: () => void;
}

export interface ChildProps {
  firstName: string;
  lastName: string;
}

const ChildComponent: ForwardRefRenderFunction <ChildHandles, ChildProps> = (
  props,
  ref
) => {
  // コンポーネントのインスタンスが拡張されます
  // 第2引数として渡されたコールバックから返されたもので拡張されます
  useImperativeHandle(ref, () => ({
    getAlert() {
      alert("we love " + props.firstName + " " + props.lastName + " !!");
    }
  }));

  return <h1>Hi</h1>;
};

// コンポーネントを `forwardRef` でラップする必要があります。
export const Child = forwardRef(ChildComponent);
```


親 (Parent.tsx)

```Parent.tsx
import React, { useRef } from "react";
import { Child, ChildHandles } from "./Child";

export const Parent = () => {
  // 子コンポーネントのインスタンスにアクセスするためには、`ref` に割り当てる必要があります。
  const childRef = useRef<ChildHandles>(null);

  const onClick = () => {
    childRef.current?.getAlert();
  };

  return (
    <div>
      <Child firstName="eric" lastName="martin" {...{}} ref={childRef} />
      <button onClick={onClick}>Click</button>
    </div>
  );
};
```

codesandboxにサンプルをあげてます

https://codesandbox.io/s/parent-child-method2-e3ydv


以上


## 参考

- https://medium.com/@jrwebdev/react-hooks-in-typescript-88fce7001d0d
- [React \- useRef с TypeScript и функциональным компонентом \- CodeRoad](https://coderoad.ru/60554808/React-useRef-%D1%81-TypeScript-%D0%B8-%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%BE%D0%BD%D0%B0%D0%BB%D1%8C%D0%BD%D1%8B%D0%BC-%D0%BA%D0%BE%D0%BC%D0%BF%D0%BE%D0%BD%D0%B5%D0%BD%D1%82%D0%BE%D0%BC)
Firebaseの新規ユーザ登録を禁止する

#１．まとめ
* Firebase Authenticationのログイン機能(EmailAuth)で、signInOptionsのパラメータにdisableSignUpを使えば、UI画面からの新規ユーザの登録を制限できる。

#２．問題

* Firebaseはウェブアプリ作るのに便利で使わせてもらっているが、[デフォルトのログイン機能](https://firebase.google.com/docs/auth)を実装すると、そのままだとログイン画面で勝手に新規ユーザ登録がされてログインされてしまう。SNS等はこれで便利だが、ちょっとクローズなサイトなどは勝手に入ってきてもらうと困る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/6caa1c30-ec66-a992-42f2-2d9c9fbd5d97.png)

↓
↓
↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/159b6f89-3432-fded-ce33-3d4109cabe2f.png)

↓
↓
↓

<font color="red">ログイン成功！！！</font>


* 従来、これを禁止する方法として、独自にログインフォーム作れとか、登録はできてもすぐに無効化するとか色々議論されたりしていた様子。詳細は[ここ](https://qiita.com/41semicolon/items/d1c8503c3c5b1adfc510)

* 今年の３月くらいに、[signInOptionsのパラメータにdisableSignUpが追加されていて、これを使えばOK](https://github.com/firebase/firebaseui-web#configure-email-provider)と判明(下記は適用結果）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/6caa1c30-ec66-a992-42f2-2d9c9fbd5d97.png)

↓
↓
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385220/c8a9db37-89ae-f93d-5c1b-7e8384ae313f.png)



*一方、上記の設定ファイルではAPI経由での登録は制限できないようなので、別途対策が必要とのこと。
>Note that this flag will only disable sign up from the UI and will not prevent sign up via REST API. It is highly recommended that Identity Platform projects enforce this policy via one of these 2 mechanisms:
>*Blocking functions: Set a beforeCreate trigger to disable sign up for email providers.
*In the Cloud Console / Settings / USERS tab, uncheck Enable create (sign-up) checkbox. Though for this setting, sign up for all providers will be disabled.




２．具体的な書き方
[ここ](https://github.com/firebase/firebaseui-web#configure-email-provider)に「signInOptionsに追加して」、と書いてあるのだが、どう書けばいいのかわからずに困った。
結局、下記のようにsignInOptionsを書けばいいのだと判明したので参考でメモ。
disableSignUp: {status:true}　⇒がミソ

```javascript
//4.8.0が必要とのこと
    <script src="https://www.gstatic.com/firebasejs/ui/4.8.0/firebase-ui-auth.js"></script>
    <link type="text/css" rel="stylesheet" href="https://www.gstatic.com/firebasejs/ui/4.8.0/firebase-ui-auth.css" />

//・・・略・・・

var uiConfig = {
      callbacks: {
        signInSuccessWithAuthResult: function(authResult, redirectUrl) {
        return true;
        },
        uiShown: function() {
        // The widget is rendered.
        // Hide the loader.
        document.getElementById('loader').style.display = 'none';
        }
      },
    signInFlow: 'popup',
    signInSuccessUrl: 'success.html',
    signInOptions: [{
      provider:firebase.auth.EmailAuthProvider.PROVIDER_ID,
      disableSignUp: {status:true}
    }
    ],
    // Terms of service url.
    tosUrl: 'terms-of-services.html',
    // Privacy policy url.
    privacyPolicyUrl: 'privacy-pocily.html'
   
};


      var ui = new firebaseui.auth.AuthUI(firebase.auth());
      ui.start('#firebaseui-auth-container', uiConfig);

//・・・以下略・・・

```


設定を反映させるのに
disableSignUp.status(true)
とか
disableSignUp.status=true
とか色々試してだめだった結果、２〜３時間かかってしまった。
OpenMPI (GPU Direct対応)をビルドする

スパコン上でGPU Direct対応のOpenMPIをビルドしたのでその方法を記述します。
通常のクラスター計算機でも一部の環境設定を変更すれば、同様の方法でビルドできると思います。

## 実施した環境
- Cray CS-Storm
- CPU: Xeon Gold 6150 x2 (36core)
- Mem: 768 GiB
- GPU: NVIDIA V100(PCIE) x10
- I/F: Infiniband 
- OS: CentOS 7系

スパコン上では下記の環境設定コマンドを実行しました。
通常のクラスターであれば、cuda 10.2とgcc 6.1.0の環境と同等です。

```
$ module switch cudatoolkit/9.0.176 cudatoolkit/10.2.89
$ module switch intel/17.0.4 gcc/6.1.0
```


## OpenUCXのビルド
高速インターコネクト(Infiniband)のライブラリ。

https://github.com/openucx/ucx

バージョン1.10.0を使用しました。
ダウンロードと展開。

```
$ wget https://github.com/openucx/ucx/releases/download/v1.10.0/ucx-1.10.0.tar.gz
$ tar xvfz ucx-1.10.0.tar.gz
$ cd ucx-1.10.0
```

続いてconfigureおよびmakeを行います。
CUDAのバージョン指定やAVXなどCPUに合わせた最適化とInfinibandのmellanoxドライバに合わせたオプションを追加しています。

```
$ ./configure --prefix=${HOME}/OpenMPI/ucx-1.10.0 --with-cuda=/usr/local/cuda-10.2 --enable-optimizations --with-avx --with-mcpu --with-march --with-mlx5-dv --with-ib-hw-tm
$ make
$ make install
```

## OpenMPIのビルド
いよいよOpenMPI本体のビルドです。
本記事では、4.1.0を使用しました。

https://www.open-mpi.org/

ダウンロード展開

```
$ wget https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.0.tar.gz
$ tar xvfz oepnmpi-4.1.0.tar.gz
$ cd oepnmpi-4.1.0
```

configureの前に先程ビルドしたOpenUCXのパスを設定しておきます。

```
$ export PATH=${HOME}/OpenMPI/ucx-1.10.0/bin:$PATH
$ export LD_LIBRARY_PATH=${HOME}/OpenMPI/ucx-1.10.0/lib:$LD_LIBRARY_PATH
```

configureとmakeを実施します。
ジョブ制御PBSの指定（省略可）、ucxの指定、CUDAの指定などを行なっています。

```
$ ./configure --with-verbs --prefix=${HOME}/OpenMPI/openmpi-4.1.0 --with-tm=/opt/pbs/13.1.3.170747 --with-ucx=${HOME}/OpenMPI/ucx-1.10.0 --enable-orterun-prefix-by-default --with-cuda=/usr/local/cuda-10.2 --with-gnu-ld --enable-mpi-cxx CC=gcc CXX=g++ LDFLAGS=-ldl
$ make -j 4
$ make install
```

## 動作確認

ビルドしたOpenMPIを使用するため、下記の環境変数を設定する。

```
export MPIROOT=${HOME}/OpenMPI/openmpi-4.1.0
export PATH=$MPIROOT/bin:$PATH
export LD_LIBRARY_PATH=$MPIROOT/lib:$LD_LIBRARY_PATH
```

コンパイラおよびmpirunの確認。

```
$ mpicc --version
gcc (GCC) 6.1.0 20160427 (Cray Inc.)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ mpirun --version
mpirun (Open MPI) 4.1.0

Report bugs to http://www.open-mpi.org/community/help/

```

###mpirun実行時の設定

mpirun実行時にInfinibandの環境変数を設定しないとエラーとなりました。
実行時に必要な環境変数設定をまとめると下記です。
ジョブスケジューラで実行する場合は、PBSジョブスクリプトに下記をまとめて記載します。


```
# CS-Storm環境の場合のCUDA, GCC設定
module switch cudatoolkit/9.0.176 cudatoolkit/10.2.89
module switch intel/17.0.4 gcc/6.1.0

# UCX環境設定
export PATH=${HOME}/OpenMPI/ucx-1.10.0/bin:$PATH
export LD_LIBRARY_PATH=${HOME}/OpenMPI/ucx-1.10.0/lib:$LD_LIBRARY_PATH

# OpenMPI環境設定
export MPIROOT=${HOME}/OpenMPI/openmpi-4.1.0
export PATH=$MPIROOT/bin:$PATH
export LD_LIBRARY_PATH=$MPIROOT/lib:$LD_LIBRARY_PATH

# Infiniband環境設定
export OMPI_MCA_btl_openib_allow_ib=1
export OMPI_MCA_btl_openib_if_include="mlx5_0:1"
```

OMPI_MCA_btl_openib_if_includeには、ibstatコマンドを実行してCAの行に表示される値(OFEDのバージョン)を設定する。
iOSデバイスでのRAMサイズの取得

**Swift 5:**

```Swift
ProcessInfo.processInfo.physicalMemory
```
GBでの取得の場合

```Swift
ProcessInfo.processInfo.physicalMemory / (1024 * 1024 * 1024)
```
参考にした記事
https://stackoverflow.com/questions/20211650/total-ram-size-of-an-ios-device
postgresでのview確認方法

## POSTGRESでのView確認方法

psqlで確認する際よく忘れて何度も調べるので備忘録として記載

### view hogehogeを確認

表示

``` 
\d+ hogehoge
```

SQLで確認

```
SELECT definition FROM pg_views WHERE viewname = 'hogehoge';
```

ファイルに出力

```
\o ファイル名.txt
SELECT definition FROM pg_views WHERE viewname = 'hogehoge';
\q
```

バックアップ・リストア

```
pg_dump -h hostname(or IP) -U user -t hogehoge database > hogehoge.sql
psql -f hogehoge.sql  -U user -d database -h hostname(or IP)
```
SendGridのDynamicTemplateでtext/plainなメールを送信する方法

知ってる人には当たり前かもしれないのですが、DynamicTemplateばかり使ってるとこの方法が全然わからず、記事も全然出てこなかったので備忘です。

```C#
var message = new SendGridMessage
{
    TemplateId = templateId,
    Personalizations = personalizations,
    Contents = new List<Content>
    {
        new Content
        {
            Type = "text/plain",
            Value = "<% body %>"
        }
    }
}
```

SendGridMessageのContentsにtext/plainのみを指定したContentを入れれば送信できました。
<% body %>はDynamicTemplateの中身で展開されるらしい。

templateIdやpersonalizationsについては公式ドキュメント見れば書いてあるのでこちらは大丈夫なはず。
Cordova：InAppBrowserのエラー処理で林檎にしてやられた件

良い子の皆さんは、InAppBrowserをそのままエラー処理なしで使ってなんかないと思います。

僕はクズ野郎なのでエラー処理なしで使ってました。
そうすると、ネット接続不良時とか、画面が真っ白になってアプリが死にます。クレーム殺到オワタ！(*^-^*)ﾉミ_☆

というわけ、ようやく一般常識に気づいた僕は、InAppBrowserのエラー処理を実装してみました！

```javascript
            this.Ref.addEventListener("loaderror", function(){
                // なんか処理
            });
```

えらい！これでぼくもまっとうなぷろぐらまーだ！

と思ってたら、iPhoneでエライことになります。
どうもiOSの場合、InAppBrowserでリンク先への遷移実行中（ブラウザが考えてるとき）に再度リンクをタップするとエラーが発生するらしいです。クレーム殺到オワタ！(*^-^*)ﾉミ_☆


```javascript
            this.Ref.addEventListener("loaderror", function(e){
               if(e.code == -999){

                   return;
                }

                 //なんか処理
            });
```

これで大丈夫。
安心してリリースできます。


……と思ったら、さらに問題が発生。
エラー後にlocal側のエラーページにて、再度InAppBrowserを起動する処理をしたら、InAppBrowser側の描画領域（アス比？ｗ）がおかしいときがアリンス。
画面下端のボタンとか消えてるｗｗｗ

色々試したけど全部ダメだったので、とりあえず放置してリリースしました。
解決方法募集中。
林檎果樹園を焼き討ちしたい。