OmniAICreator/Qiita-1.07M huggingface dataset:
自分用アウトプット2020/12/05

# githubの使い方
*ファイルやディレクトリの変更修正をリポジロリに反映させることをcommitという
*変更をリモートリポジトリに反映さ出ることをpushという
*変更修正を一時的に記録しておく場所のことをindexという
*溜まった変更修正の中から追加するコミットを選択することをアドという

コミットは細かく分けるほうがエラーが起きた時にわかりやすいだけでなく、作業の進捗も管理しやすい。
作業完了ごとに逐一コミットの操作をするのは効率が悪いため、インデックスとアドを利用する

### githubを開発に用いる際のフローチャート
1.ブランチを切る
2.ローカルリポジトリにコミットする
3.リモートリポジトリにプッシュする
4.プルリクエストを作成する
5.レビュアーがチェック
6.修正依頼
7.修正
8.レビュアーがlgtm
9.リモートリポジトリのマスターブランチにマージ
10.ローカルリポジトリのマスターブランチにぷる

問題がなければ6.7は省く

### コンフリクト

ブランチごとに違う作業を行なったことでファイルに辻褄が合わなくなることをコンフリクトという。例えばコントローラーファイルを同時に編集し、一人はindexアクションを追加し、もう一人はdestroyアクションを追加した場合などに起こる。
この場合、お互いのファイルに存在しないアクションが生まれてしまう。

##### コンフリクトをなるべく回避するために
*作業の前にマスターブランチからpullを行う
*無闇に同じファイルを編集しないようにメンバーと連絡を取り合いながら作業する
*あらかじめコンフリクトが起きそうな場所を把握しておく

### リヴァー
間違えてpushしたコミットを取り消すことができる。
コミットを修正するというよりも、間違えたコミットと逆の作業を行なったコミットを追加するイメージ。

# テスト
*単体テストはモデルやコントローラーなどの機能ごとに問題がないか確かめる
*結合テストはユーザーがブラウザで操作する一連の流れを試して問題がないか確かめる。
*ユーザーが開発者の意図する操作を行った時の挙動を確認するテストを正常系という
*ユーザーが開発者の意図しない操作を行った時の挙動江尾かっ九人するテストを異常系という


以下は異常系の単体テストの例

```ruby
RSpec.describe User, type: :model do
  describe '新規登録' do
    it "nameが空だと登録できない" do
      user = User.new(name: "", email: "kkk@kkk", password: "00000000", password_confirmation: "00000000")
      user.valid?
      expect(user.errors.full_messages).to include("Nickname can't be blank")
    end
    it "passwordが空だと登録できない" do
      user = User.new(name: "hiro", email: "kkk@kkk", password: "", password_confirmation: "00000000")
      user.valid?
      expect(user.errors.full_messages).to include("Password can't be blank")
    end
  end
end

```

### 異常系のテストの流れ
1.保存するデータを作成する
2.作成したデータが、正しく保存されるかどうかを確認する
3.正しく保存されない場合、生成されるエラーメッセージが期待されるものかどうかを確認する

##### it
どのような結果になるか試しているのかを記述する

##### examaple
itに記述した名用の総称

##### expect(X).to eq Y
結果がXになることを期待してYと比較する

##### マッチャ
includeはマッチャの一種。Yの内容がXに含まれているか判定する
他にはeqなどがある
### .errorsメソッド
エラーを表示するためのメソッド
### .full_messagesメソッド
生成されたエラーの中からエラーメッセージを出力するためのメソッド

##### valid?
データが正しく保存される場合はtrueをそうではない場合はfalseを戻り値として返す
Strong Parametersについて調べてみた

##Strong Parametersとは…
ざっくりいうとWeb上から、`取得したパラメータ(外部から入ってくる値)`が
`DB(データベース)にはいる前に安全なデータかを検証した上で、
取得する仕組み`のこと！Rails4から実装されている

`想定どおりのパラメータ`かどうかを`ホワイトリスト方式`で
チェックする機能のこと

##Strong Parametersの効果
strong parametersを用いることで、

Action Controllerのパラメータが許可されるまで
Active Modelの`「マスアサインメント」`に利用されることを禁止できます。

多くの属性を一度に更新したい場合は、
どの属性のマスアップデートを許可するかを開発者が明示的に指定しなければならない

大雑把にすべての属性の更新を一括で許可してしまうと、
外部に公開する必要のない属性まで誤って公開してしまう可能性が生じるため、
そのような事態を防ぐための機能

###Strong Parametersが実装される前…
実際に意図しないデータの登録・更新が発生していた事例が
多数あったよう

例)パラメーターに「admin」属性を付与してあげれば
管理者権限を取得することが簡単にできてしまい
なりすましが可能となったりした

Strong parametersを用いることで…
パラメータが許可されるまでモデルの「マスアサインメント」に

利用されることを禁止できる。

###マスアサインメントとは、
`フォームから送信されたデータ`を、
そのまま`チェックせずにデータベースに登録すること`をいう

例)
```rb
Person.new(name: 'test', age: 20)
person.update(name: 'test name', age: 21)
```
DBの更新系処理で複数のカラムを一括で指定できる


不適切なデータを判断せずに、登録ができてしまっては、まずい

##Strong parametersの使い方
```rb
def user_params
  params.require(:キー(モデル名)).permit(:カラム名１).merge(カラム名: 入力データ)
end
```

例) Userモデルのname, ageカラムのみを受け取る場合

```rb
def user_params
  params.require(:user).permit(:name, :age)
end
```

カラム名は複数入力することも可能


##「require」メソッド
「require」メソッドを使用することで、

`受け取る入力必須`のパラメータ群を指定することができる
params内の特定のキーに紐付く値だけをとる事が可能となる
そのため、引数には取り出したい値のキーを指定する必要があります

##「permit」メソッド
「permit」メソッドを使用することで、

`利用可能な許可された値`のパラメータ名を指定することができる

permitメソッドの引数には、登録を許可する全てのカラム名を指定しておく
必要がある。もし、許可されいないカラムがparams内に存在したとき、
そのデータは取得されず無視されてしまうので注意が必要

##まとめ
- ストロングパラメータは、マスアサインメント機能の脆弱性問題を回避するために作られた機能である
- 「require」メソッドで受け取るカラム名を、「permit」メソッドで許可するパラメーター名を指定することができる

##参考リンク
https://railsguides.jp/action_controller_overview.html#strong-parameters

https://qiita.com/ozackiee/items/f100fd51f4839b3fdca8

https://qiita.com/tbpgr/items/63028f5e19a2d1617e40
れふオート 導入方法

1.Pythonistaをインストールする又は
  1度アインストールしてインストール
  し直す。
2.受け取ったリンクを開き、その他をタップして
  Run Pythonista Scriptタップして
  Import Fileをタップしてokをタップ
3.Pythonistaを開いて
  This iPad(iPhone)をタップ。
4.ファイルができてるからそれを押して
  Extract Archive…をタップ。
5.左上の3本線押したらファイルが
  できてるからそれをタップ。
6.開いていくとmoduleがあるから
  開いてEdit押して全て選択して
  左下のファイルの中に→があるやつを
  タップする。そしたら色々出てくるから
  site-packages-3をタップ
7.main.pyを開いて右上の▶をタップした
  ら数字が出てくるのでdmにその数字
  送る。
8.オートIDが送られてきたら
  オート設定.pyを開いて00000を消して
  IDを入れる。
9.オート設定.pyを開いてAPIを入れる
10.main.pyを開いて右上の工具マークを
  タップしてshortcutタップして
  Keyboardをタップして色々あるから
  全て-を押してDeleteする。
  全部消したら+押して名前を
  付けてaddタップしてdoneをタップ。
11.RSA設定.pyを開いて右上の工具
   マークをタップしてshortcutを
   タップしてKeyboardをタップして
   +を押して名前を付けてaddタップ
   してdoneをタップ
12.端末の本体設定に行って
   一般>キーボード>キーボード>新しい
   キーボードを追加をタップして
   Pythonistaのキーボードを追加して
   フルアクセスを許可をON
13.あとは実践！
【JavaScript】mouseover, mouseout, mouseenter, mouseleaveの違いについて図解で理解する。

※当方駆け出しエンジニアのため、間違っていることも多々あると思いますので、ご了承ください。また、間違いに気付いた方はご一報いただけると幸いです。


mouseover, mouseout => 対象ノードへの接触を監視
mouseenter, mouseleave　=> 対象ノードへの出入りを監視

このような入れ子構造のノードがあったとします。

```html
<div id = "parent">
  <div id = "child">
  </div>
</div>
```
図でイメージするとこんな感じとします。

![IMG_7155 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/2dc1ee66-3259-6f4a-2ab6-ecc06107ca1a.jpeg)


今、id="parent"を監視対象としているとします。

マウスがparentノードに入ってきた場合。
当然、mouseenterは発火します。
またparentとマウスは接触した状態となったので、mouseoverも発火します。
![IMG_7154.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/99732c94-2b1e-6125-0570-c1415b397c0d.jpeg)

マウスがchildノードに入ってきた場合。
マウスとparentとは接触しない状態と変化したため、mouseoutが発火します。
なお、parentノードからマウスが出た訳ではないのでmouseleaveは発火しません。
この、「parentノードからマウスが出た訳ではない」という解釈ですが、parentを家、childeを部屋と考えたらイメージしやすいかもしれません。
玄関から家に入り、さらに部屋に入った時、「家から出た」とはならないですよね。


![IMG_7156.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/61528361-f9ff-9e77-0f71-583975c00fc0.jpeg)
マウスがchildノードから出た場合。
マウスとparentとは接触する状態と変化したため、mouseoverが発火します。
当然、mouseenterは発火しません。
部屋か出た時、「家に入った」とは言わないですよね
![IMG_7157.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/cf9abd68-20b1-0b15-58cc-1934ba911965.jpeg)

マウスがparentから出た場合。
当然、mouseleaveは発火します。
またparentとマウスは接触しない状態となったので、mouseoutも発火します。
![IMG_7158.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547556/e4c83611-3f22-81f3-e019-d0f31c748a57.jpeg)

いってらっしゃい。マウス。
GitHub Actionsで修正のあったファイルを取得しformatterを実行する

歴史あるリポジトリとかで数千ファイルが既にあったりするケースのリポジトリに対して全体的にformatterをかけたりはしたくないけど直近で修正してるファイルはformatterをかけたいみたいなケースで使える小技。

GitHub scriptを自分たちで書いても良さそうだが既に良さげなActionが公開されているので使ってみる。

[jitterbit/get-changed-files](https://github.com/jitterbit/get-changed-files)

#### 使ってみる

以下の例では修正されたファイルをjsonに入れている。ドキュメントを読んでるとスペース区切りとcsvでも取得できる模様。

``` yaml
      - name: get-changed-files
        id: files
        uses: jitterbit/get-changed-files@v1
        with:
          format: 'json'
```

あとはjqなりなんだりでシェルスクリプトを書いて修正ファイル分ループさせつつformatterを実行すれば用件は達成できる。

``` yaml
      - name: Run Formatter
        run: |
          pip install --upgrade black
          readarray -t files <<<"$(jq -r '.[]' <<<'${{ steps.files.outputs.added_modified }}')"
          for file in ${files[@]}; do
            if [[ ${file##*.} == "py" ]]; then
              black ${file}
            fi
          done
```

#### まとめ

今回はformatterを使った例を書いてみましたが修正ファイルが取れるのでそこから任意のラベルをPRなりに貼ったり他CI用のエンドポイントに渡したりと結構応用的に使えそうな小技の紹介でした。
【Kotlin】setFragmentResultを用いた画面遷移

## setFragmentResultとは

フラグメント間でデータの受け渡しを行うときに使用する。
フラグメントBからフラグメントAにデータを返す場合は、フラグメントAに結果リスナーを設定します。

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Use the Kotlin extension in the fragment-ktx artifact
    setResultListener("requestKey") { key, bundle ->
        // We use a String here, but any type that can be put in a Bundle is supported
        val result = bundle.getString("bundleKey")
        // Do something with the result...
    }
}
```

フラグメントBでは、同じ`requestKey`を使用して値を渡します。

```kotlin
button.setOnClickListener {
    val result = "result"
    // Use the Kotlin extension in the fragment-ktx artifact
    setResult("requestKey", bundleOf("bundleKey" to result))
}
```

## 複数のデータをまとめて渡す場合

調べても複数のデータをまとめて`setFragmentResult`で渡す実装が出てこなかったため以下に記載しておきます。

例えば、ユーザー一覧画面でユーザーを選択すると選択されたユーザーの編集画面に遷移する場合、画面の遷移時に複数のデータの受け渡しが必要になります。

```kotlin
data class user (
    val id: Int,
	val name: String,
	val icon: String,
	val registerDate: String
)
```

UserListFragment

```kotlin
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setFragmentResult("request_key", bundleOf(
        "id" to selectedUser.id
	"name" to selectedUser.name
	"icon" to selectedUser.icon
	"registerDate" to selectedUser.registerDate
    )
}
```

UserDetailFragment

```kotlin
setFragmentResultListener("request_key") { requestKey, bundle ->
        val id = bundle.getInt("id")
				val name = bundle.getString("name")
				val icon = bundle.getString("icon")
				val registerDate = bundle.getString("registerDate")
}
```

上記のように設定することで複数のデータをフラグメント間で扱うことができます。
しかし、このような実装だと、リテラルがバラバラなところに書いてあり、`setFragmentResult`側と`setFragmentResultListener`側でキー名がずれたときに追跡しにくくバグの温床になります。

## data classをまとめて受け渡す

UserDetailFragment

```kotlin
companion object {
        const val REQ_KEY: String = "UserDetailFragment"
        private const val ARG_USER: String = "user"

        fun createArguments(user: User): Bundle {
            return bundleOf(ARG_USER to user)
        }
 }
							・
							・
							・
// 一覧画面から選択された値を取得
setFragmentResultListener(REQ_KEY) { _, bundle ->
	// getSerializableによりUserデータをまとめて受け取ることができる
      val user = bundle.getSerializable(ARG_USER) as User
      id = user.id
	  name = user.name
							・
							・
							・
}
```

UserListFragment

```kotlin
override fun onClickRow(tappedView: View, selectedUser: User) {
		// 呼び出し側でBundleに入れるキー名を与えなくても済む
		setFragmentResult(
		    UserDetailFragment.REQ_KEY,
		    UserDetailFragment.createArguments(selectedUser)
		 )
}
```

User

```kotlin
data class User(
	val id: Int,
	val name: String,
	val icon: String,
	val registerDate: String
): Serializable // BundleにはSerializeを入れることができるため追加
```

このコードで行ったこととしては

- ModelをSerializable化し、Userのデータをまとめて渡す。
- `createArguments`メソッドにより、呼び出し側でキー名を知る必要がなくなる。

このようにリファクタリングすることで複数箇所に`RequestKey`を記述する必要がなくなり、バグが発生する可能性を低くすることができます。
バーチャル MixJuice で Kidspod のプログラムを取得する

この記事は、[IchigoJam Advent Calendar 2020](https://qiita.com/advent-calendar/2020/ichigojam) の 7 日目です。

(2020年12月10日 加筆修正)

# 登場人物

* [IchigoJam web](https://fukuno.jig.jp/app/IchigoJam/)
* [MixJuice](http://mixjuice.shizentai.jp/)
* [Kidspod](http://kidspod.club/)

IchigoJam web で利用できる「バーチャル MixJuice」については、[今年のアドベントカレンダー 1 日目の記事](https://blog.balloon.im/2020/11/ichigojam-web-%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%81%A3%E3%81%9F%E3%83%90%E3%83%BC%E3%83%81%E3%83%A3%E3%83%AB-mixjuice-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%8B/)で詳しく書かれています。

# 問題

2020年12月現在、以下の理由により IchigoJam web のバーチャル MixJuice で Kidspod のプログラムを取得できません。

* Kidspod のウェブサーバが http しかサポートしていない
  * https な IchigoJam web からアクセスするのは Mixed content となり、昨今のブラウザはこのようなアクセスを拒否するようになっています。
* Kidspod のウェブサーバが Access-Control-Allow-Origin の設定をしていない
  * 昨今のブラウザは、異なるオリジンにあるリソースへのアクセスを基本的に拒否するようになっています。
  * 福野氏も、[この記事](https://fukuno.jig.jp/3013)や[この記事](https://fukuno.jig.jp/3014)で CORS の設定が必要なことに言及しています。
  * [CORS とは](http://www.tohoho-web.com/ex/cors.html)

# 解決策

[CORS Anywhere](https://github.com/Rob--W/cors-anywhere)

> CORS Anywhere is a NodeJS proxy which adds CORS headers to the proxied request.

これを組み込んだウェブサーバのデモが [Heroku 上で動作しており](https://cors-anywhere.herokuapp.com/)、このサーバを経由して Kidspod にアクセスすることで、上述の問題を二つともクリアできます。

Usage にあるように、ウェブサイトの URL `https://cors-anywhere.herokuapp.com/` の末尾に本来アクセスしたい URL を付け足すだけで良くて、例えば、Kidspod のプログラム参照用 URL が `http://kidspod.club/mj/976` であるならば、アクセスすべき URL は `https://cors-anywhere.herokuapp.com/http://kidspod.club/mj/976` となります。
これを踏まえ、IchigoJam web で以下のように入力することで、Kidspod のプログラムを取得できます。(MixJuice のチェックを入れておくのを忘れずに)

```
?"MJ GETS cors-anywhere.herokuapp.com/http://kidspod.club/mj/976"
```

実行結果はこんな感じです。
![スクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152579/25ff8526-982d-7e2d-fe7d-cb897c5e7051.jpeg)
あくまでこのサーバはデモとして提供されているものなので、ちょっと試す分には問題ないでしょうけど、常識の範囲内で利用し、やりすぎに注意しましょう。
あと、第三者のサーバを経由する以上、アクセスした URL などがログとして記録されている可能性も否定できないので、その辺りのリスクを承知の上で試してください。

# 要望

IchigoJam web に CORS Anywhere を組み込んでくれれば…などというのは筋違いで、そもそも昨今のセキュリティ事情からブラウザがこのような挙動をするようになったわけで、この解決策はその流れに逆らっていると言えます。
まずは Kidspod がさっさと https に対応し、fukuno.jig.jp からのアクセスを許可する設定をするのを期待してます。

# 追加情報 (2020年12月10日 追記)

[イチゴジャム レシピ](https://15jamrecipe.jimdofree.com/)が管理運用している [MixJuice 短縮 URL サービス](https://github.com/fu-sen/15jm.li)にて、Kidspod のプログラムを取得するための対応が入ったようです。Kidspod の作品 ID が分かっていれば、`https://15jm.li/K/(作品 ID)` にアクセスすることでプログラムを取得できます。
具体的には IchigoJam web で以下のように入力します。

```
?"MJ GETS 15jm.li/K/976"
```
次の関数の第二引数なんだよなー(Elixir)

この記事は、[Elixir その2 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/elixir2) 6日目です。
前日は[二次元リストの操作(Elixir)](https://qiita.com/torifukukaiou/items/8d67e857cdfb8fa4657c) でした。

----

前の計算結果を次の関数の第二引数[^1]にいれたい([Pipe operator](https://hexdocs.pm/elixir/Kernel.html#%7C%3E/2)でつなぎたい)ことありませんか！？
**ありますよね。** (そうじゃないと、この記事のレゾンデートルがない)

[^1]: 第二引数、第三引数、第四引数、...、第N引数――第一引数以外に指定したいという話です

たとえば

```elixir
content = DocomoTextToSpeech.run!("エリクサー")
File.write("output.wav", content)
```

[docomo_text_to_speech](https://hex.pm/packages/docomo_text_to_speech)

# その1

```elixir
DocomoTextToSpeech.run!("エリクサー")
|> (fn content -> File.write("output.wav", content) end).()
```

# その2

```elixir
DocomoTextToSpeech.run!("エリクサー")
|> (&File.write("output.wav", &1)).()
```

# Wrapping Up :lgtm: :santa: :santa_tone1: :santa_tone2: :santa_tone3: :santa_tone4: :santa_tone5:  :lgtm:
- Enjoy [Elixir](https://elixir-lang.org/) !!! :fire::rocket::fire::rocket::fire::rocket::rocket::rocket:
[Ruby on Rails]orderメソッド〜レコードの所得順の変更方法〜

今回の記事では、テーブル（データを格納しておく場所）のレコード（個別の情報）を所得する際の順番を入れ替える方法を説明します。

○orderメソッド

モデルが使用することができるActiveRecordメソッドの一つ。
テーブル（データベース）から所得した複数のレコード情報を持つインスタンス（変数）を並び替えることができるメソッド。

引数に
並び替えの基準となるカラム名と並び順を以下のように指定することで使用ができる。

インスタンス　＝　モデル名.order("並び替えの基準となるカラム名 並び順")

並び順は
DESC:Descending(降順)①旧→新、②小さいものから大きいものへ
ASC:Ascending（昇順）①新→旧、②大きいものから小さいものへ
Vue.jsで早くWebサービスを作るならBuefyが良い

本記事は[iCARE Advent Calender 2020](https://qiita.com/advent-calendar/2020/icare) の6日目です。

# Buefyとは?
[Buefy](https://buefy.org/)とは[BULMA](https://bulma.io/) と [Vue.js](https://jp.vuejs.org/) を組み合わせた UI コンポーネントです。
オープンソースとして公開されています。MIT ライセンスです。

要はコンポーネントが用意されていて、使い方としてもpropsに適切な値を渡してあげれば、ある程度のデザインが効率的に作成できます。

# tailwindcssではダメなの？
## 2020年12月現在のnpm trends
![npm trends](https://res.cloudinary.com/dwq6umozu/image/upload/v1607140392/FireShot_Capture_234_-_bulma_vs_buefy_vs_bootstrap_vue_vs_vuetify_vs_tailwindcss_-_npm_trend__-_www.npmtrends.com_endhtw.png)

[npm trends](https://www.npmtrends.com/)を見てみると、tailwindcssが群を抜いているのが分かります。

ここでBuefyとtailwindcssを比較することがそもそもナンセンスですが、タイトルの通り`Vue.jsで早くWebサービスを作る`ことを最優先にするのであればコンポーネントが既に用意されているので、機能を重視した開発が可能です。

ちなみに[tailwindcss](https://tailwindcss.com/)は、よく使うCSSが変数化、共通化されているので拡張性が非常に高いです。
スクラッチでstyleを組むのは大変だけど、自分たちで独自のコンポーネントを作りたいときはtailwindcssが良いかと思います。

# Buefyの具体例
## ボタンの例
`b-button`というコンポーネントが用意されているのでtypeに`is-dark`を、booleanで`rounded`をpropsで渡します。

![](https://res.cloudinary.com/dwq6umozu/image/upload/v1607146814/carbon_v84ubf.png)

画面に表示するとこんな感じ↓
![](https://res.cloudinary.com/dwq6umozu/image/upload/v1607146872/Screen_Shot_2020-12-05_at_14.39.10_ptoxt9.png)

## テーブルの例
dataとcolumnsをpropsで渡してあげれば、テーブルが完成します。
ソート機能も追加可能です。
![](https://res.cloudinary.com/dwq6umozu/image/upload/v1607148148/carbon_2_op9cox.png)
![](https://res.cloudinary.com/dwq6umozu/image/upload/v1607148150/carbon_3_icsdz4.png)

こんな感じ↓
![](https://res.cloudinary.com/dwq6umozu/image/upload/v1607147953/Screen_Shot_2020-12-05_at_14.59.01_h8neag.png)

# 気になるVue3対応は？
[Vuejs 3 (vue-next) support #2505](https://github.com/buefy/buefy/issues/2505)
GitHub上で議論は行われていますが、新しいBranchやPull Requestは存在しないようです😭
プロジェクトを作って、アップデートする気はありそうなので積極的にコミットしていきたいところです。


# iCAREのフロントエンドはVue.js+Buefy+TypeScript+GraphQLで構成されている
10月にiCAREにジョインしたため、技術採用の歴史的背景を深く理解していませんが、モダンな技術スタックな印象です。
サーバーサイド側で定義されたスキーマを元にGraphQL、Vue.js側の型も縛っているので型安全です。

[採用](https://bit.ly/3oilsjo)も行っているので気になる方よろしくおねがいします！
[DM](https://bit.ly/3mdE6Ix)からでも採用担当に繋ぐことができます！
https-portalでお手軽https化

# 概要
https://github.com/SteveLTN/https-portal

https-portalは簡単にhttpsサーバーを用意できるツールです。
docker-composeにserviceを定義するだけで、NginxとLet's Encryptを使ったhttpsサーバーを立てることができます。

# localhostのhttps化
まずはlocalhostをhttps化してみます。
検証のためにpythonでサーバーを立てます。

```docker-compose.yml
version: "3.7"

services:
  https:
    image: steveltn/https-portal:1
    ports:
      - "80:80"
      - "443:443"
    environment:
      DOMAINS: localhost -> http://python:8000
      STAGE: local
  python:
    image: python:alpine
    command: python -m http.server
    working_dir: /
```

これだけでpythonで立てたサーバーをhttps化できました。
`https://localhost` にアクセスすると確認できます。
ただし、自己署名証明書なので警告は出ます。

# 公開中のwebサイトをhttps化
次に公開中のwebサイトをhttps化してみます。
と言ってもlocalhostをhttps化した時とだいたい同じで、環境変数を少し書き換えるだけです。
なお、Let's Encrypt'sからtest用の証明書を発行するので時間がかかります。

```docker-compose.yml
    environment:
      DOMAINS: YOUR_DOMAIN -> http://python:8000
      STAGE: staging
```

stagingで動作確認が出来たらproductionに変更します。
これでブラウザで警告が表示されなくなり、公開中のサイトをhttps化できました。

# 注意点
いきなりSTAGEをproductionで動作確認をしていると、Let's Encrypt'sのレート制限に引っかかってしまうことがあるらしいです。
コントローラーとビュー

モデルが作成できたので、次はコントローラーとビューを実装しましょう！

コントローラーもジェネレーターで作成できます。

```terminal
書式
$ bin/rails g controller コントローラー名 [アクション名 アクション名 アクショ...] [オプション]
```
さて、どの様なアクションが必要でしょう、作りたいのは**タスクのCRUD機能**です。

| URLの例 | HTTPメソッド | アクション名 | 機能名 | 役割 |
|:-:|:-:|:-:|:-:|:-:|
| /tasks  | GET  | index  | 一覧表示  | 全タスクを表示する  |
| /tasks/17 | GET  | show  | 詳細表示  | 特定のIDのタスクを表示する  |
| /tasks/new  | GET  | new  | 新規登録画面  | 新規登録画面を表示する  |
| /tasks  | POST  | create  | 登録  | 登録処理を行う  |
| /tasks/17/edit  | GET  | edit  | 編集画面  | 編集画面を表示する  |
| /tasks/17  | PATCH,PUT  | update  | 更新  | 更新処理を行う  |
| /tasks/17  | DELETE  | destroy  | 削除  | 削除処理を行う  |

URLやHTTPメソッドはユーザーのWebブラウザからアプリケーションに向けて特定したアクションに処理をさせる。

##★controllerを作ってみよう。
controllerのジェネレーターでアクションを指定すると、アクションと同名のビューも作ってくれます。
★ちょっとしたコツ★
**HTTPメソッドがGETのアクションは同名のビューを使うことが多い**と言う法則があって
HTTPメソッドがGETとなるアクション名をジェネレーターのコマンドの引数として指定するのが効果的。

上の表を参考に、GETアクションの**index,show,new,edit**の４つを指定してジェネレートコマンドをする。

```terminal
$ bin/rails g controller tasks index show new edit
```

今回はパターン通りのルーティングを一括設定したいので、```config/routes.rb```から４つのアクションの設定を消します。

```rb
#下記を消します。
get 'task/index'
get 'task/show'
get 'task/new'
get 'task/edit'
```
代わりに

```rb
resources :tasks
```
resourcesメソッドは上記表の全てのアクションに関するルーティングを一括で設定してくれます。

追加で、同じ場所にルートパスを設定します。
Railsのデフォルト画面ではなく、タスク一覧が表示される様にしてみましょう。

```rb
Rails.application.routes.draw do

root to: 'tasks#index'
resources :tasks
```
APIを使い始めた君へ【1分で学べるAPI】

Web APIってなんですか？という質問に口頭で答えられるようになればいいなーと思い改めてAPIについて超初歩的な解説の記事を作成しました。

## APIとは?

Application Programming Interfaceの略。
APIは自社のサービス(コード)の一部公開して、他のサービスと機能を共有できるもの。
公開することによって、誰でも外部から利用することができるようになります。
それによって、自社のAPIサービスに他のサービスの機能を埋め込むことができるようになるので、アプリケーション同士で連携することが可能になる。APIは基本無料で使用可能。また、APIはWEB上で利用することが普通なのでWebAPIと呼ばれることも多く、API=WebAPIと認識していいでしょう。例えば天気を調べるサービスだと下記のような感じになります。
![スクリーンショット 2020-12-05 11.59.18（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/6709d903-e903-882f-b479-a3ac6c5fadcc.png)

## メリット
### アプリ開発が簡単
今までは自社でプログラミングをし、アプリを製作しなくてはなりませんでした。
しかしAPIを利用することで、API提供側アプリと自社アプリで共通の部分は開発が省略できるので、アプリ製作のハードルが下がります。



### 開発コストの削減
APIを利用することで、アプリを開発する際にわざわざ一からソフトを作る必要がなくなりました。これにより、開発にかかる時間、コストを大幅に減らすことができます。

また、エンジニアの技量やリソース的にそもそも不可能だとされていたものも、これにより可能になります。そのため、ベンチャー企業であっても、大規模なアプリやWebサイトを製作できるようになってきています。

### UX(顧客体験)の向上
最近ではSNS同士が連携し、TwiterやFacebookのアカウントを使って他のアプリやサイトを利用できるようになってます。
ユーザーも別のサービスを利用する際にスムーズに活用する事ができます。
リポジトリのインターフェースはどこに置く？

本記事は、 [DDD\-Community\-Jp Advent Calendar 2020](https://qiita.com/advent-calendar/2020/dddcj)の5日目です。


# はじめに

DDD-Community-JP(以下、DDDCJ)内では架空の会議室予約のドメインを考え、C#で実装するモデリング会を隔週ペースで行っています。

この勉強会の中で実装をしていたときに、

**リポジトリのインターフェースってどこに置く？**

という疑問が出てきました。



<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Repository Interface はどこに書く？って話と、どういうフォルダ名にする？って話が出た。<br><br>どこっていうと大きく二択。<br>- domainに置く<br>- Applicationに置く<br><br>「集約の操作なんだからDomain」というのと「集約をどう扱うかはDomainの関心外」というので考え方分かれる。<a href="https://twitter.com/hashtag/ModelingKai?src=hash&amp;ref_src=twsrc%5Etfw">#ModelingKai</a></p>&mdash; 98lerr (@98lerr) <a href="https://twitter.com/98lerr/status/1330532023954411520?ref_src=twsrc%5Etfw">November 22, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 結局の所、どちらに正解、不正解はない

議論をしていた時には、大別すると二種類のパターンがあるよね、という話がありました。

- ドメイン層
- ユースケース/アプリケーション層

結論としては、そのプロジェクトでちゃんとチーム内で取り決めて、開発していければ問題はないと思います。
（プロジェクトによってマッチするしないはあると思いますので）

ただ、そこに置くと決めた背景や考え方を、それぞれ理解しておくこと自体に、
非常に価値があると思っておりますので、少しまとめてみます。

# 各レイヤーの責務

まずは前提合わせとして、各レイヤーはどんなことをするのかを書いておきます。

- プレゼンテーション層
    - APIの値の受け取り、バリデーション、変換
- ユースケース（アプリケーション）層
    - ユースケースの実現と表現
- ドメイン層
    - ビジネスにおけるロジック、計算判断
- インフラストラクチャ層
    - データベースへのアクセスなど

# ドメイン層の持ち物だよね、派

- リポジトリのメソッドが唯一、「集約の範囲」をコードで定義している、という考え方
- リポジトリは集約単位のみ永続化層との入出力をしないので、この「集約の範囲」を明示するのは、ドメイン層の重要な知識の1つという考え方
    - 「集約の範囲」 → 集約は強い整合性が保たれる範囲とか境界
    - 「RDBのトランザクションも集約と同じ境界」であること。
- 実装上で考えると、ドメインサービスからリポジトリを参照したいことを考えたい時に、ユースケース層にインターフェースが置いてあると参照できなくなって困る
- 集約と同じパッケージ内に置いておかないと、気づかない人もいる

# ユースケース/アプリケーション層の持ち物だよね、派

- リポジトリをそのままドメインオブジェクトと呼ぶのに、違和感がある
    - だから外界（ドメイン層の外）とのやり取りをするリポジトリは、ユースケース層に置いておきたい
- ドメイン層に置きたい理由の一つであった、ドメインサービス内でリポジトリを使うことに関しては、作らないように取り決めしておく


このユースケース層に置いた方が良いという考え方につきましては、別記事で @t2-kob さんに、書いて頂こうと思っております。

→書いて頂きました :sparkles:
[なぜリポジトリのインターフェースを UseCase/Application 層に置きたいと考えるか？ \(Advent Calendar 2020 アンサー編\) \- Qiita](https://qiita.com/t2-kob/items/b46a7ac789619ef2165a)

# 所感

話を聞いていますと、「リポジトリをドメインオブジェクトとして扱うのか、それ以外の何かとして考えるのか」という捉え方の違いで、どこに置くのかというのが分かれてそうな気がしました。

個人的には、リポジトリはドメインオブジェクト（ではあるけど、直接モデルを表さない補助的なもの）だと思っているので、
リポジトリのインターフェースがドメイン層の中に置いてあるのは、自然だなと感じています。

ただ、ユースケース層に置きたいという話もわかるため、
自分の意見を絶対だと思わず、相手の意見の背後にある考え方を聞くのはあらためて大事だと感じました。


# おわりに


ざっと2パターンを出してみましたが、
私はこの層に置くよ/やったことがあるよ、みたいな意見もあると思います。[^1]

[^1]: そもそもな話、置く場所なんてどこかに一箇所に決めればそれでいいよ、という意見もあるかもしれません

ぜひこういう考え方もあるよ、みたいなのがあればぜひ教えて頂けたらと思っております…！

# 2020/12/06 追記

DDDCJの中で、この話をしましたところ、
エヴァンス本的には「知識、影響、または活動の領域」と定義されているけど、その「領域」をどのように線引するのかが、あまり語られてないよね、という話がありました。

「ドメインに含まれるものは何？」という話をした上で、その前提から上のような「リポジトリのインターフェースってどこに置く？」みたいな話に派生していくのだと。

このお話を聞いて、自分はドメインに含まれるものは、アプリケーションの適応対象となる業務になるのだろうという認識を持っていますが、その中に記録の範囲が入るかというと、また悩ましい感じがしています。

ただ、システムにあるデータを意味のあるデータとしてまとめ、記録、取り出してドメイン層の中で扱えるようにする、という意味では、ドメイン層の中に置いておくのが、いまのところ収まりが良いとは、個人的にはしています。

# 参考資料

- [ドメイン駆動設計 モデリング/実装ガイド](https://booth.pm/ja/items/1835632)
- [ドメイン駆動設計入門 ボトムアップでわかる！ドメイン駆動設計の基本](https://www.amazon.co.jp/dp/B082WXZVPC/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
【BEV】OpenCVでbird eye view変換を実験してみる

<h1>背景</h1>
「前から見てるものをBird Eye View(上からの視点)に変換するってどういうこと？」
「上にもう一個カメラがついてるんじゃなくて？」

最近まで数学的に全くイメージ出来なかった。

BEVの考え方をツラツラと書いていく。

<h1>アルゴリズム</h1>

<h2>どうやったら上からの視点になるの?</h2>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/dbad27f6-4c6e-25d9-95bb-252f2fa9dbfe.png)

上から見た道路の写真って白線が直線になっていると思います。
*線がカーブでなければ
*平行な直線であれば何でもokay

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/a06d6593-46f8-06d1-58ae-31a867313f34.png)
しかし、前から見ると八の時型になっていますね。これは遠いものが小さく見える事から起きます。

実際は直線である4点を選び、直線であるという事実から、直線になるように引き伸ばすイメージで変換すると、BEVになります。

opencvで実際やってみたので見てください。

<h2>設定</h2>
必要な事は直線である4点を選ぶだけ

```
lane_shape = [(584, 458), (701, 458), (295, 665), (1022, 665)]
top_left, top_right, bottom_left, bottom_right = lane_shape
source = np.float32([top_left, top_right, bottom_right, bottom_left])
destination = np.float32([(bottom_left[0], 0), (bottom_right[0], 0),
                                  (bottom_right[0], self.img_height - 1), (bottom_left[0], self.img_height - 1)])
self.overhead_transform = cv2.getPerspectiveTransform(source, 
   destination)
```

<h2>bird eye view変換</h2>

```
    def warp_to_overhead(self, undistorted_img):
        """
        Transforms this camera's images from the dashboard perspective to an overhead perspective.

        Note: Make sure to undistort first.
        """
        return cv2.warpPerspective(undistorted_img, self.overhead_transform, dsize=(self.img_width, self.img_height))
```


<h2>結果</h2>
before
![step2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/a4b7b091-a499-5287-235a-c3ad1bafa191.png)

after
![step3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/27c3a35c-860e-bb2b-3b21-305cc0b2d27e.png)


<h1>結論</h1>
・平行な直線という事実から4点を選ぶと変換するためのParameterが得られる。
・このメソッドだと地面に対するカメラの傾きや地面が平らでない場合などは使えない。

距離の情報を持ってるのかな〜とか期待したのでがなかったです。
【Swift】初めてDelegateを実装する方向けの、サンプルと解説

#この記事の対象者
・まずはDelegateの必要最低限のコードを知りたい。という方。
・一通り関連記事を読んだが
　→ Delegate実装に「必要/不必要なコード」の区別がつかず難して挫折しそうな方
　→ 必要なコードは分かったけど「記述場所」が掴めきれず困っている方


主に下の絵の様な（Delegate初実装時の私）状態のかた向けです。

![Frame 3 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461535/44ee65ba-e990-38fa-6c3b-24aea9d840f3.png)

#この記事の非対象者
Delegateについて深く理解したい方
Dlegateの利用方法/活用場面（どんな時に使うの？）を知りたい方
エンジニアとして現場で活躍している方（←の方は特に読まないでください）

#実装コード
今回は下記の絵の場面を実装します
![Frame 2 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461535/e45e1b74-75f9-dd11-401f-b2de5a5881e1.png)

##処理を任せる側のファイル

```swift:NudeMan.swift

protocol NudeManDelegate {
    func buyHuku()
}

class NudeMan { 

    var delegate: NudeManDelegate?
    
    func cold() {
        self.delegate?.buyHuku()
    }
}
```

##コード解説

####``protocol``
``class``や``func``と同じ様に``protocol``と書かなければいけません。
急に登場した``protocol``が難しく感じますね！
【強敵protocolの倒し方】（難しさ緩和方法）
私は、処理を任せる時だけclassがprotocolに名前を変える。
と思う様にして難しさを緩和しました


　
####``NudeManDelegate ``（ protocolの後につく名前 ）
``class名``と同じ様に任意で構いません。
補足
任意ですが、ホニャララDelegateと書かれるのが一般的です。
(Swiftが元から用意しているprotocol名も``UITextFieldDelegate``など、○○Delegateと命名しています)


　
####``protocol``の中身
ここは裸の男(任せる側)の「服買ってきて」にあたる部分です
今までは
``func hoge()``の後に必ず　`` { 何らかの処理　} ``　を書いていたと思いますが
今回の``protocol``の中には書きません
`` { 何らかの処理 }``は任せる側に書きます。
  

     

####------　↓ここからNudManクラスの中　---------------　
####``var delegate: NudeManDelegate?``
一瞬見慣れない事をやっている様に感じますが、
やっている事は
``var sumpleClass: SumpleClass?``と同じです。



 

####``self.delegate?.buyHuku()``
このタイミングで処理を任せたい(服買ってきて！)という所に書きます。
今回はサンプルで``Func cold()``で処理を任せましたが
実際は、
ボタンがタップされたタイミング、何かの処理が終わった後、などで使われます。
処理を任せたいタイミングで
``self.delegate?.buyHuku()``を実行しましょう。

##処理を任される側のファイル
```swift:Woman.swift

Class Woman: UIViewController, NudeManDelegate  { 
 
    var nudeMan: NudeMan?

    override func viewDidLoad() {
        super.viewDidLoad()  

         nudeMan = NudeMan()
         nudeMan.delegate = self
     }

       func buyHuku() {
        print("マフラー買ってきます")
     }

}
```



####``class Woman: UIViewController, NudeManDelegate ``

``UItableView`` を使った事がある人は``UITableViewDelegate``
で見た事がありますね。同じ様にNudeManDelegateもここに書きます。
（初めての方はここに書く物だと覚えて下さい)


 
### ``nudeMan = NudeMan()``
依頼する側のクラスをインスタンス化します。
(インスタンス化が分からない方は、とりあえず依頼する側のクラス名に()を付けて
変数に代入しましょう）

###``nudeMan.delegate = self``

NudeManクラスの依頼を「私が受ける！」と宣言しています

ん！？
``NudeManクラス``の``delegate``の型は``NudeManDelegate``なのに
何で代入できるんだ？と気づいたあなた！さすがです

ここが``delegate``の難しいポイントです
しかし今回の目的は「実装コードを知る」なので
「delegateを深く理解する」は一旦スルーしましょう

(テンプレと割り切るのも挫折しない１つの方法だと思います。)

　
どうしても気になる人用にちょっとだけ・・・
``Womanクラス`` と ``NudeMandelegate`` は型違い（無関係）に見えますが
``Womanクラス`` は ``NudeMandelegate`` を継承してViewControllerを実装しています。
なので代入できる。今回はこの程度で。


　
#### ``func buyHuku() { }``
この中で依頼された側それぞれで何を買いに行くか決めます。

##あとがき
今回は、delegateで挫折しない為に
- Class-only Protocol
- 循環参照
- plotocol内のメソッドで引数も渡せる事
- プロパティも実装できる事
などなどあえて触れていない事がまだ沢山あります
この記事を足掛りに、さらに理解を深めて、頂ければ幸いです。
また、出来るだけ専門用語を使わず解説したつもりでしたが、記事内で出てきた用語、説明の仕方で、分かりにくい部分があれば遠慮なくご指摘下さい。
記事内画像: icons8 https://icons8.com/
Unreal Engine 4.25 アニメーションのデフォルト圧縮方法の変更

UE4.25 でデフォルトのアニメーション圧縮方法を変更する方法のメモ。[（手順へジャンプ）](#アニメーションのデフォルト圧縮方法の変更)

#前置き
アニメーションの圧縮が重い。インポートは仕方ないとしても、圧縮が重い。しかもPCを変えたりすると度々こいつが動く。辛いので、軽くする方法を調べてみた。
アニメーションの圧縮とはこれ **↓** の事。圧縮は助かるけど、なにぶん時間がかかりすぎ。
<img width="350" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388152/1e38f83b-f34d-7380-5524-4bab90e6cbc3.png>
ちなみに、デフォルトの圧縮方法は **DefaultAnimBoneCompressionSettings**という名前（下図左部分）。何もしてなければ`Program Files\Epic Games\UE_4.25\Engine\Content\Animation`あたりに居る。Program filesの中とか変更したくなーい！
<img width="800" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388152/236a530c-0b0d-fdb6-5489-babf4c8882ec.png>
圧縮方法が複数の登録されていて、その中に遅い方法が含まれてるのが重い主な原因らしい（上図右）。
直接この中を減らす方法も考えたけど、前述の通りなので DefaultAnim～ は変更したくない。(※ちなみに、実際にDefaultAnim～の中身を早いの一種類のにしたら圧縮時間はすごく減った)
また、別の事情として別のPCにコピーしたりチェックアウトしたりする事もある。つまり、圧縮の設定はプロジェクトの方に含めたい。

圧縮方法自体は最初から **Bitwise** とか色々用意されてる。この最初から用意されている圧縮方法の諸々については、[ほげたつ](https://hogetatu.hatenablog.com)さんの [アニメーション圧縮検証（UE4.20/4.21）](https://hogetatu.hatenablog.com/entry/2018/12/05/000944) で勉強させてもらった。感謝。

さて、上記ブログ内のラストで名前だけ紹介されていた [**Animation Compression Library**](https://www.unrealengine.com/marketplace/ja/product/animation-compression-library) (ACL) が別で調べた感じ良さそうらしい。なので今回は、これを使って設定する方法をまとめた。

#■アニメーションのデフォルト圧縮方法の変更
1．[**ACLPlugin**](https://www.unrealengine.com/marketplace/ja/product/animation-compression-library)をインストール
2．インストールが終わると、以下の場所にACL標準の設定ができるので、これを使いたいプロジェクト以下にコピー

```
UE_4.25\Engine\Plugins\Marketplace\ACLPlugin\Content
ACLAnimBoneCompressionSettings.uasset
ACLAnimCurveCompressionSettings.uasset
```
例えば下記みたいな場所（フォルダ「ACLPlugin」は適当に作った）

```
プロジェクトフォルダ\Content\ACLPlugin
```
3．肝の初期設定変更。UEプロジェクトの初期設定を変更するためには **DefaultEngine.ini** を編集する。
　ここを変更する事で、初期のインポート時に設定した方法で圧縮されるようになる。
　(※DefaultEngine.iniはプロジェクトフォルダの中を検索すれば簡単に見つかるはず)
　自分が開いた DefaultEngine.ini では該当の項目が無かったので、新規に書き加えた。

```
[Animation.DefaultObjectSettings]
BoneCompressionSettings="/Game/ACLPlugin/ACLAnimBoneCompressionSettings"
CurveCompressionSettings="/Game/ACLPlugin/ACLAnimCurveCompressionSettings"
```
正常に設定できていれば、アニメーションのインポート直後で下図のようにアセットが変わってるのが確認できる。
<img width="400" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/388152/73ccb99c-17a1-c4fb-e926-6713c967afc6.png>
以上。簡単だね！
実際に変更してインポートを試してみたら、デフォルトに比べて**圧縮時間が1/25**くらいになった（50s→2s）
アニメーション圧縮による動きの変化については、まだ未検証のなのでそこは注意。

簡単なのに調べるのに一日かかってしまった。
[ACL の github にしっかり書かれてる](https://github.com/nfrechette/acl-ue4-plugin/tree/develop/Docs#how-to-change-the-default-compression-codec)にも関わらず見落としたのが原因。アホすぎて泣ける。

#補足追加メモ
※Bone Compression Settings はアニメーションアセットの **Asset Details** から確認できる
　Details じゃなくて **Asset Details** だから注意（Window>**Asset Details**で開く）
　アニメーションアセットを開いても肝心の項目が見つからずしばらく彷徨った:disappointed_relieved:
　

#####※手元にあるアニメーションを色々つっこんでの圧縮方法別必要時間（20/12/15追記）
・デフォルト...34660 sec（約9時間）
・ACL...2618 sec（約45分）
・Bitwiseのみ...228 sec（約4分）
容量そこまで気にしないし、変化もほとんどないらしいし、ACLよりBitwiseが最強？
Azure BlobStorageにサブフォルダ作成

#はじめに
Azure BlobStorageを利用していますが、サブフォルダ作成できるかは資料だと不明確です。

#BlobStorageとは
>大規模な非構造化データの格納とアクセス
Azure Blob Storage を使用すると、お客様の分析のニーズに合わせてデータ レイクを作成することができ、強力なクラウドネイティブおよびモバイル アプリを構築するためのストレージが提供されます。長期的なデータ用に階層型ストレージを使用してコストを最適化し、ハイパフォーマンス コンピューティングと機械学習のワークロード用に柔軟にスケールアップできます。

出典：https://azure.microsoft.com/ja-jp/services/storage/blobs/

#Blob Storage のリソース
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346425/b3054f50-86a5-c3f2-278a-d9e86b807f56.png)

- ストレージ アカウント
- ストレージ アカウント内の コンテナー
- コンテナー内の BLOB

出典：https://docs.microsoft.com/ja-jp/azure/storage/blobs/storage-blobs-introduction

#Blobのところ、サブフォルダ作成できるか？
上記の図だと、サブフォルダ例がないので、できるかは不明です。
また、AzureのPortalサイトにもサブフォルダ作成することはできないです。アップロード時にはファイルまで指定する必要がありました。

#JAVAで操作するライブラリ
```build.gradle
// https://mvnrepository.com/artifact/com.azure/azure-storage-blob
compile group: 'com.azure', name: 'azure-storage-blob', version: '12.9.0'

```

アップロード例：

```java
      String connectInfo = "xxxxxx";
      BlobServiceClient blobServiceClient =
          new BlobServiceClientBuilder().connectionString(connectInfo).buildClient();

      BlobContainerClient blobContainerClient =
          blobServiceClient.getBlobContainerClient("containerName");

      // Virtual directory作成
      BlobClient blobClient = blobContainerClient.getBlobClient("subforlder1/subforlder2/" + "test.txt");

      // upload
      blobClient.uploadFromFile(file.getAbsolutePath(), true);

      // mata, headerなど
      //  blobClient.setHttpHeaders(headers);
```

参考：JAVAでファイルアップロードなど
https://docs.microsoft.com/ja-jp/azure/storage/blobs/storage-quickstart-blobs-java-legacy

以上
Xcode12でCarthageビルドができない場合の対処法

## Xcode12にしてからCarthageのビルドが通らない
Xcode12になってからCarthageでビルドできない問題はCarthageを利用している方はほとんど遭遇したのではないでしょうか。

```
Task failed with exit code 1:
```

や

```
Task failed with exit code 65:
```

のようなエラーが発生するものです。

これらのエラー回避の方法が非公式にいろいろあって当初はうまくいったのですが、Xcode12.2にアップデートしたところ再度同じようなエラーに遭遇するようになってしまったので再度調べたところCarthage公式にて
[Using Carthage with Xcode 12](https://github.com/Carthage/Carthage/blob/master/Documentation/Xcode12Workaround.md)
というドキュメントが公開されていて、これをそのまま実行したところうまく行きました。
2020年12月現在のやり方をそのままではありますが記載しておきます。

## carthage.shファイルの作成
任意の場所に`carthage.sh`（ドキュメントでは`/usr/local/bin/carthage.sh`）を作成します。
スクリプトは以下をコピペでオーケーです。

```sh:carthage.sh
# carthage.sh
# Usage example: ./carthage.sh build --platform iOS

set -euo pipefail

xcconfig=$(mktemp /tmp/static.xcconfig.XXXXXX)
trap 'rm -f "$xcconfig"' INT TERM HUP EXIT

# For Xcode 12 make sure EXCLUDED_ARCHS is set to arm architectures otherwise
# the build will fail on lipo due to duplicate architectures.

CURRENT_XCODE_VERSION=$(xcodebuild -version | grep "Build version" | cut -d' ' -f3)
echo "EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200__BUILD_$CURRENT_XCODE_VERSION = arm64 arm64e armv7 armv7s armv6 armv8" >> $xcconfig

echo 'EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200 = $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64__XCODE_1200__BUILD_$(XCODE_PRODUCT_BUILD_VERSION))' >> $xcconfig
echo 'EXCLUDED_ARCHS = $(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT)__XCODE_$(XCODE_VERSION_MAJOR))' >> $xcconfig

export XCODE_XCCONFIG_FILE="$xcconfig"
carthage "$@"
```

```
chmod +x /usr/local/bin/carthage.sh
```
上記コマンドで実行権限を与えます。

## スクリプトの実行

あとは

```
sh carthage.sh bootstrap --platform iOS --cache-builds
```

のようにして実行します。引数・オプションはこれまで実行していたとおりで、carthageの部分をcarthage.shに置き換えます。
実行するとこれまで通りと同じようにビルドができるはずなので完了です。
JavaScriptでnull判定をしないといけないよーって話。

JavaScriptって、クリック判定したい時にDOM要素とってきて、そいつがクリックされた時〜
って処理を書くけど、そのDOM要素がない時は普通にエラーを吐く。

なので、きちんとnull判定をしておかないといけないよって話でした。

```
Uncaught TypeError: Cannot read property 'addEventListener' of null
```

上記エラーが出ないようにするために

```
var btn = document.getElementById('form_submit_button');

if (btn != null) {
    btn.addEventListener('click', function () {
    document.getElementById('quill_content').value = JSON.stringify(quill_1.getContents());

    //submit()でフォームの内容を送信
    document.quill_form.submit();
});
}

```

こんな感じでnull判定をする。
【Rails】ユーザー退会機能（退会時に投稿データも削除）

# はじめに
ポートフォリオ（投稿アプリ）にユーザー退会機能を追加してみました。
今回は、アプリの性質上データ復元の必要性が低いため物理削除で実装し、ユーザーが退会したタイミングで、そのユーザーに紐づく投稿も削除する仕様にしました。

# 前提
・Ruby2.7.0
・Ruby on Rails6.0.3
・MySQL8.0

# 論理削除と物理削除
## 論理削除とは
・実際にはデータを削除しないが、ユーザーには削除しているかのような振る舞いを見せること。
・データベースに削除されたと見なすフラッグと呼ばれるカラムを設定。
・謝って削除したデータも復元可能。
・データ表示の際、where句で絞り込み検索を行うのに削除フラグの条件を追加する必要がある。
・データが増加し続け、データベースの容量の圧迫、パフォーマンス性の低下を起こす可能性がある。
## 物理削除とは
・データをDELETE(Railsだとdestroy)でデータベースから完全に削除すること。
・データは完全に削除され復元や参照が出来ない。

# 流れ
1. コントローラ編集
1. モデル編集
2. ルーティング編集
3. ビュー編集

# コントローラ編集
` users_controller.rb`に` destroy`アクション追加。

```ruby:users_controller.rb
class UsersController < ApplicationController
  # before_action :set_user, :only => [:show, :favorites, :comments]
  before_action :set_user, :only => [:show, :favorites, :comments, :destroy]

  def destroy
      @user = User.find(params[:id]) 
      @user.destroy
      flash[:notice] = 'ユーザーを削除しました。'
      redirect_to :root #削除に成功すればrootページに戻る
  end

  private
  def set_user
     @user = User.find_by(:id => params[:id])
  end
end
```

# モデル編集
` user.rb`に` dependent => :destroy`を追加することで、退会したユーザに紐づく全投稿が削除される。

```ruby:user.rb
has_many :posts, :dependent => :destroy
# 退会ユーザーに紐づくお気に入りも削除する場合
has_many :favorites, :dependent => :destroy
# 退会ユーザーに紐づくコメントも削除する場合
has_many :comments, :dependent => :destroy
```

# ルーティング編集
` routes.rb`に` destroy`アクション追加。

```ruby:routes.rb
# resources :users, :only => [:show, :edit, :update]
resources :users, :only => [:show, :edit, :update, :destroy]
```

# ビュー編集
マイページに退会ボタン作成。
` "data-confirm" => "本当に退会しますか？"`で確認ダイアログも表示。
簡単ログイン機能でテストユーザーとしてログインした場合は、退会ボタンが表示されないようにする。

```ruby:app/views/users/show.html.erb
<% if user_signed_in? && @user == current_user %>
  <% unless @user.email == "test@example.com" then %>
     <div class="mt-3">
        <%= link_to "退会",user_path(current_user.id), class: "destroy-user", method: :delete, "data-confirm" => "本当に退会しますか？" %>
     </div>
  <% end %>
<% end %>
```

このままだと、` post.user.name`みたいな記述をしているビューはエラーが出るので、` if文`追加。

```ruby:app/views/posts/index.html.erb
<% @posts.each do |post| %>
  <% if post.user %>
　<% end %>
<% end %>
```

# 終わりに
以上でユーザー退会機能の実装完了。
退会ユーザーに紐づく投稿も無事削除できました。
今度は勉強も兼ねて論理削除での実装にもチャレンジしたいと思います！

初学者のため、理解不足な点が多々あると思います。気になった点やアドバイスなどありましたら、教えていただけますと幸いです！

# 参考サイト
・[1分でわかる論理削除 -メリットとデメリットを考える-](https://qiita.com/wanko5296/items/f1af9c7bf020e867c2dd)
・[削除機能の設計(物理削除とは/論理削除とは)]
(https://qiita.com/shukan0728/items/1a7b2db01ae25f8f7f88)
・[論理削除と物理削除とは](https://qiita.com/jonson29/items/4743409eda08fcdf5410)
・[退会時に投稿データを削除する [Rails]](https://qiita.com/mailok1212/items/533bbf7d97a9d4bd4573)
・[Railsでユーザー退会機能をつくる](https://qiita.com/kenz-dev/items/d52054000c16cb363707)
・[【Rails 退会】railsで簡易的な退会機能を作る](https://qiita.com/facultyoflaw11/items/664c5c0fa0cd09bece38)
MYSQL基礎知識(データベース、テーブル、ユーザー作成)

#MYSQLデータベース作成


###SQLにログインする　

実行コマンド mysql -u root(rootユーザーでログインする場合)

```
xxxxxx@MacBook-Pro bin % mysql -u root
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 8.0.22 Homebrew

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

#データベースについて

###データベースの確認

```
mysql> SHOW DATABASES;
```


###データベースの作成

```
mysql> create database データーベース名;
Query OK, 1 row affected (0.01 sec)
```


###データベースの選択

上記のコマンドで作成したデータベースを選択する。

```
mysql> USE 使用するデーターベース名;
Database changed
```

###データベース使用許可追加

```
mysql> GRANT ALL ON データベース名.* TO 'your_mysql_name'@'your_client_host';
```

###データベースの削除

```
 drop database 削除するデータベース名;
```


#テーブルについて


###テーブルの確認
```
mysql> SHOW TABLES FROM データベース名;
```

###テーブルの作成
()内には値が入る。

```
mysql> CREATE TABLE テーブルを作成するデータベース名.作成するテーブル名 (id int,name VARCHAR(20));
```

※VARCHAR =可変型の文字列を意味するデータ型　
※int 　　=整数のデータ型


###テーブルの削除

```
drop table データベース名.削除するテーブル名;
```


###テーブルの確認

```
DESCRIBE データベース名.テーブル名;

```
```
mysql>  DESCRIBE travel_apps.test;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.00 sec)
```

###データの追加

```
INSERT INTO データベース名.テーブル名(xx,, yy)VALUES(aa, "bb");
```

###追加した値の確認

ISERTで追加した値は以下の通り、確認ができる

```
mysql> SELECT * FROM データベース名.テーブル名;
+------+------+
| id   | name |
+------+------+
|    1 | test |
+------+------+
```



#カラムについて

###カラムの追加

```
mysql> ALTER TABLE データベース名.テーブル名 ADD カラム名 データ型;
```
以下の通りcolumnの追加を確認

```
mysql> DESCRIBE データベース名.テーブル名;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
| age   | int         | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
```

**更新に関してはUPDATE, 削除に関してはdropを使う。**


#ユーザーについて

###ユーザーの作成

```
create user 'ユーザー名'@'localhost又はIP' identified by 'パスワード';
```

###ユーザー一覧の確認

```
mysql> SELECT Host, User FROM mysql.user;
```

###ユーザーの削除

```
mysql> drop User ユーザー名;
```
STUDIOで初めてwebサイトを作ってみた感想


- STUDIOとは？
    - HTMLやcssのコーディングいらずでサイトが作れる画期的なサイト作成サービス
    - 基本的には無料（いくつかプランはある）

- 作業した人の知識量
    - HTML→ちょっとだけわかる
    - css →全然わからない
    - STUDIO→初めて触る
    - デザイン→初心者

- どんなサイトを作ったか
    - https://lp.openlogi.com/partner
    お洒落さより見やすさ、分かりやすさを重要視して作成しました。

- 苦労したところ
　とにかくやれることが多いので慣れるまで時間がかかるのですが、やりたいことをヘルプページで調べると簡単に出てきたのであとは操作に慣れるだけでした！
　cssの知識がなかったため、paddingやmarginがわからず困ることが多かったのですが、直感的に操作できたためpaddingとmarginのお勉強にもなりました！
 途中でレスポンシブデザインのレイアウトを作成するのがちょっと難しかったです・・・
 自分の思うようにレイアウト変更しようとすると少し手間がかかる印象です。
苦労したところとは違うのですが、バックアップの方法がそのページのコピーを取るしかないので少し不安かもしれないです・・・

- よかったところ
　FAQが親切なのでわからなくなった時はとりあえずFAQから探してみればなんとかなります！
 デザインに迷った時はパーツのテンプレートやサイトのテンプレートなども利用できるのでデザインに詳しくなくてもとにかく簡単にお洒落なサイトを作成することができます。
　ヘッダーやフッダー、パターンなどそのまま保存できるので複数ページを作る時にとても楽でした。
 
- やってみての総括
    最初は操作感に慣れず大混乱で頑張ってましたが、操作感に慣れてからはやりたいことがほぼできて作業中普通に楽しかったです。
    入れ子構造がレイヤーと同じ見え方になっているのでとても勉強になりました！
    ![](https://s3-ap-northeast-1.amazonaws.com/openlogi-crowi/uploads/upload_53ae21960b2496fedfef0e1c1c7b7203.png)

    今度お洒落なサイトも作ってみたいなという気持ちです！
【Kotlin】KFunctionが拡張関数かどうかjavaMethodから判定する

# TL;DR
- 拡張関数の`KFunction`に`EXTENSION_RECEIVER`パラメータが無い場合でも、`javaMethod`は`EXTENSION_RECEIVER`パラメータを要求する
- これにより`KFunction`と`javaMethod`の引数の数が異なるため、拡張関数かどうか間接的に判定できる

# 本文
インスタンスからメソッドリファレンスで取得した`KFunction`は`EXTENSION_RECEIVER`パラメータを要求しません。
加えて、`KFunction`には`isExtension`というようなプロパティも無いため、そのような`KFunction`が拡張関数かを単体で判定することはできません。

ここで、拡張関数の`javaMethod`はパラメータとして`EXTENSION_RECEIVER`を要求することから、そのような`KFunction`の定義とは引数の数が異なることになります。
これを用いることで`KFunction`が拡張関数かどうか判定することができます。

```kotlin
fun Foo.topLevelExtensionFunc(arg1: Int, arg2: String) = /* 略 */

fun test(foo: Foo) {
    val topLevelExtensionFunc: KFunction<*> = foo::topLevelExtensionFunc
    // -> 2
    println("Top level param size:\t${topLevelExtensionFunc.parameters.size}")
    // -> 3
    println("Top level javaMethod param size:\t${topLevelExtensionFunc.javaMethod!!.parameters.size}")
}
```
IBM Watson Discovery 便利プログラム

# コレクション内のすべての文書を削除する
collectionに文書を入れていろいろ試したあと、いったんすべての文書を消してまた何かしたい...。
かといってcollectionを再作成すると、collectionIDとかconfigIDとかが変わってしまうのは困る!
ということがあったのでcollection内のすべての文書を削除するプログラムをTypeScriptで作成してみました。

ソースは[git](https://github.com/Ryota-Amano/ibmcloud-discovery)にあります。
Qiitaの記事ではプログラムの仕様や概要を説明します。利用方法はgitをご覧ください。
**ご利用は自己責任でお願いいたします。**
改善点や不明点等ございましたら連絡いただけますと嬉しいです。　
## 仕様
* 資格情報の入力はプログラム実行後に画面から入力
* 入力する資格情報は
    * url
    * APIkey
    * environmentID
    * collectionID
* Discovery APIバージョンは固定値(`2019-04-30`)
* 一度に取得できるDocumentIDは10000まで
* 削除できる文書数に限りはない


## 前提条件

1. IBM Watson Discovery のコレクションに文書がある
1. Node,npm,git(ソースclone用)がインストール済み

## 環境
* Node v10.16.3
* npm 6.14.9
* git version 2.23.0.windows.1
* Windows 10 Pro

##フォルダ構成

```
ibmcloud-discovery/(root)
 ├─ dist/
 │   ├─ src/
 │   └─ app.js 
 ├─ node_modules/
 ├─ src/
 │   ├─ api/
 │   │   └─ Discovery.ts
 │   ├─ DeleteDocuments.ts
 │   ├─ QueryCollection.ts
 │   └─ UserInput.ts
 ├─ .gitignore
 ├─ app.ts
 ├─ package-lock.json
 ├─ package.json
 ├─ RRADME.md
 └─ tsconfig.json
```

**`dist/`**　tsをコンパイルした後のjsファイルが格納されている。プログラム実行時はdist/app.jsを実行する。
**`Discovery.ts`**  DiscoveryへのAPIコール処理を行うtsファイル
**`DeleteDocuments.ts/`** 取得した複数のDocumentIDを使用し繰り返し削除を行うtsファイル
**`QueryCollection.ts/`** DocumentIDの取得を行うtsファイル
**`UserInput.ts/`** プログラム実行後の資格情報入力を促す処理を行うtsファイル
**`app.ts/`** メインのTypeScriptファイル

##フローチャート
大まかな流れをフローチャートで書きました。
綺麗なものではないですがご勘弁ください。

![flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649992/91069014-5784-2715-d0a6-2a94c15d38f3.png)

## 最後に

他にも、ああいう便利プログラムが欲しい!!などあれば、できる限り作っていきたいと思います。
formを部分的に共通化

「`新規作成画面`と`編集画面`」のように`form_with`等を使用してデータの登録、編集を実装したい。
そこで、共通している入力フォームはパーシャルにしてしまおう！！と考えました。

ですが、`form_with`内には`登録ボタン`や`更新ボタン`など部分的に違う箇所もあるので全部共通化はできません。
その際実装した内容を記述して残しておきます。

#### 実装時のポイント
・同じ箇所は共通化する
・違う箇所は条件分岐で表示の切り替え
・`render`時に引数を渡す

この3点を行いました。


最初の状態はこんな感じ。(フォーム内容は例になります)

(新規作成画面)

```　new.html.erb
<%= form_with model: @post, url: confirm_posts_path, html: { method: :post }, local: true do |f| %>
  <div class="sample">
    <div>
      <%= f.label :画像 %>
      <%= f.file_field :image, id: "post_img" %>
      <%= f.hidden_field :image_cache %>
    </div>
    <div>
      <%= f.label :名前 %>
      <%= f.text_field :user_name %>
    </div>
    <div>
      <%= f.label :犬の名前 %>
      <%= f.text_field :dog_name %>
    </div>
  </div>
  <%= f.submit "確認画面へ" %>
<% end %>
```
(編集画面)

```　edit.html.erb
<%= form_with model: @post, local: true do |f| %> 
  <div class="sample">
    <div>
      <%= f.label :画像 %>
      <%= f.file_field :image, id: "post_img" %>
      <%= f.hidden_field :image_cache %>
    </div>
    <div>
      <%= f.label :名前 %>
      <%= f.text_field :user_name %>
    </div>
  </div>
  <%= f.submit "更新" %>
<% end %>
```

(共通箇所)

``` 
<div class="sample">
  <div>
    <%= f.label :画像 %>
    <%= f.file_field :image, id: "post_img" %>
    <%= f.hidden_field :image_cache %>
  </div>
  <div>
    <%= f.label :名前 %>
    <%= f.text_field :user_name %>
  </div>

```

(切り分けたい箇所)

```　new.html.erb
    <div>
      <%= f.label :犬の名前 %>
      <%= f.text_field :dog_name %>
    </div>
  </div>
  <%= f.submit "確認画面へ" %>
```

```　edit.html.erb
  </div>
  <%= f.submit "更新" %>
```


## 部分テンプレートの作成

`_post_form.html.erb`に` <% if local_assigns[:edit_flag].present? %>`と記述することでpartialの指定したローカル変数に値が入っているか判別し分岐させる。


`_post_form.html.erb`を新しく作成して以下のように記述します。

``` _post_form.html.erb
<div class="sample">
  <div>
    <%= f.label :画像 %>
    <%= f.file_field :image, id: "post_img" %>
    <%= f.hidden_field :image_cache %>
  </div>
  <div>
    <%= f.label :名前 %>
    <%= f.text_field :user_name %>
  </div>
  <% if local_assigns[:edit_flag].present? %>
    <div>
    <%= f.submit "更新" %>
  <% else %>
    <div>
      <%= f.label :犬の名前 %>
      <%= f.text_field :dog_name %>
    </div>
  </div>
  <%= f.submit "確認画面へ" %>
  <% end %>
</div>
```

各HTMLは以下になります。

```　new.html.erb
<%= form_with model: @post, url: confirm_posts_path, html: { method: :post }, local: true do |f| %>
  <%= render :partial => 'post_form', :locals => {:f => f} %>
<% end %>
```

```　edit.html.erb
<%= form_with model: @post, local: true do |f| %> 
  <%= render :partial => 'post_form', :locals => {:f => f, :edit_flag => true} %>
<% end %>
```

かなりスッキリさせることができました。
使用したいページでrenderの引数を定義すれば良いだけなので簡単です。