OmniAICreator/Qiita-1.07M huggingface dataset:
vscodeでサブディレクトリにgo.modを管理している場合はexperimentalWorkspaceModuleを有効化する必要がある

:::note warn
コメントで指摘頂いた通り、ExperimentalWorkspaceModuleはdeprecatedになったため、VSCode の Multi-root Workspaces 拡張機能かgo.workを利用することを推奨します。
https://qiita.com/chanhama/items/a21ca7d5cd43d6f3f90d#comment-55530e230c93991ef5c0
:::
以下のようなディレクトリ構成でgoprojectディレクトリから開くとvscodeがサブディレクトリのgo.modを認識してくれず、`can not import`エラーが発生し困っていました。

```
goproject
|- test1
|  |- mani.go
|  |- go.mod
|  |- go.sum
|- test2
   |- mani.go
   |- go.mod
   |- go.sum
```

調べたところLanguage Serverのgoplsのデフォルト設定だとルートディレクトリにgo.modファイルが無いとダメなようで、**experimentalWorkspaceModule**の有効化で上記が解決しました。

# 環境
- macOS Catalina v10.15.7
- vscode v1.51.1
- go version go1.15 darwin/amd64

# 有効化
## 拡張機能
vscodeの拡張機能でGoをインストールします。
![拡張機能__Go_—_tipstar-ops.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266372/50bc24b0-b2c1-aad3-5627-989f1eeabb81.png)

## Language Server
Code > Preferences > Settings から `go.useLanguageServer` を検索して有効化します。
![設定_—_tipstar-ops.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266372/dcdb4720-f6c2-9c7f-cbf4-df9cddc0732c.png)

## GO111MODULE
vscodeのsettings.jsonを開き、以下を設定します。

```
{
    "go.toolsEnvVars": {"GO111MODULE": "on"},
}
```

## gopls
cmd+shift+Pでコマンドパレットを開き、`Go: Install/Update Tools` を検索した後で gopls を選択してインストールします。

![gopls.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266372/30dcf134-6733-3114-f665-69f93c84d205.png)

実行後、goplsのバージョンがv0.5.0以上であることを確認してください。

```
$ gopls version
golang.org/x/tools/gopls v0.5.4
    golang.org/x/tools/gopls@v0.5.4 h1:PkQWDfzw8CxoseHDQniF2GhzmndN8KnQL6gcG2gnF3Y=
```


なお、コマンド実行時にxcron errorが発生した場合はxcode-selectをインストールしてください。

```
# エラー内容
xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun 
undefined

# インストール
xcode-select --install
```

## experimentalWorkspaceModule
vscodeのsettings.jsonを開き、以下を設定します。

```
{
    "gopls": { "experimentalWorkspaceModule": true}
}
```

以上です。importエラーが解決しないようであれば、vscodeを再起動してください。

# 参考
https://github.com/golang/go/issues/37838
https://github.com/golang/go/issues/32394#issuecomment-728194166
「The Biostar Handbook が面白すぎる件」に対して思ったこと

これは
[Workflow Advent Calendar 2020](https://adventar.org/calendars/5339)
の1日目の記事になる。

タイトルのまんまで
@kojix2 さんの[「The Biostar Handbook が面白すぎる件」](https://qiita.com/kojix2/items/6556a56450401218f226)
に対して思ったことを述べる。

> biostarsは、バイオインフォマティックス領域のstackoverflowとでも言うべきQ&Aサイトです。バイオインフォマティックスでは、初心者向けの日本語の資料があまり多くはありません。そのような状況で、biostarsを検索すると親切な回答が掲載されていることが多く、非常に参考になりますね。実際に自分で質問してみたこともありますが、丁寧で良質な回答がつくことが多いのでとても便利です。

自分はこれまでbiostarsをまともに見たことが一度も無かった。
試しに「KEGG」「pathway」といったキーワードで検索してみたがそれらのヒット結果(回答)に惹かれるものは無かった。
分野によっては「丁寧で良質な回答がつく」のだろうか。
キーワードを書かずにざっと見るとBioconductorというwordがちらほら見えたがBioconductorに関することはbiostarsではなく https://support.bioconductor.org/ で質問した方がいい。
(Cytoscapeというwordは見かけなかった(検索まではしてない)が同じくbiostarsではなく https://groups.google.com/g/cytoscape-helpdesk で質問した方がいい。)

> 価格は非常に安くて、2500円とか、3500円とか、そのぐらいの値段です。学術書の値段を考えると、本当にお買い得の価格だと思います。

サンプルが「404 Error. File not found.」ばかりで見れないように思った。
なので買う前にお買い得そうかわからなかった。
(そして自分は買ってない。)

> 質量ともに、これほどまとまったバイオインフォマティックスの初心者向け日本語の資料は地球上に存在しないと言い切ってよいでしょう。

「質量ともに、これほどまとまった」か、また「バイオインフォマティックス」が何なのかが自分はわかってないが「初心者向け」だと https://datacarpentry.org/lessons/#genomics-workshop とかみたいなの方がよかったりしないだろうか。(ちなみに自分は配列無知。)

> 時間を無駄にしない方法が面白すぎる
さて、biostarハンドブックを買って一番おもしろかったのが、「時間を無駄にしない方法」という項目です。あまりにも面白かったので、どっかーの方面からお叱りが入るかも知れませんが引用したいと思います。

これは確かに「面白」がる必要があると思う。
各技術の利用が「時間を無駄にし」てしまってないかは気をつけたい。

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/51e66a47-c8c1-2142-2b56-aec55076967f.png)

「Dockerを必要とするソフトウェアはすべて、Dockerを必要としない、...、よりシンプルなソフトウェアに置き換えることができます。」ってこたないと思う。
がしかし、
「Docker無しでも済みそうって場合でも「とにかくDockerから」と言ってくれるな！」
、という感じには同意する。

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/ffe1beb9-d22c-0c2c-aefe-3cc769511ca6.png)

たぶん怒りのソースは「使い方がわからない！」かと思う。
なので AnVIL/Terra (下記画像はYouTubeのリンクです。QiitaでYouTube埋め込みを実現する方法がわかりませんでした)

[![Sehyun Oh, Levi Waldron, Workshop 100: Cloud based genomics using Terra AnVIL](http://img.youtube.com/vi/KYBDeDIf5tQ/0.jpg)](http://www.youtube.com/watch?v=KYBDeDIf5tQ)
みたいなのから入ると「クラウドええやん！」になったりするかもしれない。

> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7591/83cbe3fe-c166-0724-1f55-41419519f8b3.png)

Workflow Advent Calendar 的にはこれが一番重要かと思う。

確かに自分が

- CWLを使用したほうがよいと思っただけ
- 利点を明確にすることができません

になってないか常に気をつける必要があると思う。

> しかし、全てのツールは誰かの手によって作られたものです。単に盲信するのではなく、どこがダメなのかを知る。愛のある健全な批判的な精神でながめるというのは必要でしょう。

というか目的を忘れ、まず流行やソフトウェア名から入りがちなので気をつけたい。

以上。
Railsのformでのselect_box使い方！【初学者向け】

Railsでselect_boxの綺麗な書き方を知りたい！
そんな方必見です

# 前提知識
- RubyとRailsの基礎知識
- form_withの使い方の知識
- MVCの基本的な知識

# 書き方
<%= f.select( プロパティ名, タグの情報, {オプション} ) %>
こんな普通に記述していきます！

プロパティ...カラム名
タグの情報...セレクトボックスに使いたいデータ
オプション...セレクトボックスのオプション(include_blankなどをよく使います)

カラム名はuser_idやmenu_idなどidをとってくることが一般的です！！
タグの情報はoptionタグに使われるデータなので配列かハッシュで指定します！

[[表示名, 送信したいデータ], [表示名, 送信したいデータ]]

オプションは{ include_blank: '選択してください'}のように書くことが多いと思います。
このオプションをつけると

![スクリーンショット 2020-12-02 7.27.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/3edc9fb9-dea1-faa1-4258-1f305008668b.png)

こんな風にデフォルトの選択肢が指定した文字列になります！

# 設定
今回はmenusテーブルとreserationsテーブルを設定し、メニューを選択し、予約ができる！
といった設定にしていきます！

menusテーブル

```ruby:schema.rb
  create_table "reservations", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
    t.string "name"
    t.datetime "start_time"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.integer "menu_id", null: false
  end
```
reservationテーブルnameカラムにdate_timeで予約時間を設定

```ruby:schema.rb
  create_table "menus", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci", force: :cascade do |t|
    t.string "name"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
  end
```
メニューテーブルは今回はわかりやすくnameカラムだけにします！

```ruby:reservation.rb
belongs_to :menu
```

```ruby:menu.rb
has_many :reservations
```
関係性としては1対多で設定します！

menuテーブルは今回はメニューを3つ設定します！
ドライヘッドスパ＋ハンドマッサージ15分
ドライヘッドスパ＋眼筋マッサージ　15分
ドライヘッドスパ＋首肩マッサージ　15分

# 実際に書いてみる
```ruby:reservations_controller.rb
before_action :set_menus, only: [:new, :create]

 def set_menus
    @menus = Menu.all
  end
```

今回はbefore_actionでnewとcreateにmenuのデータ全てをとってきます！
同じ記述はなるべくリファクタリングして綺麗に書きましょう！

```ruby:reservations/new.html.erb
<%= form_with(model: @reservation, local: true) do |f| %>

  <div class="field">
    <%= f.label :name, "フルネーム(必ずご自身のお名前)" %>
    <%= f.text_field :name %>
  </div>

  <div class="field">
    <%= f.label :menu, "メニューを選択してください" %>
    <%= f.select :menu_id, @menus.map { |menu| [menu.name, menu.id] },
      { include_blank: '選択してください'} %>
  </div>

  <div class="field">
    <%= f.label :start_time %>
    <%= f.datetime_select :start_time %>
  </div>

  <div class="actions">
    <%= f.submit class: "btn btn-primary reservation_btn" %>
  </div>
```
 <%= f.select :menu_id, @menus.map { |menu| [menu.name, menu.id] },
      { include_blank: '選択してください'} %>
のように配列でとってくると綺麗にかけます！

![スクリーンショット 2020-12-02 7.54.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/769fe46f-aeaa-15fd-87d3-98f74f75916a.png)

※each文とかで繰り返し処理で書くとセレクトボックスが3つ表示されてしますので注意※

# 番外編
メニューを全てではなく最初の二つだけとってきたい！
そんな場合もあると思います！

 <%= f.select :menu_id, @menus.first(2).map { |menu| [menu.name, menu.id] } %>
こんな感じで書きましょう！

```ruby
[1] pry(main)> arry = [1,2,3,4,5,6]
=> [1, 2, 3, 4, 5, 6]
[2] pry(main)> arry.first(2)
=> [1, 2]
[3] pry(main)> arry.first(5)
=> [1, 2, 3, 4, 5]
```
配列にfirst(とってきたいデータの数)で好きな数だけデータがとってこれます！！
お疲れ様でした！
React Native (Expo)でFailed building JavaScript bundleが発生する時の対処法

テストでexpo installするべきライブラリを`npm install`していたら、以下のようなエラーが出るようになってしまいました。

```
Unable to resolve module `firebase` from `screens/HogeScreen.tsx`: firebase could not be found within the project.

If you are sure the module exists, try these steps:
 1. Clear watchman watches: watchman watch-del-all
 2. Delete node_modules: rm -rf node_modules and run yarn install
 3. Reset Metro's cache: yarn start --reset-cache
 4. Remove the cache: rm -rf /tmp/metro-*
```

対処法は上記に書かれている通りですがコピペだと上手くいかなかったので、
コマンドを書き残しておきます。

## 実行したコマンド

```
1. watchman watch-del-all
2. rm -rf node_modules
3. yarn install
4. yarn start --reset-cache
5. rm -rf /tmp/metro-*
6. expo start
```

4を実行すると以下のエラーがでますが上手く実行は出来ているので、
そのまま5-6を進めましょう。

```
% yarn start --reset-cache                                                  (git)-[master]
yarn run v1.22.10
$ expo start --reset-cache

  error: unknown option `--reset-cache'

error Command failed with exit code 1.
```

これで6までいったらエラーは治っているはず！
[VSCode]Spring BootでHello World!

## はじめに
VSCodeを使って、Spring Bootで作るWebアプリケーションを作成しました。画面に"Hello World!"と表示するだけの簡単なアプリケーションです。

## 想定開発環境
**OS**: Windows10 64bit
**Visual Studio Code**: 1.51.1
**Java**: Java14
※Mavenプロジェクトにて作成します。

## 開発環境準備
VSCodeに以下の拡張機能をインストールしておく。 
・**Java Extension Pack**
https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-pack

・**Spring Boot Extension Pack**
https://marketplace.visualstudio.com/items?itemName=Pivotal.vscode-boot-dev-pack

## プロジェクトの作成
- Visual Studio Codeで「コマンドパレット」（Ctrl + Shift + p）を表示、Spring bootのプロジェクトを作成します。

### コマンドパレットでの操作
1. 「**Spring Initializr: Generate a Maven Project**」を選択

2. 「**Specify Spring Boot version**」 Spring Bootのバージョンを選択します。今回は特に指定がないので、2020/12時点の最新（2.4.0）を選択

3. 「**Specify project language**」使用する言語を選択。今回はJavaを選択

4. 「**Input Group Id**」パッケージ名を入力。
例：com.example

5. 「**Input Artifact Id**」プロジェクト名を入力。
例：demo

6. 「**Specify packaging type**」パッケージタイプ：今回はwarにします。（jarでもOK）

7. 「**Specify Java type**」使用するJavaのバージョンが求められるので、使用するJavaのバージョンを選択。今回はJava14を使用。

8. 「**Search for dependencies**」Mavenプロジェクトなので、依存関係の選択があります。今回は、「**Webアプリを作る**」「**画面を表示させる**」という目的があるので、以下2つを選択します。  
 - Spring Web
  - Thymeleaf

ここまでやると、プロジェクトの保存先を聞かれます。プロジェクトの保存場所を選択してください。

- 作成されるディレクトリは以下のような構成です。
  - **DemoApplication.java**, **ServletInitializer.java**がデフォルトで実装されています。

```
|― src
 |   |― main
 |   |    |― java
 |   |    |    |― com
 |   |    |        |― example
 |   |    |             |― demo(プロジェクト名)
 |   |    |                      |― DemoApplication.java（デフォルトで作成される）
 |   |    |                      |― ServletInitializer.java（デフォルトで作成される）
 |   |    |― resources
 |   |           |― static/ (静的ファイル)
 |   |           |― templates/ (テンプレートファイル)
 |   |           |― application.properties (環境独自の設定ファイル)
 |   |― test
 |       |― java
 |            |― com
 |                |― example
 |                      |― demo(プロジェクト名)
 |                               |― DemoApplicationTests.java
 |― .gitignore
 |― HELP.md
 |― mvnw
 |― mvnw.cmd
 |― pom.xml (Mavenの設定ファイル)
```

## アプリケーションの作成
- /demo/src/main/java/com/example/demo/controller ディレクトリ配下にControllerクラスを作成します。（SampleController.java）


 ```java
 package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class SampleController {
    @RequestMapping("/sample")
    public String sample() {
        return "sample";
    }
}

 ```

- /demo/src/main/templates内にsample.htmlを作成します。（sample.html）

```html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <title>Sample</title>
</head>

<body>
    <h1>Hello World!</h1>
</body>

</html>
```

- Spring bootアプリケーションの実行
VSCode左下の「**SPRING-BOOT DASHBOARD**」を選択し、[start] or [debug] を選択  
※ Spring Bootに内包されたTomcatが起動し、実装したアプリがコンパイルされる。

## 表示確認
- ブラウザにて表示確認。"Hello World!"と表示されるはずです。  
http://localhost:8080/sample

## 終わりに
- DBからデータ取得して表示させる等、より本格的なWebアプリケーション開発の記事を挙げる予定です。
乞うご期待！

## 参考
Spring BootをVSCodeで「Hello World」を表示させてみた
https://tech-lab.sios.jp/archives/19941
[CSS]フォントの太さを指定する

#[CSS] 見出しタグのフォントの太さを指定する

###見出しタグとは

\<h1>~\<h6>のことです。
\<h1>~\<h6>のHとはHeadingの略です。
見出しという意味です。

###見出しタグの太さ

\<h1>~\<h6>は初期状態でfont-weight: bold;になっています。
CSSでfont-weight: normal;と指定すると文字が標準の太さになります。
PlatformIOにてM5Stackの書き込み領域を増やす(OTAを無効化する)

# ことのはじまり
PlatformIO経由でM5Stackにプログラムを流し込もうとしたところ、以下のようなメッセージが出て書き込み失敗しました。

>Error: The program size (xxxxxxxxxx bytes) is greater than maximum allowed (1310720 bytes)

どうも、プログラム書き込み可能領域を超えてしまっていたようです。

# 対応内容
ESP32にはOTA(over the air)というwifi経由でプログラムを書き込む機能があります。
この部分を無効化し、その分を書き込み領域に充てることで領域を増やすことができるようです。
私はOTAを使用していなかったので、この方法を採用しました。

具体的には、platformio.ini に以下を記載することで領域を増やすことができました。

``` platformio.ini
board_build.partitions = no_ota.csv
```

# 参考URL
以下の記事が大変参考になりました。より詳しい説明や、ArduinoIDEにおける対処方法も記載されています。
[ESP32-WROOM-32のプログラム領域が足りなくなった時に、パーティションの設定を変更（OTAを無効化）して領域を増やす方法](https://asukiaaa.blogspot.com/2019/03/esp32-wroom032ota.html)
Azure Database for PostgreSQLでCLIで開発用DB作成するときにはSKU設定忘れずに（2020/12現在）

# はじめに

Azure CLIはとっても便利ですが、デフォルト設定を信じるのはやめましょう。特に省略されているオプションは気が付きにくいので、`az postgres up`で`--sku-name`が省略可能なのは、たしかに業務での利便性は高いとは思いますがカジュアルにミニマム環境をつくりたい立場としては罠っぽく感じます。


# たとえば？

[Azure App Service on Linux で Ruby および Postgres のアプリを構築する](https://docs.microsoft.com/ja-jp/azure/app-service/tutorial-ruby-postgres-app "Azure App Service on Linux で Ruby および Postgres のアプリを構築する")チュートリアルに従ってCLIコマンドいくつかだけでさくさくっとAppServiceとPostgresの環境がつくれますが、どうせ最後に消すのだからとデータベースの料金プランの指定はされていません。なのでチュートリアルの環境は、そのまま開発環境として使い続けるのは推奨されません。

```
az postgres up --resource-group myResourceGroup --location westus --server-name <postgresql-name> --database-name sampledb --admin-user <admin-username> --admin-password <admin-password> --ssl-enforcement Enabled
```

こちらのコマンドで作成されたPostgresサーバを、2020/12現在の価格を[料金計算ツール](https://azure.microsoft.com/ja-jp/pricing/details/postgresql/server/ "
Azure Database for PostgreSQL の価格")で比較してみると、単一サーバの場合でBasicの最小構成が	~¥2,779.84/月に対して、設定が省略されたときに作成される汎用目的構成だと~¥14,324.352/月と月額で1万円以上の差[^1]です。
そして当然といえば当然ですが、サーバーの作成後は汎用目的構成からBasic構成への、ダウングレードする変更はできません。[^2]

[^1]: もちろん1年とか3年のReservedにすれば価格差は縮まりますが、前提が開発用のミニマム構成なので比較対象からは外れる。
[^2]: 逆にBasic構成から汎用目的構成のアップグレードもできません。また、2020/12現在プレビュー中のフレキシブルサーバーでは未調査ですが作成時点でのワーニングが出てこないのでもしかしたら？。

# チェックすべきポイント

GUIでもコンピューティングとストレージの設定でサーバの構成を見直すと思いますが、特にCLIでは`--sku-name`オプションが省略可能なので気をつけましょう。2020/12時点では単一サーバ構成では下記がミニマム構成になります。

```
az postgres up --resource-group myResourceGroup --location westus --server-name <postgresql-name> --database-name sampledb --admin-user <admin-username> --admin-password <admin-password> --sku-name B_Gen5_1 --ssl-enforcement Enabled
```

# 最後に

時間に追われていても、オプションを精査するだけでなくドキュメントには目を通すべき（自戒）。
Microsoftさんは比較的公式が充実していますが、その分、量もかなり多くなりがちです。ある程度理解が進んでからだと探しやすくても、ピンポイントで必要な情報を探し当てるのはある程度の慣れが必要です。
JS オブジェクトを実際にコードで書く (JSアウトプット)

##あいさつ
初めての人は初めまして！知っている人はこんにちは！
中学生バックエンドPGのAtieです！
今回もJSのアウトプットをしていきます
今回はオブジェクトを実際にコードを書いて学習していきます！

##オブジェクトの宣言方法
まずはオブジェクトの宣言からです！
自分はもともとある程度JSを扱えますが「基礎」を固めるために始めました！

宣言方法

```main.js
let youtuber = {
    list: {
        business: {
            youtuber: [
                {name: "しまぶー", age: 20, teachprogramming() {}},
                {name: "あっちゃん", age: 37, teachhistory() {}}
            ],
            teach() {}
        },
        entertainment: {
            youtuber: [{name: "ヒカキン"}, {name: "はじめしゃちょー"}],
            makesmile() {}
        }
    },
    plan() {},
    uploadvideo() {}
};
```
宣言してみました
このオブジェクトは「youtuber」というオブジェクトです
プロパティやメソッドは前回学習したのでわかると思います！

##オブジェクトにアクセス
では宣言したオブジェクトにアクセスしてみましょう！
アクセス方法には二つあるのはご存じですよね？(わからない場合は前回の記事をご参照ください！)
今回は.のほうを使います

```main.js
console.log(youtuber.list.business.youtuber[0].name);
```
アクセスしてみました
youyuberというオブジェクトの中のlistというオブジェクトにアクセスしさらにbusinessにアクセスして配列youtuberの0番にアクセスしnameというプロパティにアクセスしています

前々回に「データのやり取り」と「DOM操作」がJSのお仕事と話しましたよね？
では今回は「DOM操作」をしてみます

##DOM操作
まずはブラウザを開いて[Yahoo!](https://www.yahoo.co.jp/)にアクセスしてみてください！
そしたらデベロッパーツールを開いてconsoleタブを選択してください(ブラウザによって違いますがここでは説明を省きます)
いろいろなエラーが表示されますが左上のマルに斜め線が入ったボタンをクリックするとエラーをクリアできます

DOM操作を行ってみます
まずはhtmlのIDを収得してみます

```console.js
window.document.getElementById("Masthead");  //windowは省略可
```
これをコンソールに張り付けて実行してみてください
htmlが収得できたと思います

windowオブジェクトはブラウザ自体なのでほかにもいろんなことができます

```console.js
window.console.log();     //consoleに表示
window.alert();           //アラートを表示
window.screnn.width       //ページの横幅を収得
window.screnn.heigth      //ページの高さを収得
window.location.reload()  //ページをリロード
```
windowオブジェクトを使うことで様々なことができます

##さいごに
最後まで読んでいただきありがとうございました
自分のアウトプット用なので短かったですがもっと奥が深いです
これからもJSの学習を続けていきます！
それではまた次回！

[AtieのTwitter](https://twitter.com/Atie_BackendPG)
[しまぶーのIT大学さんのTwitter](https://twitter.com/shimabu_it)

##参考、学習資料
[【JavaScript入門 #4】オブジェクトを実際にコードで書いてみよう【ヤフー出身エンジニアの初心者向けプログラミング講座】](https://www.youtube.com/watch?v=y5_rULRxYuY&list=PLwM1-TnN_NN7-zdRV8YsGUB82VVhfYiWW&index=4)
Vue.jsでjsファイル読み込み時に一瞬テンプレートのマスタッシュファイルが見えてしまう場合の対処法

## 

**html** 

1.  \<head>タグ配下に\<style>タグを追加し、 `[v-cloak] { opacity: 0; }`を定義する。
2.  コンポーネントを指定しているタグに`v-cloak`を付与する。

```
</head> 
    <meta charset="utf-8">
    <title>サンプル</title>
    <link rel="..." href="...">
    <style> 
        [v-cloak] { opacity: 0; } 
    </style> 
</head>
<body>
    <div id="test" v-cloak>
    ・・・省略・・・
    </div>
<body>

```

**main.js**

``` 
// コンポーネント
var app = new Vue({
    el : '#test' ,
    data : {}
　　・・・以下省力
```

**解説**

`v-clock`は要素が属するコンポーネントのデータ生成とデータバインディングが完了するとDOMから消去される。その性質を利用し、`v-clock`がついている間だけ、CSSで要素を非表示にすることでバインディング前の状態を隠すことができる。
batファイルでファイル名を一括リネームしたい

多数のファイルの名前の共通部分を一括でリネームしたい。
そんな時に前職で使っていたバッチファイルを思い出しながら、自分用にもう一度作ってみました。


## ファイル名の共通部分を一括でリネームするバッチ
一括リネームしたいファイルたちがいるフォルダに、下記のバッチファイルを置き、
置換前・置換後の文字列を設定します。

```file_rename.bat
@echo off

rem ------- 置換前・置換後の文字列を設定 -------
set TARGET=old
set REPLACE_WITH=new
rem -----------------------------------------

for %%F in ( * ) do call :sub "%%F"
exit /b

:sub
set FILE_NAME=%1
call set FILE_NAME=%%FILE_NAME:%TARGET%=%REPLACE_WITH%%%
ren %1 %FILE_NAME%

goto :EOF
```

実行すると、フォルダ内のファイルのold部分がnewにリネームされます。

**実行前**
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920605/bd18dea4-a72a-2de5-fec0-736211763453.png)
**実行後**
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920605/c3b39f57-9b75-087f-23cc-4c7209d4423c.png)


拡張子の一括変更も可能です。

```file_rename.bat
rem -------置換前・置換後の文字列を設定-------
set TARGET=.txt
set REPLACE_WITH=.csv
rem ------------------------------------------
```
**実行前**
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920605/e21d2563-f2aa-fc53-2d41-1ad5cb416372.png)
**実行後**
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/920605/6da849c4-3e7c-453e-c79c-7742a09378a6.png)


## 解説

#### どうやって文字を置換しているか

setコマンドの、変数の置換機能を使って置き換えしています。

```
set [変数名]=%[変数名]:[置換前文字列]=[置換後文字列]%
```

このバッチでは置換前・置換後文字列を変数に格納しているので、
変数を展開した式をsetコマンドに渡す必要があるため、

```
　call set [変数名]=%%[変数名]:%[置換前文字列の変数]%=%[置換後文字列の変数]%%%
```

という形式で記述しています。

#### どうやってファイル名を変更しているか

renameコマンドを使っています。rename は ren と略すことができます。

```
ren [現在のファイル名.拡張子] [新しいファイル名.拡張子]
```

元のファイルを残したい場合は、
「ren」部分を「copy」に変更すると、元のファイルを残しつつ、
ファイル名を置換した新しいファイルを作ることができます。
オリジナルアプリ作成1日目　タスク管理アプリ 〜Bootstrap導入〜

始めに

この記事は私自身が今後の学習において、忘れたらここを見返せば良い。という安心を得るための備忘録とアウトプット学習のために投稿しております。
初学者のため間違いなどあるかとは思いますが、優しくしてくださると幸いです。

今回はタスク管理アプリの設計からヘッダー作成まで行いました。

〜特に苦戦した内容〜

今回開発にあたりBootstrapというWebフレームワークを使うと開発がスムーズかつクオリティの良いものに仕上がると先輩エンジニアに教わっていたので、使ってみることに、ですが導入した後に「どうやって使ったら良いの？！」となってしまいアタフタしてしまいました😭

なので今回は

・インストール
・導入

をアウトプットしていきます。

今後Bootstrapを使った様々なことをアウトプット出来たら良いと思っています。
（アプリ開発が一度終わった後の息抜きにでも...)


〜Bootstrapの導入の前に〜
Gemfileにwebpackerがいることを確認

webpackerはBootstrapの導入の目的以外にも
今後JavaScriptを使ったユーザーが使いやすいを目的にした動きのあるアプリを作る際に必要となる一連の動きをまとめてくれているgemになるのでこのタイミングで導入します。標準搭載されていたようなので今回はインストールせずに進めました。

〜Bootstrapの導入〜
ターミナルで
```
yarn add jquery bootstrap popper.js
```
でBootstrapを導入することが出来ました。 
続いて　app/javascript/src/application.scss　を作成しました。
その一番上に
```
import 'bootstrap';
import '../stylesheets/application';
```
を記述しました。

最後に  app/views/layouts/application.html.erbに
```
  <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
    <%= stylesheet_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```
の２行を追加しました。

これでBootstrapの導入は完了しました。
「なぜこの機能がこのように使えるのだろう」と言った疑問は残ったままのため今後の課題なのですが、それよりも今はこのフレームワークで何が出来るのかをしっかりと学習していきたいと思っています。
WAPとは

#WAPとは

Web Application Firewallのこと。

webサーバーとインターネット(クライアント)との中間に設置され、外部ネットワークからの不正アクセスをアプリケーションレベルで遮断する。

webサーバーとクライアントの中間に設置されるため、webサーバーを保護するために使用される。
tar command Linux 

#tar commandについて

複数のファイルを１つにまとめるアーカイブを実行するために使用されるコマンド。


**○複数ファイルを1つにまとめる**

*tar -czvf (アーカイブ後のファイル名).tgz (まとめる対象ファイル)* 

```
xxxxxxx@MacBook-Pro tar-test-directory % ls
sample01.txt	sample02.txt	sample03.txt
xxxxxxx@MacBook-Pro tar-test-directory % tar -czvf archieve.tgz sample0
1.txt sample02.txt
a sample01.txt
a sample02.txt
xxxxxxx@MacBook-Pro tar-test-directory % ls
archieve.tgz		sample01.txt		sample03.txt
entire-compress.gz	sample02.txt
```

**○まとめたファイルを展開する**

*tar -xzvf (展開するファイル名).tgz* 

```
xxxxxxx@MacBook-Pro tar-test-directory % ls
archieve.tar.gz	
xxxxxxx@MacBook-Pro tar-test-directory % tar xzvf archieve.tar.gz
sasakidaisuke@MacBook-Pro tar-test-directory % ls
Users		archieve.tar.gz	sample01.txt
```

Usersというディレクトリーが作成され、ここに解凍されたファイルが格納されている。
re:Invent Andy Jassy Keynoteの気になったもの

# 背景
さっきre:InventのメインイベントのAndy JassyのKeynoteが終わりました
たくさん新サービスは出ましたが、気になったものをピックアップしてみます
新サービスが発表されて詳細を見たいってなったら、だいたい[AWS News Blog](https://aws.amazon.com/jp/blogs/aws/)に記事が出るので、それを見てました

# 気になったもの一覧
## コンピューティング
### Lambdaコンテナ対応

[New for AWS Lambda - Container Image Support | Amazon Web Services](https://aws.amazon.com/jp/blogs/aws/new-for-aws-lambda-container-image-support/)

### AWS Proton

[Preview: AWS Proton - Automated Management for Container and Serverless Deployments | Amazon Web Services](https://aws.amazon.com/jp/blogs/aws/preview-aws-proton-automated-management-for-container-and-serverless-deployments/)

## DevOps

### ECR Public(Keynoteで触れてないと思う)

[Amazon Elastic Container Registry Public: A New Public Container Registry | Amazon Web Services](https://aws.amazon.com/jp/blogs/aws/amazon-ecr-public-a-new-public-container-registry/)

[ECR Public Gallery](https://gallery.ecr.aws/)

### CodeGuru support Python

### DevOps Guru

[New- Amazon DevOps Guru Helps Identify Application Errors and Fixes | Amazon Web Services](https://aws.amazon.com/jp/blogs/aws/amazon-devops-guru-machine-learning-powered-service-identifies-application-errors-and-fixes/)

## Connect

### wisdom

[Amazon Connect Wisdom - Amazon Web Services](https://aws.amazon.com/jp/connect/wisdom/)

### Customer Profile

[Deliver personalized customer experience using Amazon Connect Customer Profiles | Amazon Web Services](https://aws.amazon.com/jp/blogs/contact-center/amazon-connect-customer-profiles/)

### Real-Time Contact Lens

[Real-time customer insights using machine learning with Contact Lens for Amazon Connect | Amazon Web Services](https://aws.amazon.com/jp/blogs/contact-center/contact-lens-real-time/)

### Tasks

[Easily prioritize, assign, track, and automate contact center agent work with Amazon Connect Tasks | Amazon Web Services](https://aws.amazon.com/jp/blogs/contact-center/amazon-connect-tasks/)

### Voice ID

[Machine learning-based caller authentication with Amazon Connect Voice ID (preview) | Amazon Web Services](https://aws.amazon.com/jp/blogs/contact-center/amazon-connect-voice-id/)

### 全体

[](https://aws.amazon.com/jp/blogs/aws/amazon-connect-smarter-and-more-integrated/)

## IoT

### Monitron

[Amazon Monitron, a Simple and Cost-Effective Service Enabling Predictive Maintenance | Amazon Web Services](https://aws.amazon.com/jp/blogs/aws/amazon-monitron-a-simple-cost-effective-service-enabling-predictive-maintenance/)

### Lookout for Equipment

[New - Amazon Lookout for Equipment Analyzes Sensor Data to Help Detect Equipment Failure | Amazon Web Services](https://aws.amazon.com/jp/blogs/aws/new-amazon-lookout-for-equipment-analyzes-sensor-data-to-help-detect-equipment-failure/)

### AWS Panorama Appliance

[AWS Panorama Appliance: Bringing Computer Vision Applications to the Edge | Amazon Web Services](https://aws.amazon.com/jp/blogs/aws/using-computer-vision-applications-at-the-edge/)
TypeScriptのオーバーロードはArrow Functionではできない

使うときになるとなぜか毎回忘れている気がするのでメモ

何も考えずarrowでoverloadしようとするとこんな感じになるとおもいますが、

```typescript
type Vec2 = [number, number]
type Vec3 = [number, number, number]

type Negative = ((vec: Vec2) => Vec2) | ((vec: Vec3) => Vec3)

const negative: Negative = (vec: Vec2 | Vec3): Vec2 | Vec3 => {
  if (vec.length === 2) {
    return [-vec[0], -vec[1]] 
  }
  return [-vec[0], -vec[1], -vec[2]]  
}
```

しかしこれは当然ながらできないです。なぜならnegativeの右辺は型定義上はVec2を受け取ったときにVec3を返す可能性を否定できないし、Vec3を受け取ってVec2を返すかもしれません。左辺ではVec2を受けたら必ずVec2で返す、と言っているのでそれに矛盾します。

一応、TypeScriptでは以下のようなsyntaxでoverloadを使用することができます。

```typescript
function negative(vec: Vec2): Vec2
function negative(vec: Vec3): Vec3
function negative(vec: Vec2 | Vec3): Vec2 | Vec3 {
  if (vec.length === 2) {
    return [-vec[0], -vec[1]] 
  }
  return [-vec[0], -vec[1], -vec[2]]
}
```

ただ、当然arrowのときと同じ問題は抱えています。これではVec2を受けてもVec3を返すかもしれません。
単にtypescriptが型不整合に対して目を瞑っているだけです。

式ではなくfunction文であるから、compilerの都合としてはそういった特殊な推論も差し込めるのだと思います。arrowの場合はどうしても式として使用することになるので、式であれば式として正当な評価/演算ができる必要がありますが、arrowでのoverloadを実現するためにはその仕組みを崩さないといけない(と思う)から現状用意されていないのではないでしょうか。

----

TypeScriptでは、残念なことに論理的に正しいoverloadをするのは無理だと思います。文法が微妙であるのが原因だと思いますが、TypeScriptは「JavaScriptのコードをそのままTypeScriptに乗せても動作する」ような言語として作られているため、その要件を満たすような文法が発見されてないのなどの原因があるのかなと思いました。

ちなみにタイトルのarrow functionではできないというのは厳密には誤りで、最初の例の右辺項でanyを使えばできます。誰もがanyは可能な限り使いたくないと思うので省略します

----

参考: https://github.com/microsoft/TypeScript/issues/33482
CloudWatchのログ保持期間を一律設定するワンライナー

CloudWatchにバンバン自動作成されるロググループは保持期限が無期限。
ランニングコストに地味に響くので無駄に保持したくない。
デフォルト設定出来ないかと探したものの見当たらない。

ということで一括設定できるシェルを用意しました。

```shell
aws logs describe-log-groups --query logGroups[].[logGroupName] --output text | xargs -t -I {} aws logs put-retention-policy --log-group-name {} --retention-in-days 30
```
【Microsoft Azure】Flaskでwebアプリ作ってコロナ対策に貢献した話

# 概要
2020年7月当時私の所属している香川高専詫間キャンパスでは，面接授業の再開に伴い寮生活も再開されようとしていました．
しかし，感染症対策の叫ばれる昨今，様々なところで対策を講じなければなりません．食堂然り，居室然り．  
その一環として「浴室での感染症対策」も必要になりました．そこで開発したのが**"[浴室予約システム](https://github.com/Yamaji-Toshiyuki/Bath-Reserve)"**です．
![bath-reserve-form.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156659/a5ab567e-9eb0-dc42-de0d-52072c545ee4.png)

)
他の集団生活のある場所でも活用できると思い，今回の事例を共有します．

# 開発・運用
ご存知かもしれませんが，高専生にはMicrosoftの包括ライセンスでMicrosoft Azureで使える100$分のクレジット付きサブスクリプションが配布されています．
今回はこちらを利用してシステムの開発・運用を行いました．(その後，従量課金制のサブスクリプションに変更)
## 開発・実行環境
+ Visual Studio Code(Azure App Serviceの拡張機能をインストールして使用)
+ Python3.8 + Flask
+ Microsoft Azure App Service(Python3.8を選択)
+ Microsoft Azure SQL

上記の環境をUbuntu20.04 or Win10上から使用しました．

## 参考にしたサイト
Azureの使用方法は公式リファレンスが非常に充実しているため，是非そちらをご覧いただければとおもいます．

+ [クイック スタート:Azure App Service on Linux で Python アプリを作成する](https://docs.microsoft.com/ja-jp/azure/app-service/quickstart-python?tabs=powershell&pivots=python-framework-flask)
+ [手順 - Web アプリケーションを実装するコードを記述する](https://docs.microsoft.com/ja-jp/learn/modules/host-a-web-app-with-azure-app-service/4-exercise-implement-a-web-application?pivots=python)
+ [チュートリアル:Visual Studio Code から Azure App Service on Linux に Python アプリをデプロイする](https://docs.microsoft.com/ja-jp/azure/developer/python/tutorial-deploy-app-service-on-linux-01)

## 運用していて困ったこと
1. **AppServiceからSQLにアクセスできない**  
これは，AzureSQL側で"Azure サービスおよびリソースにこのサーバーへのアクセスを許可する"という項目を"はい"に設定していなかったことが原因でした．
2. **100$分のクレジットが切れたとき，データの取り出しなどができなかった**  
サブスクリプションが有効な間は，各リソースの"移動"から，かんたんに別のサブスクリプションへの移動ができます．  
しかし，100$の無料クレジットを使い切った学生用サブスクリプションからは移動できず，また，データベース内の情報を取り出すこともできなかったため，復旧に必要な作業が多かったです．

# 使用方法
このシステムは，ベース部分を1週で作った突貫工事品です．そのため，様々な問題やバグを抱えている可能性があります．
それでもよければ，上に記した実行環境(Azure App Service + Azure SQL)を用意していただき，[Githubリンク](https://github.com/Yamaji-Toshiyuki/Bath-Reserve)からファイルをダウンロードしたあと，"my_server_setting.py"という名前で以下の書式に乗っとりファイルを作成することで，デプロイし，実行できるようになるはずです．

```python:my_server_setting.py
# サーバー設定
server = 'データベース接続文字列'
database = 'データベース名'
username = 'あなたが設定したデータベースのユーザー名'
password = 'あなたが設定したデータベースのパスワード'
driver = '{ODBC Driver 17 for SQL Server}'
```

# まとめ
終わりの見えないこの状況の中で，同様の問題に直面している方の助けになれば幸いです．
ではまた．
【Laravel】モデル::取得したデータをorderbyする方法（一部データ/全データ）

例えばそのモデルのデータを取得し、データの投稿時間（created_at）に沿って順番に取得する場合。
laravel6系 / 
postsテーブルとusersテーブルがある。（モデルもPostとUserあり。）


##パターン1：一部データを取得した場合

これはわりとすぐうまくいった。

 ```php
//例えばリレーションテーブルの投稿ユーザーのid：5の投稿を見つけ、
//そのユーザーの投稿のみを投稿時間に沿って取得する場合
$hoge = Post::where('user_id',5)//ユーザーid5の投稿を探す
        ->orderBy('created_at','desc')//投稿時間のdesc（降順）で取得
        ->get();
 ```


##パターン2：全データを取得した場合

これ少しはまりました。all()だとコレクションとして取得するみたいなんですが、
パターン1のように->orderBy('created_at','desc')は効かず
また下記のコメントのような方法もうまくsortされず。
結局下記のように「Post::orderByDesc('created_at')」でうまく行きました。

 ```php
$hoge = Post::orderByDesc('created_at')->get();

//Post::All()で取得すると、
//Post::All()->sortByDesc('created_at');みたいな方法があるみたいですがなぜかうまくいかず。。
 ```

いまいちはっきり原因を掴めてはいないけれど備忘録的に投稿します！
webアプリケーションの構造

**webアプリケーションの全体の流れ**
---
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/912965/636625aa-452f-6508-fef3-924a106e21dc.png)


クライアント　→　サーバー　　**リクエスト**（商品Xを見せて！）

サーバー　→　クライアント　　**レスポンス**（商品Xの情報）



**webアプリケーションの表示**
---

クライアントからサーバーを行き来するには、インターネットを介する必要があります。
そして、この間にはwebアプリケーションに関する情報やデータを送受信する、**HTTP通信**という通信方法が使われています。

**HTTP**
・情報を持っている（HTMLなど）
・通信先はURLで指定する

**URL**
・インターネット上の住所
・webアプリケーションはURLを持っている

つまり
インターネットに接続されている　＋　HTTP通信を行う　＝　webアプリケーションが使える
状態です。
パソコン初心者がおうむ返しlinebotを作ってみた話


##はじめに
これは
この記事はこちらの記事を参考してかいています。
詳しくはこちらまでhttps://qiita.com/inoue2002/items/a87df2b520f8b6e37f42
##目次
1 環境構築（必要なものをダウンロード）
>ngrok
node.js
git
VScode

##環境構築(ngrok)
[ngrok](https://ngrok.com/download)をダウンロードします。
　↑こちらからサイトに飛べます。
![5DC24C03-CAE7-4AE0-999D-3AAC0D000A2A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/d726b334-f324-fbef-b775-5788fd673c41.png)
下の方にこちらがでてきます。あとは解凍するだけ。![6F4250F8-367F-4386-952D-6A3065A0EAC8_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/429279dd-463e-a6a1-dc93-22424e33049f.jpeg)
##環境構築（node.js）
[node.js](https://nodejs.org/ja/)をダウンロードします。
　↑こちらからサイトに飛べます。
![CA315976-5300-4599-AA9F-E0617A3795FD.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/3e16b8e8-5d5e-740e-dfde-f3bbef2d31af.jpeg)

お使いのOSの方をダウンロードします。マックならmacOS installerをクリック
![4E3198D8-064A-423E-9AE3-1AA45220DE90_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/66c16e53-508b-69c5-48ff-9739c2314195.jpeg)
こちらをクリックして説明通りに進めます。
##環境構築（git）

次はターミナルで```brew install git```を入力します。
※ターミナルの開き方

Macのターミナルは、Application -> ユーティリティー -> ターミナルに存在します。
また、command + space を押し、Spotlight検索を起動して、terminal.appと入力することでも起動できます。

パスワードを求められたら自分のパソコンのログイン時のパスワードを入力します。

※エラーがあったり、きちんとインストールできないときはこちらをします。
ターミナルで次を入力してください。そして、enterを押します。

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```
![9C896A56-EF69-41BD-A66A-246D40A56F73_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/ccf73332-4db4-6ce9-de2b-d7db89f7eb53.jpeg)
Installation successfulとあれば成功です。
##環境構築（VScode）
[VScode](https://code.visualstudio.com/download)をダウンロードします。
　↑こちらからサイトに飛べます。
![C8C78C35-99B8-4A48-8DD8-05C8804A7241.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/148ddd8c-6c5d-b8a5-ddd4-a587689fdfeb.jpeg)
お使いのOSの方をダウンロードします。
![0D11CFC5-7138-4418-A2B0-5621925EA8BB_4_5005_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/763535/b7f0afa6-0b4e-623d-4c08-23cd646aeaa2.jpeg)
下の方にこれがあればオッケーです。
##ターミナルでインストールできたかを確認
####git
`git -version`とターミナルで入力する
`git version 2.23.0`と表示されたらオッケーです。
####ngrok
`ngrok -v`と入力して
`ngrok version 2.3.35`と表示されたらオッケーです。
####node.js
`node -v`と入力して
`v12.13.0`と表示されたらオッケーです。
####VScode
VScodeはFinderをクリック→ダウンロードをクリック。その中にこれのマークがあればオッケーです。
<img width="160" alt="スクリーンショット 2020-04-29 22.12.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488939/341c095e-8ce1-abc6-a5a3-47ec38c58376.png">

これで環境構築編は終了です！お疲れ様でした！

次からはインストールしたものを使ってどんどんすすめていきます！！
修正途中でcommit前に作業途中の状態を退避するやりかた



変更を退避する
$git stash save
コミットしていない変更がある状態で上記のコマンドを実行すると、変更した部分が退避される
ブランチは変更前の状態

$git stash list
stashした一覧が見れる


$ git stash list
stash@{0}: WIP on ブランチ名: 7d4de606 jpgをpngに置換
$ git stash drop stash@{0}


退避を戻す場合

$git stash apply stash@{0}
stash@{0}はstash名を指定。
このとき、現在チェックアウトしているブランチへ退避した変更が書かれる。
変更を退避したときのブランチにも、それ以外のブランチにも戻すことができる。


退避した作業を消す
$git stash drop stash@{0}
stash@{0}はstash名を指定。
退避した作業を元に戻すと同時に、stashのリストから消す
Chrome拡張機能のイベント周りや審査でハマった件について



[Amazonの検索URL末尾に `&emi=AN1VRQENFRJN5` をつけると怪しいパチモンとか高額商品とかが消えてスッキリするらしい](https://togetter.com/li/1628771)

Chrome拡張機能を作ってみたかったので、これをネタにサクッと作ってしまおうと軽い気持ちで作り始めたらいろいろハマりました

Chromeウェブストアに無事掲載できましたが、思ったより苦労したのでハマった点などを記録します。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Chrome拡張機能つくってみたかったので簡単に作れそうだったコレを作ってみた<br>Amazonの検索結果のURL末尾に &amp;emi=AN1VRQENFRJN5 をつけるだけのやつ…<a href="https://t.co/TtD9UCIxrd">https://t.co/TtD9UCIxrd</a></p>&mdash; 羽鶴パズル🔥株で借金600万マン (@HazuruPuzzle) <a href="https://twitter.com/HazuruPuzzle/status/1333750689722376192?ref_src=twsrc%5Etfw">December 1, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ソースコードは https://github.com/hazurupuzzle/amazon-emi-AN1VRQENFRJN5


## メイン機能よりChrome拡張機能のイベント周りで苦労する

URLにパラメータ付けてリロードするだけのメイン機能は1秒で実装したものの、
アクティブなタブのURLを見て拡張機能のアイコンの色を変えるのに苦労しました。

### アクティブなタブのURLを見て拡張機能の(BrowserActionの)アイコンを変更する

初見ではどのイベントが必要かなかなかわからなかった…

必要なイベントは3つ

1. `chrome.tabs.onActivated` : タブを選択してアクティブになったとき
2. `chrome.tabs.onUpdated` : タブの状態が変化したとき (URL変わったときなど) 
3. `chrome.windows.onFocusChanged` : Chromeのウィンドウにフォーカスしたとき。作った拡張機能ではChromeのウィンドウが複数ある時にこのイベント捕捉してアイコンの色を変える必要がありました

イベントハンドラにはタブの情報が渡されますが、タブのURLは `manifest.json` の `permissions` に指定したものでないと取得できません。上記のイベントでは取得できないのですが、イベントによっては取得できたりして混乱しました。

例えば `chrome.browserAction.onClicked` は拡張機能のアイコンをクリックしたときのイベントですが、
これは `permission` に何も指定されていなくてもアイコンをクリックした時のタブのURLが取得できます。

## Googleの審査に落ちた

Chrome拡張機能をChromeウェブストアに掲載するためには審査が必要です。
プライバシーポリシーのページも用意したし、
こんな単純な機能なら審査落ちる理由もないだろうと思っていたらリジェクトされました。
リジェクト理由は下記の内容です。

> 違反: キーワード スパム:
> 違反事項: アイテムの説明に過剰かつ / または無関係なキーワードが含まれている。
> 違反コンテンツ: "Amazon"
> 修正方法: 過剰かつ / または無関係なキーワードを削除します。
> プログラム ポリシーの関連セクション:
> 誤解を生じさせるメタデータ、誤った形式のメタデータ、説明的でないメタデータ、関連性のないメタデータ、過剰なメタデータ、不適切なメタデータ（拡張機能の説明、デベロッパー名、タイト> ル、アイコン、スクリーンショット、プロモーション画像を含むが、これらに限定されない）を含む拡張機能は許可されません。[（詳細）](https://developer.chrome.com/webstore/program_policies#spam)

申請時に拡張機能の必要最小限の説明しか入れていないつもりだったのでスパム判定されるとは思いませんでした。
たしかに拡張機能の説明を読み直してみると 「Amazon」 という単語が8箇所あったので、これがNG判定されました。
省略しても意味が通りそうな部分を削って再提出したら翌日申請は通りました。


## (Chrome拡張機能とは関係ないけど) ブックマークレットでハマる

[ブックマークレット](https://github.com/hazurupuzzle/amazon-emi-AN1VRQENFRJN5#%E3%83%96%E3%83%83%E3%82%AF%E3%83%9E%E3%83%BC%E3%82%AF%E3%83%AC%E3%83%83%E3%83%88) もついでに書きました。

スクリプトを1行にして終わり！
と思っていたんですがエスケープしてなくてハマりました。
シンタックスエラーになってくれれば分かりやすかったのですが、中途半端に動くせいでハマるという罠

minifyして1行にして `javascript:` を手前につけるだけでは動かないことがあります。
`encodeURIComponent` でエスケープした上でリンクにしましょう…

## 開発当初は自動でパラメータをつけるよう実装していた

Amazonの検索結果画面のURLに `&emi=AN1VRQENFRJN5` のパラメータをつけると、検索結果のカテゴリによっては結果が0件になることが判明したので、自動でパラメータをつけるのは没になりました。そんなこんなで結局1日潰してしまった…
僕が考える最強のコミットメッセージの書き方

この記事は [DeNA 21 新卒 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/dena-21-shinsotsu) の16日目の記事です。

## はじめに
Gitを使っていく上でコミットメッセージは必須なものです。
**そのメッセージ、`fix` とか適当になっていませんか？**
コミットメッセージがおざなりなままだと、どんな変更をしたのかが掴みにくく、レビュー時や後で見たときにコードを追うのが難しくなります。
逆に、コミットメッセージをこだわるだけでより良い開発環境、開発者体験を実現できます。今回は僕が良いと考えている書き方をまとめてみようと思います。


## この記事のターゲット
- Gitを使ったことがある方
- チームで決められたコミットルールを理解、改善したい方
- よりよい開発者体験を実現したい方


## ※諸注意
まず、**コミットメッセージの書き方に正解はありません。**タイトルにもあるとおり、あくまで「僕が良いと考えている」書き方なので、一意見として参考にしていただけると嬉しいです。


## 結論
以下のようになります。

```
feat: 〇〇なため、△△を追加
```

ここから各ポイントについてそれぞれ説明していきます。

1. Prefixをつける
2. 理由を書く
3. 日本語 or 英語？


## 1. Prefixをつける
Prefixとは何かしらのテキストの先頭につける文字のことです。
コミットメッセージのPrefixは様々な種類があり、独自のルールを作っているチームもあるのではないでしょうか。
[こちらの参考記事](https://qiita.com/numanomanu/items/45dd285b286a1f7280ed)でも紹介されていますが、[Angular.js/DEVELOPERS.md](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#type)のものが今の所一番しっくりきており、基本的にこのルールで書くことが多いです。

```
feat: A new feature
fix: A bug fix
docs: Documentation only changes 
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
refactor: A code change that neither fixes a bug nor adds a feature
perf: A code change that improves performance
test: Adding missing or correcting existing tests
chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
```

- feat: 新しい機能
- fix: バグの修正
- docs: ドキュメントのみの変更
- style: 空白、フォーマット、セミコロン追加など
- refactor: 仕様に影響がないコード改善(リファクタ)
- perf: パフォーマンス向上関連
- test: テスト関連
- chore: ビルド、補助ツール、ライブラリ関連

理由としては、

- どのカテゴリのものを修正したのかが見てわかりやすい
- コードロジックに影響がある変更かが瞬時にわかる

などがあり採用しています。
また、このprefixに合わせてコミットを分けることで、大きすぎず小さすぎない、適切な大きさになると思います。

## 2. 理由を書く
```
feat: 〇〇なため、△△を追加
```

変更した理由や目的を書くことでコードレビューが圧倒的にしやすくなります。例えばライブラリの追加時にも

`chore: hogeを追加`
ではなく
`chore: ネットワーク通信するため、hogeを追加`
と書いた方がよりわかりやすいと思います。

また、理由を書くように意識することで **なぜこの変更をする必要があったのか(変更の意図)**、**コミットの大きさは適切か**などを深く考えることとなり、コードもより洗練されていくと思います。

もちろん、(Modelの定義など) 理由が書きにくい場合もありますが、あくまで**後でどんな人が見てもわかるメッセージであれば大丈夫**だと思うので、場合によっては書かなくてもOKだと思います。


## 3. 日本語 or 英語？
英語で書くべきか、迷うことも多いですよね。
自分は **個人開発やOSSとして公開するものは `英語`**で書き、**日本人が多いチームでの開発では`日本語`** で書くようにしています。

#### 英語で書くメリット

- 語学力向上
- 最初に動詞が来るためぱっと見てわかりやすい
- OSSの貢献ハードルが下がる

#### 英語で書くデメリット

- 英文を考えるのに時間がかかる(語彙の検索など)
- 読むのに時間がかかる


英語の方がスキルとして伸ばせて良い感じがしますが、日本語に比べ読み書きに時間がかかってしまいがちです。
ただ、開発者チームの中で**共通意識が取れるものであればどちらでも良い**と思っています。


## 終わりに

コミットメッセージにこだわることでコードレビューも不具合への対処もスムーズになります。より良い開発者体験を実現するため、ぜひこだわってみてください！


## 宣伝
この記事を読んで「面白かった」「学びがあった」と思っていただけた方、よろしければ Twitter や facebook、はてなブックマークにてコメントをお願いします！
また [DeNA 公式 Twitter アカウント @DeNAxTech](https://twitter.com/DeNAxTech) では、 Blog記事だけでなく色々な勉強会での登壇資料も発信してます。ぜひフォローして下さい！→ <a href="https://twitter.com/intent/follow?screen_name=DeNAxTech">Follow @DeNAxTech</a>
[Android]Gradleの依存関係のimplementation/apiの使い分け

Gradleの依存関係のimplementation/apiの使い分けについて。
[Android公式](https://developer.android.com/studio/build/dependencies?hl=ja#dependency_configurations)の説明は、正しく詳細なのだが、中々理解できなかった。
ようやくimplementation/apiの使い分けが腑に落ちたので、まとめる。

最初は、ユースケースで考えた方が分かりやすいと思う。

- ライブラリモジュールの場合
  - ライブラリのAPIに使う依存ライブラリ -> "api"
  - そうでない依存ライブラリ -> "implementation"
- アプリモジュールの場合[^1]
  - "implementation"を使う。"api"でも動作変わらないが、あえて使う理由はない。

この後の説明長いが、ここを抑えておけば、読まなくても害はなさそう。

## ケーススタディ

自作ライブラリに、以下のAPIがあるとする。

```kotlin
data class User(val id: String, val name: String)

class UserRepository {
    fun getUser(id: Int): LiveData<User> {
        ...
    }

    fun add(user: User) { ... }
}
```

このケースでは、自作ライブラリを使うモジュールをコンパイルする際に、LiveDataのライブラリが必要になる。なので、自作ライブラリの依存関係の設定では"api"を使う[^2]。

自作ライブラリのbuild.gradleの記述例。

```gradle
dependencies {
    api 'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
}
```

もし、UserRepository#getUser()がprivateであれば、自作ライブラリを使うモジュールのコンパイルにLiveDataライブラリは不要である。なので、自作ライブラリの依存関係で"implementation"を指定する。

## 詳細

アプリ -> 自作ライブラリ -> LiveDataライブラリという方向で依存しているとする。
このときの、自作ライブラリのbuild.gradleの記述を考える。

LiveDataライブラリへの依存関係を"implementation"と"api"のどちらに指定しようが、自作ライブラリにとっては違いはない。自作ライブラリのコンパイル時からLiveDataライブラリは必要とみなされる。一方で、アプリからの見え方には違いが出る。"implementation"を使った場合は、実行時から必要なライブラリと扱われ、"api"を使った場合はコンパイル時から必要という扱いになる。

アプリへの依存関係の見せ方は、自作ライブラリをmavenリポジトリにデプロイしたときのpomの内容で決まる(~/.gradleを探すと外部ライブラリのpom見れる)。pomを見てみると、"implementation"は"runtime" scope、"api"は"compile" scopeに対応していることが分かる。

この記事に、図があって分かりやすい。
https://qiita.com/tkhs0604/items/7afe40599af2354eb2ad

## 蛇足

"api"の依存関係が推移する理由。
アプリ -> A -> B -> Cと依存していて、AのAPIにB、BのAPIにCを含むとする。
当然、AのAPIにCも含まれるので、アプリのコンパイルにはA, Bだけでなく、Cも必要ということになる。
これが公式の説明で言うところの、依存関係が推移するという意味。

LiveDataを自作ライブラリのクラスやinterfaceでwrapすれば、自作ライブラリからLiveDataへの依存関係に"implementation"が使えるようになる。LiveDataライブラリとその依存ライブラリが、コンパイル時に不要になるので、アプリのビルドは早くなる[^3]。


[^1]: 正確には、他のモジュールから参照されないモジュール。
[^2]: "implementation"を使った場合、自作ライブラリを使う側のモジュールにも、LiveDataのライブラリへの依存関係を記述しないといけない。
[^3]: 普通はアプリモジュールもLiveDataを使うので、例が微妙。LiveDataライブラリを汎用性のないライブラリで置き換えて考えると分かりやすいかも。
Symbol-ETLについて まとめページ

#
Symbolは色々な機能を持っていますが、やはり仮想通貨や暗号資産と呼ばれているものなので、資産の動き（資産の額及び移動元と移動先のアドレス）を追えるETLを作る過程を載せていきます。
※時間がなかったので、公開済も含め随時更新します。

##基本設計編
まずはAPIのデータ構造から資産の動きに関連しそうな部分を特定・理解していきます。
0. [基本データ構造編] (https://qiita.com/items/2f54136baeb0869b4140)
1. [Block編] (https://qiita.com/tokusyu/items/bd65b9a345f8cca541fc)
2. [Transfer Transaction編] (https://qiita.com/tokusyu/items/59c5d19e6e2b502850a9)
3. [Aggregate Transaction編] (https://qiita.com/tokusyu/items/2fc73b21e87173be9687)
4. [Cross-Chain Swaps編] (https://qiita.com/tokusyu/items/608a6270c9029a11b803)
5. Multisig Account編
6. Mosaic編
7. もう少し増やす予定。。。


##実装編
基本設計の内容をもとにETLでの処理を実装していきます。（TypeScript& JavaScript SDKを使用）
1. 構成考え中。。。
Symbol-ETL Part.0 基本データ構造編

NISでAPIで取得できるデータは大きく分けてBlockとTransactionだけでしたが、Symbolの場合、ReReceiptとかStatementとか呼ばれている処理の結果を表すデータも取得できるようになりました。


#block
ブロックチェーンの基本のBlockデータ。
後述のstatement/recipientがあるので、NIS1に比べると資産の動きの追跡における必要性は低下している？

#transaction
相変わらず多彩な種類が揃っているTransaction。
[Transaction Types] (https://docs.symbolplatform.com/concepts/transaction.html#transaction-types)

Statement/Recipientsが結果なのに対し、Transactionは命令という位置付けなので少し気を使わないとまずそうです。
またTransactionの結果は、Recipientとは別のAPIで取得する必要があり面倒。。。

#statement/recipient
他の通貨でもAPIから類似のデータ取得が可能なものがありますが、資産の動きのほとんどが記録されている通貨や、処理の成否程度の情報しか記録されていない通貨がありますが、Symbolの場合、Transactionではカバーしきれないデータの動きが記録されるようです。

[Recipientの種類] (https://docs.symbolplatform.com/concepts/receipt.html#recorded-receipts)
開発チームは星取表を作れ

この記事は [ちゅらデータアドベントカレンダー](https://qiita.com/advent-calendar/2020/churadata) の4日目の記事になります。

今日は私が4月にCTOになってから、最初にした仕事、**星取表を作る**を紹介します。

## 課題設定

この記事を読んでくれてる人は、エスパーや名探偵ではなく、普通のプログラマーやデータサイエンティスト、もしくはエンジニアと呼ばれる猫を想定してます。

さて、エスパーや名探偵ではないあなた。（しつこい）
隣で働いてるチームメイトは、**フロントエンドエンジニア** ですか？それとも **バックエンドエンジニア** ですか？
なるほど、フロントエンドエンジニアでしたか。
え、それがどうしたって？

で、あなたがバックエンドエンジニアだとして、自分が忙しい時は **隣のチームメイトにあなたのバックエンドエンジニアの仕事をお願いできますか？**

え？なんでそんな事するかって？
だって、それができたらもしかしたら、一つでも多くの機能をリリースできるかもしれないじゃないですか？
**※開発チームの目標は一つでも多くの価値ある機能を顧客に届けることですよね？**

普通のフロントエンドエンジニアのチームメイトなら、あなたのバックエンドエンジニアの仕事はお願いできないかもしれないですが、もしチームメイトが実はフルスタックのスキルを備えていたら、お願いできちゃいますよね？

でもあなたは、いま隣のチームメイトをフロントエンドエンジニアだと考えている。

さて、これはチームの課題だと思いませんか？


## 要するに

チームメイトに何を期待できるのかを可視化することが、チームのために必要なことなんです。
だから星取表を作ります。

## 星取表とは

星取表とは、スキルマップとも呼ばれる表です。
横にスキル、縦にチームメイトの名前を書いて、交差するところに ○や☓ を書きます。
たとえばこんな表になります。

|名前|Python|Vue.js|Spark|Snowflake|テスト|
|---|:-:|:-:|:-:|:-:|:-:|
|菱沼|||◎|△|○
|ジェイク|◎|||○|
|隊長|◎|◎|||
|intel|◎||○||

## 星取表があると何が嬉しいの？

- お互いの期待値のすり合わせができるようになる
    - 「実はおまえ、これできたの？」
    - 「あれ？これできないの？」
- チームのリスクが見えるようになる
    - 「あれ？これ得意な人いなくね？」
    - 「あれ？これできるのひとりだけじゃん！」 => トラックナンバー1問題([参考](https://blog.fenrir-inc.com/jp/2013/02/trucknumber.html)）
- スキルの育成や学習に方向性をモテるようになる
    - 「よし！チームで得意な人が少ないからこれやるぞ！」
- 採用や外部からのリソース調達がしやすくなる
    - 「こういうスキルを持った人を歓迎します！」
    - 「うちのチームではこういうスキルを持った人達がいるよ！」
- 新しい領域の仕事が舞い込んできた時、誰をアサインするべきかわかるようになる
    - 「お、この仕事は彼できそうじゃん！」

## 結局

作らないリスクはあるけど、作ったときのデメリットがないので、すべてのチームで作ったほうが良いでしょうね。

## つくりかた

これは私がちゅらデータでやった作り方なので、真似する必要はないです。

1. スプレッドシートを用意します。
2. 最初のシートにREADMEとします。そこに想いを書きます（ポエムが良い）
3. スキルの大カテゴリーを考えてそれぞれシートを作ります。（データ分析系、開発系、構築系、PM系…などなど）
4. 各シートにチームメンバーの名前を1列目に貼り付けます。
5. 業務でつかうスキルをみんなに1行目の列として書いてもらいます。同時に自分のスキルを入力してもらいます。
6. 新しいスキルを増やしたり、統合したり、整理しながら**みんなで作ります。(※)**

※みんなで作ることで、自分たちの星取表になるんです。

# 運用

たまに、更新するんだよ〜って声がけしたり、1on1の話題にしたりします。
どんなスキルを今後伸ばしたい！とかっていうときも業務で必要とされるスキルが可視化されているので、話がしやすくなりますね！

# さて、いかがでしたでしょうか？

あなたのチームで、星取表をもしまだ作ってないようでしたら、この機会に作ってみてはいかがでしょう？
年末ですし、スキルの棚卸しだーとか言えば、みんな理解してくれますよ！
ちなみに長年連れ添った夫婦みたいなチームには不要かもしれませんね。
（でも私はそう思っていたら、別居するはめになってるので、勝手にお互いわかりあえてるなんて思い込みは油断大敵ですよ！）
Mysql2::Error: Unknown table '~': DROP TABLE `~`の対処方法

少し前に起きたエラーで書こうか迷ったのですがまた同じエラーでつまずきたくないので書くことにしました。少しでも参考になれば幸いです。
#エラー内容
今回のエラーは僕の場合RSpecのテストのために`rails db:migrate RAILS_ENV=test`を実行したところ<strong>Mysql2::Error: Unknown table 'myapp_test.notifications': DROP TABLE 'notifications'</strong>と出ました。
#確認したこと・試したこと
mysqlでmyapp_testのテーブルを確認したがnotificationsは入っていなかった。myapp_developmentのテーブルにはちゃんとnotificationsが入っていた。
一応rails db:create RAILS_ENV=testをやってみたがすでに作られてるよと言われた。
#対処方法
エラーとなったマイグレーションファイルがあるところを参照する
僕の場合テスト環境だったので、

```
$ rails db:migrate:status RAILS_ENV=test
```
と打つと,

```
database: myapp_test

 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20201015014442  Create users
   up     20201015015259  Add index to users email
   up     20201015015729  Add password digest to users
   up     20201018020551  Add remember digest to users
   up     20201022031928  Add admin to users
   up     20201023063329  Create posts
   up     20201102044141  Add picture to posts
   up     20201103142232  Create relationships
   up     20201105025016  Create likes
   up     20201106231109  Create comments
   up     20201109071255  Create talks
   up     20201109072007  Create memberships
   up     20201109072128  Create messages
  down    20201127182835  Drop table notifications
  down    20201127183353  Create notifications

```
と出てきて、これを見ると`Create notifications`が`down`しているのが分かります。これを`up`にすればいいわけです！

```
$ rails db:migrate:up VERSION=20201127183353　RAILS_ENV=test
```
※もしupからdownにしたい場合は、

```
$ rails db:migrate:down VERSION=20201127183353　RAILS_ENV=test
```

これでrails db:migrate RAILS_ENV=testが無事通ることができました！

#最後に
なぜdownになっていたのかわからないですがエラーを直すことができてよかったです。
Notionでブラウザのアドレスバーからページを作成する notion.new

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2020](https://qiita.com/advent-calendar/2020/notion) 2日目のエントリです。
1日目は[Notionでドキュメントを検索するときは⌘ + Kショートカットを使おう](https://qiita.com/pictiny/items/7802ff60b9b9ae5c3b68)でした。

# ページの作成

Notionでページを作成する場合、以下のような方法がありました。

- サイドバーの + アイコン
- `/page` [コマンド](https://qiita.com/pictiny/items/d88a7025b8d121009ce0#%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89)
- Databaseの右上にあるNewボタン

最近のアップデートで、[http://notion.new](http://notion.new) にアクセスするだけでページを作成できるようになりました。

<blockquote class="twitter-tweet"><p lang="en" dir="ltr">We&#39;ve been working on lots of mini-projects over the past couple weeks, all based on community feedback! Open this thread for the full list 🎁<br><br>#1: Create new pages by typing <a href="https://t.co/aAHvNBbbCC">https://t.co/aAHvNBbbCC</a> into your URL bar 👇 <a href="https://t.co/rz8z3LFo1l">pic.twitter.com/rz8z3LFo1l</a></p>&mdash; Notion (@NotionHQ) <a href="https://twitter.com/NotionHQ/status/1329538709385932800?ref_src=twsrc%5Etfw">November 19, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ページをどこに作成するかは、ページ作成画面の上部の `Add to` から選択できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/1b416505-e8d9-71c9-5c52-210c4fc15dd8.png)

# まとめ
急いでメモを取りたいときに便利な機能ですね！

ページ作成については[Create a new page](https://www.notion.so/Create-a-new-page-6c3fe9aad94749099ea4bdfc072e5f97)に公式ドキュメントがありますので、そちらもご覧ください。
Dagger Hiltの@InstallInチェックを無効にする

# 概要

[Dagger Hilt](https://developer.android.com/training/dependency-injection/hilt-android?hl=ja)では「Hilt Component」という形で予め用意されたComponentを使用することでComponentの構造に悩むことが無くなり、AndroidでのDI(Dependency Injection)をよりシンプルに利用可能です。

Hiltでは、`@InstallIn`アノテーションでModuleをどのHiltコンポーネントにインストールするかを指定します。これにより、どのコンポーネント階層以下でBindingを利用できるかを制御できます。そのため、`@InstallIn`アノテーションを付け忘れると正常にBindingが提供されずエラーになります。

# Dagger Hiltの`@InstallIn`チェック

Hiltは、デバッグを容易にするために、Moduleに`@InstallIn`アノテーションをつけ忘れた場合エラーを発生させビルドを失敗させます。

例として次のようなModuleを想定します。

```kotlin:FooModule.kt

@Module
@InstallIn(SingletonComponent::class)
object FooModule {

    @Singleton
    @Provides
    fun provideFoo(): Foo = Foo()
}

class Foo {
    fun say() = "Hello"
}
```

ここで意図的に`@InstallIn`をコメントアウトすると次のようなエラーが発生し、ビルドが失敗します。

```
エラー: [Hilt]
public final class FooModule {
             ^
  com.hore1024.daggerhiltsample.FooModule is missing an @InstallIn annotation.
```

このDagger Hiltのチェック機能は非常に有用で、`@InstallIn`アノテーションの付け忘れを防ぐことができます。

# `@InstallIn`チェックを無効にする

`@InstallIn`チェックは有用ですが、そのチェックを無効にしたい場面もあります。例えば、Hilt Moduleと通常のDagger Moduleを共存させたい場合です。

`@InstallIn`チェックの無効化は、次の二つの方法で可能です。

## Compile Optionsを指定する

Annotation Processorのオプションとして`-Adagger.hilt.disableModulesHaveInstallInCheck=true`を渡します。build.gradleで次のように指定することが可能です。

```groovy:app/build.gradle
android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments += ["dagger.hilt.disableModulesHaveInstallInCheck" : "true"]
            }
        }
    }
}
```

## `@DisableInstallInCheck`アノテーションを使用する

チェックを無効にしたいModuleに`@DisableInstallInCheck`アノテーションを追加します。

```kotlin:FooModule.kt

@DisableInstallInCheck
@Module
object FooModule {

    @Singleton
    @Provides
    fun provideFoo(): Foo = Foo()
}

class Foo {
    fun say() = "Hello"
}
```

これで`@InstallIn`チェックを無効にできました。

# 参考

- https://developer.android.com/training/dependency-injection/hilt-android?hl=ja
- https://dagger.dev/hilt/gradle-setup.html
- https://dagger.dev/hilt/compiler-options