OmniAICreator/Qiita-1.07M huggingface dataset:
Cloud functionsで画像アップロードの無限列車の旅

# あらまし

Cloud functionsでCloud storageにアップロードされたファイルをリサイズして上書きすると無限ループが発生する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38174/37fec59c-c56c-9766-4d49-84aee754e8ca.png)

# 詳細

Cloud functionsでstorageのonFinalizeをトリガーにしていると、ファイルのアップロードと更新のたびにこの関数が呼ばれることになります。
で、同じファイル名でファイルをアップロードすると、再度onFinalizeのトリガーが呼ばれて無限に関数が呼ばれるというループに陥るということでした。

## 問題点1 サンプルコードが不親切

このサンプルコード、ファイル名に「thumb_」とついていたらすでに処理済なので処理しないという判定を入れていますが、それだと同じファイル名でアップロードした場合はファイル名で判定できないため使えません。

[Cloud Storage を Cloud Functions で拡張する  |  Firebase](https://firebase.google.com/docs/storage/extend-with-functions?hl=ja)

そこでmetadataなるもので印をつけて、判定しようということらしんですが、これにもハマりました。

## 問題点2 metadataの更新の仕方が深い(ネスト)

単純に

```
await bucket.upload(<ファイルパス>, {destination: <アップロード先>, metadata: {isConverted: true}});
```

としただけでは、metadataは更新されません。というか、metadata自体が消えてしまいます。

ここもサンプルコードが意図した動きになっていないとしか言えませんが、metadataの指定は、metadataをmetadataで包む必要があるようです。

ただしくはこちら

```
await bucket.upload(<ローカルファイルパス>, {destination: <アップロード先>, metadata: {metadata: {isConverted: true}});
```

### 参考

- [stackoverflow metadata-not-saving-when-uploading-a-file-through-google-cloud-functions](https://stackoverflow.com/questions/57677732/metadata-not-saving-when-uploading-a-file-through-google-cloud-functions)
- [Firebaseのfunctionsでadmin.storage().bucketを使って画像をアップロードした時に困ったこと集](https://qiita.com/HorikawaTokiya/items/8d0a9075bc49ea3e74e1)

ここのサンプルコードは間違っていないように見えるが、実際は間違ってます。気持ち的にはサンプルコードの書き方が自然な気もしますが、理由があるのか、medadataの下にmetadataを設定しないと更新されません

https://firebase.google.com/docs/storage/extend-with-functions

正しそうなサンプルコードはこちらにありました

https://googleapis.dev/nodejs/storage/latest/Bucket.html#upload

## 問題点3 metadataに含まれるfirebaseStorageDownloadTokensは必要

デフォルトでmetadataに設定されている`firebaseStorageDownloadTokens`という項目は、消さないほうが良さそうです。というのも、これがなくなるとfirebase consoleでプレビューしたときに画像が表示されません。
ここは謎仕様というか、どこかに説明があってもいいものだと思いますが、試行錯誤の上見つけた内容です。

画像のリサイズなどで、新しくmetadataを設定したい気持ちはありますが、この`firebaseStorageDownloadTokens`の値を残すか、埋め込むかをしておいたほうがのちのち楽になりそうな気がしています。
なくても動くので問題ないとは思いますが、firebase consoleで画像が確認できるのは楽ですね。

# 実際の判定方法

こんな感じで、関数の最初にチェックを入れました。

```
exports.generateThumbnail = functions.storage.object().onFinalize(async (object) => {
  let metadata = object.metadata
  if (!object.contentType || !object.contentType.startsWith('image/')) {
    return console.log('This is not an image.', object.contentType);
  }
  if (metadata.isConverted) {
    return console.log('Already converted. first.');
  }
```

また、画像アップロード時のmetadataはもともとのmetadataに`isConverted`を設定する方法にしました。`firebaseStorageDownloadTokens`をなんとなく残したいため

```
  metadata["isConverted"] = true
  await bucket.upload(<ローカルファイルパス>, {destination: <アップロード先>, metadata: {metadata: metadata}});
```
MacでReactNative開発を始める

##目的
アプリでも作ってみようかな。
参考にした、先人たちが作った手順を纏めています。

##環境構築
- 参考にした手順
    - https://dev-yakuza.posstree.com/react-native/install-on-mac/#homebrew%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB
    - brew cask → brew でOK
    - brew caskコマンドは廃止になった？
        - https://qiita.com/segur/items/373e6a78d1518e49e1eb

####トラブルシュート
- Node.js/npmインストール（アップデート）
    - https://parashuto.com/rriver/tools/updating-node-js-and-npm
- gem installでpermissionエラー
    - https://qiita.com/nishina555/items/63ebd4a508a09c481150
    - rbenvにPATHを通す部分は以下を参照
        - https://note.com/noel20181016/n/na3d50c207a2d
        - vi ~/.bash_profile 
- cocoapodsインストール
    - https://nasubiblog.hatenablog.com/entry/2018/12/21/202358
    - 環境構築の部分を参照
- Homebrew caskをインストールする必要がある場合
    - https://qiita.com/yuzukaki/items/6461079cfd0b43e55785
    - 手元ではインストールをした上で、brewコマンド（brew caskではなく）で成功
- adbコマンド有効化
    - https://qiita.com/hujuu/items/509fb234d29de10d6f1b

##プロジェクト作成/編集
- https://qiita.com/nskydiving/items/41e446ef5c821359ab79
    - App.jsを書き換える部分は丸々置き換える。
    - App.jsがシュミレータに表示されるもの。
- より詳しくExpo CLI以降の手順が書いている
    - https://www.cresco.co.jp/blog/entry/12928/
社内で自作システムを使いたい話

# 社内で自作システムを使う壁
業務効率化のために自作システムを作る、、までは簡単なんですがね。
それを組織として利用しようとするといろいろな壁があります。
ちょっと考え方をまとめてみようかなと。

### ガバナンスとの戦い（勝てない）
そもそも、セキュリティはガバナンスが肝なわけで、基本は組織はきちんと精査して安全性を担保したツールや環境以外は使わせたくないし、使えないようにガッツリシステムと制度を固めるんですよね。
で、そこにシステムを追加しようとするなら。
相応の規模のメリットがあることを示して、相応の予算と体制で既存のルールとおり合いをつけて追加する、っていう大掛かりなことになるわけです。

個人やチームがちょこちょこ使って潰すくらいのシステムでは、ガバナンスの壁はまず超えられない。
あるいは運良く壁をすり抜けてしまっても、コアメンバが抜けてガバガバな状態になった段階でガッツリ攻撃の踏み台にされたりなんかして、ガバナンスをもっとガッチガチにされる羽目になるまでのワンセット。

そういうのがない会社に行けばって？
自分の立場上、むしろガバナンスづくりに先に着手するかなぁ。。ガバナンスは必要なんですよ、実際。

### 与えられたもので頑張る？
じゃぁどうするかというと、ガバナンスが（うっかり）許可してしまっているマクロやRPAツールで渋々格好の悪い仕組みを作るくらいしか無くなる。
ただ、ここはセキュリティの流暢次第でいつ塞がれるかわからないですから、仮のすみかにしかならない。

### 自腹AWSに作っちゃう？
ダメ、絶対。
何がって、業務で使うシステムである以上、多かれ少なかれ機密情報を登録してしまうことになりますから。
そんな用途じゃない？
使ってるうちに別の用途に使えるんじゃないかとか余計なこと考えてやらかすやつが絶対でますから。。
昔Webストレージにデスクトップの全ファイルアップした同僚がいたなぁ。。何ミスりゃそうなるんだか。。


### 結局Officeかよ。
まぁそうなるんですよね。
エクセルバンザイ。
。。。。。。。。。まだだ、、、まだ諦めてたまるか！！

# 突っ走る前に。そのシステムで大丈夫？
ちょっと脱線。
業務のシステム化や自動化でツネヅネ感じていることをつらつらと。

### ちゃんと面倒見れるの？
システム使い始めた頃はいいんですよ。
それが半年、、、１年、、、まず間違いなく面倒見てる時間なくなりますし、やる気もなくなる。
チームできちんとメンテできるようにしようとすると一定のスキルマップを持った人材を定常的に育成・配備できるようにする必要があるのですけれど、当然本業は自作システムのメンテじゃないですから、、、結局もともとそういう開発を実施しているチームじゃないとシステムの面倒見きれない、という状態になります。

### 人間にできないことはやらせない
あるいはシステムありきの効率の業務が当たり前になってくると。。ある日システムがトラブルったら、、、自チームや関連チームに甚大な迷惑をかける羽目になる。
それを考えると、システムにやらせる作業は最悪人間が頑張れば実施できる（数日くらいなら、、）というくらいにとどめて置かないと怖い。
そうしないといざというときに耐えられない。
あるいは、ダウンが許されないガッチガチのハードコアな運用を求められることになってしまう。。

### 信頼しないしさせない
最悪のケース。
チームの業務が自システムありきになってしまって、、、
システムに任せっきりになりその業務できるノウハウがチームから消え去り、、
そして開発者が転職したら。

。。。何が怖いって、これがよくある話だってことなんですよね。
そもそも素人がその時のはやりのフレームワークで作ったようなもん、１年もたてば脆弱極まりないガバッガバな状態になるのですから、さっさと破棄して別のシステム作るなり、ちゃんとした商用のシステム買ってきて業務マイグレする方が遥かに正しい。
むしろそのシステムがあるからと業務のマイグレ妨げる原因になってたら元も子もない。

### 総じて
必要に応じて作って、潮目がかわったらさっさと潰す。
その程度のシステムであるべきだなと思ってます。

# 改めて、ガバナンスとの戦い
さて。
流暢は変わるでしょうけれど、現時点である程度使わせてもらいやすいかなあぁと思う技術をつらつらとまとめてみます。

### Power Automate (Microsoft)
Office 365を使っていると、実は利用ライセンスがついてたりします。
Office製品をベースとしたRPAツールとでもいいましょうか。
https://flow.microsoft.com/ja-jp/

もともと「flow」という製品名だったので、使い方をググるときはflow版の情報がヒットすることも多いですね。

GUIで箱同士を線で結んでいく感じで処理を作っていきます。
outlookでメールを受け取ったら、内容を読み込んでエクセルに書き出したり。
Teamsに起票したり。
Tasksと連携してチケット管理したり。

過去に駆動したときの条件で再試験をする、というような動作テストの使い勝手は非常に良いです。

ちょっと複雑な処理は、VBAライクな構文で書いていきます。
。。。VBAかぁ。。。
あと、WebUIでVBAを記載すると、なんか内容の反映に変なディレイがあったり、構文ミスしてると無言で入力拒否って前の値保持したり、画面の最大化しないと表示されないボタンがあったり、、めんどくさいやつです。

 ~~。。てかそれより何よりそもそもOffice製品がイケてないからそいつら連携させてもさぁ、、~~ 

ただ、これもよくよく考えると結構深刻な攻撃通せちゃいそうな感じもあります。
遠からず、封印されるんじゃないかな、、

### ブラウザ + js + localstorage
なんだかんだ行ってもブラウザはまず使えます、、、よね、、？
接続可能なサイトは多かれ少なかれ絞り込まれてるでしょうけど。

で、外部にデータを置くのがダメなら？　ローカルにおきゃいいだろ！！　って発想。
。。。チームの情報共有にすらつかえんけど。。。

外部WebサーバにはJSだけおいて、処理は全部ブラウザに押し付けて、データの保存もブラウザに押し付ければ、、、
試しに作ってみるかなぁ。。

チームの中での情報共有は最低限なんとかしないといけないけど。
WebRTC,,,?
私がガバ側なら、んなシステム見つけた時点で潰すわな。。何しでかすかわかったもんじゃない。

### （行けるか、、？）エクセルマクロ、Power Shell
現状ダメ目の位置にいる人だと思います。
攻撃メールの添付だったり、侵入後の攻撃展開用に頻繁に使われるもんだから、昨今のセキュリティ対策入れてると完全停止させられてるんじゃないでしょうか。
もう一歩進むときちんと証明書で署名したものだけ実行させる、という管理になると思うのですが、どうなんだろ。。

USBメモリもそうですけど、利便性を突き詰めて作られたはずなのにむしろ危ないからと封印される。
悲しい話ですね。。。

### 他、、
なんか良いものあったらぜひ教えてください。
二段階認証と多要素認証の違い

プログラミングの勉強をしていると、多要素認証という言葉が頻繁に出てくる。
私生活では二段階認証はよく聞くけど、多要素認証という言葉はあまり聞かない。
多要素認証とはどういうものなのか。
多要素認証と二段階認証はなにがどう違うのか。
これらについて自分なりにまとめておく。

## 多要素認証とは
多要素認証```MFA：Multi-Factor Authentication```
MFAと呼ばれることが多いらしい。

簡単にいうと、多要素認証とは複数の種類の要素で自分のアカウントだということを証明することをいう。
例えば、なにかのサービスを使用したいときにまずログインをしなければならない。

そのときに、パスワードを入力する。
これはパスワードを知っているから入力することができる。

要するに、ここで```知っている要素（パスワードを知っている)```ということになる。
また、最近では、QRコードを発行して、パスワードの入力と同時にQRコードの照合を要求するサービスもある。
これが```持っている要素(QRコードを持っている)```ということになる。

### 知っている要素と持っている要素
このふたつでログイン認証をすることによってより強固なセキュリティを構築することができる。
これが多要素認証。


## 二段階認証とはなにが違うのか？
二段階認証は、例えばパスワードをログイン後に、秘密の質問に答えるなどの方法でログインをすることなどになる。
これは、２つとも```知っている要素```ということになる。
● パスワードを知っている
● 秘密の質問の答えを知っている
要するに、この場合どちらも知っている要素であり、多要素ということにはならない。
ということで、二段階認証と呼ばれる。

## なぜ多要素認証が存在するのか？
これはセキュリティの強度を高めるため。

例えば、これまでの話の例をもとにすると、なんらかの形でパスワードや秘密の質問の答えが流出した場合に、QRコードが流出していなければアカウントを悪用されることはない。このように、一つの要素だけで認証をするよりも多要素での認証の方がより高度なセキュリティを構築することができるということ。
年齢の選択

#ActiveHash::Baseを継承したモデルで使えたらどうぞ。

```age.rb
class Age < ActiveHash::Base
  self.data = [
    { id: 1, name: '--' },
    { id: 2, name: '18歳' },
    { id: 3, name: '19歳' },
    { id: 4, name: '20歳' },
    { id: 5, name: '21歳' },
    { id: 6, name: '22歳' },
    { id: 7, name: '23歳' },
    { id: 8, name: '24歳' },
    { id: 9, name: '25歳' },
    { id: 10, name: '26歳' },
    { id: 11, name: '27歳' },
    { id: 12, name: '28歳' },
    { id: 13, name: '29歳' },
    { id: 14, name: '30歳' },
    { id: 15, name: '31歳' },
    { id: 16, name: '32歳' },
    { id: 17, name: '33歳' },
    { id: 18, name: '34歳' },
    { id: 19, name: '35歳' },
    { id: 20, name: '36歳' },
    { id: 21, name: '37歳' },
    { id: 22, name: '38歳' },
    { id: 23, name: '39歳' },
    { id: 24, name: '40歳' },
    { id: 25, name: '41歳' },
    { id: 26, name: '42歳' },
    { id: 27, name: '43歳' },
    { id: 28, name: '44歳' },
    { id: 29, name: '45歳' },
    { id: 30, name: '46歳' },
    { id: 31, name: '47歳' },
    { id: 32, name: '48歳' },
    { id: 33, name: '49歳' },
    { id: 34, name: '50歳' },
    { id: 35, name: '51歳' },
    { id: 36, name: '52歳' },
    { id: 37, name: '53歳' },
    { id: 38, name: '54歳' },
    { id: 39, name: '55歳' },
    { id: 40, name: '56歳' },
    { id: 41, name: '57歳' },
    { id: 42, name: '58歳' },
    { id: 43, name: '59歳' },
    { id: 44, name: '60歳以上' }
  ]
```
[OutSystems]Reactive Webのカスタムタスクボックスを試してみる

OutSystemsでワークフローを実現するBPT (Process) で、ユーザーに割り当てたタスクを確認するUIがタスクボックスです。
Reactive Webにも、これをカスタマイズする仕組みが提供されていたので試してみました。

# 環境
Personal Environment(Version 11.10.0 (Build 22910))
Service Studio(Version 11.10.9)
Sample Reactive Taskbox(Version 1.0.1)

# タスクボックスとは
OutSystemsでワークフローを実現するための仕組み、Processに関連した要素です。
プロセス中で人にタスクを割り当てるHumanActivityというものをProcess内に配置できます。
このHumanActivityで自分にわりあたっているタスクを表示するUIです。

一覧表示されるタスクから選択して、決められた作業（承認とか却下など）を行うこともできます。
Traditional WebではデフォルトでこのUIが表示されていました。

タスクを割り当てる手順は、以下の記事の手順を確認してみてください。
[シンプルなBPTの実装例](https://blog.house-soft.info/archives/1142)

# インストール
[Sample Reactive Taskbox](https://www.outsystems.com/forge/component_overview.aspx?projectid=8355&projectname=sample-reactive-taskbox&_gl=1*mr7vlu*_ga*mtu1mja2mdk5mc4xntk0nzi4mdm5*_ga_zd4dtmhwr2*mtyxmzm5oduzmy4zmzkums4xnjezmzk4njywlji.)からファイルをダウンロードして自分の環境にインストールする。
omlファイルなので、Service Studioで開いただけではインストールされません。Publishを忘れずに。

Platform Serverのバージョンが低いと、Human Activity（ユーザーにタスクを割り当てる機能）のDestination（タスクを処理する画面の設定）が使えないようなので注意。
> Note: Reactive apps can have human activities with a destination from platform server version 11.8 onward.

(Sample Reactive TaskboxのDetailsより）

# Reactive Web AppでBPT Taskboxを表示させる
Traditional Webだと、設定しなくてもBPT Taskboxを呼び出すUIは表示されていましたが、Reactive Webでは設定が必要です。
インストールしたタスクボックス（Sample Reactive Taskbox）を対象画面で表示されるように配置します。

## 参照追加
Manage Dependenciesを開き、インストールしたタスクボックスにあるTaskbox Blockを参照追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/cddc1c72-65d8-1499-1d80-2ba221aa51f2.png)

## 利用しているLayout Blockを確認
モジュール内の全画面にタスクボックスを表示するためには、ThemeのBlocks/Layoutプロパティに設定されているLayout Blockに配置します。通常、作成した画面のレイアウトにはこのBlockがデフォルトで使われるため。もちろん、画面作成後に別のレイアウトを選択していたら、そちらのBlockにもTaskboxを配置しないといけないですね。

ここでは、Layouts UI FlowのLayoutTopMenu Blockを使っていることが確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/d94de999-33a5-21f8-ef4c-dbe6a7e6a974.png)

## Layout BlockにTaskbox Blockを配置
LayoutTopMenu Blockを開いてTaskbox Blockを配置します。Placeholder以外であればどこに配置してもいいようです。ここではfooter HTML ElementにTaskbox Blockを配置しました。
どこにBlockを配置しても、画面上では右下にUIが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/72d07e66-62aa-1138-1ada-1ad3eaec4e39.png)

## 動作確認
プロセスを割り当てたユーザーでテスト対象モジュールを開いてみるとこんな感じになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/eee058a7-7fa0-3f63-1561-3b6a133628b5.png)

# 要件に応じてカスタマイズ
各プロジェクトで使う場合には、「Sample Reactive Taskbox」という名前では違和感があるはず。モジュール名を変更しておきましょう。
例えば、「Sample 」の部分を除外するなど。

TaskboxはBlockとして提供されているので、自由に変更できます。
例として、ActivityGuidance BlockのLabelに「 Dummy」というテキストを追加してみたところです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/7c8781fb-72bd-fdb5-39ca-ea2a8db6281b.png)
【Rails】ポートフォリオ（スイーツ専門の検索・口コミ・交流サイト）

はじめに
---
今回、約1ヶ月をかけて初めて自分自身一人でポートフォリオを作成しましたので、記録として残しておきたいと思います。
私の簡単な経歴と致しましては、前職まで6年ほど菓子屋に勤めておりましたが退職。独学期間1ヶ月、現在プログラミングスクールを利用し現在3ヶ月目を終了というところで、4ヶ月間の集大成になります。
今後も機能などにつきましては追加をしていく予定ですので、その都度更新していきたいと思います。
<br>

アプリのトップページ
---
動画として掲載したかったのですが、エラーになってしまい反映されなかった為画像を掲載させていただいております。
PC版（出来れば13インチサイズ位で見ていただきたいです...）
![スクリーンショット 2021-02-15 23.42.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/942338/65f891ab-49b8-6f58-336a-74a0f57a8a3b.png)
<br>

アプリ概要
---
スイーツに特化した検索、口コミ、交流サイトです。
● スイーツの店舗を検索し、店舗情報の確認や口コミの投稿が可能。
検索対象： フリーワード、ジャンル、ランキング

● ユーザーは自分が食べた物を写真付きで投稿可能。
コメントで他ユーザーとやりとりすることができる。

● 気に入った店舗や他ユーザーのお気に入りに追加が可能。
<br>

テーマの選定理由・まとめ
---
冒頭でもお伝えした通り前職までの経験を元にしております。
簡潔にまとめて以下の３点になります。

● 特定の種類の物(ケーキのみ、パフェのみ等)を求めるコアなお客様が多く、スイーツと一言で括るには枠が大きすぎる。

● スイーツに関わる店舗を探したいときに、スイーツに特化したサイトがあまりなく、細分化したサイトが必要と感じていたこと。

● お客様同士がスイーツを通じて親しくなっていく様を見て、そうした交流の場も含めたサイトにしたい。
<br>

実装機能一覧
---
機能やそれに伴い使用したgem、外部コンテンツなどは下記の表にまとめております。
※機能などに漏れがありましたら、申し訳ありません。

|   |機能        |gem / 備考欄|
|:-:|:--        |:--     |
|1  |ユーザー/管理者（ログイン機能）|devise    |
|2  |マイページ機能    |refile / refile-mini_magick|
|3  |つぶやき投稿     |refile / refile-mini_magick|
|4  |フリーワード検索　　|ransack|
|5  |ジャンル検索　　　 |×|
|6  |通知機能　　　　　|×|
|７  |地図表示（google map API）|geocoder / gmaps4rails|
|8  |レビュー機能（星による評価）　|raty.js|
|9  |ページネーション機能　　　　|kaminari|
|10 |いいね、お気に入り機能　　　|Ajax(非同期)|
|11 |お問い合わせ機能　　　　　|Action Mailer|
|12 |画像解析（タグ付け）機能　　|Google Vision API（LABEL DETECTION）|
|13 |レスポンシブ対応（不完全）　|13インチサイズと、モバイル版の600px以下が一番綺麗にご覧いただけます。|
|14 |コード解析　　 　　　　　　|RuboCop|
|15 |単体・結合テスト(一部)　　 |RSpec|
|16 |自動デプロイ            |AWS, GitHub Actions(CI/CDツール)|
|17 |ドメイン指定　　 　　　　　|お名前.com / AWSRoute 53|
<br>

追加実装予定
---
● フリーワード検索で複数ワードを有効にする（現在は単一ワードのみ）
● エリアごとの検索機能
● 通知機能(コメントへの通知も対応)
● SNS認証機能
● アニメーションなど動きをいれる

開発環境
---
OS：Linux(CentOS)
言語：HTML,CSS,JavaScript,Ruby,SQL
フレームワーク：Ruby on Rails
JSライブラリ：jQuery
IDE：Cloud9
<br>

ポートフォリオURL
---
興味のある方はこちらより、サイトをご覧いただけます。
ゲストユーザー機能がありますので、登録などの手間なくご利用いただけます。
何度も重複し申し訳ございませんが、レスポンシブ対応がまだまだ不完全な為、13インチサイズと、モバイル版の600px以下が一番綺麗にご覧いただけます。
少し動作が重いかもしれませんが、ご了承ください。
拙いポートフォリオではございますが、お気づきの点やアドバイス等ございましたら、コメントをいただけますと幸いです。どんなお言葉でも真摯に受け止め、また明日からの学習の励み・就活への励みにさせていただきたいと思います。

※ 現在は停止しております。
https://sweets-meguri.work/
<br>


終わり
---
今回ポートフォリオを公開させていただきましたが、私自身このアプリはまだまだ不完全な物だと自負しております。
ただ、未経験から学習を始め約4ヶ月。
せっかくデプロイしたことや良い区切りでもあるかと思い、今回思い切って自身のアプリケーションを公開させていただきました。
今後も機能面などで追加実装をした際には、その都度更新させていただきたいと思います。
長々と執筆してしまいましたが、もし最後までご覧いただいた方がおりましたら、ありがとうございます。
以上で、今回の記事は終了させていただきます。
Railsでフォームに高機能のテキストエディタを実装する方法

今回、フォームに画像挿入機能などの機能を持ったリッチテキストエディタを実装する方法についてまとめていこうと思います。
拙い文章ですがお許しください。

# Action Textの基礎知識
Action Textはリッチテキストを簡単に作成、編集、表示することができるフレームワークであり、Rails6から導入された機能になります。つまりこのAction Textを使えば、フォームで投稿する際、文章の修飾や画像の挿入を簡単にできるようになるのです。

# インストール方法
こちらの方法は追加実装の方向けになります。もし新しく実装したい場合はRailsガイドをご参照ください。
[Railsガイド](https://railsguides.jp/action_text_overview.html)
　
まず、Action Textをダウンロードします。
ターミナルで開いているアプリケーションのディレクトリに移動した以下のコマンドを実施します。

``` Ruby
% rails action_text:install

```
このコマンドを実施すると、yarnパッケージが追加されて、必要なマイグレーションファイルが作成されます。

　ここで注意して欲しいのですが、もしこれから実装するテキストエディタ部分のカラムがDBに存在するなら、必ずロールバックをしてそのカラムを削除してください。フォームのテキストエディタ部分のデータはこれから実装するAction Text専用のテーブルに保存されます。
　
　確認して大丈夫でしたら、作成されたマイグレーションファイルをマイグレートしましょう。

```Ruby
rails db:migrate

```

　次にActive Strageのセットアップをする必要があります。
Active Strageとは簡単に説明すると画像ファイルなどのアップロードや表示を簡単にできるGemになります。

まずimageMagickというツールをHomebrewからインストールする必要があります。以下のコマンドをターミナルに打ち込んでください。

```Ruby

% brew install imagemagick

```
そしてGemfileを開き、以下の２つのGemを記述してください。

```Ruby

# Gemfileの一番下に記述する

gem 'mini_magick'
gem 'image_processing', '~> 1.2'

```
そしてそれらをターミナルでbundle installします。

```Ruby	
% bundle install
```
以上でActive Strageを使う上で必要なツールは揃いました。Active Storageをアプリケーション内で使用する準備を行います。

```Ruby

% rails active_storage:install
% rails db:migrate
```
こちらでActive Strageの導入は終了です。

　そして次はモデルファイルに記述をしていきます。各自の実装したいモデルに以下の記述を行ってください。

```Ruby

class モデル < ApplicationRecord
  has_one_attached :image
  has_rich_text :content
end

```
続いてこちらのテキストエディタを表示したいビューファイルに以下のように記述します。

```Ruby

# app/views/○○○/_form.html.erb 
<%= form_with(models: ○○○) do |form| %>
  <div class="field">
    <%= form.label :content %>
    <%= form.rich_text_area :content %>
  </div>
<% end %>

```

その後コントローラー内にて、ストロングパラメーターでリッチテキストエディタの内容を取得できるように記述したら、終了になります。
[DB] 正規化の基礎知識


#正規化とは？
システムでの利用がスムーズに行えるように、エンティティを整理するプロセスです。
RDBにおけるエンティティの整理とは、「テーブルを正規形に整えること」です。
正規形とは、データベースにおいて保持するデータの重複が排除されたデータ形式のことです。

データの重複（冗長性）があると、無駄なデータ領域と面倒な更新処理を発生させてしまうので、データの冗長性はなるべく排除していく必要があります。

正規形には第１正規形〜第５正規形までの階層が存在します。
第３正規形まで達成すれば、その時点でそれ以降の正規形の条件も満たしていることがほとんどのため、
実務では第３正規形までを想定することが多いそうなので、まずは第１〜第３正規形までを確実にできるようになることを目指しましょう。


#第１正規形
「１つのフィールドには１つの値しか含まない」という原則が守られた形

なぜ第１正規形が必要かというと、主に下記２点が理由です。
・複数の値を許すと、主キーが各カラムの値を一意に定めることができなくなる
・主キーの定義に反する


正規化を扱う上で「関数従属性」という概念が、非常に重要になります。

関数従属性とは？
y = 2（x）のように、xの値を１つ決めれば、yの値が１つに決まる関係性のことを言います。
例えば上記であれば　x = 5の場合　y = 10に決まりますね。
・この関係が成立している状態を「yはxに従属する」と言います。
・記号で表すと「{ x } → { y }」    となります。

これを理解した上で、改めて正規化とは何かを考えると
「テーブルの全てのカラムが関数従属性を満たすように整理していくこと」と言えます。    
{ 主キー } → { カラム } が全てのカラムにおいて成立している状態を目指しているのです。
「カラムは主キーに従属する」


例：社員テーブル
社員ID　　　｜　名前
ーーーーーー｜ーーーーーー
　１　　　　｜　田中　
　２　　　　｜　加藤
　３　　　　｜　右京

このテーブルの場合、主キーは社員IDです。
社員IDの値が１に決まれば、当然社員IDカラムの値は１に決まりますし、
名前カラムの値は田中に決まります。

なのでこれは、主キーの値が決まればカラムの値が決まるというのが
「全てのカラムで成立している状態」{ 主キー } → { カラム } 
つまり正規化された状態と言えます。





#第２正規形
部分関数従属が解消されていて、完全関数従属のみのテーブルになっている形

部分関数従属とは？
正規化においてNGです。
複数列からなる主キーの一部のカラムに対して従属するカラムがある状態のことを指します。

完全関数従属とは？
主キーを構成する全てのカラムに対して従属性がある状態のことを指します。


例：社員テーブル
会社ID｜会社名｜社員ID　　　 ｜　名前
ーーー｜ーーー｜ーーーーーー｜ーーーーーー
１　　｜A銀行  ｜　１　　　　｜　田中　
１　　｜A銀行  ｜　２　　　　｜　加藤
１　　｜A銀行  ｜　３　　　　｜　長澤
２　　｜B建設  ｜　１　　　　｜　右京
２　　｜B建設  ｜　２　　　　｜　相田

このテーブルの主キーは{ 会社ID,  社員ID }です。
全てのカラムは会社IDと社員IDに従属します。
（会社IDが１かつ社員IDが１のときは、会社名→A銀行、名前→田中）と見れますね。

しかし、会社名カラムだけ見ると、{ 会社ID,  社員ID }に従属しているというよりは、
会社IDに対してのみ従属していることがわかります。
「主キーが複数存在するが、１つの主キーにのみ従属しているカラムが存在する」
これが部分関数従属です。

部分関数従属がある場合は、完全関数従属しかない構造に直してあげる必要があります。

例：社員テーブル
会社ID｜社員ID　　　 ｜　名前
ーーー｜ーーーーーー｜ーーーーーー
１　　｜　１　　　　｜　田中　
１　　｜　２　　　　｜　加藤
１　　｜　３　　　　｜　長澤
２　　 ｜　１　　　　｜　右京
２　　 ｜　２　　　　｜　相田

例：会社テーブル
会社ID｜会社名｜
ーーー｜ーーー｜
１　　｜A銀行  ｜
２　　｜B建設  ｜

このように２つのテーブルに分けてあげると、１テーブル１主キー構造になっており、
それぞれ完全関数従属が実現できていることがわかります。

第2正規化は
「社員」と「会社」という異なるレベルのエンティティを、テーブルでも分ける作業とも言えます。


#第３正規形
推移的関数従属が解消されている形

推移的関数従属とは？
２段階の関数従属がある状態のことです。


例：社員テーブル
会社ID｜社員ID　　　 ｜　名前　　｜　部署ID　｜　部署名　｜
ーーー｜ーーーーーー｜ーーーーー｜ーーーーー｜ーーーーー｜
１　　｜　１　　　　｜　田中　　｜　３　　　｜　営業　　｜
１　　｜　２　　　　｜　加藤　　｜　２　　　｜　開発　　｜
１　　｜　３　　　　｜　長澤　　｜　１　　　｜　企画　　｜
２　　 ｜　１　　　　｜　右京　　｜　２　　　｜　開発　　｜
２　　 ｜　２　　　　｜　相田　　｜　１　　　｜　企画　　｜

例：会社テーブル
会社ID｜会社名｜
ーーー｜ーーー｜
１　　｜A銀行  ｜
２　　｜B建設  ｜


この社員テーブルでは、

１,　会社ID, 社員IDが決まれば部署IDが決まる　   { 会社ID, 社員ID } → { 部署ID } 
２,　部署Idが決まれば部署名が決まる　　　　　{ 部署ID } → { 部署名 }

つまり、{ 会社ID, 社員ID } → { 部署ID } → { 部署名 }
という「２段階の関数従属が成立している」状態が成立しており、これを推移的関数従属と呼びます。

これによって「一時的な欠員により社員がいない部署（例えば事務）があっても、それを反映できない」というような構造になってしまっています。

推移的関数従属を解消するには、


例：社員テーブル
会社ID｜社員ID　　　 ｜　名前　　｜　部署ID　｜
ーーー｜ーーーーーー｜ーーーーー｜ーーーーー｜
１　　｜　１　　　　｜　田中　　｜　３　　　｜
１　　｜　２　　　　｜　加藤　　｜　２　　　｜
１　　｜　３　　　　｜　長澤　　｜　１　　　｜
２　　 ｜　１　　　　｜　右京　　｜　２　　　｜
２　　 ｜　２　　　　｜　相田　　｜　１　　　｜

例：会社テーブル
会社ID｜会社名｜
ーーー｜ーーー｜
１　　｜A銀行  ｜
２　　｜B建設  ｜

例：部署テーブル
部署ID｜部署名  ｜
ーーー｜ーーー  ｜
１　　｜企画  　｜
２　　｜開発  　｜
３　　｜営業 　 ｜
４　　｜事務  　｜


このように、部署名を部署テーブルに切り出してあげます。
また、社員テーブルでも部署名を参照するために、部署IDを外部キーとして指定してあげる必要があります。

こうすることによって、推移的関数従属の解消とともに「一時的な欠員により社員がいない部署（例えば事務）があっても、それを反映できない」という問題も解決することができました。

以上が第３正規形です。

第３正規形も、「社員」と「部署」という異なるレベルのエンティティをテーブルとして分離する作業と見れば、第１, 第２正規形とやっていることはほぼ変わらないとも言えます。
[nodejs] Filter keys from json with nodejs


Here is a example to filter the keys of json data.

```js
// require fs library
const fs = require('fs');

// read json from file
const fileContent = fs.readFileSync('input.json', 'utf8');

// parse as array
const jsonArray = JSON.parse(fileContent);

// for each value from json array
// pick the id column only
var result = []
jsonArray.forEach(value => {
    var obj = {}
    obj['id'] = value['id'];
    result.push(obj);
});

// convert to json string and write to file
fs.writeFileSync('output.json', JSON.stringify(result));
```
並列化で高速に大量ファイルの削除，転送．xargとか


#ファイル一括消去
ワイルドカードでは対応不可能なくらい大量のファイル

```
$ find ./ -name "*.txt" -exec rm -fv {} \;
```
-execオプションを使えばfmコマンドに渡すことができる．
こっちは逐次繰り返しrm実行

```
$ find ./ -name "*.txt" | xargs rm -fv
```
こっちは一括rm実行。
並列処理すると高速に実行できる。

```
$ find ./ -name "*.txt" | xargs -P 8 rm -fv
```
自分の環境では並列数８で頭打ちとなった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527627/91b29d78-1d80-ad13-9a73-754d9a569984.png)



#ファイル転送コピー

###特定のディレクトリを除外

```
rsync -av --exclude="data/"　 ./foge/    ./fuga/
```
オプションでフィルターを掛けるとよけいなファイルをコピーしない．
fogeというディレクトリを除外した

###高速化xargs

```
$ echo "./hoge" | xargs -P4 -i% rsync -av --progress % ./fuga 
```

#まとめ

ファイル高速転送

```
$ echo "./hoge/" | xargs -P4 -i% rsync -av --exclude="1/"  --progress % ./fuga
```

-p オプション　進捗状況表示
-e オプション　除外ファイル，ディレクトリ
-i オプション　含めるファイル，ディレクトリ

-P4 オプション　４並列する
-i% オプション　%に引数./hogeを代入
【C# ラムダ式】ラムダ式の自分なりの勝手な考え方

#この記事について#
ラムダ式ってわかりにくいですよね。
いろんな所を見て回りましたが、私の理解が及ばず…よく理解できなかったので、自分なりに '**勝手**' に解釈して理解してみました。
ちゃんと理解したい人は他の記事を見ることをお勧めします。

#ラムダ式の自分なりの理解#
自分なりのラムダ式の理解は、List<T>などのコレクションやDataTableなどのデータの集合体に対して要素を加工したり変形したりして簡単に抽出するための仕組みと理解しました。

#式の見方#
こんなラムダ式があったとします。

```ruby
int[] nums = { 1, 2, 3, 4, 5 };
var numList = nums.Where(i => i > 3);

foreach (var num in numList)
{
    Console.WriteLine(num);
}
```
結果は「4, 5」になります。
まず、ラムダ式を見て思ったのが、`=>` コレ・・・。
何ですかコレと思いました(^^;
まあ、ごちゃごちゃ難しいことは考えずに「右側で処理したものが左側に返る」だけ、
それだけ！と理解。
`i > 3`の処理または計算の結果が`=>`より左の`i`に返ると。

#拡張メソッド#
次に、この`nums.Where`の部分。
拡張メソッドによって、配列numsに`.`を付けるとWhereが使えるようになってます。
本来、配列numsにはWhereメソッドはありません。
なのに使える・・なぜ？
これは、System.Linq 名前空間で使用できるようになるので`using System.Linq`をクラスのトップに記述してないと使えないことが判明しました。
System.Linqは.NET Framework3.5から使えるようになってます。
拡張メソッドって何？
ざっくりとした感じでは、クラスとかのオブジェクトに本来持っていないメソッドを後付けでメソッドを追加（正式には呼び出せるように）したもので、
System.Linq 名前空間を使用することでSystem.Linqがあらかじめ用意してくれた拡張メソッドを利用して配列numsに後付けでWhereメソッドを追加（呼び出せる）しているようです。

#var型#
そして、結果の方ですがvar型で受け取っています。
暗黙的な型であるvar型はコンパイルの時に型が決定されるとても便利な型ですが、
便利であるが故に何でもかんでも使用しているケースがあります。
これは望ましいものではないと思います。
var型は加工をして変数に収めるLINQで使用するべきで、普通のコードではきちんと型を指定して使用するべきだと自分は思います。
後でコードを見たとき訳がわからなくなる原因になります。
普段は明示的に型を指定したほうがいいでしょう。

#IEnumerable\<T>　インタフェース#
そして、返ってきたvar型はIEnumerable\<T>のインタフェースで受け取るので上のコードではIEnumerable\<int>型の変数に格納される形になる。
IEnumerable\<T>とか、またわかりにくいの来たぞ。
List<T> 等のジェネリックコレクションクラスは IEnumerable\<T> をサポートしていると・・・。
よくわからないので、自分なりにわかりやすく考えると、List\<T>や配列やDictionary\<TKey,TValue>などの諸々のコレクションクラスを極めた達人だと考えればいいんだな（白目）

だって、

```ruby
List<int> numList = nums.Where(i => i > 3).ToList();
```
のように、`nums.Where(i => i > 3)`の後ろに`.ToList()`と付ければ明示的にList型として格納できるし、

```ruby
int[] numbers = nums.Where(i => i > 3).ToArray();
```
のように、`nums.Where(i => i > 3)`の後ろに`.ToArray()`と付ければ明示的に配列として格納できるしでIEnumerable\<T>はコレクションクラスの達人ですよ。

#遅延ロード#
IEnumerable\<T>は何やら遅延ロードというものがあるらしい。
LINQ to SQLでデータベースにクエリを発行する場合に注意が必要なようで、クエリが実際に発行されるタイミングがあるそうです。
ようするに、クエリの発行タイミングを間違えるとクエリの発行回数が増えてしまうようでLINQ to SQLでデータベースを操作する場合は要注意ですね。
ちなみに、先ほどの`.ToList()`と付けると、この時点でSQLが発行される（他にもいろいろクエリが発行されるタイミングがありますが詳しくは他をあたってください）

#最後に#
かなり、自分勝手な考え方をざっと書いてしまいました。
自分なりに理解してからラムダ式を使うと本当に便利なのを実感しております。
もっと早く知ればよかった・・・。
LaravelのCollectionのpipeを使うタイミングが全然来ない件

# はじめに
こんにちは。FXの含み損が-40万まで到達しました、筆者です:sob:

LaravelのCollection使っていますでしょうか。

配列操作がアローでスマートに書けて便利ですよね。

その中でも`pipe`について、知ったときめっちゃ便利そうって思っていたのですが、なかなか使うタイミングが無く、先日ついにその日が来たので共有します！

# 私はこれで使いました:+1:
指定の値の最大値を持つ配列を取得するときに使いました:+1:

検索対象のcollectionを`pipe`することで、コールバック関数内で複数回使えるという恩恵を受けられます。

```php
$collection = collect([
    [
        'name' => 'one',
        'priority' => 1,
    ],
    [
        'name' => 'two',
        'priority' => 100,
    ],
    [
        'name' => 'three',
        'priority' => 10,
    ],
]);

$max = $collection->pipe(function (array $v): array {
    return $v->firstWhere('priority', $v->max('priority'));
});

dd($max);
// [
//     'name' => 'two',
//     'priority' => 100,
// ],
```

# おわりに
書いてて思ったのですが、降順にソートして先頭の配列取れば、`pipe`しなくてもいけますね... :thinking_face:

```php
$max = $collection
    ->sortByDesc('priority')
    ->first();

dd($max);
```

うーん、`pipe`の出番だと思うケースがなかなか浮かびません...。
謎が深まってしまいました...。
今後も使い道を探してみたいと思います。
iOSアプリ開発：コードだけでUI画面構成を行う方法〜入門〜

#この記事は
iOSアプリの開発で画面構成(UI部分)にはStoryBoardやswiftUIなどがあるようですが、これらはgitとの相性が悪いためコンフリクションを起こしやすく、チーム開発には向いていないらしいです。というわけでStoryBoardでもなくswiftUIでもない、「コードでUIをデザインする」という方法を学習してみます。具体的には「SnapKitなどのライブラリを用いて画面を作っていく」ことになります。

#手順
・CocoaPodsとSnapKitをインストールして、SnapKitをプロジェクトに導入する
・StoryBoardを消す
・Scene Delegateを消す
・AppDelegate.swiftの編集

#CocoaPodsとSnapKitをインストールして、SnapKitをプロジェクトに導入する
私が過去に書いたこちらの記事を参考に進めて下さい。
参考：[Xcode：CocoaPodsをインストールして、CocoaPodsからSnapKitをインストールする！](https://qiita.com/mi_iroha/items/e27fa87574392699f503)

#StoryBoardを消す
以下の手順でStoryBoardを一匹残らず駆逐していきます。

・ナビゲータエリアのプロジェクトをクリック -> General -> Main Interface -> Mainから空欄にする
・ナビゲータエリアの`info.plist`のうち、`Scene Configuration`の`Storyboard Name`の項目を削除(右クリック -> Cut)
・`Main.storyboard`を削除

#Scene Delegateを消す
同様に、以下の手順で一匹残らず駆逐していきます
・`info.plist`の`Application Scene Manifest`を根こそぎ削除
・`SceneDelegate.swift`ファイルを削除

#AppDelegate.swiftの編集
とにかくこうして下さい。

```AppDelegate.swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // 最初に表示するUIViewControllerを指定する
        // windowをスクリーンサイズに合わせて生成
        window = UIWindow(frame: UIScreen.main.bounds)
            
        // ViewControllerをインスタンス化、windowのrootに設定する
        window!.rootViewController = ViewController()
        
        // 表示する
        window!.makeKeyAndVisible()
        
        return true
    }
}
```

以上で何とかなるはずです。
それでは、本当に何とかなるのか試してみましょう。
UIに関するコードは`ViewController`に書いていきます。

```ViewController.swift
import UIKit
// SnapKitをインポート
import SnapKit

class ViewController: UIViewController {
    var label: UILabel!

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 背景色を変更
        self.view.backgroundColor = UIColor.greem

        // 文字を設置
        self.label.text = "Hello, World!"
        // ラベルを設置
        self.view.addSubview(label)
        // ラベルの位置をSnapKitで指定
        self.label.snp.makeConstraints { (make) in
            make.center.equalToSuperview() // 親ビューの真ん中に配置
        }
        
    }
}
```

上記は画面の色を緑色にして、その真ん中にHello, World!を表示させるコードです
これでRunして本当にそうなっていればおｋですね。
SnapKitもUIKitも使えていることになります。

なっていなければ、どこかがおかしいのでエラーを見るかデバッグするか。

以上です！
お疲れ様でした！

#参考記事
[iOS13でSceneDelegateを使わないでアプリを作る](https://qiita.com/u5_03/items/ff005e7cab7ff509f140)

[storyboardが使われない設定にしているはずなのにcould not find storyboard named "Main"が出てエラーになる。](https://teratail.com/questions/214822)

[Storyboard派がコードでUIを実装するためのチュートリアル](https://qiita.com/gaku2n/items/fa095276ab2d75cc8797)
UE4.26でのクック処理のGC設定について

4.26でクック時のメモリ使用量に関わる処理が変更されました。若干注意点があるため情報を共有いたします。
まず大前提として、同じアセットが複数回読み込まれないようにメモリが許す限りアセットを貯めこむ方がクック時間は短く済みことが多いと思います。

(参考)UE4における大規模背景制作事例 最適化ワークフロー編
https://www.slideshare.net/EpicGamesJapan/ue4-139190804/137

クックを行うPCの性能に合わせて適切な設定を行うことが重要です。特にCIS用のPCのメモリに余裕がある場合は有効に活用してあげましょう！

#GC条件について
4.25以前と4.26の設定値と動作を解説します。

##4.25以前
デフォルト設定はBaseEditor.iniに記述されており

```BaseEditor.ini
[CookSettings]
PackagesPerGC=0
IdleTimeToGC=20
MaxMemoryAllowance=16384
MaxConcurrentShaderJobs=8192
MinReservedMemory=1024
MaxDiffsToLog=5
IgnoreHeaderDiffs=True

; ※MinFreeMemory設定なし

```

となっています。
PCに刺されたメモリが16GB以上あれば、クック中にプロセスに割り当てられた物理メモリが16GBを超えたときにGCが走ります。

#4.26
4.26では関係する設定値が変化しています。デフォルトでは、

```BaseEditor.ini
[CookSettings]
PackagesPerGC=0
IdleTimeToGC=20
MemoryMaxUsedPhysical=16384
MemoryMinFreePhysical=1024
MaxConcurrentShaderJobs=8192
MaxDiffsToLog=5
IgnoreHeaderDiffs=True
```

という設定が記述されており、**プロセスが使っている物理メモリが16GBを超え「かつ」システムの残り物理メモリが1GBを切ったときにGCが発生します**。
(具体的な実装については、CookOnTheFlyServer.cpp の UCookOnTheFlyServer::HasExceededMaxMemory() を参照してください)

システムの残り物理メモリが1GBを切ったときという条件が ORではなくANDで入っているのが大きな違いで、OSが物理メモリが枯渇しないように適切にページアウトを行っている関係上、**なかなか1GBを割りません。**物理メモリが残り1GBを割るときはいつOutOfMemoryが出てもおかしくない状態です。

タスクマネージャで数値を読む場合はここ
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464248/11f8fb3b-a1be-bc58-5d76-7d02ee80d4ef.png">

iniには記述されておらずデフォルトでは使われませんが、物理メモリでの判定ではなく **仮想メモリでの判定を行う** 、 *MemoryMaxUsedVirtual* と*MemoryMinFreeVirtual* が追加されました！

#おすすめ設定
前述の通り物理メモリはOSによる管理が入っている数字なので、アプリケーションがアロケートしたメモリの総量としてはVirtualMemoryの値を参照したほうが素直です。プロジェクトのDefaultEditor.iniに設定を記述してパラメータをオーバーライドします。

```DefaultEditor.ini
[CookSettings]
;物理メモリによる条件を判定しない
MemoryMaxUsedPhysical=0
MemoryMinFreePhysical=0
;仮想メモリ使用量が32GBを超えたらGCを行う(PCによって設定を調整してください)
MemoryMaxUsedVirtual=32000
MemoryMinFreeVirtual=0
```
tidyをlaravel等のphp環境へインストールする手順まとめ

HTML整形ライブラリ**tidy**のインストールに毎度苦戦している為、メモとして残します。
tidy自体需要が少ないのか、ライブラリ自体更新されていないようでphp7系で使おうとするとスムーズにインストールができないことがあります。


# linux環境で直接コマンド実行しインストール
php 7.4
CentOS7

```
# epelの有効化
$ sudo yum-config-manager --enable epel

# remiリポジトリがあるか
$ yum repolist | grep remi

# remiリポジトリがなければインストール
$ yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm 

# php7系tidyライブラリがあるか
$ yum list | grep tidy 

# tidyをインストール
$ yum --enablerepo=remi install -y php74-php-tidy

# 無事インストールできたか確認
$ tidy -v
HTML Tidy for Linux version 5.6.0
```



# AWS Elastic Beanstalkへインストール

### 環境1
php 7.4 running on 64bit
Amazin Linux 2/3 1.4

```path:.ebextensions/01.config
container_commands:
  # tidyのインストール
  21_php:
    command: "sudo amazon-linux-extras install epel -y"
  22_php:
    command: "sudo yum-config-manager --enable epel"
  23_php:
    command: "[ -z \"$(yum list | grep php74-php-tidy)\" ] && yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm || > /dev/null"
  24_php:
    command: "yum --enablerepo=remi install -y php74-php-tidy"

files:
  # php.iniの設定
  "/etc/php.d/01_post_size.ini":
    mode: "000755"
    owner: root
    group: root
    content: |
      extension = /opt/remi/php74/root/usr/lib64/php/modules/tidy.so

```
1. php7系に対応したtidyをインストールしたい為、epelとremiリポジトリをまず有効にする。
2. remiリポジトリがインストールされていなければインストール。(tidyがあるかgrepして確認)
3. php7系対応tidyをインストール
4. php.iniの設定でextensionのインストール先を指定
  
※ 4のインストール先は下記のコマンドで調べられます。
`rpm -ql php74-php-tidy`


一つの実行ブロックにまとめると、非同期になってしまうのかリポジトリ有効になっていない状態でtidyをインストールしようとしてしまうことがありました。
一つの実行ブロックで同期的に処理ができればそちらの方がコードがすっきりしそうです。



▼参考ページ
・[CentOS、RHEL、または Amazon Linux を実行している Amazon EC2 インスタンスの EPEL リポジトリを有効にするにはどうすればよいですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-enable-epel/)
・[Amazon Linux 2でEPELとRemi Repositoryを有効にする](https://qiita.com/charon/items/f890ddbb66aa24d9bc38)
・[CentOS7 PHP7.0にtidyをインストール](https://ytrewq.hatenablog.com/entry/2017/07/19/223327)


### 環境2
php 7.1 running on 64bit
Amazin Linux 2.9.10


```path:.ebextensions/01.config
packages:
    yum:
        php71-tidy: []
```

# docker環境へインストール

### 環境
php 7.4-fpm


```path:docker/php/Dockerfile

FROM php:7.4-fpm

RUN apt-get update && apt-get install -y --no-install-recommends \
    libtidy-dev tidy \
    && docker-php-ext-install tidy
```


dockerのphp:7.4-fpmを使用した場合なのか
Remiリポジトリのインストールは必要なかったです。
AWSのS3でデプロイするときにエラーが出た時の話

AWSのS3でサイトをデプロイしようとしたところ、下記のようなエラーが出ました。

```
npm run deploy

'bash'は内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。
```

毎度おなじみエラー

このエラーは大体パス（環境変数）が通っていないときに出るエラーです。

ちなみに``deploy-s3.sh``の中身は以下のようになっています。

```dist/deploy-s3.sh
#!/bin/sh

aws s3 rm s3://zaemonia/ --recursive
aws s3 cp dist s3://zaemonia/ --recursive
```

これは[Amazon S3でSPAをサクッと公開する](https://qiita.com/kiyokiyo_kzsby/items/77bdb81a1ce1852b30ca)の記事を参考にして作成したものです。

さて、ここで本題の環境変数を設定をしていきましょう。

これを解決するためには``bash.exe``のパスを通します。

恐らく下記のどちらかにあると思います。

・``C:\Program Files\Git\bin``

・``C:\Program Files(x86)\Git\bin``

環境変数の``PATH``にこれを追加します。

そして、``package.json``の``scripts``に``deploy``コマンドを作成します。

```
"deploy": "bash dist/deploy-s3.sh"
```

``deploy-s3.sh``でデプロイするらしいんですけど、僕は上手く行かなかったので``dist/deploy-s3.sh``とすると上手くデプロイされました。

```
> bash dist/deploy-s3.sh

delete
delete
・・・
upload
upload
```

このような実行結果が出ていればデプロイ成功です。

以上、「AWSのS3でデプロイするときにエラーが出た時の話」でした！

良ければ、LGTM、コメントお願いします。

また、何か間違っていることがあればご指摘頂けると幸いです。

他にも初心者さん向けに記事を投稿しているので、時間があれば他の記事も見て下さい！！

Thank you for reading
Ubuntu 20 に DropBox をインストールして、デーモンサービス化する

Ubuntu 20 に DropBox をインストールして、デーモンサービス化します。

````bash
cd ~ ;
wget -O dropbox.tar.gz "http://www.dropbox.com/download/?plat=lnx.x86_64"  ;
tar xvzf dropbox.tar.gz  ;

# 起動スクリプトと自動起動の設定
git clone git://gist.github.com/1196710.git gist-1196710 ;
sudo mv ./gist-1196710/dropbox /etc/init.d ;
sudo chmod +x /etc/init.d/dropbox ;
sudo update-rc.d dropbox defaults ;

# 初回認証
~/.dropbox-dist/dropboxd ;
# ここで初めての起動の場合メッセージが出るので、表示されるURLにアクセスしてマシン認証を行う
````

###参考リンク

- [DropBox設定スクリプト ubuntu用 ](https://gist.github.com/hdemon/1196735)
GitHubでThere isn't anything to compare. Nothing to compare, branches are entirely different commit historiesが出る場合の対処方法

トイプロジェクトを書いたため、GitHubにあげようとしましたがめっちゃハマりました。
こんなところでハマったことは恥ずかしいですが、もし僕と同じ問題にあう方がいるかもしれませんので投稿します。。。（自分が今後同じ問題にハマらないためにも）

GitHubのプロジェクトにpushするため、
以下のコマンドを叩きました。

```terminal
$ git init
$ git add .
$ git commit -m "init commit"
$ git remote add [project name] [branch url]
$ git push --set-upstream [branch_name]
```

そうしたらGitHubのプロジェクトに、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566437/b3fc59eb-a859-dad1-fa4a-491594ffd84e.png)
のようなメッセージが出て、なんのpull requestもできなくなりました。

localのmasterブランチと、upstreamブランチのcommitヒストリーが違うためでした。

## 試したこと
検索した結果、

```terminal
$ git checkout [BRANCH]   
$ git branch master [BRANCH] -f   
$ git checkout master   
$ git push origin master -f
```
のコマンドで解決した記事を発見。試して見ました。
しかし新しいエラーが発生

```
fatal: 'origin' does not appear to be a git repository
```
これも検索したらそもそもoriginを指定してなかったことをわかりました。

```terminal
$ git remote add origin [branch url]
$ git pull origin master
```

でoriginを指定した後、pullをしましたがまた新しいエラーが

```terminal
fatal: refusing to merge unrelated histories
```
また検索。
GitHubのレポジトリーにREADMEを作成したのが原因でエラーになっていることでした。


解決方法は

```
$ git fetch --all
$ git reset --hard origin/master
$ git pull origin master
```
までしたらcommitできるようになりました。

### 参考
https://stackoverflow.com/questions/23344320/there-isnt-anything-to-compare-nothing-to-compare-branches-are-entirely-diffe
ノートPCのバッテリーの劣化度合いを調べるスクリプト

# はじめに

バッテリーは使い続けると徐々に性能が劣化していき、満充電時の最大容量が低下していきます。
ノートPCのバッテリーも例外ではなく、使い続けると徐々に劣化していきます。

Windowsの場合、このようなバッテリーの情報は`powercfg`コマンドで取得できると知ったので、今回はバッテリーの劣化度合いを調べるスクリプトをPowerShellで作ってみました。

# 作成したスクリプト

* `powercfg`コマンドの実行結果は、デフォルトだとコマンドの結果はHTMLとして返されますが、解析しやすいXML形式で取得しているのがポイントです。
* 基本的に「1つのノートPCに、バッテリーは1つ」と仮定してXMLを解析しています。
 * そもそも、バッテリーを複数持つノートPCは存在するのでしょうか？
* バッテリーの劣化度合いは、`（設計時の容量－満充電時の容量） / 設計時の容量 * 100`で計算しています。
* また、`powercfg`コマンドの実行結果を一旦ファイルとして出力しているため、最後に作成したファイルを削除しています。

```powershell:battery_report.ps1
# ------------------------------------------------------------------------------
# ノートPCのバッテリーの劣化度合いを見るためのスクリプト。
# ------------------------------------------------------------------------------

# powercfgコマンドの実行結果の一時保存先。
$TEMP_FILE = './battery_report.xml'

# powercfgコマンドを実行して、XML形式で実行結果を取得する。
# powercfgコマンド実行時のメッセージが標準出力されないように、パイプでOut-Nullに渡している。
Write-Host 'ノートPCのバッテリーの消耗具合を確認します...'
powercfg /batteryreport /xml /output $TEMP_FILE | Out-Null

# XMLを解析して、設計時の容量（DESIGN CAPACITY）と満充電時の容量（FULL CHARGE CAPACITY）を取得する。
# バッテリーは1つしか存在しないと仮定して、Batteries.FirstChildで取得している。
$battery_xml = [xml](Get-Content $TEMP_FILE)
$design_capacity = $battery_xml.BatteryReport.Batteries.FirstChild.DesignCapacity
$full_charge_capacity = $battery_xml.BatteryReport.Batteries.FirstChild.FullChargeCapacity

$attenuation_rate = ($design_capacity - $full_charge_capacity) / $design_capacity * 100
$attenuation_rate = [Math]::Truncate($attenuation_rate * 10) / 10; # 小数点第一位までに揃える。

# powercfgコマンドの実行結果のファイルを削除する。
Remove-Item -Path $TEMP_FILE

# バッテリーの劣化度合い（%）を出力する。
Write-Host "このPCのバッテリーの最大容量は$attenuation_rate％減少しています。"
Write-Host "設計時の容量（DESIGN CAPACITY）：$design_capacity"
Write-Host "満充電時の容量（FULL CHARGE CAPACITY）：$full_charge_capacity"

# 処理結果が流れてしまわないように、Pauseを実行する。
cmd /c Pause | Out-Null
```

```text:出力結果の例
PS C:\Users\NKOJIMA> C:\Users\NKOJIMA\Downloads\battery_report.ps1
ノートPCのバッテリーの消耗具合を確認します...
このPCのバッテリーの最大容量は0％減少しています。
設計時の容量（DESIGN CAPACITY）：45010
満充電時の容量（FULL CHARGE CAPACITY）：45010
```

# 参考URL

* [Powercfg のコマンド ライン オプション](https://docs.microsoft.com/ja-jp/windows-hardware/design/device-experiences/powercfg-command-line-options)
【Rails】Heroku上でのActiveModel::UnknownAttributeError解決方法

# 概要・エラー文
本番環境（Heroku）でデータを新規保存しようとすると、「We're sorry,but something went wrong.」と表示され、保存に失敗する。
<a href="https://gyazo.com/ad35f93d2ecfd12c8873ecdafb6c7a99"><img src="https://i.gyazo.com/ad35f93d2ecfd12c8873ecdafb6c7a99.png" alt="Image from Gyazo" width="586"/></a>

# 解決までの道筋
## 1.ローカル環境で新規保存できるか確認
念のため、ローカル環境で新規保存できるか確認します。
結果、ローカル環境では成功し、本番環境(heroku)でのみ上記のようなエラーが発生します。

## 2.本番環境のログを表示し、エラーログを確認
本番環境のログを表示し、エラー詳細について調べます。本番環境のログを表示するために、ターミナルで以下のコマンドを入力します。
`heroku logs --tail --app アプリ名`

結果、ログの中にエラーログらしき文を確認しました。
`Completed 500 Internal Server Error in 14ms (ActiveRecord: 7.8ms | Allocations: 921)
ActiveModel::UnknownAttributeError (unknown attribute 'explanation' for Recipe.):`

## 3.エラー文について検索
- `Completed 500 Internal Server Error in 14ms (ActiveRecord: 7.8ms | Allocations: 921)`

500 Internal Server Error　＝　サーバーエラーレスポンス
サーバー側で処理方法がわからない事態が発生したことを示すようです。
引用：　https://developer.mozilla.org/ja/docs/Web/HTTP/Status


- `ActiveModel::UnknownAttributeError (unknown attribute 'explanation' for Recipe.):`

recipeテーブルにexplanationカラムがないことで発生するエラーのようです。
引用：　https://teratail.com/questions/92273?link=qa_related_pc

## 4.recipeテーブルにexplanationカラムがないことを確認
念のため、ローカル環境でも確認しましたが、recipeテーブルにexplanationカラムを確認しました。
次に、本番環境で確認します。本番環境でのは、以下の手順で確認します。

- ターミナルでrails consoleを起動
`heroku run rails console`

- DBとの接続情報を表示
`irb(main):014:0> ActiveRecord::Base.connection_config`

- 本番環境での全テーブル名を確認
`irb(main):005:0> ActiveRecord::Base.connection.tables`

- 本番環境の対象テーブルに対象カラムがあるかを確認
`Recipe.inspect`
Recipeテーブルにexplanationカラムが無いことを確認

引用：　https://teratail.com/questions/92273?link=qa_related_pc

## 5.本番環境のデータベースをリセット
ここまでで本番環境のデータベースにエラーの原因があることを確認したので、本番環境のデータベースをリセットし、再度マイグレートを行い、修正を試みる。

- 本番環境のデータベースをリセット
`heroku pg:reset DATABASE`

- 本番環境でデータベースをマイグレート
`heroku run rails db:migrate`

- 再度カラムを確認
`Recipe.inspect`
やはりRecipeテーブルにexplanationカラムが無い。
引用：　https://jonconan.site/technical/569

## 6.本番環境のアプリを削除→再度作成
データベースをリセットしてもエラー解決には至らなかったため、一度本番環境上のアプリを削除し、再度作成します。
`heroku apps:destroy --app アプリ名 --confirm アプリ名`
引用：　https://qiita.com/chihiro/items/5c3ff400f6cb99deb945

## 7.解決！
本番環境にて再度データを新規保存しようとしたところ、保存に成功しました。

# 結論
heroku上のアプリを削除・再作成する。

# 考察
今回の手法は、本番環境で適当なデータしか保存していなかったため可能ですね。本番環境でのデータ登録は、最後がベストであることを再認識できました。

# 開発環境

- ruby 2.6.5
- rails 6.0.0
- mysql2 0.4.4
[Linux]Firefoxのエラー「SEC_ERROR_OCSP_FUTURE_RESPONSE」の対処法

#環境
* VMWare Workstation
* Kali Linux
* Firefox

# Firefoxで「SEC_ERROR_OCSP_FUTURE_RESPONSE」のエラー
ある日、Firefoxでwebサイトを閲覧しようとアクセスしたところ、
<b>「SEC_ERROR_OCSP_FUTURE_RESPONSE」</b>というエラーで見れなくなりました。
どうやら原因はマシンの時刻が大幅にずれていることに問題があったようです。

# 対処方法
手動で時刻を設定し直してもよいのですが、再び設定し直すハメになりそうなので
NICTのNTPサーバに時刻同期させます。

①ntpdateコマンドをインストール

```
sudo apt install ntpdate
```

②ntpdateコマンドでNICTのNTPサーバを指定して実行

```
sudo ntpdate ntp.nict.jp
```

するとマシンの時刻が正しい時間に戻っているはずです。
これで問題なくwebサイトが開けます。

## 参考

<a href="https://eng-entrance.com/linux-clock-system">3分理解！時間のずれを直せるLinuxのシステムクロックの使い方</a>
Googleにインデックス登録されない 3

<h3>前回のおさらい</h3>
ホームページを作ったのですが、Google検索に表示されない上に、インデックスにも登録できませんでした。そこで、少しずつ対応を入れて何が問題なのかを調べて行くことにしました。

**対象のURLはこちら**
https://www.ailabse73.com/

**記事**
Googleにインデックス登録されない 1
https://qiita.com/JunichiFujimoto/items/55a086c2b332e71f33dd
Googleにインデックス登録されない 2
https://qiita.com/JunichiFujimoto/items/a6b77bd38b820b2cfc3c
Googleにインデックス登録されない 3
https://qiita.com/JunichiFujimoto/items/e797dedd56963548ebb8
<hr>

<h3>遂に！ 検索エンジンに表示されました!</h3>
上から<font color="red"><strong>7番目</strong></font>に表示されました
ですが、httpsではなくhttpで、wwwが入っていないURLが登録されているようです
<strong>失敗</strong> | http://ailabse73.com
<strong>正解</strong> | https://www.ailabse73.com

URL検査したら、「URLはGoogleに登録されています」という表記になっていました
![スクリーンショット 2021-02-16 21.21.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537802/b730778a-ea6b-a111-8047-f35809168e8c.png)

今まで、https://www.ailabse73.com でインデックス登録を繰り返ししていたのですが、httpとwww無しバージョンが登録されていたようです。
「クロール統計情報」を調べてみたところ、どうやら私のミスで何度も間違ったアドレスをリクエストしていたようです。
![スクリーンショット 2021-02-16 21.42.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537802/0dc1c4e7-5aa5-2a8d-7d93-b6344e4cc0ae.png)

この対処方法は、\<head>タグの中に、canonicalを入れればいいらしいので、入れてみました。
ただ、301リダイレクトでもいけるみたいです。
301リダイレクトでやるのが良いのかもしれません。
同時にやると効果が分からないので、一旦\<head>の中に入れてみました。

```
<head>
   <link rel="canonical" href="https://www.ailabse73.com">
</head>
```

他の記事で知りましたが、URL正規化というらしいです。

参考URL
https://www.gyro-n.com/seo/hack/canonical/

クローラーは毎日見に来ているみたいなので、明日にはURLの正規化は完了するかもしれません。

<hr>

### 追記 (翌日)

メールが届きました。
インプレッション数の収集が始まったららしいです。
![スクリーンショット 2021-02-17 21.30.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/537802/9c1ab8cc-20bf-cdd4-ac2f-55b5716fc59c.png)
【Javaについてまとめてみたオブジェクト編】メソッドについて

#はじめに
今回はJavaのメソッドについて書いていきたいと思います。
プログラミングといえばメソッドみたいなとこがあるのではないでしょうか！？


##メソッドとは
クラス内に作成する、何回も使う処理を記述するものです！
よく使う処理をメソッドとして作って置くことで、いちいち処理したい時にコードを書くのではなく
メソッドを呼び出すだけで処理が簡単にできてしまうというものです！

##メソッドの書き方
```java:メソッドの定義
アクセス修飾子 戻り値の型　メソッド名(引数){
	...
	return 戻り値;
}
```
基本はこんな感じで設計します。
色々と分からん単語があるので、調査していきます。
###アクセス修飾子
アクセス修飾子とはメソッドで言うと、どこからこのメソッドが呼び出して使えるのかを示して、制限するものになります。
下記の種類のものがあります。

| 修飾子名| 制限 |
|:-:|:-:|
|  public | どこでも使えるやつ。他のクラスでも呼び出せる。  |
|  private | クラスの内部でしか使えない。他のクラスでは呼び出せない。。  |
| protected  |  そのクラスを継承してるサブクラスからアクセス可能！ |
| デフォルト  | 同じパッケージに属するクラスの中ならアクセス可能！  |
何もアクセス修飾子を指定しない場合はデフォルトになります。

###戻り値
メソッドを実行したときに最終的に返す値のことです。
例えば、戻り値の型にStringを指定したら、Stringの値を返します。
戻り値の型にvoidを指定した場合は何も値を返さなくて良くなります。

###引数
メソッドに渡されてくる値です。この値を使って色々処理します。
引数がない場合もあります。
##メソッドの例
では、実際にメソッドを作成してみます。
どこからでも呼び出せて、渡されてきた数値a,bの合計値を返すメソッドを作ります。

```java:メソッドを作ります。
public int addition(int a,int b){
   retrun a+b;
}
```
出来ました。後は下記のように呼び出せばnumの中に3が入ってきます。
int num = addition(1,2);
##さいごに
メソッドどうだったでしょうか。
アクセス修飾子とかは実際に開発しないと使い分けはイメージが使みずらいかと思います。
ぜひ、思いついた処理をメソッド化して遊んでください！

ご覧いただきありがとうございました。
Vue.js リストレンダリング モーダル作成

# 目的
リストレンダリングにモーダルを取り入れる。

# 実装

v-forでオブジェクトのキーをうまく使えばすっきりしたコードになることがわかった。最近ようやくVue.jsのありがたみがわかってきたかもしれない。


```main.js
var Sample = {
  props: ['item'],
  template: `
  <div>
    <ul>
      <li v-for="link in linkList">
        <a v-on:click="openModal(link.id)" href="#" class="link">
          {{ link.name }}
        </a>
      </li>
    </ul>
    <div id="overlay" v-show="showContent">
      <div id="content">
        <p>{{ modalMessage }}</p>
        <button v-on:click="closeModal">Close</button>
      </div>
    </div>
  </div>`,
  data: function() {
    return {
      showContent: false,
      linkList: [
        {id: 1, name: 'About'},
        {id: 2, name: 'Contact'},
        {id: 3, name: 'Docs'}
      ],
      modalMessage: ''
    }
  },
  methods: {
    openModal: function(id){
      if (id === 1) {
        this.modalMessage = 'About リンク作成中';
      } else if (id === 2) {
        this.modalMessage = 'Contacts リンク作成中';
      } else if (id === 3) {
        this.modalMessage = 'Docs リンク作成中';
      }
      this.showContent = true
    },
    closeModal: function(){
      this.showContent = false
    }
  }
}

var app = new Vue({
  el: '#app',
  components: {
    'sample-component': Sample
  }
})
```

```index.html
  <div id="app">
    <sample-component></sample-component>
  </div>
```

```style.css
#overlay{
  z-index:1;
  position:fixed;
  top:0;
  left:0;
  width:100%;
  height:100%;
  background-color:rgba(0,0,0,0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}
#content{
  z-index:2;
  width:20%;
  padding: 1em;
  background:#fff;
}
```

- リンク押下前

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/837d3f6c-6483-7c35-0b65-6d3d04c26191.png)

- リンク押下後

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621414/101bd029-2b2d-2730-f602-db1fe66d71a8.png)


# 参考記事

vue.js モーダルウィンドウ実装でコンポーネント理解
https://reffect.co.jp/vue/understand-component-by-moda-window
[Unity] Firebase configured correctly?の解消方法

#はじめに
UnityでFirebaseを使用していますが、設定からダウンロードしてきた`google-services.json`を反映してもうまくいかずに下記のエラーがLogcat上で出ていました。Sample APKのfirebase analytics/pushwoosh両方初期化問題ありませんでした。

`FCM registration error: Failed to retrieve token. Is firebase configured correctly?`
` java.util.concurrent.ExecutionException: java.lang.NoSuchMethodError: No virtual method onFailedToRegisterForRemoteNotifications`

## 原因
`Play Service Resolver`を`External Dependency Manager`に変更した際にうまく機能しなくなったみたいでした。

* unity-jar-resolver： https://github.com/googlesamples/unity-jar-resolver

## 解決策
Resolveし直した結果、エラーは出なくなりました。
`Unity Editor -> Assets -> External Dependency Manager -> Android Resolver -> Resolve`

## 参考
UnityでGooglePlayServicesを入れるにはPlayServicesResolver(unity-jar-resolver)が便利
https://qiita.com/tkyaji/items/b838c97228f99f194bcd
goのdocker環境をマルチステージビルドを利用して立ててみる


go環境をdockerで構築する際、マルチステージビルドを利用するとコンテナのサイズが小さくなる。各レイヤーごとに処理をわけ、実際に使用するイメージでは必要のない生成物は、それ以前のレイヤーのみが持つように指定することができる。

## マルチステージビルドとは
Dockerfile内にFROM行を複数記述するだけで、ビルドステージを分けることができる。こうすることによって、最終的にイメージに含めたくない内容を除外することが可能になり、その結果、イメージのサイズが小さくなる。

## マルチステージビルドを利用しない場合

```dockerfile:Dockerfile

FROM golang:1.15.7

COPY . .
RUN apt install -y git tar
RUN go build -o /tmp/app main.go
CMD [ "/tmp/app" ]
```
```go:main.go
package main
import "fmt"
func main() { fmt.Printf("hello world!") }
```
```bash
image size
REPOSITORY  TAG     IMAGE ID      CREATED        SIZE
example     latest  809b451bc01f  7 minutes ago  841MB
```

## マルチステージビルドを利用する場合
```dockerfile:Dockerfile
FROM golang:1.15.7 as build
COPY . .
RUN apt install -y git tar
RUN go build -o /tmp/app main.go


FROM alpine:3.8
COPY --from=build /tmp/app /app
CMD [ "/app" ]
```

```bash
image size
REPOSITORY     TAG     IMAGE ID      CREATED        SIZE
example-multi  latest  e223c19951f4  3 seconds ago  6.46MB
```

このように、imageのサイズが 841MB - 6.46MB = 834.54MB ほど小さくなった。

## 参考サイト
https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/multistage-build/
Bootstrapを導入したアプリケーションでCSSが反応しない場合の対策

# 本記事の目的
- bootstrapを導入したRailsのアプリケーションでCSSが適用されない現象を解決する

# 背景
RailsでのBootstrapの使い方を学んでいたが、Bootstrapのテンプレではない部分にCSSが反応しなくなった。
以下がコードとブラウザ上での見た目。
(Bootstrapの使い方を試しているだけなので、アクションやファイルの意図は特にない。)

```erb:index.html.erb
<%= render 'shared/header' %>
<p class="bg-primary"><button type="button" class="close" aria-label="Close"><span aria-hidden="true">&times;</span></button>
</p>
<p class="bg-success">...</p>
<p class="bg-info">...</p>
<p class="bg-warning">...</p>
<p class="bg-danger">...</p>
```

```erb:_header.html.erb
<header id="header-wrapper"></header>
```

```scss:header.scss
#header-wrapper {
  height: 50vh;
  background-color: blue;
}
```

```scss:application.scss
@import "bootstrap";
@import "tweets.scss";
// tweet.scssは何も記述がない
@import "header.scss";
```

Google chromeで表示↓
![キータ用画像bootstrap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/832303/de4f10f8-0322-cc22-557f-dbd21c85908d.png)

緑・青・黄・赤の線はBootstrapのテンプレで、一番上の太い赤の線は自分で用意したヘッダー。
(上に黒い線が見えるが、Google chromeのバーの部分)

1点おかしな箇所がある。
ヘッダー部分を、``背景色blue、高さ50vh``で指定したのに、``背景色red、高さ5vh``になってしまっている。
たしかに、最初は``背景色red、高さ5vh``で設定したが、``背景色blue、高さ50vh``に変更できるか試したところ、変わらなくなってしまった。

# 原因
**SCSSファイルの読み込みの順番**

上記コードの記述の通り、application.scssで、Bootstrapを一番初めに読み込んでいる。
Bootstrapでは、予めクラスやIDが用意されているので、競合したものがある場合、そちらが優先されるらしい。

よって、Bootstrapを読み込む前に、自分で用意したSCSSファイルを先に読み込んでみる。

```scss:application.scss
@import "tweets.scss";
// tweet.scssは何も記述がない
@import "header.scss";
@import "bootstrap";
```

以上の様に読み込む順番を修正し、Google chromeで表示してみると、、、↓

![キータ用画像修正後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/832303/74db853d-7c40-3a9d-3161-4f7bb2dafb29.png)

ヘッダー部分がしっかり指定した様に表示された。

# 結論
読み込む順番を変えれば、SCSSがしっかりと適用される。
(Bootstrapについては学習し始めたばかりの為、原因は他にもあるかもしれない。)