OmniAICreator/Qiita-1.07M huggingface dataset:
呼び出し回数に制限がある外部サービスAPIの上限緩和方法

## 困っていた事
[Vimeo API](https://developer.vimeo.com/api/reference)を利用して、ライブストリーミング中のhls URLを、アプリケーションで許可した人にのみ配信したくて、
どうもそのようなエンドポイントは存在するものの、1分間内でのAPI実行回数制限があり、
サービスの成長途中でこの上限にぶつかりそうだなぁと思った。
APIドキュメントでは、「利用システム側でええ感じに頻繁にキャッシュしてね」と書いているものの、
取得できるm3u8 URLは有効期限が10秒とかなりタイトなため、キャッシュできるとしても、ブラウザ側であれこれアプリ全体のバンドルリソース読み込んでevalして、実行開始して、、、とかの関係ない時間を考慮すると、キャッシュできる時間はたかが知れてる。というかこれキャッシュで頑張りたくないと思った。

## どう解決したか
キャッシュするという考え方を変えた。キャッシュするんじゃなくて、ある一定時間内に大量に視聴URLのリクエストが発生した時、それらのブラウザからのリクエストに対して、Vimeoへのリクエストを1回ですませるようにした。
今回の件でいうと、「動画視聴URLを取得したい」って事なんだけど、つまりエンドユーザーにはこのURLの取得を最大1秒間待ってもらう事として、1秒間以内に同じ動画に対して視聴URL取得のリクエストが発生したら、それらを全て1つのVimeo問い合わせで解決するようにした。
なおかつ、、Vimeoへの問い合わせは非同期処理になるので、その非同期処理中にさらに同じ動画に対するリクエストを検知した時も、すでにリクエスト中の非同期処理の待機中のキューにぶらさげるようにした。
で、この仕組みを思いついた理由は下記パッケージをちょうどリリースしたばかりだったから。

## 使ったパッケージ
[async-combiner](https://www.npmjs.com/package/@dadajam4/async-combiner)

このパッケージ書いた理由は、とあるECサイトで、「月間カレンダー」なる、カレンダー日付毎の在庫状況を表示する機能を作る際、
バックエンドAPIに対して、表示中のカレンダー月毎の在庫量を取得しにいくんだけども、割とこの処理がバックエンドでは重めな処理になるので、ユーザーの元気な操作に対してロジックは遅延させる仕組みを共通化したいって思い始めて、、
ともするとフロントロジック内において、ほぼ同時的に同じ条件のリクエスト（＝きっと結果的に同じレスポンスになる）を行っている箇所が多数見られたので、
じゃあ、それを末端の機能で改善するんじゃなく、一つのライブラリでなるべくエレガントに吸収したいなと思った。
たとえば、今はaxiosを通信の仕組みによく使っているけど、これいつまで使うかわかんないので、できるだけここのユーティリティーだけは薄く個別に作っておきたい。

で、今回の件ではこのパッケージを導入して、以下のようなコード変更だけでいけた。

```ts
// before
class SomeController {
  @Get('/{room}/playback')
  async getPlaybackUrl(room: string) {
    const urlInfo = await getPlaybackUrl(room);
    if (urlInfo.playbackUrl) {
      this.setStatus(302);
      this.setHeader('location', urlInfo.playbackUrl);
    } else {
      this.setStatus(404);
    }
  }
}

// after
import { Combine } from '@dadajam4/async-combiner';

class SomeController {
  @Get('/{room}/playback')
  getPlaybackUrl(room: string) {
    return this._getPlaybackUrl(room);
  }

  @Combine({
    /**
     * APIの呼び出し回数上限をシステム側で緩和したいので、クライアントからのリクエストが必ず1秒遅延させる
     * その1秒間の間に複数リクエスト飛んできた時は全て1つのプロセスでさばく
     */
    delay: 1000,
  })
  private async _getPlaybackUrl(room: string) {
    const urlInfo = await getPlaybackUrl(room);
    if (urlInfo.playbackUrl) {
      this.setStatus(302);
      this.setHeader('location', urlInfo.playbackUrl);
    } else {
      this.setStatus(404);
    }
  }
}

```

やった事は実メソッドから、処理ロジックを別メソッドに分離して、`Combine` デコレータつけて条件を指定しただけ。コードの変更はこれ以外なし。

このパッケージ内部的に何やっているかというと、

1. メソッド実行を検知した際に、引数の情報を「リクエスト条件オブジェクト」としてパースして保持する（ある程度自由な引数でも良いけど、クラスやFunctionなどjsonとして処理しきれない引数情報には対応できない）
2. delay設定がされている場合、実処理（↑の例の場合 `_getPlaybackUrl` ）の実行を遅延する。
3. (1)の結果が確定するまでの間に同じ引数条件の後続リクエストを検知したら待機キューにのっける
4. (1)の結果がでたら全ての待機キューに結果を応答する

このパッケージはNodeJS＆ブラウザ双方で動作するんだけども、特にNode環境でもこの仕組みがマッチしたのは、NodeJSがシングルスレッドで多くのリクエストをさばくアーキだからっていう理由もある。逆にこのNodeJSプロセスを冗長化して複数インスタンスになった時は、このパッケージはそこまではカバーしない。
それでも個々のインスタンスは利用ユーザーが増えればそれに比例して多くのリクエストをさばく事になるので、このやりくちは多いにあるなと思った。
リクエスト毎にインスタンスを作るような言語体型とかでも、状態だけはどこかシングルに持つようにすれば同じやりかたはできるはず。（I/Oのオーバーヘッド考えるの難しいかもだけど）

## さいごに
業務の中で「あ、これいるな」って思うちょっとややこい機能をnpmなりなんなりパッケージとして小出しにリリースするようにしておくと、ちゃんと身を救ってくれるなと思いました。
Redmine User一覧をDataFrameで取得

クラスの一部分ですが切り出して記載。
コメント、、、ちゃんと書く（TODO）

Resourceからの情報取り出しがちょっと特殊な感じなので
ここに書いておく。

もっといい方法がありましたら教えてください。


```python

    ########################################################    
    # ユーザID一覧作成
    ########################################################
    def getAllRedmineUsers(self):
        '''


        Args:

        Returns:
           df: DataFrame  Redmine登録全ユーザを格納したDataFrame

        Raises:
            TypeError: 引数型の不備
            Exception: ID登録時の例外

        Examples:
            >>> df = self.getAllRedmineUsers() 

        Note:
            あまりこまごまとした入力チェックをやっていませんので
            利用の際には慎重に w

        '''


        # 登録処理
        print(f'ユーザID一覧を取得します')
        try:
            # ユーザ取得：API
            users = self.redmine.user.all()
        except Exception as e:
            print(f'ユーザ一覧取得に失敗しました')
            print(f'エラー詳細：{e}')
            print()
        else:
            # Resourceから情報取り出し
            _list = []
            for _ in users:
                _list.append(list(_))

            # 取り出した情報を加工
            ## ログインID、名前（first,last)、ID作成日、最終ログイン時間を抽出
            ## TODO 抽出時間(GMT）をJSTに変換する（ライブラリは会社に置いてある、それつかう）
            __list = []
            for i in range(len(_list)):
                __list.append([f'{_list[i][5][1]}',
                               f'{_list[i][7][1]} {_list[i][8][1]}',
                               f'{_list[i][10][1]}',
                               f'{_list[i][11][1]}'])

            # DataFrame化    
            df = pd.DataFrame(__list)
            df.columns = ['LoginID','Name', 'Created','LastLogin']
            return df
                                                                                            ```
JavaScript E6【基本文法】～Part 2～

#初めに
Part1に引き続き、JavaScriptの個人的に大事だと思った文法をまとめて行きます。
（前回の記事はこちら->https://qiita.com/m-yamashita613/items/0e28d4c033b9a11cd6d3）

#目次
###・アロー関数
###・コールバック関数

##アロー関数
アロー関数を使う事でE6以前よりも簡単に関数の定義が出来るようになった。

```javascript
const 関数名 = () => {
    // 関数を呼び出したときの処理
    // ...
    return 関数の返す値;
};
```

仮引き数の数や処理の量によっても省略出来る部分が変わる


```javascript
// 仮引数の数と定義
const  func = () => {}; //仮引数がないとき
const func = x => { };  //仮引数が1つのみのときは()を省略可能

// 値の返し方
const mulA = x => { return x * x; }; // ブロックの中でreturn
const mulB = x => x * x;            // 1行のみの場合はreturnとブロックを省略できる
```


##コールバック関数
関数はその場で作った匿名関数を関数の引数（値）として渡すことができる。 引数として渡される関数のことをコールバック関数と呼び、コールバック関数を引数として使う関数やメソッドのことを高階関数と呼ぶ。

```javascript
function 高階関数(コールバック関数) {
    コールバック関数();
}
```
たとえば、配列の`forEach`メソッドはコールバック関数を引数として受け取る高階関数である。 `forEach`メソッドは、配列の各要素に対してコールバック関数を一度ずつ呼び出す。

```javascript
const array = [1, 2, 3];
const output = (value) => {
    console.log(value);
};
array.forEach(output);
```
##参考記事
https://jsprimer.net/basic/function-declaration/
[Swift]クロージャ

#クロージャを理解しよう
クロージャは再利用可能なひとまとまりの処理です。
クロージャは、名前が不要であったり、型推論によって型の省略可能であったりと関数より手軽に定義ができます。
#定義方法
引数と戻り値の型は関数と同様です。

```swift
{(引数名:型)->戻り値の型 in
実行される文
必要に応じてreturn文
}
```
次の例では、Int型の引数を1つ受け取り2倍にして返すクロージャを定義しています.

```swift
let double={(x:Int)->Int in
    return x*2
}
double(2)//4
```
また、クロージャは変数や定数の型になったり、関数の引数の型として利用することも可能です。
（詳しくは後で説明します。）
#型推論
クロージャの引数と戻り値の型はクロージャの代入先の型から推論することによって、省略するケースがあります。

```swift
//型を省略しない時
let double_1={(x:Int)->Int in
    return x*2
}
//型を省略する時
let double_2={ x in
    return x*2
}
double_1(2)//4
double_2(2)//4
```
ここで、クロージャdouble_1とdouble_2はletで宣言しているため、クロージャを変更することはできません。
しかし、以下のようにvar(変数)を使って宣言すれば、クロージャを変更しても型を変えなければエラーにはなりません.
以下のdouble_1の型は、(Int)->Int型です

```swift
//varで宣言
var double_1={(x:Int)->Int in
    return x*2
}
//letで宣言
let double_2={(x)in
    return x*2
}
double_1={x in
    return 3
}
double_2={x in
    return 3
}//エラー
    
double_1(2)//3
print(type(of: double_1))//(Int)->Int
```
##クロージャの引数の特徴
外部引数名(外部から呼び出す時に、クロージャ内の引数と違う名前にすること)とデフォルト引数(クロージャを定義する時に、引数に値を代入すること)を使うことができません。
###簡略引数名
クロージャの型が推論できるケースでは、型を省略できることは前述しました。
なんと、引数名も省略することができます!!が、可読性が落ちるので、使い分けをしましょう。

```
//簡略引数名なし
let isEqual_1:(Int,Int)->Bool={(x,y) in
    return x==y
}
//簡略引数名あり
let isEqual_2:(Int,Int)->Bool={
    return $0==$1
}
isEqual_1(2,2)//True
isEqual_2(2,2)//True
```
#最後に引数としてのクロージャ
クロージャを関数や別のクロージャの引数として利用する場合の仕様として、属性とトレイリングクロージャがあります。
属性はクロージャの性質を追加する情報で、トレイリングクロージャは、クロージャを引数にとる関数の可読性を高めるための仕様です。
###属性
属性は２種類あります。
escaping属性とautoclosure属性があります。
今回はescaping属性だけを説明します。
####escaping属性
escaping属性は、関数の引数として渡されたクロージャを関数のスコープ外でも使用できることを表す属性です。
また、属性の前には@を追加します。

```swift
パターン1
var que=[()->Int]()
func number(operation: @escaping ()->Int){
     que.append(operation)
}
number(operation: {() in return 1})
number(operation: {() in return 2})

que[0]()//1
que[1]()//2


パターン2(簡略引数名)
var que=[()->Int]()
func number(operation: @escaping ()->Int){
     que.append(operation)
}
number(operation: { return 1})
number(operation: { return 2})

que[0]()//1
que[1]()//2


パターン3
var que=[()->Int]()
func number(operation: @escaping ()->Int){
     que.append(operation)
}
number{ return 1}
number{ return 2}

que[0]()//1
que[1]()//2


```
パターン1,2,3は同じ意味です。
number関数はqueの配列の中に()->Int型のクロージャを追加する関数です。
number{return 1}を実行するとque[0]に{ () in return 1}のクロージャを追加します。
次の,number{return 2}も同様に,que[1]に{() in return 2}を追加します。
また、上記のコードでescapingがないとエラーになります。
###トレイリングクロージャ
パターン3は、まさにトレイリングクロージャそのものです。
関数の引数の最後がクロージャであった場合に、関数を呼び出す時、()を省略することができます。
以下の下二つがトレイリングクロージャを利用したパターンになります。

```swift
func execute (param:Int,operation:(String)->Void){
    operation("パラメータは\(param)です。")
}
//トレイリングクロージャを利用しない場合
execute(param:1,operation: { string in print(string)})//パラメータは1です。

//トレイリングクロージャを利用する場合
execute(param:2){ string in print(string) }//パラメータは2です
execute(param:3){  return print($0) }//パラメータは3です
```
以上で、クロージャの説明を終わります。
Homebrew 使い方メモ

### 概要
Homebrew を使う時のコマンドなど

### Homebrew 本体の更新

```shell
brew update
```

### パッケージのインストール

```
brew install [package name]
```

cask

```shell
brew install --cask [package name]
```

### インストール済みパッケージの更新

全て更新

```shell
brew upgrade
```

パッケージを指定して更新

```shell
brew upgrade [package name]
```
見えないけど存在する、devise:controllers

#はじめに
昨日、deviseのコントローラー内で用いられている`super`について言及しました。本日は少しだけその続きです。

昨日の投稿↓
[deviseコントローラーで出逢ったsuperについて調べてみた](https://qiita.com/TerToEer_sho/items/d1fa31c35962f6ca72f7)

##deviseの元のコントローラーはどこだ？

```bash
% rails g devise:controller
```
上のコマンドでは、deviseの様々なコントローラーの継承元を生成することができませんでした。
次のコマンドで生成可能です。

```bash
% rails g devise:controllers [scope]
```

まぁ、わざわざ元のdeviseのコントローラーを生成しなくても、オーバーライドでメソッドをいじることができるのですが…

##終わりに

コマンドで出てきたスコープという概念、よくわかってない…
ファイルを生成させなくても処理が動くということがとても不思議。
Rspecコマンドが面倒だからRakeコマンド一発でRspecが実行できるようにしてみました

## 元々の状況・課題
Rubyで[チケット料金モデリング](https://github.com/j5ik2o/ticket-price-modeling)に挑戦中。
Rspecでテストを書いているが、ターミナルに毎回Rspecコマンドを入力するのが面倒になった。

## 目的
Rspecを簡単に実行したい。

## やったこと・結果
①[Rake](https://docs.ruby-lang.org/ja/latest/library/rake.html)というライブラリを使った。
②ターミナルにrakeコマンドを入力するだけで、全てのspecファイルが一括で実行できるようになった。
③楽になりました。

## Rakeとは（ざっくり）
Rakefileに実行したいことを書いて、Rakefileに書いた内容をrakeコマンドで簡単に実行できる。
ターミナルに長々とコマンドを打たなくても良くなる。

## ディレクトリ構成は、ざっくりですがこんな感じです。
```
├── lib
│   ├── user.rb
│   └── ticket.rb
│
├── spec
│   ├── user_spec.rb
│   └── ticket_spec.rb
│
│── Rakefile ※手順2で作成します。
```

## やったことの手順
### 1. rakeのインストール
```
gem install rake
```

### 2. Rakefileを作成し、Rakefileにコードを書く。
```Ruby:Rakefile
① require "rspec/core/rake_task"

##これでrakeコマンドのみで,③が実行できる。
② task :default => :spec

##rakeコマンドを実行した際に、rspecディレクトリ配下のファイルを自動でテストファイルとして認識し、テストを実行する。
③ RSpec::Core::RakeTask.new(:spec) 
```
（補足説明）
・[こちら](https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/rake_task.rb#L28-L28)にspecディレクトリ配下のファイルを指定している旨のコードがあります。
・③について、[こちら](https://go-journey.club/archives/7695#Rake_%E3%81%A8%E3%81%AF%EF%BC%9F)の記事が勉強になりました。
> 「::」は、「クラス」や「モジュール」や「メソッド」の呼出しです。
> または「::」は、名前解決をする際に入れ子（ネスト）環境下での場所を特定します。
> 単純に言うと、場所を特定します。（概念を分かりやすく説明するのは難しいです）
> 「RSpec」クラスを呼び出す場合　→　RSpec 
> 「RSpec」クラスの中の「Core」クラス or モジュール or メソッドを呼び出す場合　→　RSpec::Core
> 「RSpec」モジュールの中の「Core」モジュールの中の「RakeTask」モジュールを呼び出す場合　→　RSpec::Core::RakeTask

### 3. rakeコマンドの実行
ターミナルで、rakeコマンドを実行すると、specディレクトリ配下の`**_spec.rb`が一括で実行されます。

```
rake
```

## 参考
- https://docs.ruby-lang.org/ja/latest/library/rake.html
- https://rubydoc.info/github/rspec/rspec-core/RSpec/Core/RakeTask
- https://msp-greg.github.io/rspec/RSpec/Core/RakeTask.html
- https://github.com/rspec/rspec-core/blob/main/lib/rspec/core/rake_task.rb#L28-L28
- https://qiita.com/hikao/items/36d514cc4e6349bb40cd
- https://go-journey.club/archives/7695#Rake_%E3%81%A8%E3%81%AF%EF%BC%9F
マイグレーションファイルをupの状態で削除してしまった場合の解決法

# はじめに
railsでアプリを作っていたところ、不要なテーブルをマイグレートしてしまい、そのマイグレーションファイルを手入力で削除してしまった。
マイグレーションファイルをupの状態で消してしまうと

```shell
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210116053731  ********** NO FILE **********
   up     20210118091408  Devise create users
```
このように NO FILEという表示になってしまい、同じファイルを作ろうと思ったら、
「そのファイル名はすでにあるよ！」と怒られてしまい、途方に暮れたので、忘備録としてメモ。

# 結論
結論からいうと、別のマイグレーションファイルを作って、そこにファイルを消すような指示を出す、ということ。
今回だと、まず、dbディレクトリの配下にMigration IDを持ったファイルを作る。
上の例ならば、
「20210116053731_sample.rb」
というファイルを作る。
そして、その状態で

```shell
rails db:migrate:status
```

とターミナルに打ち込むと

```shell
 Status   Migration ID    Migration Name
--------------------------------------------------
   up     20210116053731  Sample
  down    20210118091408  Devise create users
```
というようにファイル名が変わる。そして、その状態で

```shell
rails db:rollback
```

と打ち込むことで、マイグレーションファイルはdownの状態になる。

```shell
Status   Migration ID    Migration Name
--------------------------------------------------
  down    20210116053731  Sample
  down    20210118091408  Devise create users
```

そして、downになったことを確認したら、手動で先ほどのマイグレーションファイルを削除する。
そうすると、テーブルを消すことができる。

# まとめ
Migration　IDから新しくファイルを作って、そこから、マイグレートやロールバックをして削除する方法があったとはいろいろな方法がある物だと感心した。
90分ほど時間をとってしまったので、次は３分で解決できるな！
Ceph(Octopus)の構築(設定編 共通)

##__はじめに__
この記事では、タイトルのとおり現時点(2021.01)で最新である__ceph(octopus)__の構築を目的としています。
また、自分で構築した手順の備忘録を兼ねているので、細かいところで間違いなどあるかもしれません。

基本的には公式のDOCUMENTATIONが必要なことを全て網羅しているので一読しておくことをお勧めします。
Linuxの知識もある程度必要になるので他サイトや書籍などで事前に基本は押さえておくとよいでしょう。

##__関連記事__
[Ceph(Octopus)の構築(準備編 ハードウェア)](https://qiita.com/iriya_v00v/items/651eff2955d5ad7eadf6)
[Ceph(Octopus)の構築(準備編 ソフトウェア)](https://qiita.com/iriya_v00v/items/e3268fe75423ba0304b3)
Ceph(Octopus)の構築(設定編 共通)　この記事
[Ceph(Octopus)の構築(設定編 ブートストラップ)](https://qiita.com/iriya_v00v/items/d7bcf4dfa6324bacd91a)
[Ceph(Octopus)の構築(設定編 mon/mgr/osd)](https://qiita.com/iriya_v00v/items/75eefdefb7ec61d24812)
[Ceph(Octopus)の構築(設定編 cephFS/mds)](https://qiita.com/iriya_v00v/items/931838d6d56e568bd6d8)
[Ceph(Octopus)の構築(設定編 Crush Map)](https://qiita.com/iriya_v00v/items/2a263a7817434e8b91ed)

##__クラスタ構成__
15台のノードを3グループに分け構成します。各グループ毎にL2SWを用意し、L3SWで集約しました。詳細は以下のとおりです。
以降、この構成を前提に話を進めていきます。

|グループ|ホスト名|役割|
|:---:|:---:|:--:|
|0|ceph-mon01|mon/mgr/osd|
|0|ceph-mds01|mds/osd|
|0|ceph-osd01|mds(※)/osd|
|0|ceph-osd02|osd|
|0|ceph-osd03|osd|
|1|ceph-mon11|mon/mgr/osd|
|1|ceph-mds11|mds/osd|
|1|ceph-osd11|mds(※)/osd|
|1|ceph-osd12|osd|
|1|ceph-osd13|osd|
|2|ceph-mon21|mon/mgr/osd|
|2|ceph-mds21|mds/osd|
|2|ceph-osd21|mds(※)/osd|
|2|ceph-osd22|osd|
|2|ceph-osd23|osd|

※ mdsはceph-mdsXXをactiveとし、ceph-osdXXをstandbyとします。

##__OS準備__
OSのインストールについては私が説明するよりも他サイトを参考にされた方がよいと思うのでここでは省略します。今回は__CentOS7__を利用しました。
cephを動かすためにデスクトップ環境は不要なのでMinimalを使いました。

公式のDownloadから適当なミラーを選んでダウンロードしましょう。
[CentOS Project](https://www.centos.org/)

##__OS標準機能の設定__
#####時刻同期
chronyを使って時刻同期設定を行います。参照可能なサーバを指定します。
今回は各グループのceph-monXXが既設NTPサーバと同期し、それ以外のノードは各グループのmonノードと同期するようにしました。

```
vi /etc/chrony.conf
```

monノードの場合、以下を追加
>server [NTPサーバのIP] iburst
>allow [他ノードのネットワークセグメント]

monノード以外の場合、以下を追加
>server [monノードのIP] iburst

#####SSH
DNSを使う設定(デフォルト)の場合、名前で接続すると遅いことがあるので無効にします。

```
vi /etc/ssh/sshd_config
```

>UseDNS no

#####FW
万が一うまく動かなかったときの原因切り分けがめんどくさいのでFWは止めておきます。

```
systemctl stop firewalld
systemctl disable firewalld
```

#####SELinux
FWと同様の理由で無効化しておきます。

```
vi /etc/selinux/config
```

>SELINUX=disabled

#####hostsの編集
ノードとなるホスト名をhostsへ追記します。

```
vi /etc/hosts
```
>192.168.1.101 ceph-mon01
>192.168.1.102 ceph-mds01
>192.168.1.103 ceph-osd01
>・・・
>192.168.1.111 ceph-mon11
>・・・
>192.168.1.121 ceph-mon21
>・・・
>192.168.1.125 ceph-osd23


#####パッケージ更新
とりあえず最新版にアップデートしておきます。

```
yum -y update
```

##__追加機能の設定__
#####dockerの追加
octopusではコンテナソフトが必須なのでdockerをインストールしました。イメージのpullはブートストラップを実行したときとクラスタにノードを追加したときに自動的に実行されます。そのため、ここではパッケージのみ入れておけば大丈夫です。

```
yum -y install yum-utils device-mapper-persistent-data lvm2
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
yum -y install docker-ce docker-ce-cli containerd.io
systemctl start docker
systemctl enable docker
```

#####python3の追加
cephadmに必要だったような気がします。入れておかないと何か大事なコマンドが使えなかったはずです。(ごめんなさい忘れてしまいました。)

```
yum -y install python36
```

##__おわりに__
共通して全てのノードに必要な作業は以上です。
OSだけ先にインストールして、TeraTerm等で作業をすると効率的にできます。
hostsについては全ノードに同一のもの(15台記載)を設定する必要があるかどうかは不明です。
もしかしたら必要ないかもしれません。(monノードには恐らく必要だと思います。)

cephの個別設定については次の記事に投稿しようと思います。
【用語】PG初心者がまとめましたpart1

#はじめに
通りすがりのプログラミング初心者。
エンジニア専門用語について、まとめたので投稿しますわ😇

##目次
[変数](#変数)
[オブジェクト](#オブジェクト)
[オブジェクト指向](#オブジェクト指向)
[クラス](#クラス)
[インスタンス](#インスタンス)
[プロパティ](#プロパティ)
[メソッド](#メソッド)

##変数
名前をつけて一時的に数字や文字などのデータを記憶しておく箱。

##オブジェクト
現実世界に存在するあらゆる「もの」や「概念」のこと。
ex.「りんご」「Aくん」

##オブジェクト指向
制作プロジェクトにおいて重要な要素のひとつが、
「いかに整理された効率の良いプログラミング構成を作りあげていくのか」
↓
整理方法の一つである、<strong>オブジェクト指向</strong>と呼ばれるプログラミングの考え方。
オブジェクト指向の整理方法は、
<font color="DeepPink">「設計書を作っておく」のと「設計書をもとにモノを作り上げる」という工程</font>である。

##クラス
特定の関連性のある変数や関数、オブジェクトをまとめた抽象概念。
オブジェクト指向の最大級の設計書である。
ex.「3年B組」「男性」「運動部」
※クラスを作成＝クラスを定義

##インスタンス
設計書から実際にモノを作る（機能を使えるようにする）こと。
※クラスからインスタンスを生成。
 クラスを設計書とした場合、インスタンスはその実際の値であったり、データのこと。
※クラスもインスタンスもオブジェクトである。

##プロパティ
クラス内に用意した変数、定数。

##メソッド
クラス内に用意した関数。
処理をひとまとまりに部品化したもの、その手段。
★1　メソッドを作成＝メソッドを定義
　2　メソッドを使用＝メソッドを呼び出す
定義されたクラスから作成されるオブジェクト(レシーバーと呼ぶ)に対して行わせたい処理を記述するもの。

#まとめ
Rubyの場合の「クラス」「変数」「関数（メソッド）」。
![スクリーンショット 2021-01-19 23.19.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692507/fee6f518-a6a2-c647-5632-e13d50d79567.png)




#参考
・TechAcademyの「Webアプリケーションコース」から自分なりに解釈
　https://techacademy.jp


#おわりに
備忘録はどこまでも。続きます💨（多分）
Well-ArchitectedFrameworkの設計原則

## 記事の目的
・well-architectedFramework とは何かについて簡単に学ぶ
・well-architectedFrameworkTool とは何をする為のツールなのか簡単に学ぶ

## well-architectedFramework について
AWSの基本的な5つの設計原則。

|原則|概要|
|----|----|
|信頼性|可用性、回復力、信頼性の高いアーキテクチャの設計がされている。|
|パフォーマンス効率|コンピューティングリソースの効率的な使用に焦点を当てた設計が成されている。|
|セキュリティ|情報とシステムの保護(機密性と完全性)に焦点を当てた設計がされている。|
|コスト最適化|不要なコストの回避が出来ている設計がされている。|
|オペレーショナルエクセレンス|ビジネス価値を提供するためのシステムの実行とモニタリング、およびプロセスと手順の継続的な改善に焦点を当てた設計が出来ている。|


## well-architectedFrameworkを実現するための補助
・上記の設計原則はAWSの Well-architectedFrameworkホワイトペーパーに記載されている。
・AWSのSA、認定パートナーによるコンサル( well-architectedFrameworkを実現方法について )
・セルフチェック向けのwell-architectedTool( well-architectedFrameworkに沿った設計ができているか )

## 基本のアーキテクチャ設計
1つのリージョンで複数のAZに跨ってマルチAZをするのが基本中の基本

【マルチAZ構成】
VPC領域に複数のAZを跨らせてサブネットを確保してEC2インスタンス(サーバー)やDBなど構成していく、ELBを使用して冗長化(可用性、耐障害性、信頼性を高める)させていく。
※ELBとはトラフィック分散を行い可用性、耐障害性、信頼性を高める。自動でスケーリングするように設定も可能。
※スケーリングとはトラフィックの増加に伴って処理能力を増強する際に、単体の性能を向上(スケールアップ)させたり、稼働数を増やして処理を分散し、全体として処理能力を高める。(スケールアウト)
例)AZ1に10.0.1.0/24のサブネット確保、AZ2に10.0.2.0/24のサブネットを確保
=> 冗長構成を確立させる事で高い可用性を実現させる。

さらに可用性を高める為に。。。
【マルチリージョン構成】
route53を介して2つのリージョンに跨って同じ2つのシステム構成をフェイルオーバーすることが可能。
基本はマルチAZを採用して冗長化を図るがより可用性を高めたいときはマルチリージョン型も検討する。
もしくは別のリージョンにバックアップをとっておく。大きな地震や災害にも耐えられる。
Riverpodクラス整理メモ

Riverpod関連でクラスや関数が多すぎて訳がわからないので整理してみた。

## 整理方法
各パッケージのexportから主要なクラスや関数をピックアップした。

## riverpod
Riverpod本体。Dartだけで動く。

* StateNotifierProvider
* StateProvider
* FutureProvider
* StreamProvider
* AsyncValue

## flutter_riverpod
RiverpodにFlutter用のクラスを追加した物。

* ChangeNotifierProvider
* Consumer
* ConsumerWidget
* ProviderScope
* ProviderListener

## hooks_riverpod
FlutterRiverpodにHooksの関数を追加した物。
依存関係の最上位にあるので、このパッケージを入れることで、Riverpod、FlutterRiverpod、StateNotifier、FlutterHooksがインストールされる。

* useProvider

## state_notifier
Flutterデフォルトで入ってるValueNotifierをDart用に再実装したもの。  
状態管理用のクラス。

* StateNotifier

## flutter(default)
flutterデフォルトで入ってる状態管理用のクラス。

* ChangeNotifier
* ValueNotifier
【AWS】Amazon EFSとAmazonS3の違い

どちらもクラウドストレージ。

## Amazon S3

- HTTPSでアクセスできるエンドポイントを提供。
- バックアップ等で使うことが多い？

## Amazon EFS
- EC2等にマウントして使う。
- 複数サーバー間の共有ストレージとして使うことが多い？

## 結論
EC2にマウントして、ディレクトリの一部として使うならEFS、HTTPSでアクセスできるエンドポイントが欲しいならS3のように使い分けると良い（たぶん）

## 参考
https://www.acrovision.jp/service/aws/?p=2630
Golangでのゼロ埋め

# Golangでのゼロ埋め
0~9の場合は数字の前に0を付け、
10以上の場合は0を付けない場合は以下の様に実現できる

```
s := 3
str := fmt.Sprintf("%02d", s)
fmt.Println(str)
// 03

s2 := 13
str2 := fmt.Sprintf("%02d", s2)
fmt.Println(str2)
// 13
```
​
知らずに以下の様な回りくどい方法で実現したので知ったときは衝撃だった...

```
if num < 10 {
​
    numStr = "0" + strconv.Itoa(num)
​
} else {
​
    numStr = strconv.Itoa(num)
​
}
```
フレックスボックスのまとめ

自分の知識整理のため、Udemyの講座で解説されていたものをいろいろ試して自分用にまとめてみた。

Webデザイナーのキャリアを未経験からスタートするためのオールインワン講座
https://www.udemy.com/share/1026bmAEcZcllWTX0F/


# 用語
## フレックスコンテナ
`display:flex`と指定されたブロックのことで、これを親要素として扱う

## フレックスアイテム
フレックスコンテナの直下にあるブロック群で、これらの伸縮や配置を行う

## フレックスボックス
フレックスコンテナとフレックスボックスを合わせたレイアウトモデルの通称

## 主軸と交差軸
主軸は伸縮が出来る方向で`flex-direction`によって指定され、既定値は横方向
主軸に対して垂直になる軸を交差軸といい、こちらは配置調整はできるが、伸縮はできない


# フレックスボックス設定
## display : flex
自ブロックをフレックスコンテナとして指定し、内包直下の子ブロック群をフレックスアイテムに指定
CSSプロパティと配置プロパティの組み合わせでboxの位置を自動的に配置


# CSSプロパティ


## flex-direction`[親]`
フレックスコンテナの主軸（既定値は横軸）と方向（既定値は左→右）を指定する
`column`指定の時、`html,body{height:100%;`に指定しないと、画面全体に伸縮しないので注意

* `row`：横軸で→方向
* `row-reverse`：横軸で←方向
* `column`：縦軸で↓方向
* `column-reverse`：縦軸で↑方向

## flex-wrap `[親]`
ビューポートに合わせて、フレックスコンテナの折り返しの指定

* `nowrap`：折り返しなし
* `wrap`：折り返しあり
* `wrap-reverse`：上下反転した折り返しあり

`flex-grow：grow`とは両立しないが、`min-width`指定あればOK

## flex-flow`[親]`
`flex-direction`と`flex-wrap`を一括指定する

## flex-grow `[子]`
フレックスコンテナのサイズに応じて、フレックスアイテムの主軸方向への伸長係数を指定
既定値は`0`で、正の値のみ有効
コンテナサイズが広くなった時に、アイテムの幅をどういった割合で伸ばすかを指定できる
`max-width`で最大値を制限する

## flex-shrink `[子]`
フレックスコンテナのサイズに応じて、フレックスアイテムの主軸方向への収縮係数を指定
既定値は`0`で、正の値のみ有効
コンテナサイズが狭くなった時に、アイテムの幅をどういった割合で縮めるか指定できる
`min-width`で最小値を制限する

## flex-basis `[子]`
フレックスアイテムのコンテンツボックスの初期寸法を指定
あまり使わないほうがよさそう

## flex `[子]`
`flex-grow`、`flex-shrink`、`flex-basis`の3種類のCSSプロパティを指定する

## order `[子]`
コンテナアイテムの順番を指定し、既定値は`0`で整数（-も使える）のみ指定可能

# 配置プロパティ

## フレックスアイテムの横方向の配置
フレックスコンテナの主軸に対して、フレックスアイテムの間隔を指定する
`flex-grow`が指定すると効果がない

* 右寄せ：`justify-content: flex-end`
* 中寄せ：`justify-content: center`
* 左寄せ：`justify-content: flex-start`
* アイテム間均等：`justify-content: space-between`
* アイテム間均等+左右半均等：`justify-content: space-around`
* アイテム間均等+左右全均等：`justify-content: space-evenly `

## フレックスアイテムの縦方向の配置
フレックスコンテナの交差軸に対して、フレックスアイテムの配置を指定する
フレックスアイテムを個別に指定するには子要素に`align-self`を使用する

* 上寄せ：`align-items: flex-start`
* 中寄せ：`align-items: center`
* 下寄せ：`align-items: flex-end`


## フレックスアイテムの間隔を指定
フレックスアイテムの左右上下の間隔を指定する
`flex-grow`を指定すると効果がある

* 主軸の間隔：`row-gap:数値`
* 交差軸の間隔：`column-gap:数値`
* 両軸の間隔：`gap:主軸数値 交差軸数値`
mp3のタグ(ID3v1)をRubyで読み込む（ライブラリ不使用）


# ソースコード

```ruby:mp3tagID3V1read.rb

#!/usr/bin/ruby

if ARGV.size() == 0 then
  print "need an argument."
else
  if File.exist?(ARGV[0]) then
    stat = File.stat(ARGV[0])
    a = File.binread(ARGV[0], 128, stat.size-128)
    
    if (a[0..2]=="TAG") then
      title   = a[ 3..32].force_encoding("Shift_JIS").rstrip
      artist  = a[33..62].force_encoding("Shift_JIS").rstrip
      album   = a[63..92].force_encoding("Shift_JIS").rstrip
      yearStr = a[93..96].rstrip
      trackMark = a[125]
      genreNo = a[127]

      if trackMark == "\0" then
        # track info exists
        comment = a[97..124].force_encoding("Shift_JIS").rstrip
        trackNo = (a[126].bytes)[0].to_s
      else
        comment = a[97..126].force_encoding("Shift_JIS").rstrip
        trackNo = ""
      end

      print "track : <" + trackNo + ">\n"
      print "album : <" + album   + ">\n"
      print "artist: <" + artist  + ">\n"
      print "title : <" + title   + ">\n"
      print "year  : <" + yearStr + ">\n"
      print "comment: <" + comment +">\n"
    end
  end
end
```

※拡張子チェックとファイルサイズチェック入れ忘れた・・

# 所感

久々にRuby書いてみた。

`binread`で得られるデータの型が、配列ではなく、`ASCII-8BIT`エンコーディングの`string`っていうややこしさよ。
ただ、添え字の書きやすさ・見やすさがイイ。これに慣れると`Substring`とかで切り出すのダルくなりそう。

# 環境

OS : Windows 10
Ruby 2.6.5 (C:\Ruby26-x64\bin\ruby.exe)


# 参考
 - [IO.binread (Ruby 3.0.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/IO/s/binread.html)
 - [String#force_encoding (Ruby 3.0.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/String/i/force_encoding.html)
 - [String#bytes (Ruby 3.0.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/latest/method/String/i/bytes.html)
 - [mp3のタグ(ID3v1, ID3v2)を読み込む（ライブラリ不使用） - Qiita](https://qiita.com/kob58im/items/681dc2262f791f64abdc)
>テストコード時のターミナルエラーについて

#問題
users_spec.rbにコードを記述し、
bundle exec rspec spec/system/users_spec.rb
をこなったところ、
Failure/Error: <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
     
     ActionView::Template::Error:
       Invalid CSS after "}": expected "}", was ""
とエラーが表示されました。

□仮説と検証
コードのミスか？
→users_spec.rbのコードは遡って、vs　コード内でcompareをかけたため正しいと思われる。

application.cssの間違いか？
Invalid CSSとあるので、application.cssのコードを確認
→特に問題はないと考えられる。



users_spec.rbのコード

```
require 'rails_helper'

RSpec.describe "ユーザーログイン機能", type: :system do
  it 'ログインしていない状態でトップページにアクセスした場合、サインインページに移動する' do
    # トップページに遷移する
    visit root_path

    # ログインしていない場合、サインインページに遷移していることを確認する
    expect(current_path).to eq new_user_session_path
  end
end
```


ターミナルのスクショ
https://gyazo.com/7eef8973d87de86f2d1ec4a69ba6e5a7

CSSのスクショ
https://gyazo.com/33aae2ea9a1f122d17f0d5e8c0b1219d

#結果

CSSのコーディングミスである仮説は正しかった。
/Users/taniguroarata/projects/chat-app/app/assets/stylesheets/room.css
の最後に　}　を明示し忘れたためエラーとなってしましった。
 Invalid CSS after "}": expected "}", was ""
とターミナル内にヒントがあるため、ヒントを辿るとエラーを解決できることを学んだ。

room.cssのスクショ
https://gyazo.com/f0e9e121985e9c8b32c1ce754d0468b7
Goでスライス内の最大値・最小値を抽出する関数

## はじめに
Goでコードを書いているとスライス内の最大値、もしくは最小値を算出する処理を
何度か利用したので忘れないためにもメモ  

### スライス内の最大値を取得
```
func maxInt(a []int) int {
    sort.Sort(sort.IntSlice(a))
    return a[len(a)-1]
}
```

### スライス内の最小値を取得

```
func minInt(a []int) int {
    sort.Sort(sort.IntSlice(a))
    return a[0]
}
```

### サンプルコード

以下コードを[The Go Playground](https://play.golang.org/)でコピペして実行

```
package main
import "fmt"
import "sort"

func main() {
	test := []int{7, 8 ,1, 4, 3, 21}

	fmt.Println("max:", maxInt(test))
	fmt.Println("min:", minInt(test))
}


func maxInt(slice []int) int {
    sort.Sort(sort.IntSlice(slice))
    return slice[len(slice)-1]
}


func minInt(slice []int) int {
    sort.Sort(sort.IntSlice(slice))
    return slice[0]
}
```

## 参考
- https://teratail.com/questions/147628
【Ruby】each_with_indexなどの添字付きの繰り返し処理を初心者向け解説！

皆さん添字付きの繰り返し処理はご存知でしょうか？

添字付きの繰り返し処理とは、each_with_indexメソッドやwith_indexメソッドのことです。

これらを使うことで、人間にわかりやすく配列を表現したりするなど、情報の使い方にレパートリーが増えるので、是非理解してみてください！

## each_with_indexを解説！

each_with_indexとは、配列の要素に添字をいれることのできるメソッドです。

とは言っても、これだとわかりにくいので、コードを確認してみましょう。

```ruby
fruits = ['orange', 'apple', 'melon']

 # 下のブロックの引数のiには0,1,2...と要素の添字が入る

fruits.each_with_index {|fruit, i| puts "#{i}: #{fruits}"}

#=> 0: apple
#   1: orange
#   2: melon
```

まず、fruitsという変数に配列を渡します。

そして、fruitsにeach_with_indexメソッドを使用し、doとendを省略したブロックを定義します。

それを出力すると、各要素に定義した通り添字が入るという流れです。

putsブロック内のputs以降をうまく定義してあげることで、人間にわかりやすい内容を出力することができます。


## いろんな組み合わせができるwith_indexを解説！

実は、each_with_indexメソッドのような方法以外にも、配列の要素に添字をつけることができる方法があります。

それはwith_indexメソッドです。

このメソッドはeach以外に、mapやdelete_ifなどのメソッドに適用することができます。そして、それらのメソッドを使用する際に添字をつけることができます。

使用する方法はeach_with_indexとほとんど変わりません。

```ruby
fruits = ['orange', 'apple', 'melon']

fruits.delete_if.with_index {|fruits, i| fruit.include?('a') && i.odd?}

#=> ["apple", "melon"]
```

このように、delete_ifなどのメソッドにwith_indexメソッドを使用するだけです。

## まとめ

どうでしたでしょうか。

このようなメソッドも使うこともあるかもしれないので、知っておくと便利かもしれません。

これからも1日1記事を目標に、初心者に向けて基本的な知識を記事にしていくので、よろしくお願いします。
【Laravel6】セッションの値が多重連想配列の時に特定のkeyに対応するvalueを更新する方法

## はじめに

あまりググっても出てこなかった方法なので、残しておきます。
この選択肢があればセッションの扱える幅が広がると思います。

## 対象のセッション（仮）

例えば

```php
//セッションからkeyが'cartData'の値を取得
$request->session()->get('cartData');
```

これで取得した値が以下の場合を想定する

```php
[
    [0] => [
        'item_name' => 'ジャケット',
        'item_count' => 1,
    ],
    [1] => [
        'item_name' => '靴下',
        'item_count' => 3,
    ],
    [2] => [
        'item_name' => 'バッグ',
        'item_count' => 2,
    ],
]
```
## 実現したいこと
靴下の個数を3 → 5個にしたい！

## セッションの特定のkeyに対応するvalueを更新する方法

以下のコードで更新できる

```php
$request->session()->put('cartData.1.item_count', 5);
```

`->put()`の第１引数に連想配列の階層を文字列連結することで特定のkeyのvalueにアクセスすることができる。

※`config()`と同じ感じですね

## さいごに

ドキュメントにも明確には記載されていなかった...

[Laravel 6.x HTTPセッション
](https://readouble.com/laravel/6.x/ja/session.html)
zabbix-agent をroot権限で起動する方法 

##0.記事の経緯
絶対忘れるため、メモ用。
勿体無いついでに公開

##1.Zabbixとは
ZabbixとはOSSで利用できる監視ソフトウェアのこと。
監視ソフトウェアの中でも、自由度が非常に高く無料で利用できるため、人気が高い。
無駄にオプション料金をとる商用ソフトウェアと比較して、かなり安価に高度な監視を組み込むことができるが、自由度の高さを引き換えに、異常に構築が面倒。


##2. Zabbixで監視できること
Zabbixでは以下の監視が可能


- 死活監視(ICMP監視)
- ステータス監視
- ログ監視
- 閾値監視
- サービス監視（プロセス監視）



なお、上記の監視にアクション、スクリプト 実行、メール通知などが可能
正直いくらでも拡張ができるため、アプリケーション層の内部的な処理についても監視可能(だと思う...)
そもそもZabbix-agentが優秀なので、上記のインフラの基本的な監視は問題なくできる。

##3.優秀とはいえども、困るものは困る
最近・・・とはいえないが、Zabbix5.0になった。しかし、日本語版の情報は 2.2くらいで止まっている。
有志による掲示板や、フォーラムがあるので、なんとかなっているが、実際は5.0くらいになるとほぼ日本語の情報がない。
今関わっている案件では５.0だったので、古い情報があてにならなかったところが多い。
そういった状況だったので、古い情報だけでは苦戦も多く、タイトル通りrootでagentを実行しようとしたが、2.2や3.0の情報だけでは、実行ができなかった。

##4.rootで実行する理由
そもそもrootでagentを実行する必要があるのか、という点だけど、ログ監視をする場合、経験上linuxでは大概syslogの監視組み込む場合が多いが、syslogは基本的にはrootでしか読み取ることができない。
また、アプリケーションのログの中にはrootや特定のサービスアカウントでしか読み取りできないログも存在する。(ほぼ権限変更できると思うが・・・)
いずれにしもrootで実行する方法は理解しておくと便利。セキュリティ上は危険だけど。。。

##5.設定方法

###使用している環境
- ZabbixServer OS:CentOS8
- Zabbix-Server:5.0.4
- ZabbixAgent OS:CentOS7
- Zabbix-agent:5.0.4



Zabbix-agentをインストールしたサーバから`/etc/zabbix/zabbix-agentd.conf`をviで以下のように編集する

```
#AllowRoot=0
#↓追記
AllowRoot=1　
``` 

上記はrootで実行を許可しているだけなので、実際にrootで実行する設定をサービスファイルに書き込む必要がある。
zabbix-agentd.conf設定完了後は`/usr/lib/systemd/system/zabbix-agent.service`をviで
修正する。

```
#User=zabbixを修正
User=root
#Group=zabbixを修正
Group=root
```

設定後、以下を実行

```
systemctl daemon-reload
systemctl restart zabbix-agent
```

完了後は`ps -ef |grep "zabbix_agent"`を実行し、rootで起動されていること確認する。

これだけで、zabbix-agentはrootで起動する。
あとはsyslogの権限周りのこともあるが、ログ監視となるため、別記事に記載しようと思う
(調べれば出てくるので、不要かな。。。)
wordpress を使ってエンジニアポートフォリオ作成

## Wordpressを使ってエンジニアポートフォリオを作成
以下のサイトからテーマを取得
https://webdesign-trends.net/entry/11500
DEMOサイト
https://demos.pixelgrade.com/noah-lite/about/

## Topページの作成
SmartSlider3

## メニューバー

## Slider

## 問い合わせフォームを作成
https://www.xserver.ne.jp/blog/contact-form/

## 多言語対応
https://ja.wordpress.org/plugins/weglot/?gclid=CjwKCAiAo5qABhBdEiwAOtGmbhv7AwSPbXWsVbRTu9C0Jth2fIqxddAQRHou0x1n1e8jg_Knzfye-BoCsBkQAvD_BwE

## SEO対策
ポートフォリオでは特にSEO対策する予定はないが
今後ブログ作成など行うので書く予定


## まとめ
作成完了したらまたいろいろ書く
Gitのプッシュ時に終了コード１が出た時の対処法

Gitでプッシュした時たまに終了コード1が出てしまうというのはあるあるだと思います。

調べてみるとGitのバージョンを上げないとエラーは解消されないらしいのですが、pullしたあとにコミット&pushすればエラーは解決します。

エラーの原因は恐らくリモートとローカルで登録された内容に差分が生じてるからだと思われます。
複数人で作業していると色んな人がリモートにプッシュするので、ローカルとリモートで登録されている内容に違いが生じやすいんでしょうね。

しばらく経つとプッシュしたフォルダにエラーが出ていて「あれ？コミットしたのに何故？」となりますが、これは他の人がリモートリポジトリにプッシュしたことによる差分が原因なので、またpullしてcomit＆pushすれば解決します。

余談ですが、pullしてcomit＆pushするとBitBucketだと何故かmergedと表示されます、これはpullした差分を表しているので安心して大丈夫です。
Expo.ioでの回転(Orientation)の扱いについて

# Expo.ioでの回転系処理

Expo.ioでの回転の扱いは下記docを参考にすると良いです

https://docs.expo.io/versions/latest/sdk/screen-orientation/

## インストール

```
expo install expo-screen-orientation
```

## 使い方

インポートする

```typescript
import * as ScreenOrientation from 'expo-screen-orientation';
```

### 回転のロック

画面の向きをロックしたければ、 `ScreenOrientation.lockAsync` を使えば良いです。

```typescript
async function lockScreenOrientation() {
  await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.PORTRAIT_UP);
}
lockScreenOrientation();
```

Function Componentなのであれば、`useEffect` 内に書いておけばOK

ただし、画面が遷移されてもロックされてしまうので、ロックされるのが好ましくない画面では、unlockする処理を書いておく必要があります。
`ScreenOrientation.unlockAsync` でOKです。

```typescript
async function unlockOrientation() {
  await ScreenOrientation.unlockAsync();
}
unlockOrientation();
```

### イベントリスナ

回転されたときになにがしかのイベントを発火させたい場合は `addOrientationChangeListener` を利用すればいいです。

```typescript
const onChangeOrientation = (event: ScreenOrientation.OrientationChangeEvent) => {
  // 回転されたときの処理
}
ScreenOrientation.addOrientationChangeListener(onChangeOrientation);
```

ちなみに `event: ScreenOrientation.OrientationChangeEvent` の中身は

```
Object {
  "orientationInfo": Object {
    "horizontalSizeClass": 1,
    "orientation": 1,
    "verticalSizeClass": 2,
  },
  "orientationLock": 3,
}
```
とかです。

ただし、`verticalSizeClass ` と `horizontalSizeClass` はiOS Onlyです。

`orientationInfo.orientation` は 1なら縦(`Orientation.PORTRAIT`)。3は右に回転させた状態(`Orientation.LANDSCAPE_LEFT`)、4は左回転(`Orientation.LANDSCAPE_RIGHT`)です。

```typescript
export declare enum Orientation {
    UNKNOWN = 0,
    PORTRAIT_UP = 1,
    PORTRAIT_DOWN = 2,
    LANDSCAPE_LEFT = 3,
    LANDSCAPE_RIGHT = 4
}
```

`orientationLock` も同様に下記のように定義されています。

```typescript
export declare enum OrientationLock {
    DEFAULT = 0,
    ALL = 1,
    PORTRAIT = 2,
    PORTRAIT_UP = 3,
    PORTRAIT_DOWN = 4,
    LANDSCAPE = 5,
    LANDSCAPE_LEFT = 6,
    LANDSCAPE_RIGHT = 7,
    OTHER = 8,
    UNKNOWN = 9
}
```

`verticalSizeClass ` と `horizontalSizeClass` は `SizeClassIOS`として下記の定義です

```typescript
export declare enum SizeClassIOS {
    REGULAR = 0,
    COMPACT = 1,
    UNKNOWN = 2
}
```

ちなみにサイズクラスについては下記記事が参考になります。

https://developer.apple.com/library/archive/featuredarticles/ViewControllerPGforiPhoneOS/TheAdaptiveModel.html

よきExpoライフを。
量子コンピューターにおけるエルミート行列の期待値測定について

# エルミート行列の期待値測定
量子コンピューターにおいて、状態$|\psi \rangleにおける$エルミート行列$H$の期待値$\langle \psi | H | \psi \rangle$の測定について、
以下のような説明をよく目にします。特にVQE等の文脈で。

*$H$はエルミートなので、量子ゲートコンピューター上ではそのままゲート操作として実装できない。
そこで$H$をパウリ行列$X,Y,Z,I$の直積($\otimes$)の線形結合で表す。
するとパウリ行列$X,Y,Z,I$の直積たち(例えば$X \otimes Y$)はユニタリ行列であるので、量子ゲート上に実装できる。
よって量子ゲートコンピューターでそれぞれ期待値が計算できる。
あとは期待値の線形性から、それらの和を取れば元の$H$に対する期待値が復元できる。*

**Kumaの理解としては、この文章は間違いとまでは言えないが、少し誤解を招くのではないかと思います。**
これを説明するのが今回の記事です。

# どこが危ういか？

下記に注目します。

*するとパウリ行列$X,Y,Z,I$の直積たち(例えば$X \otimes Y$)はユニタリ行列であるので、量子ゲート上に実装できる。
よって量子ゲートコンピューターでそれぞれ期待値が計算できる。*


この、「量子ゲートとして実現できれば、そのゲートの期待値が計算できる」という部分は、実は自明では有りません。
量子ゲート操作$U$を考えます。状態を$|\psi \rangle$としたとき、
「$\psi \rangle$に$U$を作用させた後に期待値を計算すれば、$\langle \psi | U | \psi \rangle$が得られるのではないか？」と思いがちです。
これは違います。
なぜならば、得られるのは $\langle \psi | U^{\dagger} U | \psi \rangle$ = $\langle \psi | \psi \rangle = 1$ であって$\langle \psi | U | \psi \rangle$ではありません。
しかし計算する方法はあります。それがアダマールテストという量子アルゴリズムです。
**アダマールテストを使うことで、**$U$の期待値の実部を計算できます。ちょっとした工夫で虚部も計算できます。
これで$U$の期待値が求まります。

**しかしアダマールテストは通常VQEアルゴリズムでは使われないと思います。[^1]**
アダマールテストでは$U$の制御演算を使わなければならないので、避けたいのだと思います。

ではどうやって期待値を計算しているかというと、座標変換による対角化を利用しています。

# 座標変換による対角化と期待値計算

座標変換による対角化と期待値計算の方法は以下のQiita記事が大変わかりやすいと思います。

[VQE/QAOAの期待値測定の部分を学ぶ](https://qiita.com/gyu-don/items/efbd66c691981d7185c5)

まず、任意のエルミート行列$H$は、（パウリ行列積たちが正規直交基底を成すことから）パウリ行列積の線形結合で書けます。
期待値の線形性から、各パウリ行列積の期待値を計算すればよいことになります。
例えば$X$の期待値$\langle \psi | X | \psi \rangle$を計算したいとします。
このとき、対角化 $X=H^{\dagger}ZH$ を使います。ここでの$H$はアダマールゲートです。
期待値を測定したい状態$| \psi \rangle$に対して、事前に$H$ゲートを掛けます。状態は$H | \psi \rangle$となります。
そのうえで$Z$期待値を計算します。

$\langle \psi | H^{\dagger} Z H | \psi \rangle$

となります。$X=H^{\dagger}ZH$ だったので、これは$\langle \psi | X | \psi \rangle$に等しいです。

これは、基底を$Z$から($H$ゲートの作用によって)$X$が対角化される座標系へ座標変換し、その上で対角行列の期待値計算をしていることになります。
対角行列の期待値計算が簡単なことを利用しています。

上記の方法で、任意のエルミート行列の期待値が(対角化を経由して)計算できます。
パウリ行列の場合、座標変換のゲート（これは必ずユニタリです。エルミート行列は常にユニタリで対角化できるため）が
比較的に簡単な形をするので、パウリ行列積に分解してからやったほうが楽というわけです。
**これは、パウリ行列が（エルミートかつ）ユニタリであることとは直接関係ありません。**
**ユニタリだから期待値計算が出来たのではなく、対角化するための座標変換用ゲートが容易に実装できる形だから期待値計算ができたのです。**

いじわるな例として、ユニタリ行列$XY$を考えます。（直積ではなく、1量子ビットに作用するゲートです)
**これはユニタリ行列なので「期待値が計算できる」はずですが、アダマールテスト無しで期待値計算することは難しいと思います。
$XY$ゲートを実装したところで、求まるのは
$\langle \psi | U^{\dagger} U | \psi \rangle$ = $\langle \psi | \psi \rangle = 1$ であって$\langle \psi | U | \psi \rangle$ではありません。**


# 結論
VQE等の、通常アダマールテストを前提としないアルゴリズムにおいて、
「ユニタリ行列ならゲート実現できるから、期待値計算が出来る」
という文言には注意が必要。

[^1]: 認識が間違っているとしたら、ここかもしれない。
意外と知られていない。SpringBoot のもう一つのPlatformTransactionManager

意外と知られていない。SpringBoot のもう一つのPlatformTransactionManager
それは：org.springframework.data.transaction.ChainedTransactionManager　です。

使用するイメージ

```java
    @Bean(name = "chainedTransactionManager")
    public ChainedTransactionManager transactionManager(@Qualifier("primaryDs") PlatformTransactionManager ds1,
                                                    @Qualifier("secondaryDs") PlatformTransactionManager ds2) {
         return new ChainedTransactionManager(ds1, ds2);
    }
```

```java
@Transactional(value="chainedTransactionManager")
public void updateDb01() {
    Entity01 entity01 = repository01.findOne(1234);
    entity01.setName("Name");
    repository01.save(entity01);

    //Calling method to update DB02
    updateDb02();
}

public void updateDb02() {
    Entity02 entity02 = repository02.findOne(1234);
    entity02.setName("Name");
    repository02.save(entity02);

    //Added this to force a roll back for testing
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
```

要するに、DS1とDS2を同時にコミット/ロールバックできることです。
DS1 -> insert -> OK
DS2 -> update -> OK
DS1,DS2 -> commit

DS1 -> insert -> OK
DS2 -> update -> NG
DS1,DS2 -> rollback

参考サイト
https://www.it-swarm-ja.tech/ja/spring/%E8%A4%87%E6%95%B0%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BD%E3%83%BC%E3%82%B9%E3%81%AB%E3%81%BE%E3%81%9F%E3%81%8C%E3%82%8B%E3%83%88%E3%83%A9%E3%83%B3%E3%82%B6%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E4%BC%B4%E3%81%86spring-transactional/837725347/
[OutSystems]Architecture Specializationのサンプル問題についてメモ 2/2

最近、新しく追加された試験「Architecture Specialization」のサンプル問題が公開されています。

各問題を確認し、回答に必要な資料へのリンクと解説をまとめます。

全部で10問で、この記事では6問目-10問目が対象。

[1問目-5問目](https://qiita.com/jyunji_watanabe/items/c503f8a1ef128b3f5cdb)

試験問題は、
https://www.outsystems.com/learn/certifications/
の、「Architecture Specialist (OutSystems 11)」項目のリンク「Exam Details (.pdf)」でダウンロードできる資料から。

# 6 命名規則の重要性
[モジュールの命名](https://www.outsystems.com/ja-jp/training/lesson/1223/module-naming)のスライド「命名規則のメリット」が問題そのもの。

> - 各モジュールや要素の性質を明確にできる
- 参照アーキテクチャを適用できる
- パターンを正規化できる

つまり、選択肢のすべてが正しいので、Dが正解。

# 7 Discovery
Forgeに[Discovery](https://www.outsystems.com/forge/component-overview/409/discovery)というツールがあり、アーキテクチャの検証（ルール違反の検出）を支援してくれます。

この問題は、このDiscoveryの診断結果から、アーキテクチャ上の問題点を読み取るものです。

このツールについては、以下の動画の後半で解説されています。日本語字幕が利用可能であり、更に教材も日本語化されています。
[アーキテクチャの検証](https://www.outsystems.com/ja-jp/training/lesson/1228/validating-an-architecture)

Discoveryで発見できるアーキテクチャ上の問題点は以下の3種類（スクリーンショットはツールのヘルプから）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/b60f0322-e660-12d8-7268-a40277639670.png)

これは、[4 3つの検証ルール](https://qiita.com/jyunji_watanabe/items/c503f8a1ef128b3f5cdb#4-3%E3%81%A4%E3%81%AE%E6%A4%9C%E8%A8%BC%E3%83%AB%E3%83%BC%E3%83%AB)で書いた検証ルールそのものですね。

というわけで画像を見ると、

- End-userレイヤーで循環参照が1つ、横参照がたくさん
- Coreレイヤーで上方参照と循環参照がそれぞれ複数
- Foundationレイヤーで循環参照が2つ

検出されています。
合致する選択肢は、最初の問題点End-userレイヤーで横参照がたくさん検出されている　→　つまりEnd-userレイヤーなのに再利用されているshared serviceがあることを示すC。

# 8 要素の他モジュールへの移動
問題は「要素を別のモジュールに移動させる時、注意を要するものはどれか」というもの。

[Refactoring an Application](https://www.outsystems.com/training/lesson/1229/refactoring-an-application?LearningPathId=8)で例の説明があります。ここは教材には記載がないので動画の字幕で見る必要があります。

> 一例は、エンティティをモジュール間で移動する場合です。あるエンティティをモジュールから取り除き、別のモジュールへ貼り付けるか、そこで作成すると現在からのデータベース内で新たなテーブルが作成されます

選択肢を見てみると、この例通りのものがあります。データ永続化を含む要素（Entityなど）が論理的な定義を移動するだけで、別のテーブルを作成することになるから、としているBが正解。

# 9 複数レイヤーのフレームワークがアーキテクチャ設計に重要な理由
恐らく、[アーキテクチャの重要性](https://www.outsystems.com/ja-jp/training/lesson/1218/why-is-architecture-important?LearningPathId=8)の教材にあるスライド「アーキテクチャの一般的な問題」が参考になる。挙げられている問題点の解決のためにArchitecture Canvasというツールがあるはずなので。

> 1. サービスが適切に抽象化されていない
2. 依存関係が管理できていない
3. レガシーシステムの更新が低速で柔軟性がない

1が選択肢A、2がB、3がCに対応していそうです。
よって全て正しいとするDが正解。

# 10 スタイルガイド
アプリケーションに共通する見た目を提供するためのモジュールをスタイルガイドと呼びます。
いくつかの標準のスタイルガイドが提供されていますが、問題は、どのようなときにカスタムのスタイルガイドを作成すべきか、というもの。

カスタムのスタイルガイドについては、以下の動画で解説されています。

[カスタムスタイルガイドのアーキテクチャ](https://www.outsystems.com/ja-jp/training/lesson/1236/custom-style-guide-architectures?LearningPathId=8)

動画の教材中の「カスタムスタイルガイドのアプローチ」スライドにスタイルガイドを、どのようにプロジェクトの要求に合わせて用意するか、4つのアプローチが挙げられています。

> 1. 基本となるスタイルガイドを使用する（基本となるテンプレートアプリから）
2. 基本となるスタイルガイドを加工する
3. 基本となるスタイルガイドをカスタマイズする
4. 「一から」作成する

カスタマイズしない選択肢があることから、「常に」としている選択肢Dは×。
また、「アプリケーションがデプロイの独立性と他アプリとの低レベルでの相互依存を必要とする場合に」としている選択肢Cはスタイルガイドで解決しようとする問題「共通の見た目の提供」からずれるので×。

残った選択肢AとBは、既存テーマで要求を満たせない場合にカスタムスタイルガイドを利用するという点では共通。
A：カスタムスタイルガイドを「最も複雑な既存テンプレートをクローンして」作る
B：カスタムスタイルガイドを「最も基本的なテンプレートから」作り始める
という点が違っています。

ただ、ちょっとこれは微妙ですね。
クローンするテンプレートを変更することで要求を実現できるならAで正解だし、既存テンプレートでは全く要求を満たさない場合は、Bを取るべき。

答えはBとされています。
仮説としては、Aは「最も複雑な」としていて、「要求に適した」テンプレートではない点が問題なのかもしれません。
谷藤賢一『いきなりはじめるPHPワクワク・ドキドキの入門教室』でPHPを勉強してみた(2)

以下の内容を学習。
chapter3-9　アンケート項目を増やそう！
chapter3-10　前ページに戻る機能をつけよう！
chapter3-11　入力データを消さないでページを戻る方法！

【やらかしたミス】
入力フォームに文字を記載して送信しても、ブラウザにプログラムが表示された。

【原因】
ファイル「index.html」をダブルクリックしたせい。アドレスバーに「http://localhost/phpkiso/～」を入力すればいい。
あと、MANPを起動するのを忘れていた。



HTML/CSSで作ったホームページはローカル環境でも確認できるのに、PHPはわざわざサーバーを起動させないと動かないのはなんでなんだ？
AWS ソリューションアーキテクト アソシエート合格までのまとめ

#目次

#0. はじめに
先日、AWS ソリューションアーキテクト アソシエート に合格したので、忘れないうちに色々とアウトプットしておこうと思います。これから受験を考えている方の役にたてればと思います。
どんな人間がどのくらいの時間をかけて取得したのかを説明するために、少しだけ自分語りをさせてください。
24歳のインフラエンジニアです。現在は GCP とか AWS を仕事で触ってます。クラウドは触り始めて半年くらいです。ネットワークは少しだけ詳しいですが、プログラミングはほとんどできません。持ってる資格はこんな感じ
![スクリーンショット 2021-01-18 20.17.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/689597/4c7517ee-6eb9-62fc-b7aa-8fee7876219c.png)


#1.受験動機
クラウドを触り始めたはいいけどどこから手をつければいいのかわからず、体系的に学習するために受験を決めました。

#2.出題の範囲
まーあ広いです。細かな内容はここにはかけませんが、設問に出てくる課題に対して、どのサービスを使えば解決できるのかを引き出せるようにしておくといいかもしれないです。

#3.勉強方法
Udemy の講座と問題集のみを教材にし、わからないところを公式のドキュメントで埋め合わせるような勉強方法で進めました。
Udemy で購入した教材はこちらです。
[これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座（SAA-C02試験対応版）](https://www.udemy.com/share/101WKkAEEdc11TRXQD/)
[【SAA-C02版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/share/101rfMAEEdc11TRXQD/)
上記の２つで合格はできるかなと思います。
私の場合は、講座の方は1.5倍速 + ハンズオンは設定画面を見るだけという進めかたをしたため、勉強時間は 30h ほどでした。サービスの細かなオプションはいったん飛ばして、概念や構成を優先的に理解していくと効率がいいのかなと感じました。（どんな資格にも言えますが、概念をしっかり理解しないと、ただの暗記ゲーになってしまいます）
また、試験に出てくる問題の配分も講座内で解説があるため、何を重点的に学習するのかを決めておくことは、合格への戦略の一つかと思います。

#4.試験の感想
とにかく問題分が長いです。(プロフェッショナルはもっと長いらしい)これを 65 問は真面目に読んでるとかなりしんどいし、時間も迫ってくると思います。
ですが、問題文の要点を2、3つ抑えればあとは消去法で解けるような問題でした。
例えば、可用性を担保したいのか、コストより性能をとるのか、運用負荷をさげたいのかなどなど
問題文を1文にまとめれれば、あとは知識勝負って感じです



#5.試験に活きたメモ
実際の試験に活きた学習メモを残そうと思いましたが、メモがぐちゃぐちゃなので少しずつ更新していきます。


#6.1 EC2

### インスタンスタイプ

**スケジュールドリザーブドインスタンス**

特定の期間で定期的にインスタンスを使用する場合に選択する

日次、週次、月次の単位で予約することができる

例えば、毎週金曜日だけバッチ処理用のインスタンスが必要など

**オンデマンドインスタンス**

利用時間に応じた料金を支払う

**ハードウェア占有インスタンス**

AWS アカウント単位で、物理的なサーバを占有することができる

同じ AWS アカウントとは 物理サーバを共有する可能性がある

**Dedicated インスタンス**

同じ AWS アカウントでも IAM の権限単位で物理的なサーバを占有することができる

同一サーバに他テナントを入れいてはいけないなどの、セキュリティ面での制約がある場合に使用する

**リザーブドインスタンス（コンバーティブル）**

途中でインスタンスファミリー、OS、テナンシー、支払オプションを変更することができる

#6.2 S3

**ブロックパブリックアクセス**

バケット単位、またはアカウント単位での、全てのパブリックアクセスをブロックすることができる

デフォルトでは有効になっているため、インターネット上にバケットを公開するには、無効化する必要がある

**ライフサイクル管理**

オブジェクトのライフサイクルを設定することができる

使用頻度の高いクラスから低いクラスへの移動はできるが、その逆はできない

例えば、Glacier から Standerd への移動はできない

**S3 Select**

シンプルな SQL ステートメントを使用することで、オブジェクトの内容をフィルタリングし、取り出しデータのコスト削減、待ち時間を軽減できる

高度なデータ解析には向いていない

**クロスリージョンレプリケーション**

リージョン間でバケットをレプリケーションする際に使用する

レプリケーションのトリガーはバケット内の変更になるため、バージョニング機能を有効にする必要がある

別アカウントとバケットと共有する場合も、別アカウントのリージョンが異なる場合は、クロスリージョンレプリケーションを使用する必要がある

**アクセスポイント**

バケットにアタッチされた名前付きのネットワークエンドポイント

S3 への大規模なデータアクセスの管理を簡素化することができる

→１つのバケットに対して、接続元ごとに複数のバケットポリシー を作成するのはめんどい

**S3 MFA Delete**

オブジェクトを削除する際に、MFA 認証を必須とすることができる

→ 誤操作でのオブジェクトの削除などを防ぐことができる

**Transfer Acceleration**

クライアントと S3 バケット間のファイル転送を、高速・簡単・安全に行える

Cloud Front のエッジロケーションを使用する

例えば、クライアントが世界規模の場合などに使用すると効果的
連想配列の最初のキーを取得するためにarray_key_first()を使おうと思ったらphp7から追加された要素で使えなかったから、php5でも使える方法にしてみた

# どうも、7noteです。array_key_first()と同じことをphp5でもする。

連想配列の1番目かどうかを判断させるのに、`array_key_first()`が使えます。
しかし、これはphp7から追加されたものになるのでそれ以前のphpの環境では使えません。

なので、php5以前でも同じような処理ができる方法を解説。


## php7.xなら`array_key_first()`が使えるが・・・

**php5.xで同じことをするならこんな方法がある

```php
$city = array('東京'=>'tokyo', '愛知'=>'aichi', '大阪'=>'osaka');

reset($city);
$first_key = key($city);

foreach($city as $key => $value) {
	if($key === $first_key){
		// 最初の処理
	} else {
		// それ以外の時の処理
	}
}
```


## おまけ

**array_key_first()の使い方**

php7以降なら`array_key_first()`で連想配列の最初のkeyを取得可能。

```php
// php7.x
$city = array('東京'=>'tokyo', '愛知'=>'aichi', '大阪'=>'osaka');

foreach($city as $key => $value) {
	if($key === array_key_first($city)){
		// 最初の処理
	} else {
		// それ以外の時の処理
	}
}
```


## まとめ

phpはバージョンによって使える関数が違うことがあるので、よく使うものは代替策の書き方を知っておくと便利！

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)



参考：https://gotohayato.com/content/59/
[rails] gem 'rinku' 

#概要
rinkuは「http://」「https://」「ftp://」「mailto://」で始まるテキストをリンクにしてくれます。
自動リンクするリンクの種類は、:all・:urls・:email_addressesから指定できます。
'target="_blank"'を設定することで、外部リンクで開く様に設定も可能です。

gemfileにgem 'rinku'と記述し、bundleを実行します。

Rinku.auto_linkの部分でエラーが出る場合、下記3つを試してみてください。
1, サーバー再起動時にgemが読み込まれる仕組みです。忘れず再起動しましょう。
2, 使いたいファイルにrequire 'rinku'と記述
3, Bundler.requireで、 Gemfile の group に設定された gem を 一括でrequireする



リンク仕様にする `Rinku.auto_link(h(テキスト））`
[![Image from Gyazo](https://i.gyazo.com/c495aec3e23b5bd3824da5c2cbd7037d.png)]
(https://gyazo.com/c495aec3e23b5bd3824da5c2cbd7037d)


別タブで開く `Rinku.auto_link(テキスト, :all, 'target="_blank"'）`
[![Image from Gyazo](https://i.gyazo.com/1ef1761e0eebde0db8f0558e05fffd35.png)](https://gyazo.com/1ef1761e0eebde0db8f0558e05fffd35)
パンくずリスト実装

## はじめに
利用しているユーザーがどのページにアクセスしているのかを一目で分かりやすくするために、パンくず機能を実装したので、載せておこうと思います。
今回は**gretel(リンクを設置したリストを表示するGem)**を用いて、実装しました。

## 1.Gemの導入・ファイル作成
**1.Gemfileに gretel を記述し、bundle installする。

```ruby:Gemfile
gem 'gretel'
```

```:ターミナル
% bundle install
```

**2.パンくずリストの親子関係を記述するファイルを作成する。**

```:ターミナル
% rails g gretel:install
```
すると、config / breadcrumbs.rb が作成される。

## 2.パンくずリスト親子関係記述
**1 で作成した breadcrumbs.rb にコードを記述していく**

```ruby:config/breadcrumbs.rb
crumb "viewで呼び出す時のページ名" do
  link "リストの表示名", "アクセスするページのパス"
  parent :前のページ名
end
```

```ruby:config/breadcrumbs.rb
crumb :root do
  link "トップページ", root_path
end

crumb :new_idea do
  link "アイデア新規投稿", new_idea_path
  parent :root
end

crumb :idea_show do |idea|
  link "アイデア詳細", idea_path(idea.id)
  parent :root
end

crumb :edit_idea do |idea|
  link "アイデア編集", edit_idea_path
  parent :idea_show,idea
end
# 中略
```

##3.viewで呼び出す
**2 で作成した親子関係をviewに呼び出す。**

```html:views/ideas/show.html.erb
<% breadcrumb :idea_show ,@idea%>    　　　　　<!--呼び出したいパンくずを記述-->
<%= breadcrumbs separator: " &rsaquo; " %>　　<!--パンくず間の区切りである「>」を示す-->
```
<br>
ひとまず実装完了！！！ あとはCSSで整えていく感じです。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/941480/21c57ee5-1806-9cf9-0233-755b25b283c1.png" width=50%>

##　最後に
実装したパンくず機能はあらゆるサイトやアプリなどに用いられているので、今回の実装は勉強になりました。
活用できる機会があれば用いていきたいと思います。
node.jsやnodebrewなどをインストールし.bash_profileで設定完了→次の日できなくなってたの巻/Mac OS X 10.15

[環境]
intelチップのiMac
appleシリコンのM1 Mac（mini、imac）
と、今年になってから複数環境でmacのsetupしております。



正確には次の日ではなくターミナル落として再度開いたら、でしたが、、
mac OS 10.15での環境構築のお話です。
nodeやnodebrewをインストールし、bash_profileに環境設定pathを通します。


## 試したこと 

homeの中の「.bash_profile」 ファイルには

```shell
export PATH=/usr/local:$PATH
export PATH=$HOME/.nodebrew/current/bin:$PATH
```
と記述済み。念のためターミナルでも

```shell
export PATH=$HOME/.nodebrew/current/bin:$PATH
```

と実施。

で、ターミナルで
node -v
などを実行してちゃんとバージョンが見れておりました。

ーーーーーーーーー

が、時間を開けてもう一度ターミナルを開き、同じ操作をすると
「zsh: command not found: node」となります。

```shell
export PATH=$HOME/.nodebrew/current/bin:$PATH
```

をターミナルで実行すると動作するため、データは入ってはいるよう。

少しはまりましたが、ターミナルにあるようにシェルが「zsh」というバージョンのため、
.bash_profileに書いたものは無効になってしまいます。
この場合、このファイル名をそのまま.zprofileに名前変更すればうまくいきます！
（または利用シェルバージョンをbashに戻す方法でもよし）


macでは、10.15以降デフォルトでシェルがzhsに変更されております。
理由なんかも合わせてさがすと参考になりました！
https://www.infoq.com/jp/news/2019/07/macos-ditches-bash-for-zsh/


## 環境変数pathとは？（補足）
例えばあるツールを利用するときに、その処理のコマンドを実施するにはそのツールのパスを指定した上でコマンドを実施する必要があります。
が、毎回npmなどを実施する際にhomeディレクトリからのパスを入力するのは面倒なので、あらかじめコマンドを実施するシェル（ターミナル上の操作）に環境変数pathを読み込ませておくことで、例えば

home/hoge/huge/hogege と実施しないといけない状態だったのが
hogegeだけで実施できるようになる、というものです。今回の例であるnodeなどは通常、macでは.bash_profileというhome直下のファイルにこのpathを書き込むのが一般的でした。
それが最近のmac osでは、.zprofileに変わっている、というお話でした。


## 補足2
zprofile　以外にも.zshenvや.zshrcなど、環境変数を記載できるファイルがいくつかあります。
それぞれどのような時に読み込まれるかと言った違いがありますが、自分は前述した「.zprofile」で試してます。
https://suwaru.tokyo/zshenv/