OmniAICreator/Qiita-1.07M huggingface dataset:
Vagrant upでdocker composeをインストールする

## 紹介する内容
- Vagrantfileでdocker composeをインストールするshellスクリプトを書きます
   - CentOS7上でdocker composeインストールします
   - 参考：https://www.vagrantup.com/docs/provisioning/shell.html


## 結論
### docker composeがすぐ使えるVMが用意できます
- shell他のもプロビジョニング方法はいろいろあります
   - 参考：https://www.vagrantup.com/docs/provisioning



## 紹介始めます
### ディレクトリ構成
全体ソースコードは https://github.com/cheekykorkind/qiita-example/tree/master/vagrant/docker-compose で確認できます

- 全体図
![allD.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247584/75986b9c-d823-ce8e-8846-abe33b75ac06.png)

- docker composeをインストールするshellスクリプト部分
![shell.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247584/c98391d2-99a9-0268-ed7d-32f83ae49222.png)



### Vagrantfileファイル説明
いろいろ書かれてますが、必要な部分だけ書きます

- `./Vagrantfile`ファイルです 
  - `config.vm.synced_folder '.', '/vagrant', disabled: true`部分
     - `There was an error when attempting to rsync a synced folder.`エラーを防ぎます
  - `config.vm.provision :shell, path: 'scripts/set_docker_compose.sh'`部分
     - Vagrantfileファイルがあるデレクトリを基準として、パス`scripts/set_docker_compose.sh`のshellファイルを実行してくれます
   
### set_docker_compose.shファイル説明
- `./scripts/set_docker_compose.sh`ファイルです
- dockerやdocker composeをインストールする内容が書かれてますが、一つだけ書き方を共有したいと思います
   - 以下のコマンドの意味は`user名vagrantとしてbash shellで命令ブロックを実行する`です
   - vagrantがshellを実行する時は基本rootになりますから、`rootではないuserで作業する時`に活用できると思います
   - `NEWUSER_BLOCK`と書いたところは必ず`NEWUSER_BLOCK`である必要はありません

```
sudo -u vagrant /bin/bash <<\NEWUSER_BLOCK
sudo usermod -aG docker $(whoami)
exit
NEWUSER_BLOCK
```


### 試し順番です
1. Vagrantfileがあるデレクトリーに移動します 
  - `cd qiita-example/vagrant/docker-compose`
2. vagrantでVM起動します
  - `vagrant up`
3. vagrantで作ったVMにsshで入れます
  - `vagrant ssh`

### 試し結果
- vagrant upした部分
![vagrantUp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247584/024c5bc9-1daa-ae7b-f586-d98e6390f029.png)

- vagrant upが成功した後、vagrantのVMにSSHに入ったら、インストールされたdocker composeのバージョンが確認できます
![dockercomposeV.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247584/71dcd049-d7f4-7492-98ad-d36113750422.png)
Ubuntu(20.04)でMozcを使って日本語と英数入力をいい感じに切り替える方法

# Ubuntu(20.04)でMozcを使って日本語と英数入力をいい感じに切り替える方法
Mozcのショートカット設定をして、`Ctrl+Space`で`日本語→英数`、`英数→日本語`の切り替えができるようにします。大体の人は[4. 「直接入力」の「IMEを有効化」のキーをCtrl+Spaceに設定する](#4. 「直接入力」の「IMEを有効化」のキーをCtrl+Spaceに設定する)以降を確認すれば解決する気がします。

## 1. 右上から設定を開く
<img src="https://i.imgur.com/u7ONNQu.png" width="300px">
## 2. 地域と言語を選んで入力ソースのMozcから、設定ボタンを押す（Mozcがない場合は、＋を押して`日本語`からMozcを選択）
<img src="https://i.imgur.com/GDimj48.png" width="700px">
## 3. 下の方の`編集...`を押す（このメニューはアプリケーションからMozcの設定を直接開いてもたどり着ける）
<img src="https://i.imgur.com/hWIt9ue.png" width="400px">
## 4. 「直接入力」の「IMEを有効化」のキーをCtrl+Spaceに設定する
真ん中のカラムを３回くらいクリックするとショートカットキー入力画面が開く。直接入力とは、英数入力のこと。つまり、英数入力時にIME（日本語入力変換を助けてくれる機能）を`Ctrl+Space`でONにする。
![](https://i.imgur.com/QtsMUQY.png)
## 5. 「入力文字なし」の「IMEを無効化」のキーをCtrl+Spaceに設定する
手順４と同じようにショートカットキーを設定する。日本語入力時に`Ctrl+Space`を押すことで、IMEを無効化する。
![](https://i.imgur.com/buB1GYm.png)

## 6. 再ログインする
多分、`Ctrl+Space`での入力切り替えがうまくできるようになっているはず
Githubのwebブラウザ上でファイルを削除する方法


ブラウザ上で削除したいファイルをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/b1706301-78f1-e34f-4b9c-c554a76b6535.png)


次の画面でゴミ箱ボタンをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411106/690f05f3-a2c9-c578-8f61-502444b73403.png)
WordPress(headlessCMS)+Gatsbyの折衷案的なブログを作ろうとしている話

# 概要

WordPressをheadlessCMSとして使い、フロントをGatsbyで作る構成に魅力を感じたのでつくってみることにしました。

この記事では既存のWordPressブログにある記事をローカルでGatsbyで表示するところまでやります（それ以上のことは勉強中なのでまた後日）


# WordPress(headlessCMS)+Gatsbyの構成を選んだ理由

非IT人材にブログ更新をやってもらいたい場合、contentfull,microCMSなどでは難しいだろうと判断したからです。

使い慣れたWordPressで記事投稿をしてもらいつつ、フロント側をGatsbyでつくってサイトのパフォーマンスを上げるという折衷案的な使い方ができるとおもってこの構成を選びました。

ちなみにWordPressの記事更新をフックとして自動デプロイもできるのであとでやろうと思います。



# 必要なもの

・WordPressサイトのドメイン
・wp-graphql（プラグイン）
・wp-graphiql（プラグイン）
・gatsby-cli

# 手順

## 1.WordPressと連携するようのプロジェクトを作成

```
gatsby new [プロジェクト名] https://github.com/GatsbyCentral/gatsby-starter-wordpress
```

## 2.gatsby-config.jsを編集

編集する項目は**baseUrl**と**includedRoutes**
**baseUrl**にはWordPressで運用しているサイトのドメインを記入



``` gatsby-config.js
module.exports = {
  siteMetadata: {
    title: 'Gatsby + WordPress Starter',
  },
  plugins: [
    'gatsby-plugin-react-helmet',
    'gatsby-plugin-sass',
    {
      resolve: 'gatsby-source-wordpress',
      options: {
        // The base url to your WP site.
        baseUrl: 'WordPressサイトのドメイン',
        // WP.com sites set to true, WP.org set to false
        hostingWPCOM: false,
        // The protocol. This can be http or https.
        protocol: 'https',
        // Use 'Advanced Custom Fields' Wordpress plugin
        useACF: false,
        auth: {},
        // Set to true to debug endpoints on 'gatsby build'
        verboseOutput: false,
        includedRoutes: [
          '**/categories',
          '**/posts',
          '**/pages',
          '**/media',
          '**/taxonomies',
          '**/users',
          '**/tags',
        ],
      },
    },
    'gatsby-plugin-sharp',
    'gatsby-transformer-sharp',
    {
      // Removes unused css rules
      resolve: 'gatsby-plugin-purgecss',
      options: {
        // Activates purging in gatsby develop
        develop: true,
        // Purge only the main css file
        purgeOnly: ['/all.sass'],
      },
    }, // must be after other CSS plugins
    'gatsby-plugin-netlify', // make sure to keep it last in the array
  ],
}
```


## 3.WordPress側をGraphQLに対応

下記の2プラグインをzipとしてDLしてWordPressの管理画面からアップロードして有効化してください。

・[wp-graphql](https://github.com/wp-graphql/wp-graphql)
・[wp-graphiql](https://github.com/wp-graphql/wp-graphiql)



## 4.Gatsbyをビルドして記事読み込めるか確認

```
gatsby build
```

確認

```
gatsby develop
```

こんな感じでブログの記事がみれます。
![jamstack.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390321/6e04949b-09aa-3271-8638-27b973f7ac12.png)



# 今後のタスク

・TypeScript化
・ブログの見た目かっこよくする
・自動デプロイ


# 参考サイト

https://haniwaman.com/gatsby/
https://www.gatsbyjs.org/docs/glossary/wpgraphql/
RustでFutureなクロージャを関数の引数にしてみる

# 目的
RustでFutureなクロージャを関数の引数にしてみる。

# コード
```rust:main.rs
use std::future::Future;

async fn example<Fut>(f: impl FnOnce(i32, i32) -> Fut) -> i32
where
    Fut: Future<Output = i32>,
{
    f(1, 2).await
}

async fn example2<Fut>(f: impl FnOnce(i32, i32) -> Fut) -> String
where
    Fut: Future<Output = String>,
{
    f(1, 2).await
}

async fn example3<Fut>(f: impl FnOnce(String, String) -> Fut) -> String
where
    Fut: Future<Output = String>,
{
    f("xxx".to_owned(), "yyy".to_owned()).await
}

async fn example4<Fut>(aaa: &str, f: impl FnOnce(String, String) -> Fut) -> String
where
    Fut: Future<Output = String>,
{
    f("xxx".to_owned(), aaa.to_owned()).await
}

async fn example5<Fut>(f: impl FnOnce(&str) -> Fut) -> i32
where
    Fut: Future<Output = i32>,
{
    f("xxx").await
}

fn example6(f: impl FnOnce(&str) -> i32) -> i32
{
    f("xxx")
}

#[tokio::main]
async fn main() {
    let z = 3;
    let res = example(|x, y| async move { x + y + z }).await;
    println!("Hello, world! {}", res);

    let res = example2(|x, y| async move { format!("{},{},{}", x, y, z) }).await;
    println!("Hello, world! {}", res);

    let res = example3(|x, y| async move { format!("{},{},{}", x, y, z) }).await;
    println!("Hello, world! {}", res);

    let res = example4("xyz", |x, y| async move { format!("{},{},{}", x, y, z) }).await;
    println!("Hello, world! {}", res);

    //let res = example5(|x| async move { x.len() as i32 }).await;
    //println!("Hello, world! {}", res);

    let res = example5(|_x| async move { 999 }).await;
    println!("Hello, world! {}", res);

    let res = example6(|x| { x.len() as i32 });
    println!("Hello, world! {}", res);
}

```

# 解説
## example1
Futureなクロージャーを引数で受ける方法はスタックオーバーフローのカービーが教えてくれた(自分が質問したわけじゃないけど)。example1はクロージャーの引数も戻り値もCopyできるもの。

## example2
戻り値だけCopyできないもの

## example3
引数もCopyできない。さらに借用ではない

## example4
呼び出す関数に借用な引数を与えてみる

## example5
クロージャーの引数を借用にしてみる。借用した値をクロージャーの中で使うとエラーになる。使わないなら動作する。

```sh
error: borrowed data cannot be stored outside of its closure
  --> src/main.rs:58:39
   |
58 |     let res = example5(|x| async move { x.len() as i32 }).await;
   |               ------------------------^^^^^^^^^^^^^^^^^^-------
   |               |        |              |
   |               |        |              cannot be stored outside of its closure
   |               |        ...because it cannot outlive this closure
   |               borrowed data cannot be stored into here...

error: aborting due to previous error
```

## example6
Futureでないクロージャーなら借用を利用しても問題無い

# 関連リンク
[How to accept an async function as an argument?](https://stackoverflow.com/questions/60717746/how-to-accept-an-async-function-as-an-argument)
[fastlane]  No provisioning profile providedの対処方法

## はじめに
Xcodeでプロビジョニングプロファイルを設定していても、次のエラーが発生することがあります。

```
Error Domain=IDEProvisioningErrorDomain Code=9 ""hoge.app" requires a provisioning profile." UserInfo={IDEDistributionIssueSeverity=3, NSLocalizedDescription="hoge.app" requires a provisioning profile., NSLocalizedRecoverySuggestion=Add a profile to the "provisioningProfiles" dictionary in your Export Options property list.}

** EXPORT FAILED **
[14:58:48]: Exit status: 70
[14:58:48]: No provisioning profile provided
[14:58:48]: Make sure to pass a valid provisioning for each required target
[14:58:48]: Check out the docs on how to fix this: https://docs.fastlane.tools/actions/gym/#export-options
```

## 対処方法

`export_options`に`provisioningProfiles`を加えると、解決します。

```txt:Fastfile
lane :dist_me do
  increment_build_number
  build_ios_app(
    export_options: {
      method: "ad-hoc",
      provisioningProfiles:{ // <- これを加える
        "com.hoge.fuga"=>"<ProvisioningProfile>"
      }
    }
  )
```

## 参考文献
[gym - fastlane docs](https://docs.fastlane.tools/actions/gym/)
jsで配列を分解した全パターンを取得する

#やりたいこと
わかりやすく言葉で説明できないので、完成イメージをかきます！

```js
console.log(allSubArray([1,2,3]);
/* 
[
[[1], [2], [3]], 
[[1, 2], [3]],
[[1], [2, 3]],
[[1, 2, 3]]
] 

(順番の入れ替え([[1, 3], [2]]など)は考慮しません)
*/
```

何に使うの？とか言わないでください :)

#考え方
###再帰使えるかな・・・

```js
const allSubArray(array) => {
     // 再帰終了条件
    if(array.length === 0) return [[]];

    cosnt result = [];
    // array = [1,2,3,4]とする
    /* 最初は0番目の要素[1]とそれ以外[2,3,4]に分割して考える　*/
    const subArrays = allSubArray([2,3,4]);
    // subArrays = [[[2], [3], [4]], [[2,3],[4]], [[2],[3,4]], [[2,3,4]] ] が期待される

    // [1]とsbuArraysの各要素をくっつけたものをresultにpush
    /* 期待されるresultは
　　　[
       [[1], [2], [3], [4]],
       [[1], [2,3], [4]],
       [[1], [2], [3,4]],
       [[1], [2,3,4]]
     ]
   */

  /* 次に、1番目までのの要素[1, 2]とそれ以外[3,4]に分割して考える*/
  /* 今感じで行けるか・・・？　*/

}
```

#やってみよう

```js

const allSubArray = (array) => {
    // 再帰終了条件
    if(array.length === 0) return [[]];


    const result = [];
    // array = [1,2,3,4]とする
    /* 最初は0番目の要素[1]とそれ以外[2,3,4]に分割して考える　*/
    for(let i = 1; i <= array.length; i++)　{
      const fixedArray = array.slice(0, i);  //i=1の時:fixedArray = [1], i=2の時:fixedArray =[1,2]
      const otherArray = array.slice(i); //i=1の時:otherArray = [2,3,4]

      // i=1の時:subArrays = [[[2], [3], [4]], [[2,3],[4]], [[2],[3,4]], [[2,3,4]] ] が期待される
      const subArrays = allSubArray(otherArray);
      for(const subArray of subArrays) {
        result.push([fixedArray].concat(subArray));
      }
    }
    return result;
}
```

#実行結果

<img walt="結果-qiita.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/671997/25f8bd95-d7c5-a48f-1e70-c66ed2e83e70.png">

できてる！！（何に使うんだろう）
【javascript】デフォルトパラメータとレスパラメータ

こちらの記事は以下の書籍を参考に執筆しました

- [PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)

#デフォルトパラメータ
以下はデフォルトパラメータを使用した例

```javascript
function approvalChart(rating,width=800,height=with/2){
  //処理  
}
const nationalChart=approvalChart(narionalRatings)//800x400
const geogiaChart=approvalChart(geogiaRatings,400)//800x400
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)



デフォルトパラメータには式が割り当てることができる。
式が評価されるのは関数が評価されるとき。

パラメータのデフォルト値はパラメータリストのインデックスに紐付けられる。


#レストパラメータ
```javascript
function avg(...args){
  //...
}
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)

これで引数がargsという変数の配列として格納される。

レストパラメータの後にパラメータを配置するとエラーになる。

##レスト演算子を使って関数間で引数を渡す
何らかの画像処理を行うライブラリを使用していてログ機能を追加するために処理関数をフックする必要があるとする。多くのライブラリにはミドルフックがあるが、常にそうとは限らない。
そういう場合は**モンキーパッチ**を実行する。

###モンキーパッチ
元の関数を呼び出す前にカスタムロジックを注入して関数を再定義するプロセス

```javascript
{
  //元のメソッドへ参照を取得
  const originProcess = imageDoctor.process;
  //引数をすべて集める新しい関数を定義
  imageDoctor.process = function(...args) {

    //ロブ機能を注入
    console.log('imageDoctor processing', args)

    //argsを使って呼びだされた元の関数の結果を返す。
    return originProcess.apply(imageDoctor, args)
  }
}
```
>出典：[PHPフレームワークLaravel入門 第2版](https://www.amazon.co.jp/PHP%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AFLaravel%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E6%8E%8C%E7%94%B0-%E6%B4%A5%E8%80%B6%E4%B9%83/dp/4798060992/ref=tmm_hrd_title_0?_encoding=UTF8&qid=1595991312&sr=1-2)


process関数にモンキーパッチを実行し、レスト演算子をまとめた上で元の関数に返している。
これにより、元の関数が常にラッピング関数を同じ引数を使って呼び出されるようになる。
Oracle Master Bronze DBA 2019 に合格する情報まとめ【Part1】

#Oracle Master Bronze が新しくなりました
2020年1月以降からOracle Master 新資格体系が導入されています。

|認定資格名|前提条件|試験合格|証明するスキル|
|:---|:---|:--|:--|
|ORACLE MASTER Bronze DBA 2019|なし|1Z0-085-JPN: Bronze DBA Oracle Database Fundamentals（2020年2月27日リリース）|DB の基礎知識|
|ORACLE MASTER Silver DBA 2019|なし|1Z0-082-JPN: Oracle Database Administration I（2020年1月9日リリース）|DB の運用管理（Gold DBA で証明するスキルを除く） SQL の基礎知識|
|ORACLE MASTER Gold DBA 2019|Silver DBA 2019|1Z0-083-JPN: Oracle Database Administration II（2020年2月27日リリース）|バックアップ・リカバリ マルチテナント・アーキテクチャ インストール・アップグレード 18c, 19c 新機能概要

##新資格体系のポイント

* __Gold DBA に挑戦しやすくなりました：__DB 管理者にはマルチテナントやバックアップ・リカバリのスキルは必須。そこで、Gold DBA まで挑戦しやすくするために要履修コースをなくし、また必要な試験数を 4 試験から 2 試験に減らしました。

* __Silver DBA に挑戦しやすくなりました：__Gold DBA まで必要としない運用担当者の方には Silver DBA がお勧めです。Silver DBA に挑戦しやすくするために Bronze DBA の取得を任意としました。1 試験の合格で Silver DBA に認定されます。

* __Bronze DBA は DB 基礎知識を証明します：__全 IT エンジニアに必要となる DB の基礎知識を証明する資格として Bronze DBA を再定義しました。

* __Silver SQL は SQL のスキルを証明します：__開発者やデータ・アナリスト向けに SQL のスキルを証明する資格を提供します。

>https://www.oracle.com/jp/education/certification/index-172250-ja.html


#記事の方針
この記事では、上記新資格の内「ORACLE MASTER Bronze DBA 2019」の合格を目指してその情報をまとめようと思っています。
基本はOracleDBAに関する情報を載せていき、基本となるデータベース等の知識は知っている前提で記載していきます。


#Oracleの特徴
リレーショナルデータベースは、Oracle以外にも、MicrosoftSQL Server、IBM DB2、MySQL、PostgreSQLなど他の選択肢もたくさんあります。
その中で、わざわざOracleを選択する要因は何が存在するのでしょうか？
Oracleには他の製品にはない、以下の優れた特徴があります。

##商用RDBMSシェアNo.1
Oracleは世界及び国内で50%近いシェア（販売金額ベース）を持ち、企業向けシステムを中心に、非常に多くのシステムで使われているRDBMSです。
MySQLなどオープンソースRDBMSも広く使用されるようになっていますが、導入分野はおもにWeb系の新規システムに限定され、企業向けシステムにおけるOracleのシェアNo.1はゆるぎないと考えられます。

##多くの対応OSと互換性
Oracleは、Windows、Linux、商用UNIXなど主要なOSに対応しています。こんため、システムで採用できるOSの選択肢が広がります。
他のRDBMS製品では、たとえば、SQLServerはWindowsにしか対応していないため、SQLServerを使用するシステムではLinuxを採用できません。
また、各OS向けのOracleの間でデータベースの構造やSQLに互換性があるので、OSをWindowsからLinuxに変更しても、データベースやアプリケーションを簡単に移行できます。

##企業向けシステムに求められる高度な機能を持つ
##高いパフォーマンス
##高度なセキュリティ機能
Oracleは政府や金融機関をはじめとする高い機密性を求められる組織で使用されています。このため、Oracleは監査、内部からのデータ漏洩防止、暗号化などの高度なセキュリティ機能を持っています。
##多重化構成、災害対策構成
データベースはシステムの中心的な役割を担うため、データベースの停止はシステムの停止に直結します。
このため、データベースには高い耐障害性が求められます。
また、大規模な災害の発生時もサービスを継続できることが重要です。Oracleには複数サーバーによる多重化構成を実現するRAC（Real Application Clusters）および災害発生時のサービス継続を実現するData Guardという機能があります。


#参考・引用書籍
Oracleの基本 ～データベース入門から設計／運用の初歩まで Kindle版
> https://www.amazon.co.jp/dp/B075N6RB2K/
Ruby on Rails 遷移元によって条件を変更させる2パターン

プログラミングスクールのチーム開発でECサイトを作成している際、
どこのリンク先から遷移したかでインスタンス変数を変えたい・・・
というような場面がありました。
その時に2パターンの方法があったので、備忘録として残します。

【環境】
Ruby: 2.5.7
Rails: 5.2.4
使用した中で関係するgem：devise(顧客、管理者を作成)

# 前提条件
- 管理者側のページで注文一覧を表示する際、下記のように設定したい。
 - トップページから遷移 => 本日作成された注文一覧
 - 顧客の詳細ページから遷移 => その顧客の注文一覧 
 - ヘッダーの注文一覧ボタンから遷移 => 全ての注文一覧

## テーブル
```rails:schema.rb
create_table "orders", force: :cascade do |t|
　　 t.integer "user_id", null: false
   (略)
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

create_table "users", force: :cascade do |t|
   (略)
  end

```

## モデル(アソシエーション)

```rails:user.rb
has_many :orders, dependent: :destroy
```

```rails:order.rb
belongs_to :user
```

## ルート

```
namespace :admins do
    get '', to: 'products#top'
    resources :users, only: [:index, :show, :edit , :update]
    resources :orders, only: [:index, :show, :update]
end
```

# 実装パターン①：遷移元をコントローラで取得する
[参考にした記事：Railsで遷移元のコントローラーとアクションを取得する](https://qiita.com/krppppp/items/8200af97140c0487ae05)

```rails:admins/orders_controller.rb
def index
　path = Rails.application.routes.recognize_path(request.referer)

　# path[:controller]で遷移元コントローラーを、path[:action]でアクションを取得
　if path[:controller] == "admins/products" && path[:action] == "top"
 　 @orders = Order.where(created_at: Date.today)
　 elsif  path[:controller] == "admins/users" && path[:action] == "show"
    @orders = Order.where(user_id: path[:id])
 　else 
　  @orders = Order.all
　 end
end
```
これで、3パターンの変数を持たせることができました。
ただ、この内容だと【トップ画面からヘッダーの注文履歴ボタンを押した】際、
トップ画面から遷移したと判断されてしまいます。
そのため、最終的には下記の方法で実装を行いました。

# 実装パターン②：リンク元にパラメーターを付ける

遷移元のリンクページには下記の通りパラメータを持たせました。

```rails:admins/products/top.html.erb
　<%= link_to "本日の注文件数", admins_orders_path(order_sort: 0) %>
```

```rails:admins/users/show.html.erb
　<%= link_to "注文一覧", admins_orders_path(order_sort: 1) %>
```

そしてコントローラ側では、持ってきたパラメーターで変数を振り分け

```rails:admins/orders_controller.rb
def index
 case params[:order_sort]
 when "0"
   @orders = Order.where(created_at: Date.today)
 when "1"
   @user = User.find(params[:user_id])
   @orders = @user.orders
 else
   @orders = Order.all
 end
end
```
これによって①の問題は解消されました。

# まとめ
- ①の方法であればコントローラ側で一目見れば分岐条件がわかりやすいと思うが、状況に応じた実装が求められる。
- ①の方法を応用すれば、updateやdestroyアクションのリダイレクト先などを分岐させることも可能。
AWSコスト削減でやってみたこと

#はじめに

サービス開始後、時間が経つにつれ肥大化するAWSのコスト。
とうとうその金額に白羽の矢が立った為、[AWSのコストを削減する９の方法](https://aws.amazon.com/jp/blogs/news/9ways-to-optimize-aws-cost/) を実際に試したので、その実施内容を紹介します。


##1. 未使用状態のAmazon EC2やAmazon RDS インスタンスへの支払いを止める
効果が最も高かったのがこれです。すぐに着手すべき最強の一手でした。


###EC2のスケジューリング
DEV環境やSTG環境は平日夜間・休日は使用しないしない為、平日日勤のみ起動するようにしました。
Auto Scalingで管理していたので、[Auto Scaling のスケジュールに基づくスケーリング](https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/schedule_time.html)を利用しました。また、公式に[AWS Instance Scheduler](https://aws.amazon.com/jp/solutions/implementations/instance-scheduler/)というものがあるのでこちらを利用しても良いかもしれません。

###RDSのスケジューリング
こちらもEC2同様、平日日勤のみ起動するようにしました。
RDSインスタンスの起動停止はboto3によるRDSインスタンスの起動停止を行うLambdaを作成し、cloudwatch eventで定期実行させています。

##2. Amazon DynamoDB にはオンデマンドのキャパシティーモードを利用する

DynamoDBの課金形態は「オンデマンドキャパシティー」という使った分だけ費用が発生するものと、「プロビジョニング済みキャパシティー」という予め需要予測を行い、指定したキャパシティに応じて費用が発生するものの2種類があります。

今回は、費用対リクエストの観点でクラスメソッドさんの[DynamoDBのオンデマンドとプロビジョニングの料金を比較をしてみた](https://dev.classmethod.jp/articles/reinvent2018-compare-dynamodb-on-demand-price-with-provisioned-price/)を参考にコストを見積もり、

- オンデマンドキャパシティーを利用
- プロビジョニング済みキャパシティーにてキャパシティ容量を最適化
 
の2種類で対応しました。


##3. 十分に活用されていないEC2インスタンス(RDSインスタンス)への支払いを止める

インスタンスタイプが需要に対して過剰に設定されているインスタンスのダウンサイジングを実施しました。
資料中には`「CPU使用率が 40% 未満」`が一つの目安として挙げられており、こちらを参考にしています。

RDSインスタンスも同様にダウンサイジングを行ましたが、EC2に比べこちらの方が効果は大きいように感じています。
理由の一つとして、RDSインスタンスはEC2インスタンスに比べ1インスタンスあたりの料金が高いことがあるのではないかと思います。

##4. 十分に活用されていないネットワークリソースを削除する

不要なELB、EIP の削除を実施しました。
各AWSコンポーネントはコードで管理していたのですが、EIPはコード管理していなかった為、一時的に取得されたものや不要になったものが存在していました。

##5. Savings Plans、リザーブドインスタンスを利用する
常時起動前提のインスタンスはスケジューリングによる停止ができない為、Savings Plans及びリザーブドインスタンスの利用によりコストを削減しました。

Savings Plansは昨年発表された新しい割引プランですが、リザーブドインスタンスとの使い分けとして以下の使い分けができそうです。

`EC2インスタンス、Fargate、Lambda　->　Savings Plans`

`RDS、Redshift、ElastiCache、Elasticsearch　-> リザーブドインスタンス`

#まとめ

AWSコストはEC2インスタンスとRDSインスタンスの占める割合が多いことを改めて感じさせられました。
闇雲に手を付けて工数対削減費用効果が弱くなることを懸念していた中で今回の要点は良かったように思います。
日々のコスト管理もできるようにしたいですね！



## 参考文献

この記事は以下の情報を参考にして執筆しました。

- [AWSのコストを削減する９の方法
](https://aws.amazon.com/jp/blogs/news/9ways-to-optimize-aws-cost/)
- [AWSのコストを削減する９の方法 第二回](https://aws.amazon.com/jp/blogs/news/9ways-to-optimize-aws-cost-part2/)
- [AWSのコストを削減する９の方法 第三回](https://aws.amazon.com/jp/blogs/news/9ways-to-optimize-aws-cost-part3/)
cask+anyenv+jenvを使ったJavaのバージョン管理

# 環境
OS：macOS Catalina 10.15.5
brew：2.4.3

# caskを使ったJavaのインストール
brew caskをそのまま使うと古いバージョンのJavaをインストールができない。
そのため以下のコマンドでを使って古いバージョンもインストールできるようにする。

```zsh
$ brew tap homebrew/cask-versions
```

各種バージョンをインストールする

```zsh
// インストール可能なjavaのバージョンの確認
$ brew search java

// java14
$ brew cask install java

// java11
$ brew cask install java11

// java8
$ brew cask install adoptopenjdk8

// javaのバージョン確認
$ /usr/libexec/java_home -V
```

# anyenvのインストール
anyenvは*envを管理することができる。今回の場合はjenvを管理するために導入する。

```zsh
// brewでanyenvをインストール
$ brew install anyenv

// パス追加　zsh版
$ echo 'eval "$(anyenv init -)"' >> ~/.zshrc

// マニフェストディレクトリ作成
$ anyenv install --init
これで.anyenvディレクトリが作成される。

// SHELLの再起動
$ exec $SHELL -l

// anyenvコマンド
// インストールした*envのバージョン確認
$ anyenv versions

// anyenvでインストールできる*envのリスト
$ anyenv install -l
```
※うまいことzshrcの設定が反映されない場合は`source ~/.zshrc`で反映する

### 便利なanyenvのプラグインを入れる
プラグインは任意ですが入れておくと便利です。

```zsh
// プラグイン用のディレクトリ作成
$ mkdir -p ~/.anyenv/plugins

// anyenv-update anyenvで入れた*envを一括でアップデートしてくれるプラグイン
$ git clone https://github.com/znz/anyenv-update.git ~/.anyenv/plugins/anyenv-update

// anyenv-git anyenvで入れた*envをgitコマンドで実行できるプラグイン
$ git clone https://github.com/znz/anyenv-git.git ~/.anyenv/plugins/anyenv-git
```

# jenvのインストール
caskでインストールしたJavaを管理する

```zsh
// jenvをインストール
$ anyenv install jenv

// SHELLの再起動
$ exec $SHELL -l

// 確認
$ anyenv versions
jenv:
  system
  1.8
  1.8.0.252
  11
  11.0
  11.0.2
  14
  14.0
* 14.0.1 (set by /Users/masa/.anyenv/envs/jenv/version)
  openjdk64-1.8.0.252
  openjdk64-11.0.2
  openjdk64-14.0.1
```

# Javaをjenvで管理する設定
各種Javaのバージョンをjenvに登録して切り替える方法です。

```zsh
// 紐付け jenvにaddする
$ jenv add `/usr/libexec/java_home -v "1.8"`
$ jenv add `/usr/libexec/java_home -v "11"`
$ jenv add `/usr/libexec/java_home -v "14"`

// jenvで管理しているjavaのバージョン確認
$ jenv versions

// global設定
$ jenv global 11.0.2

// javaのバージョン確認
$ java versions

// シェル起動
$ jenv exec zsh

// JAVA_HOMEを自動で設定するようにする
$ jenv enable-plugin export

// JAVA_HOME確認
$ echo $JAVA_HOME

// Topic 特定のディレクトリ内で別バージョンのJDKを利用する場合
$ jenv local 11.0.2
```
※JAVA_HOMEの設定がうまいこと反映されない場合はterminalを再起動等すれば反映されるときがあります。
TECH CAMP学習　個人アプリ作成③

# ユーザー情報編集機能の追加
まずはターミナルにて以下のコードを入力します。

```terminal.
$ rails g controller users
```

続いてルーティングで下記を入力します。

```routes.rb
 devise_for :users
 root "photos#index"
 resources :users, only: [:edit, :update]
```
resourcesの意味は日本語では資源をいう意味で、usersの中で編集と更新の機能を利用するという解釈でよいと思います。



続いてコントローラーを編集します。

```users_controller.rb
def edit
end

def update
   if current_user.update(user_params)
      redirect_to root_path
   else
      render :edit
   end
end

private

def user_params
   params.require(:user).permit(:name, :email)
end

```

①current_userはdeviseのヘルパーメソッドで、ログイン中のユーザー情報を取得できます。
②redirect_toは本来受け取ってるパスとは別のパスへ転送します。上記ではroot_pathに転送するということです。
③上記が失敗した場合、renderはeditを呼び出します。
④privateはプライベートメソッドで、クラス外から呼び出すことのできないメソッドです。
メリットしては
・classの外部から呼び出されたら困るメソッドを隔離
・可読性、classの外部から呼び出されたメソッドを探すときにprivate以下の部分は目を通さなくてよくなる。
⑤user_params以下はストロングパラメーターで、指定したキーを持つパラメーターのみを受け取るようにするものです。
⑥ストロングパラメーターの中でuserを要求(require)して:name,:emailの許可(permit)を得る。詳細を確認するにはupdateの直後にbinding.pryを使用する。
【Kotlin】仕様変更に強い FizzBuzz

ネタ元：[「fizzbuzzについて思うこと」](https://qiita.com/jamashita/items/d07e8dd6fd53a6e15c07)
TypeScript版：[【TypeScript】仕様変更に強い FizzBuzz](https://qiita.com/sdkei/items/a661989ce3b259f45de3)
更に仕様変更に強くした版：[【Kotlin】更に仕様変更に強い FizzBuzz](https://qiita.com/sdkei/items/83ab053d15e9dd35f84a)

FizzBuzz の、割る数、出力する文字列、変換規則の数や順番が変わっても
最小限のコード変更で済むようにする。

```Kotlin
/**
 * FizzBuzz を行うためのクラス。
 * 
 * [invoke] 関数に数値を与えると対応する文字列を返す。
 */
class FizzBuzz private constructor(
    private val fizzBuzzMap: List<Pair<Int, String>>
) {
    /**
     * @param fizzBuzzMap 割る数と、
     *  それで割り切れたときに出力する文字列の組の列。
     */
    constructor(
        fizzBuzzMap: Iterable<Pair<Int, String>>
    ) : this(fizzBuzzMap.toList())

    /**
     * @param fizzBuzzMap 割る数と、
     *  それで割り切れたときに出力する文字列の組の列。
     */
    constructor (
        vararg fizzBuzzMap: Pair<Int, String>
    ) : this(fizzBuzzMap.toList())

    /** 与えられた数値に対応する文字列を返す。 */
    operator fun invoke(num: Int): String =
        fizzBuzzMap.asSequence()
            .mapNotNull { (divisor, str) ->
                if (num % divisor == 0) str
                else null
            }
            .joinToString("")
            .takeUnless { it.isEmpty() }
            ?: num.toString()
}
```

## 普通の FizzBuzz

```Kotlin
/** 変換規則の定義。 */
val fizzBuzz = FizzBuzz(
    3 to "Fizz",
    5 to "Buzz"
)

fun main() {
    (1..15).asSequence()
        .map {
            fizzBuzz(it)
        }.forEach {
            println(it)
        }
}
```

出力

```
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
```

## 割る数と出力する文字列を変更

```Kotlin
/** 変換規則の定義。 */
val fizzBuzz = FizzBuzz(
    7 to "Foo",
    2 to "Bar"
)

// main 関数は同じなので省略
```

出力

```plaintext
1
Bar
3
Bar
5
Bar
Foo
Bar
9
Bar
11
Bar
13
FooBar
15
```

## こんなことも

```Kotlin
val fizzBuzz = FizzBuzz(
    1 to "<",
    3 to "Fizz",
    5 to "Buzz",
    1 to ">"
)

// main 関数は同じなので省略
```

出力

```plaintext
<>
<>
<Fizz>
<>
<Buzz>
<Fizz>
<>
<>
<Fizz>
<Buzz>
<>
<Fizz>
<>
<>
<FizzBuzz>
```

／以上
ゼロから始めるLeetCode Day83 「102. Binary Tree Level Order Traversal」

# 概要

海外ではエンジニアの面接においてコーディングテストというものが行われるらしく、多くの場合、特定の関数やクラスをお題に沿って実装するという物がメインである。

どうやら多くのエンジニアはその対策としてLeetCodeなるサイトで対策を行うようだ。

早い話が本場でも行われているようなコーディングテストに耐えうるようなアルゴリズム力を鍛えるサイトであり、海外のテックカンパニーでのキャリアを積みたい方にとっては避けては通れない道である。

と、仰々しく書いてみましたが、私は今のところそういった面接を受ける予定はありません。

ただ、ITエンジニアとして人並みのアルゴリズム力くらいは持っておいた方がいいだろうということで不定期に問題を解いてその時に考えたやり方をメモ的に書いていこうかと思います。

[Leetcode](https://leetcode.com/)

Python3で解いています。

[ゼロから始めるLeetCode 目次](https://qiita.com/KueharX/items/6ee2502c3b620c795b70)

前回
[ゼロから始めるLeetCode Day82「392. Is Subsequence」](https://qiita.com/KueharX/items/ddf57a3f819e70f7e61f)


[Twitter](https://twitter.com/kueharx)やってます。

**[技術ブログ](https://kueharx.blogspot.com/)始めました！！**
技術はLeetCode、Django、Nuxt、あたりについて書くと思います。**こちらの方が更新は早いので**、よければブクマよろしくお願いいたします！

# 問題

[102. Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/)
難易度はMedium。
前回と同じく問題集からの抜粋です。

問題としては、バイナリツリーが与えられた場合、そのノードの値の階層順の横の同値をまとめたリストを返すアルゴリズムを設計してください。(すなわち、左から右へ、レベルごとに)というものです。

```
For example:
Given binary tree [3,9,20,null,null,15,7],
    3
   / \
  9  20
    /  \
   15   7
return its level order traversal as:
[
  [3],
  [9,20],
  [15,7]
]
```

例はこんな感じ。
言いたいことは理解してもらえたと思います。

# 解法

DFSで解きました。

```python 
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def levelOrder(self, root: TreeNode) -> List[List[int]]:
        ans,level = [],0
        self.dfs(root,level,ans)
        return ans
    
    def dfs(self,root,level,ans):
        if not root:
            return
        if len(ans) < level+1:
            ans.append([])
        ans[level].append(root.val)
        self.dfs(root.left,level+1,ans)
        self.dfs(root.right,level+1,ans)
# Runtime: 32 ms, faster than 86.02% of Python3 online submissions for Binary Tree Level Order Traversal.
# Memory Usage: 14.2 MB, less than 43.09% of Python3 online submissions for Binary Tree Level Order Traversal.
```

シンプルなDFSですね。
リストとして返すということが決まっているので、リストの長さをとって上げると階層の要素を上手く網羅できます。

今回は慣れている深さ優先探索で解いてしまいましたが、discussにはBFSで解いた例や、キューを使って解いた解答もあったりと、個人の好きな解き方が現れそうな感じの問題ですね。

では今回はここまで。お疲れ様でした。
【PowerShell】Linuxのgrepのように行を検索する方法(Windows)

# はじめに
WindowsのPowerShellでLinuxのようにgrepする方法について書きます。

# そもそもgrepとは？

簡単に言うと、Linuxのファイルの行を検索するコマンドになります。
詳しくは下記ページをご覧下さい。

[grepコマンドの詳細まとめました【Linuxコマンド集】](https://eng-entrance.com/linux-command-grep#grep-2)

```bash:使用例
[root@tspweb01 network-scripts]# grep IPADDR ifcfg-enp0s8
IPADDR=192.168.56.30
[root@tspweb01 network-scripts]# 
```

**※コマンド実行前の状態**

```bash:コマンド実行前
[root@tspweb01 network-scripts]# cat ifcfg-enp0s8
TYPE="Ethernet"
BOOTPROTO="none"
IPV6INIT="no"
NAME="enp0s8"
UUID="81d71b89-d1b6-4ca9-853d-c5bf74c8487e"
DEVICE="enp0s8"
ONBOOT="yes"
IPADDR=192.168.56.30
PREFIX=24
[root@tspweb01 network-scripts]# 
```

# PowerShellのgrep方法

## 実行コマンド

```powershell:コマンド
 <コマンド> | Out-String -Stream | Select-String <検索したい文字列> 
```

## 使用例①

**Get-NetFirewallProfile**の実行結果から「Domain」の行を抽出

```powershell:文字列抽出前
 PS C:\Users\Administrator> Get-NetFirewallProfile 

Name                            : Domain
Enabled                         : False
DefaultInboundAction            : NotConfigured
DefaultOutboundAction           : NotConfigured
AllowInboundRules               : NotConfigured
AllowLocalFirewallRules         : NotConfigured
AllowLocalIPsecRules            : NotConfigured
AllowUserApps                   : NotConfigured
AllowUserPorts                  : NotConfigured
AllowUnicastResponseToMulticast : NotConfigured
NotifyOnListen                  : False
EnableStealthModeForIPsec       : NotConfigured
LogFileName                     : %systemroot%\system32\LogFiles\Firewall\pfirewall.log
LogMaxSizeKilobytes             : 4096
LogAllowed                      : False
LogBlocked                      : False
LogIgnored                      : NotConfigured
DisabledInterfaceAliases        : {NotConfigured}

〜〜〜省略〜〜〜

PS C:\Users\Administrator>  
```

**文字列抽出結果**

```powershell:文字列抽出前
PS C:\Users\Administrator> Get-NetFirewallProfile | Out-String -Stream | Select-String Domain

Name                            : Domain

PS C:\Users\Administrator>  
```

## 使用例②

**test.txt**の中から「test」の行を抽出

```powershell:文字列抽出前
 PS C:\Users\Administrator\Desktop> cat .\test.txt
aaaa

aaaa
test


vagfafa

fafeaea

iiaaaa

faejfajefa
```

**文字列抽出結果**

```powershell:文字列抽出結果
PS C:\Users\Administrator\Desktop> cat .\test.txt | Out-String -Stream | Select-String "test"

test

PS C:\Users\Administrator\Desktop>  
```

# まとめ

下記コマンドで行を検索できる。

```powershell:コマンド
 <コマンド> | Out-String -Stream | Select-String <検索したい文字列> 
```
Dockerのimage名をrepositoryとtag名で検索する

# コマンド
- `docker images [OPTIONS] [REPOSITORY[:TAG]]`

## 説明

```
docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
openjdk                 16-slim-buster      0b97ad2b2200        25 hours ago        417MB
openjdk                 16-jdk              b735a7317062        25 hours ago        500MB
mysql                   8.0.20              be0dbf01a0f3        4 weeks ago         541MB
quay.io/cybozu/golang   1.13-bionic         ec982649cca5        4 months ago        761MB
```

- 上のような結果のときにREPOSITORYが `openjdk` のものだけを取り出したいとき


```
docker images openjdk
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
openjdk             16-slim-buster      0b97ad2b2200        25 hours ago        417MB
openjdk             16-jdk              b735a7317062        25 hours ago        500MB
```
- タグ指定も出来る。

```
docker images openjdk:16-slim-buster
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
openjdk             16-slim-buster      0b97ad2b2200        25 hours ago        417MB
```

- 部分一致も出来る

- repository

```
docker images quay.io/*/*
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
quay.io/cybozu/golang   1.13-bionic         ec982649cca5        4 months ago        761MB
```
   
- tagの指定

```
docker images *:16-slim-buster
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
openjdk             16-slim-buster      0b97ad2b2200        25 hours ago        417MB
```

- optionとの併用

```
docker images openjdk -qa
0b97ad2b2200
b735a7317062
```

### 終わりに
- 今までずっとgrepかfilter使ってたけど、こっち使ったほうが便利。


## 参考
- https://docs.docker.com/engine/reference/commandline/images/#list-images-by-name-and-tag
【初心者向け】Swift基礎用語まとめ

これまでなんとなくで理解していたSwiftの用語を備忘録としてまとめていきます。

この間、初めてレビューを受けて基本用語が理解できておらず、苦しかったため…:bow:

わからない単語は今後追記していく予定です。（多分）

間違っていることなどありましたら優しく教えてください:bow:

[1.letとvarの違い](#1-letとvarの違い)
[2.クロージャ](#2-クロージャ)
[3.オプショナル](#3-オプショナル)
[4.アンラップ](#4-アンラップ)
[5.オプショナルバイディング](#5-オプショナルバイディング)
[6.guard](#6-guard)
[7.didSet](#7-didSet)
[8.lazy](#8-lazy)
[9.lifecycle](#9-lifecycle)
[10.[weak self]](#10-[weak self])
[11.参考文献](#11-参考文献)


#1. letとvarの違い
let・・・一度初期化したら、後から書き換えられない変数に使う
var・・・後から書き換えることができる変数に使う

また、型を宣言しなくてもswift側で自動判別してくれる

```
var num = 10
num = 20    //書き換えられる


let num2 = 3.14
num2 = 4.14  //　　エラーが発生する
```

#2. クロージャ
##クロージャとは
クロージャとは実行可能なコードとそれが記述された箇所の環境を取り込んで、後から評価できるように保存したものです。
要するに再利用可能なひとまとまりな処理で、関数の一種です。

```
{(仮引数：型)-> 戻り値の型 in
  クロージャ実行時の処理
}
```

これが基本形です。サンプルを書くと

```
var c1 = { (x:Int) -> Int in
 x+1
}

c1(3)   //実行結果:4
```
c1に代入されているものが**クロージャのインスタンス**で、代入の右辺は**クロージャ式**と呼ばれます。

クロージャ実行時の処理が複数行ある場合はブロックの中でreturn文を実行しなくてはいけません。

```
let c2 = { (a:Int, b:Int) -> Double in
 if b == 0 {return 0.0}          //bが0の場合は0を返す
 return Double(a) / Double(b)    //0以外の時は割り算した値を返す
}

print(c2(10,8))  // 実行結果 1.25
```

##クロージャと関数の違い
クロージャは関数と同じように実行できますが、関数と区別する必要はないそうです。基本的には、クロージャと関数は区別なく扱うことができますが、変数や定数に格納された関数の呼び出しには注意が必要です。

//TODO


#3. オプショナル
オプショナル型は、通常の変数と異なり**空の値（値が無い）状態を保持することができる変数**です。

オプショナル型を宣言するときは、変数の型の後ろに?(クエスチョン)をつけます。

```
var a: Int = 0
var b: Int? = 10
b = nil   //代入可能
a = nil   //エラー発生
```

また、初期値を設定しないとnilになります。


#4. アンラップ
オプショナルInt型は整数かnilなのですが、Int型そのものではないため変数に代入や演算に使うことはできません。

```
var tax: Double? =1.10
var price = 1000 * tax   //エラーになる
```

上記のようにオプショナル型からデータを取り出すことを**アンラップ(開示)**と言います。アンラップのためにはオプショナル型に対して「!」という記号を使います。

```
var tax: Double? =1.10
var price = 1000 * tax!   
```


#5. オプショナルバイディング
オプショナル型の式の値がnilではなかった場合、その値をif文のthenで使いたい時に用いるのがこの**オプショナルバイディング（if-let文)**です。オプショナル型に入っている値がnilかどうかわからない時に使います。

```
var tax: Double? =1.10
if let x =　tax {
   var price = 1000 * tax   
} else {
   print("エラー発生")
}
```

オプショナル型がnilでないことをif文で確認後、taxを演算に使用しています。
そのため、オプショナルバイディングのあとは**アンラップは不要**です。

#6. guard
安全にデータを取り出す際にguard文を使います。

```
guard 条件 else { 
 　　　breakやreturn
}
```

条件が成立しなかった際にelse文が実行され、そのコードブロックから抜け出します。

チェックする値がオプショナル型である場合、nilチェックと同時にアンラップすることができ、そのアンラップされた変数をguard文の後も使うことができます。

```
func printMessage(message: String?) {
	guard let thisMessage = message else {  //nilのチェックをし、同時にアンラップされた変数を使用可能にしている。
		print("nilです")
		return
	}
	print(thisMessage)
}
```



#7. didSet
Storyboardからボタンやテキストフィールドを生成した際に、部品をまとめて書くことができる。

```
@IBOutlet weak var emailTextField: UITextField! {
    didSet {
            emailTextField.placeholder = R.string.localizable.email()
            emailTextField.clearButtonMode = UITextField.ViewMode.always
           }
}
```

これによってviewDidLoad()をスリムに書くことができ、また、コードの可読性が上がる。


#8. lazy
#9. lifecycle
#10. [weak self]

#11. 参考文献
https://medium.com/@daikimochizuki/ios-swift-didsetでviewdidloadをスリム化しよう-867fe1e97ddc
https://www.sejuku.net/blog/32607
vimのscrolloffをwindowの高さに合わせて割合設定する


vimrcにscrolloffという設定があるのを知りました。
いろんなパソコンでvimを利用していると固定値で設定するより割合で設定した方が便利なことが多いですよね。
初めて設定値を動的に入れられるようにしてみたので、記録してみます。

## 目次

- 最終的な設定
- 動き.gif
- 簡易解説
- 後書き

## 最終的な設定

早速ですが、最終的に作成した設定になります。  

```vimrc
" windowの20%をscrolloffに設定
autocmd BufRead,BufNewFile,WinEnter * execute "setlocal scrolloff=" . str2nr(string(floor((line('w$') - line('w0')) * 0.20)))
```

20%に設定しているのは `0.20` の部分です。
お好みに合わせて数値を変えてください。  

## 動き.gif

この記事をピンポイントで探している方は動きを理解しているとは思いますが、せっかくなのでscrolloff設定の有無を動きで見てみます！  

### scrolloffがない場合

![scrolloff_off.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586917/2f54520d-f3c4-1535-8d78-08fc2c217e5c.gif)

通常通り、カーソルがファイルの最下部を超えると画面がスクロールします。  

### scrolloffがある場合

![scrolloff_on.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586917/a7c2d7cd-fd7d-604c-c9c4-e68273f0d569.gif)

この場合scrolloffで設定した位置をカーソルが超えるとスクロールします。
コードを読むときなどに、こちらの方が個人的には使いやすいです。  

## 簡易解説

今回はautocmdで特定タイミングで自動でコマンドを実行するようにして設定をしました。
autocmdは以下のような構文です。  

```
autocmd <イベント> <ファイルパターン> <実行コマンド>
```

> イベント: BufRead,BufNewFile

ここでコマンドを実行するタイミングを指定しています。
これはそれぞれ以下のようなタイミングで実行されます。

```
BufNewFile: 存在しないファイルの編集を始めたとき。新しいファイルを作成したときなど
BufRead: 新しいバッファの編集を始めたとき。
WinEnter: 既に開いているウィンドウにカーソルが入ったとき。
```
参照: [イベント一覧](https://vim-jp.org/vimdoc-ja/autocmd.html#{event})

WinEnterは頻繁に発生するイベントなので重い処理は入れない方が良いと思います。
今回は以下のようなケースに対応するために追加しました。

1. ウィンドウ幅を超えたファイルを開く
2. ウィンドウ幅以下の行数のファイルを開く
3. scrolloffが小さく設定されてしまう。

画面上に写っている行の開始と終了から計算しているため、ウィンドウの行数以下のファイルを開くとscrolloffが変わってしまうんですよね...
そこへ対処するためのWinEnterです。
もっと良いやり方があれば教えてください！

> ファイルパターン: *

これはそのままですね。全てのファイルを対象にしています。

> 実行コマンド: execute "setlocal scrolloff=" . str2nr(string(floor((line('w$') - line('w0')) * 0.20)))

ここは最初以下のようにしていたのですが、うまく動作しませんでした。
`setlocal scrolloff=str2nr(string(floor((line('w$') - line('w0')) * 0.20)))`

どうも=の右側が全て文字列として渡っていたようで、処理が実行できていませんでした。
そのため今回は `execute` コマンドを利用することで処理を実行できるようにしています。

[line()](https://vim-jp.org/vimdoc-ja/eval.html#line()) 部分は行数の取得です。
w0でカレントウィンドウの最上行、w$でカレントウィンドウの最下行を取得して計算しています。
割合を掛けたあとは `floor` で端数を切り捨てています。

scrolloffにはintしか値が渡せないようだったので、その後にstr2nr(string()) で float型になっている値を無理やりintに変換しています。
もっとシンプルなキャスト方法ないのでしょうか？？

試行錯誤しましたが、こんな感じで機能を実現できました!!


## 後書き

vimは自分でカスタマイズしていけるのが楽しいですね。
今回たまたまscrolloff設定などを見つけたので、定期的に設定一覧を眺めてみるとどんどん便利な機能が発見できそうな気がしました。
AWSのベストプラクティスとなる主な設計原則(自分用メモ)

■主な設計原則には次のような内容がある。

　◎スケーラビリティ
　◎デプロイ可能なリソース
　◎環境の自動化
　◎疎結合化
　◎サーバー代わりのマネージドサービス
　◎柔軟なデータストレージオプション
品質向上のため、関数の戻り値はエラー情報の返却で統一する

# この記事について

C/C++言語において、品質を向上するためのコツについて記載します。本記事では品質向上を考慮した関数定義の方法について記載します。


# 関数定義のコツ

関数を定義する場合、通常は引数は関数の入力、関数の戻り値に出力を定義するようになっていますが、品質を考えた場合に、関数の機能に関わらず、呼び出し元に関数でエラーが発生したかどうかの情報も取得できるようにする必要があります。

この時、各関数でエラー情報の出力方法が異なっていると、呼び出し元でのエラー処理漏れなどにつながり品質を低下させる恐れがあります。

これを防ぐために、関数の戻り値はエラーを表すように統一すると、エラー処理忘れなどを防ぐことができ品質向上に貢献できます。この場合、関数から戻り値を得たい場合は、呼び出し元より関数の引数で与えた領域に返してもらうようにすることで達成します。

C言語の場合、以下のようなパターンで関数を定義します。

**関数定義のパターン**

```c

//--------------------------------------
// 入力なしの関数の定義
//--------------------------------------
// 規定パラメータの設定処理など、必ず成功する関数の場合のみ採用します
void function(void);
void function(Type* p_output);

//--------------------------------------
// 入力ありの関数定義
//--------------------------------------
// 入力がある場合、関数作成者ではコントロールできないエラーが
// 発生する可能性があるため、エラー情報は必ず返すようにします
Error function(const Type* p_input);
Error function(const Type* p_input, Type* p_output);
```

エラー型(Error)の定義は例えば、以下のようにdefineすることで定義できます。

```c:error_type.h
#ifndef Error
#define Error uint32_t
#else
/* すでにdefineされていた場合のエラー処理 */
#endif
```

具体的なエラーは以下のように定義することができます。

**エラー種別の定義例**

```c:error_type.h
// 成功は０で定義します
#define E_SUCCESS            (0x0000)

// 各種エラーの種別を定義します
// 先頭バイトで種類分けするとエラー種別の追加などで拡張する際に整理しやすくなります
#define E_SYSTEM_ERROR       (0x1000)

#define E_IO_ERROR           (0x2000)
#define E_IO_ERROR_NEW_FILE  (0x2001)
#define E_IO_ERROR_OPEN_FILE (0x2002)

// エラー判定用のマクロは以下のように定義できます
#define E_IS_SUCCESS(err)  ((err) == E_SUCCESS)
#define E_HAS_ERROR(err)   ((err) != E_SUCCESS)
```

この定義を使ったファイルを作成するプログラムの例を示します。
記載が多少冗長にはなりますが、書き方が統一されることでレビューなどで
エラー処理漏れが検出しやすくなり、品質向上に貢献できるようになります。

**関数定義の適用例**

```c:サンプル
#include <error_type.h>

Error create_file( const char* filename, FILE** pp_fp){
    FILE* p_tmp;
    p_tmp = fopen(filename, "w");
    
    if( NULL == p_tmp ){
        // fopen()がNULLを返却したということに対して
        // エラー番号を返すことで意味を付加して呼び出し元に通知できます
        return E_IO_ERROR_NEW_FILE;
    }
    else{
    }

    // 成功した場合のみ、戻り値の領域を変更します
    *pp_fp = p_tmp;
    return E_SUCCESS;
}

int main(void){
    Error err;
    FILE* p_file   = NULL;
    const char* filename = "sample.txt";

    // 入力（引数）がある関数は必ずエラーを返すルールにより
    // エラー処理漏れがわかりやすくなります
    err = create_file( filename, &p_file );
    if( E_HAS_ERROR(err) ){
        printf("Open Error!")
    }
    else{
        // ファイルオープン成功
    } 
    return 0;
}
```

# 参考

- [IPA ISEC エラーハンドリング](https://www.ipa.go.jp/security/awareness/vendor/programmingv2/contents/c502.html)
- [JPCERT ERR02-C. 正常終了時の値とエラーの値は別の手段で通知する](https://www.jpcert.or.jp/sc-rules/c-err02-c.html)
icu4c がバージョンアップされたせいでphpが動作しなくなったときの解決策

# 背景

`php artisan list` など php のコマンドが実行できなくなった。
`php -v` すら動作しない。

```
$ php -v
dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.66.dylib
  Reason: image not found
```

# 調査

かるく調べてみたところ、 `brew yarn install` (あまり自信がないがたぶんこれが原因)により、 `icu4c` がバージョンアップされてしまい、依存関係が崩れてしまったためのようだ。

```
$ brew info icu4c
icu4c: stable 67.1 (bottled) [keg-only]
```

どうやら、エラーから察するにこれをv66系にダウングレードする必要がありそう。

ちなみに、phpは `phpenv` でコントロールしていて、 `php7.2.24` で稼働しているのだが、 `新しめのバージョン(php7.3.11)` の場合は依存関係がクリアであるため問題なく動作する。

```
$ php -v
PHP 7.3.11 (cli) (built: Feb 29 2020 02:50:36) ( NTS )
```

（今回はphpとの依存関係で発生しているが、他のものとの依存関係は発生すると思うので、どちらかをアップグレード、またはダウングレードして合わせる必要がある。今回はダウングレードを選択した。）

# 解決策

で、過去のバージョンに切り替えるのだが、過去のバージョンがCellerに残っているとき以下に各バージョンが出てくる。

```
$ brew info icu4c
icu4c: stable 67.1 (bottled) [keg-only]
C/C++ and Java libraries for Unicode and globalization
http://site.icu-project.org/home
/usr/local/Cellar/icu4c/67.1 (258 files, 71.2MB)
  Poured from bottle on 2020-07-08 at 12:10:46
（ここにずらっとバージョンがならぶ）
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/icu4c.rb
```

その場合、 `brew switch icu4c 66.1` みたいな感じで切り替えが可能だが今回はないので、過去コミットから取得してくる必要がある

```
// Formula へ移動
cd /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/Formula

// コミットを確認ん
$ git log --oneline icu4c.rb
88b9cc7898 icu4c: update 67.1 bottle.
e7d9d76421 icu4c 67.1
22fb699a41 icu4c: update 66.1 bottle.  <-ここに戻したい
c78114de12 icu4c 66.1
a806a621ed icu4c: update homepage and url (#44812)
896d1018c7 icu4c: update 64.2 bottle.

// 戻したいバージョンにアップデート
// これで古いバージョンをインストールする状態になった
$ git checkout 22fb699a41 icu4c.rb
Updated 1 path from f3a60216be

// reinstall
$ brew reinstall icu4c

// バージョンの再確認
$ brew info icu4c
icu4c: stable 66.1 (bottled) [keg-only]
```

ダウングレードができたので、もう一度 `php -v` を試してみます。

```
$ php -v                                                                                                                                                                      (git)-[feature/add_official_account_report]
PHP 7.2.24 (cli) (built: May  3 2020 10:40:39) ( NTS )
```

無事動きましたとさ

# 参考文献
- brewの用語やコマンドはこちら [Homebrew使い方まとめ](https://qiita.com/vintersnow/items/fca0be79cdc28bd2f5e4)
- brewのダウングレードはこちら [Homebrewで過去バージョンにダウングレードする2つの方法](https://blog.mothule.com/mac/homebrew/mac-homebrew-how-to-downgrade)
Webpacker::Manifest::MissingEntryError

#画像のエラーを解決するのに手間取りすぎたから、備忘録メモです。
<img width="989" alt="スクリーンショット 2020-07-10 16.38.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653956/0b2e6e38-7e3a-3265-7d46-599141ecbc96.png">

##先に結論
僕の場合は`docker-compose run --rm web yarn install`したら解決した

##環境
【環境】
・Ruby 2.6.6
・Rails 6.0.3.2
・Docker

## webpackerについて参考にさせていただいた記事
https://qiita.com/Furuta03/items/0957e69c0927be5c1a8b

##Dockerfile
```ruby:qiita.rb
FROM ruby:2.6

# install package to docker container
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev \
    && apt-get install apt-transport-https \
    && curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list \
    && apt-get update && apt-get install -y yarn \
    && curl -sL https://deb.nodesource.com/setup_10.x | bash - \
    && apt-get install -y nodejs \
    && mkdir /アプリ名

WORKDIR /FANTRA
COPY Gemfile /アプリ名/Gemfile
COPY Gemfile.lock /アプリ名/Gemfile.lock

COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

```




##確認したこと
- webpackerインストールしてるか？
    - rails webpacker:install 実行ずみ
（実行すると、`conflict config/webpacker.yml`が出る）
- yarnインストールしてるか？
    - 1.22.4
- nodejsインストールしてるか？
    - v10.21.0 

必要な物は揃っているはずなのになぜかできない。。。






##わかってなかったこと
そもそもwebpackとは？
>Webpackとは、CSS、JavaScript、画像などを１つのファイルとしてまとめるためのモジュールバンドラーで、node.jsのモジュールの1つ。

yarn ないし npm はruby でいうところの**bundler**で、ライブラリを管理してくれる**nodejs**のツールのこと。
`bundle install`しないと ruby のライブラリが利用できないのと同じように`yarn install`を実行しないと、 package.json によって指定されている nodejs ライブラリがダウンロードされず実行できないらしい。
webpack はnodejs のライブラリやから、このエラーを解消するためには`yarn install` を `bundle install` と同じような取り扱いで実行する必要があるらしい。





##yarn installをしてみる

```ruby:qiita.rb
 $  docker-compose run --rm web yarn install 
```

無事にエラーを解決することができました。


##メモ
DockerfileのRUNしてるものとかymlの内容とかで実行しないといけないコマンド違ってくるのかな？？
【AWS】WordPress「画像を切り抜く際にエラーが発生しました。」の対処方法

#現象
Amazon LinuxインスタンスでWordpressをたてた。その際に画像を編集すると「画像を切り抜く際にエラーが発生しました。」とエラーが発生し、画像を切り抜けない。

#原因
原因はphp-gdというプログラムがインストールしていないため。
実際にphp-gdがインストールされているか、下記コマンドを入力して確かめたが、やはりインストールされていなかった。

```
yum info php-gd
```

表示結果

```
$ yum info php-gd
読み込んだプラグイン:xxx
利用可能なパッケージ
名前                : php-gd
アーキテクチャー    : xxx
バージョン          : xxx
リリース            : xxx
容量                : xxx
リポジトリー        : xxx
要約                : A module for PHP applications for using the gd graphics
                    : library
URL                 : http://www.php.net/
ライセンス          : PHP and BSD
説明                : The php-gd package contains a dynamic shared object that
                    : will add support for using the gd graphics library to PHP
```

(一部内容省略)

#対処法
1.php-gdを下記コマンドでインストール。

```
sudo yum -y install php-gd
```

2.下記コマンドで再起動して有効化。

```
sudo systemctl restart httpd.service
```

3.念のため、再起動できているか確認。

```
sudo systemctl status httpd.service
```

4.php-gdがインストールされているか確認。

```
$ yum info php-gd
読み込んだプラグイン:xxx
インストール済みパッケージ
名前                : php-gd
アーキテクチャー    : xxx
バージョン          : xxx
リリース            : xxx
容量                : xxx
リポジトリー        : installed
提供元リポジトリー  : xxx
要約                : A module for PHP applications for using the gd graphics
                    : library
URL                 : http://www.php.net/
ライセンス          : PHP and BSD
説明                : The php-gd package contains a dynamic shared object that
                    : will add support for using the gd graphics library to PHP.
```

(一部内容省略)

上記作業で、画像を編集する際も「画像を切り抜く際にエラーが発生しました。」というエラーが解消され、画像を切り抜けるようになった。


参考
https://webbibouroku.com/Blog/Article/wordpress-php-gd
https://www.it-swarm-ja.tech/ja/php/amazon-linux-2%e3%81%aegd%e7%94%bb%e5%83%8f%e6%8b%a1%e5%bc%b5%e3%81%ab%e9%96%a2%e3%81%99%e3%82%8b%e5%95%8f%e9%a1%8c/807484822/
GAS でAPIを作って公開する。



# この記事に目的。
表題の備忘

# 手順
## 1 コード

下記のようにJsonを返すWebアプリを作成

```javascript

function doGet(e){
  var json;
  json = {
    "hoge" : "hoge",
    "foo" : "bar"
  }
  json = ContentService.createTextOutput(JSON.stringify(json));
  return json;
}
```

## 2 webアプリケーションとして公開
公開したらブラウザからアクセスしてみると、jsonが表示できるはず。
Chromeの拡張機能　json Viewer　を使うと表示が楽ちん。

## 3 クライアント JS


```javascript

var request = new XMLHttpRequest();

request.open('GET', "ここにGASで発行されたWebアプリのurl", true);
request.responseType = 'json';

request.onload = function () {
  var data = this.response;
  console.log(data);
  var o = document.createElement("span");
  o.innerHTML = data["foo"];
  document.body.appendChild(o);
};

request.send();

```


## 補足
外部ドメインからだと、クロスドメインの制約に引っかかると思う。