OmniAICreator/Qiita-1.07M huggingface dataset:
Flutter TDD Clean Architecture Course その10 - Bloc ScaffoldingとInput Conversion

- [こちらのチュートリアル](https://resocoder.com/2019/10/07/flutter-tdd-clean-architecture-course-10-bloc-scaffolding-input-conversion/)の解説をします。
- チュートリアルを読むのが早いと思いますが、[概要をまとめた](https://qiita.com/maria_mari/items/8fdd92af13a36c663360)のでこちらもご参照ください。


# 前回まで
- CleanArchitectureに基づき以下をTDDで実装しました
    - Domain層
    - Data層
# 今回やること
- Presentation層の実装に着手します
    - BLoCの作成に着手します

--- 

# チュートリアル解読
## Presentation層
### 以下のようなもので構成さｓれる
- WidgetによるUI
- Presentation Logic
    - ChangeNotifier
    - BLoC
    - ViewModel等
- ここではBLoCを用いる

## BLoC
### 概要
- Business Logic Component
    - CleanArchitecture上ではPresentation Logicを扱う
        - なのでDomain層ではなくPresentation層の役割を担う
        - Domain層がビジネスロジックを担っている

### 構成
#### Events
- "get concrete number" のようなイベント
- UIから送られる

#### Bloc
- Eventsを受け取る
- CleanArchitectureではUseCaseを実行する

#### States
- BlocからUIに送られる
    - UIはそのStatesを基に描かれる
- NumberTriviaのようなインスタンスを持つ


## BLoCの実装
### Events
- NumberTriviaアプリでは2つのイベントを作る
    - 理由: ConcreteNumberとRandomNumberを表示させる2つのボタンを持つから
- EventsはWidgetsから送られる
    - Buttonを押すことで、TextFieldに入力されたStringが送られる

### InputConverter
- `Either<Failure, int> stringToUnsignedInteger(String str)`を持つ`InputConverter`を作成する
    - TextFieldに入力されたStringをint（またはFailure）に変換する

### States
- 以下のStateを作成する
    - Empty
    - Loading
    - Loaded
    - Error

# 学んだこと
- CleanArchitectureではBlocはPresentation層に位置する
    - MVVMのVMのような位置だと思う
    - EntityとUseCaseがDomain層となる
- 通常の設計だとBloCがDomain層に位置することがあるのだと思う

## Blocの構成
- UIがEventをBlocに送る
- Blocが受け取ったEventをもとにStateを作成し通知する
- Stateを受け取ったUIが再描画する
WordPressのカスタム投稿で新規投稿をできないようにする

ワードプレスのテーマtwentytwentyoneを基盤に、カスタム投稿で新規投稿をできないようにする実装を行ったので、備忘録的にこの記事を残す。

# 環境情報

PHP：version 7.3.12
WordPress：version 5.5.3
WPテーマ：twentytwentyone

# 作業

functions.php に下記のコードを追加する

```functions.php
// 新規追加ボタンの非表示化
function custom_edit_newpost_delete($hook) {
	if($hook == 'edit.php' || $hook == 'post.php'){
        $postType = get_post_type();
        if ( $postType == 'company' ) {
            echo '<style>.wrap .wp-heading-inline + .page-title-action{display: none;}</style>';
        }
	}
}
add_action('admin_enqueue_scripts', 'custom_edit_newpost_delete');
```

functions.php の args に下記のコードを追加する

```functions.php
'capabilities' => array(
  'create_posts' => false,
),
'map_meta_cap' => true, //編集機能を残すために必要
```
RedHat系にインストールするPostgreSQLのRepository RPMの探し方

## はじめに
RedHat系で使うPostgreSQLのRepository RPMの探し方です（最近、忘れがちな自分向けの備忘録）。

## 手順
[PostgreSQL Linux downloads (Red Hat family) ](https://www.postgresql.org/download/linux/redhat/#yum "https://www.postgresql.org/download/linux/redhat/#yum")へアクセスします。

1. PostgreSQL Yum Repositoryにある「Select version:」で対象バージョンを選択します。
2. 「Select platform:」から対象OSバージョンを選びます。
3. 「Select architecture:」から対象アーキテクチャを選びます。
4. 「Copy, paste and run the relevant parts of the setup script:」の「# Install the repository RPM:」下に対象のRepository RPMのURLが出てくるので、こちらを使います。

![qiita-SS2020-12-22-152013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240816/9e51a389-3c57-79d5-cebc-661f43f97ce8.png "PostgreSQL Yum Repository")
.Net FW2.8 Global.asax内イベント発生する順序を参考にされては



Asp.Net Global.asax内イベント発生する順序を参考にされては

Application_Start
↓
Application_BeginRequest (HTTPリクエストハンドラでのリクエスト処理開始前）
↓
Application_AuthenticateRequest (認証準備完了後）
↓
Application_AuthorizeRequest (ユーザ認証完了後）
↓
Application_ResolveRequestCache (キャッシュからの後続の要求を処理するために使用する応答をキャッシング モジュールで格納できる)
ここまでセッションを利用できません。
↓
Session_Start （セッション開始、この前のイベント内セッションを利用できません。）
↓
Application_AcquireRequestState (リクエストに関連した状態（セッション等）を取得時
↓
Application_PreRequestHandlerExecute (HTTPハンドラによるページ実行直前）
↓
Application_PostRequestHandlerExecute (HTTPハンドラによるページ実行終了後）
↓
Application_ReleaseRequestState (実行処理の終了後）
ここからセッションを利用できません。
↓
Application_UpdateRequestCache (出力キャッシュ更新後）
↓
Application_EndRequest (HTTPリクエスト処理完了後）
↓
Application_PreSendRequestHandlers (HTTPヘッダ情報送信前）
筆者の環境ではこのイベント入りません
↓
Application_PreSendRequestContent (HTTPコンテンツ情報送信前）
【Git】不要なファイルをPushしないPRに含めない(自戒)

# はじめに

プルリクエストに余計なファイルを含めてしまうみなさんこんにちは！！！！！
つい脳死で全ての差分をpushしてしまう自分への自戒を込めて、pushしないための対策とやらかしたときの対処法を書きます。

# なぜこの記事を書くに至ったか
僕は現在サイバーエージェントでiOSエンジニアとしてインターンをしているのですが、PRのなかで「このファイルは必要ない」という指摘をめちゃくちゃいただきます。
実装ではない部分にコメントをいただくことが多いのはあまりよろしくないことだと思ったのでこういった記事を書くに至りました。

# そもそも不要なファイルをpushしない
そもそもpushしなければあとから対処する必要もありません。

```
$ git status
```
git statusでステージングする前にファイルを確認しましょう。

```
$ git add 対象のファイル

$ git add -p 対象のファイル
```
のどちらかでpushする必要のあるファイルのみステージングしましょう。

# ミスってGitHubにpushしちゃったら

```
$ git checkout master -- 対象のファイル

$ git add 対象のファイル

$ git commit -m"コミットメッセージ"

$ git push origin ブランチ名
```
もしくは

```
$ git checkout 1つ前のcommitID 対象のファイル

$ git diff --cached

$ git commit -m"コミットメッセージ"

$ git push origin ブランチ名
```

このどちらかで取り消すことができます。
僕と同じやらかしをした方はぜひ使ってみてください！！！
WordPressで管理画面の「編集」「クイック編集」「ゴミ箱」「プレビュー」の項目を非表示にする

ワードプレスのテーマtwentytwentyoneを基盤に、管理画面のサイドバーのメニューの順番を並び替える実装を行ったので、備忘録的にこの記事を残す。

# 環境情報

PHP：version 7.3.12
WordPress：version 5.5.3
WPテーマ：twentytwentyone

# 作業

```functions.php
function custom_action_row( $actions ) {
    unset($actions['edit']); //編集
    unset($actions['inline hide-if-no-js']); //クイック編集
    unset($actions['trash']); //ゴミ箱
    $postType = get_post_type();
    if ( $postType == 'works' || $postType == 'topic' ) {
        unset($actions['view']); //プレビュー
    }
    return $actions;
}
add_filter( 'post_row_actions', 'custom_action_row', 10, 2 );
```

※「works」と「topic」のカスタム投稿だけ「プレビュー」を削除するようにしています。
Java15の気になる新機能について触れてみた

# はじめに
こちらは [ゆるWeb勉強会@札幌 Advent Calendar 2020](https://adventar.org/calendars/5068) 23日目の記事です。
Qiita には約1年ぶりの投稿となりました。

今回は、2020年9月15日にリリースされた **Java15** の新機能について少し触れてみたいと思います。

# Java15 の新機能
Java15 での主な変更点は下記URLにまとめられています。
https://openjdk.java.net/projects/jdk/15/

この記事では、以下の3点を取り上げます。

- テキストブロック
- レコード
- パターンマッチング

## テキストブロック
改行を含む文字列リテラルを定義できるテキストブロック。Java12よりプレビュー機能として実装されていましたが、今回正式版としてリリースされました。

テキストブロックは、ダブルクォーテーション3つ（`"""`)で囲みます。

```java
String htmlText = """
    <html>
        <body>
            <span>Text Blocks</span>
        </body>
    </html>
""";
```

HTMLやJSONのような（JSONはベタで書くことは少ないかな？）複数行の文字列を扱う機会は意外に多いので、ソースコードの可読性向上という面では、とても便利な機能だと思います。

テキストブロックの主な特徴：

- 開始の区切り文字の直後は改行のみ（続けて文字を書くことはできない）
- 各行の末尾の空白は除去される
- インデントは、テキストブロック内の各行で最も浅いインデントで統一される

その他の仕様や機能追加の経緯については JEP のページを確認してみてください。
[JEP 378: Text Blocks](https://openjdk.java.net/jeps/378)

## レコード（セカンドプレビュー版）
レコード（record）を使うと、データを保持するためのイミュータブル（不変）なクラスを簡潔に定義できます。Java14 でプレビュー版として実装され、今回よりセカンドプレビュー版となりました。

レコードを定義する時は `record クラス名(引数の指定) {}` のように記述します。
具体的な例を見てみましょう。

Person というデータクラスに、フィールド name・age を定義するとします。

```java
public record Person(String name, int age) {}
```

上記の記述だけで、コンパイル時にはコンストラクタや getter メソッドなどが自動的に生成されます。データクラスのコード記述量が圧倒的に少なくなりますね！！

```java
public class Person extends Record {
    private final String name;
    private final int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    // getterのメソッド名は
    public String name() {
        return name;
    }
    public int age() {
        return age;
    }
    // ...以下省略...
}
```

コンストラクタで引数チェックを追加したい場合などは、必要に応じて処理を拡張することもできます。

Records はまだプレビュー版のため、Eclipse で動作させたい場合は、以下設定画面よりプレビュー機能を有効化してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49458/6ebd4967-2d78-75d5-c81f-c393b55b3a5c.png)

参考：
[JEP 395: Records](https://openjdk.java.net/jeps/395)

## パターンマッチング（セカンドプレビュー版）
こちらは正規表現を指すものではなく、`instanceof` 演算子でオブジェクトの型チェックをした際、型のキャストが不要になるというものです。

従来の `instanceof` 演算子は、以下のように型チェックの後でキャストする必要がありました。

```java
if (obj instanceof String) {
    String s = (String)obj;
    System.out.println(s.length());
}
```

パターンマッチングを使用する場合、型チェック後のキャストは不要で、指定した型の変数に格納するところまでを自動で行なってくれるようになります。

```java
if (obj instanceof String s) {
    System.out.println(s.length());
}
```
参考：
[JEP 375: Pattern Matching for instanceof (Second Preview)](https://openjdk.java.net/jeps/375)

# 余談： Javaのプレビュー版とは？
Javaのプレビュー版とは、新機能を正式に取り込む前に、試験的に実装される機能のことです。
基本的には以下のステップを踏んで正式リリースされます。

①プレビュー版として実装される
②セカンドプレビュー版として実装される
③正式版として実装される

プレビュー機能は開発者からのフィードバックを受け、最終的に正式リリースとなる場合もあれば、廃止となる場合もあります。

# まとめ
先日リリースされたばかりの Java15 の新機能から、比較的内容が分かりやすく導入しやすそうな機能をピックアップしてご紹介しました。

現場では「他の言語と比べて Java は記述量が多くて面倒だ」といった声をよく耳にしますが（涙）、最近のリリース内容を見てみると、ソースコードの可読性や開発効率向上のための改善がどんどん採用されていることが分かります。

新しい書き方を積極的に取り入れて、もっと Java の良さを周りに伝えられるようになりたいです。

# 参考記事
- [Javaのプロフェッショナルが教えるJava14とJava15の新機能
](https://logmi.jp/tech/articles/323179)
- [Java 15新機能まとめ](https://qiita.com/nowokay/items/2858699bc1cd89222cd8)
DNS設定の時に感じた疑問点Q&A

自分がDNS設定の時に感じた疑問ベースで書いているので体系立っていないですがご了承ください(土下座

## Q. レジストリ、レジストラとは？

**レジストリ**・・・TLDごとに存在する、TLDを管理する組織。例: [.com](https://www.verisign.com/?inc=www.verisigninc.com)、[.org](https://www.publicinterestregistry.org/)、[.edu](https://net.e 6uhyhb ducause.edu/)など。
**レジストラ**・・・各レジストリと契約を結び、レジストリデータベースに直接ドメイン情報を登録する事ができる業者。例: [お名前.com](www.onamae.com/)、[Netowl](https://px.a8.net/svt/ejp)など。

[ドメイン名の登録 - JPNIC](https://www.nic.ad.jp/ja/dom/registration.html)

## Q. ゾーンファイルとは？
ゾーンファイル = **IPアドレスとドメイン名の対応表**

## Q. SOA、NSレコードの役割とは？
SOA…ゾーンに関する情報
NS…DNSサーバの名前

これが一番わかりやすかった。笑
[SOAレコードとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word12285.html)
[NSレコードとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word12286.html)

## Q. SOA、NSレコードの中身の見方
**SOAレコードの中身**
「プライマリネームサーバのホスト名 管理者のメールアドレス シリアル番号 セカンダリネームサーバとの連携に使われるパラメータ3つ TTL」

**NSレコードの中身**
「ネームサーバ名」

[DNSレコードの登録ルール - レコードタイプごとの登録ルール](https://manual.iij.jp/dpf/help/19629152.html#DNS%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E7%99%BB%E9%8C%B2%E3%83%AB%E3%83%BC%E3%83%AB-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%82%BF%E3%82%A4%E3%83%97%E3%81%94%E3%81%A8%E3%81%AE%E7%99%BB%E9%8C%B2%E3%83%AB%E3%83%BC%E3%83%AB)


## Q.digコマンドの使い方・見方

```
$ dig <ドメイン名> ns
```

のコマンドで、

```
;; ANSWER SECTION:
```

からの出力部分が使用されているネームサーバー。

[DNSサーバーが正常に動作しているかどうか確認するには？　digコマンド：ネットワーク管理の基本Tips - ＠IT](https://www.atmarkit.co.jp/ait/articles/1409/25/news001.html#sample2)
## Q. DNS設定のドメイン末尾の.は何？
そもそもコンピュータの世界ではドメインの末尾にドットがついた状態が**正しい記法**。
末尾のドットを書かないと**省略記法**と見なされて別の解釈がなされてしまう。
[＠IT：DNS Tips：ゾーンファイルの書き方について教えてください](https://www.atmarkit.co.jp/fnetwork/dnstips/031.html)

## Q. TXTレコードの "" は必ず必要？
基本的に**必要**。
[DNSレコードの登録ルール - レコードタイプごとの登録ルール](https://manual.iij.jp/dpf/help/19629152.html#DNS%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E7%99%BB%E9%8C%B2%E3%83%AB%E3%83%BC%E3%83%AB-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%82%BF%E3%82%A4%E3%83%97%E3%81%94%E3%81%A8%E3%81%AE%E7%99%BB%E9%8C%B2%E3%83%AB%E3%83%BC%E3%83%AB)

## Q. 値の先頭がアンダースコアなのは何か意味がある？
**SRVレコード**や**TLSAレコード**だと値の先頭をアンダースコアで設定する必要がある。
あと他にもレコードによって_が使えたり使えなかったりがある。
[DNSレコードの登録ルール（バリデーションルール）](https://manual.iij.jp/dns/help/1481516.html)


おしまい。
Docker開発環境でdeviseの日本語ファイルを作成しようとしたところ発生したエラーの解決方法について

開発環境にDockerを導入している状態で、deviseを導入し、エラーメッセージなどを日本語で表示させるために日本語ファイルを作成しようと下記コマンドを実行したところ

```
$ docker-compose run web rails g devise:views:locale ja
```
すると下記のようなエラーが発生した。

```
Starting aoo_db_1 ... done
Could not find devise-i18n-1.9.2 in any of the sources
Run `bundle install` to install missing gems.
```

`devise-i18n-1.9.2`というGemが見つからないから、 `bundle install`を実行してGemを入れてねってことらしい

けど、Gemはしっかりと書いてあるし、`bundle install`も問題なく通るし、なんだこれ？？なっていたが、調べてみるとどうやらキャッシュで bundle install が実行されない場合があるらしい。

解決方法としては下記のコマンドを実行すればOK

```
$ docker-compose build --no-cache
```

上記を実行したあとに

```
$ docker-compose run web rails g devise:views:locale ja
```

を実行すると

```
Creating network "app_default" with the default driver
Creating app_db_1 ... done
      create  config/locales/devise.views.ja.yml
```

といった感じに無事に日本語ファイルが作成された。



原因としてはサーバーを起動している状態でコマンドを打ったせいで、`bundle install`がうまく行かずに、Gemが正しくインストールされずに起こったっぽいので次回からはしっかりとサーバーを止めてから、`bundle install`を行うように気をつけたい。

Gemしっかりと入ってるはずなのになぜ！！？と少し焦ったが、調べてみると対策がすぐに見つかったので助かった。先人様様ですわね！！先人しか勝たん！！！

参考：https://fuqda.hatenablog.com/entry/2019/03/21/204118
NetBSDのnlコマンドとProblem Reports


この記事は[NetBSD Advent Calendar 2020](https://qiita.com/advent-calendar/2020/netbsd)、23日目の記事です。
[nlコマンド Advent Calendar 2020](https://qiita.com/advent-calendar/2020/nl)も開催中です。よろしくおねがいします。


#nlコマンドのPOSIX非互換

[macOSの`nl`でPOSIXの非互換を見つけた](https://qiita.com/Carol_815/items/0e7de6dd1fb3d821ec6e#bsd%E7%B3%BB%E3%81%AEnl%E3%81%AE%E3%82%BB%E3%83%91%E3%83%AC%E3%83%BC%E3%82%BF%E3%81%A8posix)のですが、調べてみたら[NetBSD由来](https://qiita.com/Carol_815/items/a298d7063e77d00d8bec#bsd%E7%B3%BBmacosfreebsd%E7%AD%89)だということがわかりました。そこでNetBSD 9.1をインストールして試したところ同じように再現しました。

```console:NetBSD-9.1
$ yes '' | head | nl -s @
      @
      @
      @
      @
      @
      @
      @
      @
      @
      @
```

これ、[POSIX](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/nl.html)的には`@`が出ちゃダメなんですよね。

>When line numbers are suppressed for a portion of the page; the \<separator\> is also suppressed.

というわけで、macOSの`nl`まで反映されるのかはわかりませんが、ひとまずNetBSDの不具合として報告してみることにしました。


#問題を報告する

このページに従って報告すればよさそうです。

[NetBSD Problem Reports](https://www.netbsd.org/support/send-pr.html)

> Submitting a bug or problem report via the Web
This is a two-step process:
1. Checking the problem is not already reported, using the Query PR form
2. Submitting a new problem report, using the Send PR form

簡単！2ステップ！つまり投稿前に類似がないかちゃんと調べてねってことみたいです。
NetBSDなら`send-pr`というコマンドが使えるようです。（私ユーザーじゃないんですごめんなさい）

## Query PR

ここで既に報告がないか調べます。
https://www.netbsd.org/support/query-pr.html

`nl`で検索すると`only`とかが引っかかって大変なので、`nl[^a-z]`とかやってみたらそれなりの数になりました。一応、Closeしたやつも検索対象に入れましょう。

## Send PR

類似の報告がなければ、こちらのフォームを埋めます。
http://www.netbsd.org/cgi-bin/sendpr.cgi?gndb=netbsd

フィールドの説明は[PRの最初のページ](https://www.netbsd.org/support/send-pr.html)に書いてあるので参考にしましょう。

今回の報告については、Severityの欄をnon-criticalにしました。おそらく世界の誰も困っていないですし、「ドキュメントと一致しない」というのが説明に書かれていたからです。

>non-critical
The product, component or concept is working in general, but lacks features, has irritating behavior, does something wrong, or doesn't match its documentation.

あとは問題を説明するのに必要な情報を書くだけです。内容については特に変わったところもなかったです。
ボットよけの方法が独特でサーバーのOSを答えさせる問が最後にありました。

>This server runs NetBSD. To verify you are not a bot, which OS does this server run?



レポートを投稿すると最後にこんなメッセージが出ます。

> Thank you for your problem report. You should receive confirmation of your problem report and an internal identification number by electronic mail in less than 24 hours.

そしてまもなくトラッキング番号がメールで送られてきました。

おしまいです。あとは返事をのんびり待ちます。
NimでReactiveExtensionsしてみる（追記中）

# Rx(Reactive Extensions)とは

ReactiveExtensionsはC#から出てきたもので
購読と通知という概念があります。
詳しくはこちらがわかりやすくまとめられていると思います。
https://qiita.com/nomok_/items/39b5d7c61810f274768d

# なんのために？

ネイティブ開発のように複数の画面がありつつ、
複数のお互いの画面が生きているのか分からず、
それぞれの画面ライフサイクルを考慮しつつ
双方向に、非同期に通知を行う際にとても便利です。

# NimでRx

https://github.com/nortero-code/rx-nim
こんなライブラリがあったので紐解きつつ使えそうかみていきます。

```Nim
import nimrx
import sugar # =>をつかうため

let subj = behaviorSubject(123)
var test = 0
discard subj.subscribe((val: int) => (test = val))
echo test
subj.next(321)
echo test
#discard subj.subscribe((val: int) => (test = 555))

```
Googleスプレッドシートで出力したcsvをindesignでデータ結合する方法

Googleスプレッドシートで書き出すと、おそらく文字コード「UTF-8」で書き出されます。
でもindesignのデータ結合では「SHIFT_JIS」しか読み込めません。
なので、
（他のツールでも全然いいですが、）Bracketsのここで「SHIFT_JIS」に変換してから、文字をペーストしたら直りました。以上です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276138/8b02c941-465c-82bd-f53f-7077efbdea76.png)
React高階コンポーネント(HOC)について

# はじめに

業務でReactを利用していますが、高階コンポーネントについて学んだことを備忘録を兼ねて投稿します。

# 高階コンポーネントとは

あるコンポーネントを受け取って、新しいコンポーネントを返す関数です。
高階関数のコンポーネント版といった感じです。

```js
// 公式ドキュメント
const EnhancedComponent = higherOrderComponent(WrappedComponent);

// react-redux
export default connect(mapStateToProps, mapDispatchToProps)(Component);

// react-router
export default withRouter(Component);
```

# どういうときに使うのか

横断的関心事を処理する方法として利用します。
横断的関心事とはコンポーネントにまたがって処理しなければならない要素の事で、以下のような事柄を指します。

- 認可・ログイン状態
- ログ・トラッキング
- 例外・エラー処理

例えばreact-routerでは、ルーティングに必要な機能をコンポーネントのpropsに渡すために、withRouterという関数が用意されています。

以下がwithRouterの実装ですが、ReactのContext APIを使い、ラッピングしたコンポーネントに対してRouterContextから購読した値をpropsに渡しているのがわかるかと思います。

```jsx
/**
 * A public higher-order component to access the imperative API
 */
function withRouter(Component) {
  const displayName = `withRouter(${Component.displayName || Component.name})`;
  const C = props => {
    const { wrappedComponentRef, ...remainingProps } = props;

    return (
      <RouterContext.Consumer>
        {context => {
          invariant(
            context,
            `You should not use <${displayName} /> outside a <Router>`
          );
          return (
            <Component
              {...remainingProps}
              {...context}
              ref={wrappedComponentRef}
            />
          );
        }}
      </RouterContext.Consumer>
    );
  };
  ...
  return hoistStatics(C, Component);
}
```

https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/withRouter.js

# まとめ

高階コンポーネントは、Reactのメジャーな周辺ライブラリでも採用されているテクニックですので、今後機会があれば利用したいと思います。
今まで横断的関心事にはミックスインが利用されてきましたが、こちらは現在推奨されない実装のようですね。別途記事にしたいと思います。
https://ja.reactjs.org/blog/2016/07/13/mixins-considered-harmful.html

## 参照

https://ja.reactjs.org/docs/higher-order-components.html
Cloud9からgitに登録する際にキャッシュを削除する。

Cloud9からgitにfirst commitしたら.c9というCloud9のキャッシュフォルダまでgit commitされちゃうんだよね...

https://stackoverflow.com/questions/26345488/git-continues-to-push-a-c9-folder-despite-it-being-in-gitignore

まあここに書いてあることそのままだけど、

```console
git rm --cached .c9/ -r
```
で再帰的にキャッシュ削除して、

```.gitignore
#Ignore all .c9 specific files
/.c9/
```

vimで、（ってエディタならなんでもいいが）gitignoreに追加して、再度Pushする、ってだけだね。
ローカルでNode-REDを実行してみた

Node-RED アドベントカレンダー22日目！
今まで Node-RED は enebular や IBM Cloud 上で使ったことがありましたが、そういえばローカルで実行したことがないなぁと思ったのでやってみました。

ドキュメントの[「ローカルでNode-REDを実行する」](https://nodered.jp/docs/getting-started/local) を読みながら自分のローカル環境で実行した時の手順をまとめてみます。

#実行時のローカル環境
- macOS 10.14.6（Mojave）
- Node.js 10.16.3

#手順ざっくり
1-a. Node.js のインストール
1-b. 既にインストールしたことがある場合は [Node.js のバージョン確認](https://nodered.jp/docs/faq/node-versions)
　　※ 2020年12月22日現在、バージョン 10.x と 12.x の Node.js を推奨しているようです
2. npm で Node-RED をインストール
3. Node-RED を実行する
4. ブラウザから Node-RED エディタにアクセスする

#手順詳しく
###1-b. Node.js のバージョン確認

```shell:ターミナル
# 以下のコマンドを実行
node --version

# 実行結果で以下のように表示されたら成功です！
v10.16.3
```

###2. npm で Node-RED をインストール
```shell:ターミナル
# 以下のコマンドを実行
sudo npm install -g --unsafe-perm node-red

# 実行結果の最後の行で、以下のように表示されたら成功です！
+ node-red@1.2.6
added 364 packages from 321 contributors in 37.524s
```

###3. Node-RED 実行する
```shell:ターミナル
# 以下のコマンドを実行
node-red

# 実行結果の最後の行で、以下のように表示されたら成功です！
22 Dec 17:58:03 -[info] サーバは http://127.0.0.1:1880/ で実行中です
```

###4. ブラウザから Node-RED エディタにアクセスする
ローカルで起動したサーバーのURL（ http://127.0.0.1:1880/ ）へ、ブラウザからアクセスします。
![スクリーンショット 2020-12-22 18.11.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526082/aa2dfa4d-096f-3e44-e623-1c8e628fdecc.png)
アクセスすると、Node-RED エディタが表示されました！
![スクリーンショット 2020-12-22 18.28.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526082/5e5f9b28-337e-2b00-5124-041c434d7507.png)

#サーバーを停止する時は
ターミナルで `control+c` で停止します。

#おわりに
思っていたよりも簡単に Node-RED をローカルで実行できました！
ただ、ターミナルを使ったことがない人にとっては enebular や IBM Cloud が良いんだろうなと思いました。enebular や IBM Cloud に加えて、今度からはローカルも開発の手段にしていこうかなと思います〜
Strapiを使ったこと無い人が使う時の勘所を書いてみた #strapi #HeadlessCMS

さきにお断りをいれておきます。
昔話を交えながら、Strapiってこんな風につかうのかな？という私感を書いたポエムです。
そして、私はStrapiを使ったことがありません。社内で別なチームがStrapiを使って開発していることを傍らで見た印象で書いています。

### 結論から言ってしまうと、、、
このStrapi Advent Calendarでは、他のHeadlessCMSの比較や動かし方がわかりやすく書かれており、開発の省力化に貢献すると思うので少数精鋭でプロダクト開発しているチームなら利用することを検討してみては？と思います。

#### Strapiはデータモデルに従ったBackend APIを提供してくれる
Tomigieさんが書いた[Strapi Quick Start Guide 日本語訳](https://zenn.dev/tomigie/articles/e6c77540fb42f5)を見てもらえうと分かる通り、`Content-Types`を作成してPublish操作などすることで自動的にAPIが生成されます。
生成されたAPIも山上さんが書いた[ブログ](https://qiita.com/yamagamisan/items/c1053d1ee021e5f30c13)の通り、カスタマイズすることができます。

そのため、DB定義やデータモデルが決まっていれば、Backendが簡単に生成することができるのでオススメです。

あとは、FrontendとBackendを開発チームが別々に作る場合、BackendのモックAPIサーバとして利用することもできそうです。というのも、このStrapi Pluginで[Swaggerを生成できる](https://strapi.io/blog/api-documentation-plugin)ため、先行してFrontendを作成して、Strapiで生成したSwaggerをもとにAPIを製造していくこともできそうです。

### Strapiを使うときの勘所
Strapiを使う場合の勘所としてはデータモデルをベースにコードを生成しているので、モデル設計が緩い状態では自動生成するとは言え、戻り作業が増えるので注意が必要になりそうなイメージです。
CRUDのAPIが生成されてURLも `/{Content-Types}/:id`という感じになるため、モデルのキーが変わった場合に影響が大きそうです。

スクラム開発でもウォーターフォール開発でもデータモデルがキモだったりしますので、そこのブレが少なくなってから使ってみるのが良いと思われます。

このStrapiでは、APIを自動生成しますが、REST APIを設計する時の勘所がとても良くまとまったブログがクラスメソッドの都元さんが書かれているので、ご紹介しておきます。

- Classmethod Developers.IO: [Developers.IO 2018 で「API 設計」の話をしてきた](https://dev.classmethod.jp/articles/cmdevio2018-api/)



### さて、昔話ですが、、、
昔からコードを書く量をいかに少なくして、プログラマーがよりクリエィティブなUXの向上やマネタイズな部分に時間を使えるようにするか？が至上命題でいまでも苦心していることが多いと思います。Strapiではモデルを作成することで、モデルに対応するCRUDのAPIが生成されるようになっています。

その昔、カード型データベースと呼ばれるデータを単票形式で保管することに特化したものがありました。これは、現在の年賀状ソフトの住所録をイメージしてもらうとわかり易いと思います。UIとして個人の住所を登録するものがあり、UIから直接にDBへ記録されます。
個人の住所録など小規模であれば、メンテナンスや検索速度の問題は顕著になりませんが、大規模になった場合には単票の検索性の悪さや単票１枚に項目が多くなったり、冗長な項目が増えてデータの肥大化するなどの問題が発生します。

手軽なUIとRDBのいいとこ取りを目指した例として、マイクロソフトAccessを挙げることできます。
Accessでは、DBのテーブル項目をUIのフォームへ配置し、UIから直接CRUDを実現することができました。また、一覧画面を作ればテーブルのデータを全て閲覧したり、フィルタすることができました。
この状況は、簡便な方法としてCSS（クライアント・サーバ・システム）と呼ばれるシステムでも利用されていました。（もちろん、CSSでFrontendをVBやCで組んで、DBとの関係性を疎にする仕組みが多数を占めるようにはなっていました）

その後、時代はWebになり、FrontendとDBがつながっていた関係性からFrontend＋Backend＋DBという３階層のプログラム構成になり、MVC/MVVCといわれるアーキテクチャになりました。FrontendではAjaxを使って非同期で処理しつつ美麗なUIを表示し、Backendではバッチ処理で実施していたような複雑なビジネスロジックの実装が必要になりシステムが巨大化していきました。

巨大化システムをいかに素早く作るかということで、ソースコードの自動生成システムが大手SIerを中心に開発されて発売されていました。仕組みは、だいたい一緒でシステムで取り扱う項目（画面、DB）を洗い出して、その項目をモデルとして登録し、そこからBackendを生成するものでした。（O/Rマッピングを生成する感じですね）
項目を一元管理して、そこから生成するのでケアレスミスを少なくすることができ、冗長なコードをプログラマーが書かなくてもよく、開発スピードが上がることが期待されていました。筆者の経験としては開発スピードは速くなった気がします。仕様が揺らぐプロジェクトでDB設計が変わると影響範囲が大きくなりがちで苦労した思い出はあります。

このStrapiでもデータモデルに変更があった場合、大きな影響が予想されるので、しっかりとユーザーストーリーやユースケースが洗い出されていることを重要かもしれませんね。
新卒がリモート環境で社内勉強会を任され苦労した話

この記事は[Zeals Advent Calendar 2020](https://qiita.com/advent-calendar/2020/zeals)の22日目の記事です。

# はじめに

こんにちは！Zealsの新卒でエンジニアしております赤羽です。
弊社の社内勉強会が一周年を迎えたので運営する上での課題やそれに対しての施策を共有できればと思います。

# 読んで欲しい人
- リモートワークで社内勉強会を開催している運営の人
- 社内勉強会の集まりが悪く続かないと悩んでいる人

# 勉強会

弊社では去年の12月から毎週勉強会が行われています。立ち上げたのは私ではない先輩エンジニアで、3ヶ月ほど経ってから新卒に運用が任されることになりました。
私は企画・運営などは大学のサークルで少し経験済みだったので軽く引き受けたのですがこれが予想以上大変でした。
### リモート前
オフィスにいる頃の勉強会は順調で業務をしている人も手を止めて発表に耳を傾ける文化ができていてかなり盛り上がっていました。
発表者も先輩エンジニアが先頭に立ち率先して発表していたこともあって途切れる事はなく特に大きな問題はなかったです。
### リモート後
しかし今年の4月からリモートワークが開始されオンラインでの勉強会になり参加者が可視化され、2,3ヶ月経ったある頃毎週のように参加者が減っていることに気づきました・・・
エンジニアは全体で25名ほどいましたが最も集まらない時は `12名`で約半数。。。 
それと同時に発表者を募ってもなかなか手が上がらず特定の人に依存する状態でした😨


このままだと勉強会が消滅しかねないのでそれまで私一人で運用していましたが助けを求め運営チームを作りPDCA回す事にしました。


# 現状調査
まずは現状調査ということでアンケートを取りました。
回答数22
### 勉強会への満足度
![スクリーンショット 2020-12-22 13.36.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414247/3488afb8-8950-0f12-5456-5f79d2b71eaf.png)
最も多いのは77%で3。その次に多いのは13%で2でした。
これでは満足度が高いとは決して言えません。


### 発表回数
![スクリーンショット 2020-12-22 13.48.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414247/7e6749f0-f3b9-b26f-ba9b-ce11e3bb1257.png)

発表回数で一番多いのは36％で2~3回。
これだけで見れば多いと思われるでしょうがこれは勉強会が始まってから9ヶ月が経過してからのアンケートで勉強会は毎週行っています。
4回以上の発表者の中には10回を超える方もいるので実は大きな偏りがあるのです。

### 課題
アンケートを整理すると以下の3つの課題が大きく浮かび上がってきました。

- 満足度が低い
- 業務が忙しくて発表できない
- ネタが無いので発表できない

この3つの課題をベースに施策を打って出ることを決めました。

# 現在実施している施策
## 満足度が低い

### 勉強会終わりに発表者と運営にフィードバックを貰う。
毎週満足度を調査することで現状を把握します。
発表者へフィードバックを伝えることで発表者のモチベーションアップを図ります。
運営へのフィードバックはその次の週の最初に返答することで改善していることをアピールできます。
フィードバックがなかなか集まらない時はフィードバックを書いてもらう時間を勉強会内で作りましょう。
特に発表者へのフィードバックはまた発表したいと思っていただく上で重要だと考えています。

## 業務が忙しくて発表できない

### チームごとにリーダーを作る
運営が全エンジニアの仕事の状況や各々が興味を持っている分野を把握することは難しく、各チームに一人ずつリーダーを作り発表を促すようにお願いしました。
これにより普段積極的に発言しない方でも「この人が言うのであれば」ということで発表して頂けるようになりました。
ただこれはチームとしてまとまりがあることが必須であり全エンジニアをカバーできておりません。

### 2週間後まで予定を埋める。
それまで当日に発表者を募っていましたが大抵の場合、資料を土日に作成するので遅いという意見を頂きました。
現状2週間前までに発表者を埋めるようにしていますが、すんなり埋まるときもあれば一週間前まで決まっていないということもあるので改善が必用です。
今後3週間前でも良い気はしています。

## ネタが無いので発表できない

### アウトプットすることを目標設定する
エンジニアは日々勉強しインプットすることが不可欠です。
そこで得た知識を勉強会でアウトプットすることで自分の知識へと定着させることを目標に置きました。
なのでライトニングトーク呼ばれる簡素な内容でも良いという周知を行っています。

## 他にも
### KPIを設定し毎週目標達成できているか確認する。
KPIを置くことで毎週定量的に現状を把握できます。
今KPIにしている内容は参加者数です。最近はコンスタントにクリアできているので次のKPIを模索中です。

### 盛り上がっている感を作る！
盛り上がっている感とはslackでの勉強会の告知や全体MTGなどでKPIの報告をして、楽しそうなイベントが毎週あることを印象付けることです。
そりゃ楽しい事に人は集まりますよね。

# 施策を行った結果
毎週のフィードバックの満足度は日に日に高くなっており運営として勉強会を改善できている実感があります。
そして以前は参加者が12名ほどでしたが今では平均して `20名` ほど参加して頂いており、KPIの21人（エンジニアの80%）も達成することが多いです。
しかしまだまだ課題は多く

- リーダーシステムが一部しか機能しておらず運営が直接声掛けしにいくことが多い。
- 外国人エンジニアが多いため日本語しか話せないエンジニアとのディスカッションが難しい。
- 自ら手をあげて発表する人が少ない。
- エンジニアのレベルが高いため質に拘って発表者が辞退してしまうことがある。

などがあり、これらを改善すべく次なる施策を考えております。

# 最後に
勉強会を通して企画・運営の難しさを実感しました。
エンジニアがこういった貴重な経験を積めているのはありがたいことだと思っています。
この記事が少しでも参考になればと思います！！
nulab Backlog CLI: nulab の Backlog をコマンドラインで見ることにした

nulab の Backlog をコマンドラインで見るために、 ツールを作りました。

## 経緯

開発者に予定を聞くと、 Backlog の 課題(Issue)番号でなにをやるかを答えてくることが結構ありました。
しかし Backlog をいちいち開くのも時間がかかります。
コマンドラインで見られればもっと仕事はやくおわるのではと思ってツールを作りました。

## 作ったツールの使い方

まだ jar 作るところまでしかやってないのですが、 https://github.com/qw3rtman/jbin など使うと単体で実行できるアプリにできるみたいです。

### はじめに

最初に実行するとドメイン名とAPIキーを聞かれます。
入力するとホームディレクトリに `.blt/config` というファイルを作って保存します。

```
input domain: XXXXXX
input api key: XXXXXX
Save? [y/N]
```

2回目からは保存された情報を使います。

### プロジェクトの設定

`set project XXXX` と入力して使うプロジェクトを決めます。

```
set project XXXXX
The project is set to XXXXX.
```

ここからプロジェクト内の課題やPRを見ていくことができます。

### 課題の一覧を見る

issue と入力するとCloseになっていない課題を100件まで表示します。
次の100件を見る機能はそんなに重要じゃなかったのでまだ作っていません。

```
> issue
XXXX-8369 This is the issue title
XXXX-8368 This is the issue title
XXXX-8367 This is the issue title
XXXX-8366 This is the issue title
XXXX-8365 This is the issue title
XXXX-8364 This is the issue title
```

### 課題の内容を見る

これが今回一番使いたかった機能です。
`issue 9999` のように 課題 の番号を入力するか、
`issue XXXX-9999` のようにキーを入力すると 課題の内容が表示されます。

```
> issue 9999
Issue title

(no detail)

Creator: Kenji Otsuka (大塚健司) (kok.fdcm@gmail.com)
Assignee: Kenji Otsuka (大塚健司) (kok.fdcm@gmail.com)
Due Date: (none)

```

タイトル、内容、作成者、担当者、期日を表示します。

まだコメント表示はできていません。

### Repository を設定する

`set repo XXXXX` とすることで リポジトリを設定できます。
これにより、リポジトリに関する操作ができるようになります。

```
> set repo sample
The repository is set to sample.
```

### Pull Request の一覧を見る

`pr` と入力すると リポジトリのPRを一覧で表示します。

```
> pr
1015 [WIP]XXXXXXX
1157 XXXXXXX
1205 [WIP]XXXXXXX
1437 YYYYYYYYYY
1489 [WIP] XXXXXX
1537 [WIP] XXXXXX
```

番号とタイトルを表示します。

### Pull Request の詳細を見る

`pr 1234` と入力すると Pull Request の詳細が表示されます。

```
> pr 3230
Pull Request Title

(no description)

feature/Sample -> develop
```

Pull Request のタイトル、内容、ブランチが表示されます。

ここでもコメント表示機能は未作成です。

## Repository

https://github.com/KenjiOhtsuka/backlog_tool

## 技術要素

* 設定ファイルはJSONで保存
    * https://github.com/Kotlin/kotlinx.serialization/blob/master/docs/basic-serialization.md
* Backlogとの連携は公式ライブラリ
    * https://github.com/nulab/backlog4j
* 細かいパラメータを実装するときはこれがきっと役に立つと思って依存関係に追加した(まだ使ってない)
    * https://github.com/Kotlin/kotlinx-cli

## その他

* GitHub にリポジトリがあれば [Homebrew](https://docs.brew.sh/Formula-Cookbook) でインストールできたりするらしいので余裕があればそちらも進めていきたい。
    * 参考
        * https://qiita.com/minamijoyo/items/8bb3c80974b77b8ae81f
        * https://qiita.com/minamijoyo/items/285d8838ffaa7ae1fe5f
* 別のプロジェクトで作っていたコードをコピーしてきた経緯があるので、使っていないコードがたくさんある。 毎回インスタンス作る部分などあるしクラス設計も雑。効率化できるところはたくさんある。
* 似たツールに gitb というのがあって、 コマンドラインで Backlog の URL を作れるんだけど求めていたのとは違った。
* コマンドラインでIssueも作成できたら楽。
* git を使っている場合にその情報からプロジェクトの内容など取得できるとよいですね。
[Node.js] Node.jsからMySqlへのデータの登録・更新・削除

#Node.jsからMySqlへのデータの更新

※自分用の覚え書きでございます。

req を受け取り、MySql へ post します。

###INSERT

```javascript:app.js
app.post('/entry', (req, res) => {
  connection.query(
    'INSERT INTO tbl_items (name) VALUES (?)',
    [req.body.itemName],
    (error, results) => {
      connection.query(
        'SELECT * FROM tbl_items',
        (error, results) => {
          res.render('index.ejs', {items: results});
        }
      );
    }
  );
});
```

###UPDATE

```javascript:app.js
app.post('/update/:id', (req, res) => {
  connection.query(
    'UPDATE tbl_items SET name = ? WHERE id = ?',
    [req.body.itemName,req.params.id],
    (error, results) => {
      res.redirect('/index');
    }
  );
});
```

###DELETE

```javascript:app.js
app.post('/delete/:id', (req, res) => {
  connection.query(
    'DELETE FROM tbl_items WHERE id = ?',
    [req.params.id],
    (error, results) => {
      res.redirect('/index');
    }
  );
});
```
【IQ Bot】テーブルのマッピング（段組みの表の取得方法）

2020年も年の瀬が迫ってまいりました。

Qiita上のIQ Bot関係の記事も100トピックを超えてきましたが、まだまだ、書いたつもりで書いていないトピックがありますねー。

そのひとつが「段組みの表のマッピング」です。

#IQ Botは段組みの表でも取得ができる

まずそもそもの話として、IQ Botは段組みの表でも取得ができます。
![段組みの表.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/7bc15751-eb59-dc38-d9f6-f8a1b9651769.jpeg)

もちろん、取得には一定の条件があって、めちゃくちゃ複雑な構造の段組みでも無条件にとれるわけではありません。
上記の場合は、

- 明細の１行の高さが常に固定
- 規格・寸法が常に１段目
- 材質が常に２段目

という規則性があり、かつ画質も高めで構造が安定的にとれるので取得可能というわけです。

#マッピングのやりかたは？

上記のサンプルを取得するマッピング方法は以下のとおりです。（得意のGIFアニメ！）

![段組みのマッピング基本.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/ea28f7b9-aaa6-f1b8-29f4-91c152f985a4.gif)


#こんな表はどうする？

IQ Botが段組みの表を処理できることを知っている程度にはコアにIQ Botを触ってくれているお兄さんから先日、「こんな表もうまくとれますか？」と質問をいただきました。

![段組みの表2_縮小.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/4d1fe89a-a6c8-a84b-abac-386a3e60fbbd.jpeg)

結論から言うととれます。

ポイントは２つあって、

1. 帳票上のラベルの名前に引きずられず、項目の意味を考えよう
2. 同じラベルを複数の項目の取得に使いまわしても大丈夫

です。

いっこずつ解説。

##1. 帳票上のラベルの名前に引きずられず、項目の意味を考えよう

上記の表なんですが、帳票上のラベル（列名）は「品名」としか書いていないですが、まず気づいてほしいのは「書いてある中身、品名だけじゃないじゃん！」ということです。

![段組みの表2_色つき.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/1db8f998-826a-a49a-0630-0040d62fb34e.jpeg)

「品名」として書いてある表の中に、少なくとも型番、品名、日付の３つの項目が入っています。

なのでそもそもIQ Botのインスタンスを作るときに、上記の3つの中から必要な項目を取得項目として定義しておく必要があるということです。

ここでは、型番と品名と日付をそれぞれ全部取得したい、という前提で以下の解説を進めます。
その場合、型番、品名、日付をすべてインスタンス作成時に取得項目として定義しておく必要があります。
（もちろん[作成後に追加](https://qiita.com/IQ_Bocchi/items/7baa94dadd174c78ac62)してもOKです。）
![インスタンス作成画面.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/97c40be0-96aa-722a-85c3-23553c9beb0f.jpeg)
※すみません、図中では型番を「品番」と表記しています。

##2.同じラベルを複数の項目の取得に使いまわしても大丈夫

さて、品番や日付を取得項目に含めたはいいものの、品番と日付にはラベルがありません。

さぁ、どうマッピングしましょうか？

……というときに考えてほしいのは、「仮のラベルを使う」ということです。
「仮のラベル」の考え方については、[こちらの記事](https://qiita.com/IQ_Bocchi/items/9082c2b262004694bada)で解説しています。

仮のラベルの考え方は、フィールド項目だけではなく、テーブル項目にも使えます。

そして、このケースでは「品名」のラベルを「品番」のラベルとしても、「日付」のラベルとしても使いまわします。

そんなわけで、やりかたはこんなかんじです。

![段組みのマッピング応用.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587845/c2e89188-e3d8-594a-3c66-497b3edd1717.gif)

##注意点

表の抽出時にひとつのラベルを複数の項目に使いまわすやりかたは、OCRがGoogle Visionのときはうまくいかないようです。

#まとめ

- IQ Botは段組みの表でも取得ができるよ
- 段組みの表を取得するには一定の条件があるよ（行の高さが固定、画質が安定しているなど）
- 帳票上に記載されたラベルに引きずられず、どんな項目を"出力"するべきかを意識して取得項目を定義しよう
- フィールド項目／テーブル項目ともに、ひとつのラベルを複数の項目のラベルとして使いまわせるよ
- ただし表のラベルを使いまわす方法は、OCRがGoogleVisionのときはうまくいかないよ
Rails逆引きリファレンス

# 機能要件

[[Rails]機能要件の逆引きリファレンス](https://qiita.com/zizynonno/items/ae936e4a4832a8f18858)


# 非機能要件
## Model系
[[Rails]Model系](https://qiita.com/zizynonno/items/3ba21e70011e58c7c4b4)

## View系
[[Rails]View系](https://qiita.com/zizynonno/items/3ac6f0d7e9735aae979c)

## Controller系
[[Rails]Controller系](https://qiita.com/zizynonno/items/881960041557b839c004)

## URL,ルーティング系
[[Rails]ルーティング系](https://qiita.com/zizynonno/items/d64e94b4d43be9b57db6)

## DB,ActiveRecord系
[[Rails]DB,ActiveRecord系](https://qiita.com/zizynonno/items/913a88d3a2e3bbce681c)


## セキュリティ系
[[Rails]セキュリティ系](https://qiita.com/zizynonno/items/a5b1c52986711c4a0ed7)


## デバッグ系
docker下のbinding.pryでのデバッグの方法
https://qiita.com/STHEXA/items/1de2411cb3987066c9b9
https://qiita.com/sukezane/items/c97b9e977d111794d810
https://qiita.com/hb5kz/items/7c9d266480079910de5c




## エラー系
[Rails]エラーメッセージをブラウザ画面に表示したい
https://railstutorial.jp/chapters/basic_login?version=5.1#sec-rendering_with_a_flash_message
https://railstutorial.jp/chapters/sign_up?version=5.1#sec-signup_error_messages
https://railstutorial.jp/chapters/sign_up?version=5.1#sec-the_flash

## タイミング系

[Rails]Emailアドレスをデータベースに保存する際に事前に小文字にしておきたい - コールバック 
https://qiita.com/okamoto_ryo/items/458097542e826623b7ad
https://railstutorial.jp/chapters/account_activation?version=5.1#sec-activation_token_callback
コールバック。オブジェクトが生成(create)、更新(update)、破壊(delete)される時や、バリデーションを実行する時の前後に共通の処理を追加する仕組みのことを指す
before_save { self.email = email.downcase }
ブロックを渡してユーザーのメールアドレスを設定します
before_create :create_activation_digest
上のコードはメソッド参照と呼ばれるもので、こうするとRailsはcreate_activation_digestというメソッドを探し、ユーザーを作成する前に実行するようになります




## 認可、認証、権限関連
[[Rails]認可、認証、権限関連](https://qiita.com/zizynonno/items/137e031230efeee80084)

## DRYに書きたい(可読性、保守性)

[[Rails]DRYに書きたい(可読性、保守性)](https://qiita.com/zizynonno/items/514aedfc8ec47a622d94)

その他
[Rails]rails sがバックグラウンドにあり、ctrl+cで消せない場合
https://qiita.com/kanuu/items/fd6e33fca6ad6a90d059



[Rails]ユニーク制約とは？どんなメリットがある？

[Rails]シンボルを使うタイミング
https://uxmilk.jp/25934

[Rails]attr_accessor とは？
http://bryankawa.hatenablog.com/entry/2017/01/28/150537



非同期で通信がしたい→Ajax,JS
https://railstutorial.jp/chapters/following_users?version=5.1#sec-a_working_follow_button_with_ajax


http://railscasts.com/episodes/205-unobtrusive-javascript
商品の一覧を表示する機能

#はじめに
　今回実装する上で詰まった商品表示機能についてまとめる。

#実装機能
・画像・商品.商品名の３つの表示。
・商品は投稿日が早いもの順に表示。
・売却済みの商品にはsold outを表示。

##画像・商品.商品名の３つの表示

```
<%= @item.price %>円<br><%= @item.shipping_method.name %>
```
今回商品を出品する際に**配送方法、商品の状態、都道府県など**はActive Hashを用いた。

####注意したい点
Active Hashを用いているため上記のnameのところをカラムと同じidとするとidが表示される。

##商品は投稿日が早いもの順に表示
コントローラーのindexアクションでorderメソッドを用いる。
####orederメソッド
テーブルから取得してきたレコード情報を持つインスタンスの並びを変更してくれるメソッド。
並び順にはASC（昇順）とDESC（降順）の2種類がある。

```
@users = User.all.order(カラム名: :並び順)
```
今回の場合、**保存された時間が早いものから表示**させたい。
なので、下記のように保存された時間を保存する**(created_at)カラム**を用いた。
並び順は**新しい物から古い物(降順)**なのでdescを用いた。

```
@items = Item.all.order(created_at: :desc)
```

##売却済みの商品にはsold outを表示

この機能を実装する上で使用したメソッド
・if文を用いて商品が売り切れた場合、sold outを表示したい。
ではどのようにすれば商品が売り切れた時、売り切れていない商品を区別できるのか？　答えは、**presentメソッドを使う**ことで解決できる。

####presentメソッド
オブジェクトであるレシーバーの値が存在すればtrue,存在しなければfalseを返してくれるメソッドである。
if文などの条件分岐を用いる際に使われる事が多い。

```
変数名.present?
```
上記の様に記述する事で使用。
？を一緒につける。
このメソッドを使い今回売却済みの商品にsold outを表示していくと下記のようになる。

```ruby
<% if item.purchase.present?  %>
   <div class='sold-out'>
    <span>Sold Out</span>
   </div>
<% end %>
```
・**itemは商品の情報が入ったテーブルの変数名**
・**purchaseは購入した商品の情報が入ったテーブルの変数名**
この2つは予めアソシエーションを組んでおく必要がある。
認定Platformデベロッパー試験対策

#はじめに
<p>
前回の記事に引き続き、会社がSalesforceのコンサルティングパートナーの申請をするために、認定Platformデベロッパーの試験を取ることになりました。<br>
前回の認定Sales Cloudコンサルタントの試験対策の記事でも記載しましたが、2017年に認定アドミニストレーターの資格を取得し、実際コードを書く開発へも参加しています。
</p>
#前提
<p>
認定Platformデベロッパーの試験対策のTrailheadではSalesforceの独自言語であるApexやVisualforce、またSPAのLightningコンポーネントを学習します。<br>
その前提としていJavaなどのオブジェクト指向言語、HTMLとCSS、Javascriptなどの言語知識を求められます。
</p>
#学習方法
<p>
今回は以下のように学習を進めました。
</p>
* Trailmixでの学習
* 試験対策ウェビナーを受講
* 試験想定問題を解く
* 開発者ドキュメントに目を通す

##Trailmixでの学習
以下のTrailmixで学習を行いました。
[Prepare for Your Salesforce Platform Developer I Credential](https://trailhead.salesforce.com/ja/users/strailhead/trailmixes/prepare-for-your-salesforce-platform-developer-i-credential)
途中Apex SpecialistのSuperbadgeが出てきますが、認定Sales Cloudコンサルタントで出てきたSuperbadgeに比べると簡単な印象でした。
また、途中で関連するTrailなどが紹介されるので、そこから自分用のTrailmixを作成しました。

##試験対策ウェビナーを受講
認定Platformデベロッパーは無料の試験対策ウェビナーを行っています。
私の場合タイミングよく試験の半月前に開催されたため、受講いたしました。
ジャンクションオブジェクトなど、こちらを受講して知る知識もあったため、タイミングが合えば参加されることをお勧めします。
[Salesforce Certification Days](https://www.salesforce.com/jp/campaign/trailhead-academy/certification-days/)

##試験想定問題を解く
こちらは認定Sales Cloudコンサルタントの際も使用した以下のサイトをつかって試験対策を行いました。
ただし実際の試験では選ぶ回答数が指定されていますが、以下のサイトでは問題の回答数が指定されていないため、難易度は高めとなっています。
実際資格を取得できましたが、試験想定問題の正解率は6割程度でした。
最後に間違った問題についてはなぜ間違えなのかはしっかり調べるとよいと思います。
[Salesforceの一番星](https://keneloper.com/getting-certified-for-salesforce-certified-platform-developer/)
[セーブポイントが見つからない](https://savepo.com/salesforce_platform_developer_exam_top)

##開発者ドキュメントに目を通す
認定Platformデベロッパーでは結構細かい部分まで試験で聞かれるので、以下の開発者ドキュメントには目を通しておくとよいと思います。

* SOQL および SOSL リファレンス
* Apex 開発者ガイド
* Salesforce Developer の制限および割り当てクイックリファレンス
* Visualforce 開発者ガイド
* Lightning Aura コンポーネント開発者ガイド
* Lightning Web Components Dev Guide
* プラットフォームイベント開発者ガイド

#試験の所感
##1回目(不合格)
試験対策問題やウェビナーであまり掘り下げていないLightningコンポーネントについての問題が出題されました。コードに関する問題も出るので、Lightningコンポーネントの知識を重点的に対策したほうがよいと感じました。またイベント処理に関する問題も出題されます。
ほかの問題に関しては受験範囲を確認していれば試験対策とのズレはあまり大きくないないと感じましたが、かなり細かいことが問題として出るので、試験時に回答が不安な問題が見直してみると21問ありました。
![デベロッパ1回目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331410/c5576ee0-a85f-1fb2-930f-451ebe713d85.png)

##2回目(合格)
1回目の試験から1週間時間を空け、Lightningコンポーネントとイベント処理を重点的に学習し試験に臨みました。また、認定Platformデベロッパーの試験は問題とその解答が調べればすぐにわかるものが多いため、前回の試験の問題を復習しました。
2回目の試験では回答が不安な問題が13問程度でした。
2回目の試験では1回目の試験と似たような問題や、同じ問題が多く出題されました。そのため試験対策をしっかり行うことが重要と感じました。
![デベロッパ2回目.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/331410/bc805cc5-c1f7-2ee5-598c-db00549bef8f.png)
AWS EC2からRDSに接続しようとしたら「ERROR 2003 (HY000): Can’t connect to MySQL server」が出た

今回はlaravelでAWSにデプロイをしたいという思いでAWSのエラーと現在格闘中です。
少し詰まった箇所を備忘録として投稿させて頂きます。


今回のエラーは

```
ERROR 2003 (HY000): Can’t connect to MySQL server
```

になります。

###今回、参考にして欲しい方は以下の条件になります

`1 インバウンドルールとポートは合っている!!
 2 rdsにあるパブリックアクセシビリティは 「はい」 にした。
 3 https://noumenon-th.net/programming/2020/04/10/ec2-rds-laravel/
  上記のHPを参考にしている `


#エラー対処1
https://noumenon-th.net/programming/2020/04/10/ec2-rds-laravel/
を参考にしてインバウンドルールを新たに作成されたと思います。
デプロイしたいインスタンスにルールをちゃんと設定されましたか?
![“スクリーンショット” 2020-12-21 13.15.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/b4ed0501-2695-b0a4-e351-96fe6ae2196a.jpeg)
してないですよね・・・
ではセキュリティグループを変更しましょう

#エラー対処2-1 セキュリティグループを変更しよう
セキュリティグループを変更するには`アクション` `セキュリティ` `セキュリティグループを変更`の順に進めます。
下記のスクショを参考にして下さい。
![“スクリーンショット” 2020-12-21 13.15.19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/c3ed7f4b-a610-a1ae-cd2f-b329169df77a.jpeg)

#エラー対処2-2 セキュリティグループを変更しよう
`削除`ボタンを押します。押したとしてもセキュリティグループの設定されたデータは消えませんので安心して下さい。
そして`セキュリティグループを編集`のボックスをクリックしてlaravel用にセットしたセキュリティグループを選択。
最後に`保存`をしてください。下記のスクショを参照して下さい。
![“スクリーンショット” 2020-12-22 18.26.53.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/ef72c9cb-4da8-393d-27ac-18bb635e6df8.jpeg)
すると更新ボタンを押して見るとセキュリティグループは変更されているのでしょうか?

これが終わったらインスタンスを起動してEC２を立ち上げて下さい。
![ .jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/30985c13-d588-e3d4-09eb-9f72ed504c7f.jpeg)
それでもエラーが出るのであればインバウンドルールのポートがおかしい可能性があります。

以上です。
CakePDFでファイルサイズを下げる

# 環境

- CakePHP 3.8
- friendsofcake/cakepdf 3.5.2
- DomPDF

# やりたいこと
CakePHP3 で構築しているサイトで、cakepdf を使って PDF 生成をしています。
が、ダウンロードした PDF サイズがなんか 4.3 MB と大きいので、小さくしたかった。

# 方法
使ってる PDF エンジン は DomPdfEngine です。
こちらのサイト↓を参考に、DomPDF の中を見てたらそれっぽい設定値があったので、それらしきオプションを設定。結果、35 KB まで減りました。

[DOMPDFでPDFファイルサイズを小さくする](http://madroom-project.blogspot.com/2012/12/dompdfpdf.html)


```config/bootstrap.php
$this->addPlugin('CakePdf', array('bootstrap' => true));
Configure::write('CakePdf', [
    'engine' => [
        'className' => 'CakePdf.DomPdf',
        'options' => [
            'isRemoteEnabled' => true,
            'isFontSubsettingEnabled' => true, //←これを追加
        ],
    ],
]);
```


▼設定前と設定後のファイル容量
![filesize.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152333/27b7250b-9414-4931-5f70-12ec2c4ca275.png)

XXMB にしたい！という要望だとちょっとこの方法では出来ないのですけど、単にサイズ小さくしたいだけなら問題なさそう。
PDF のダウンロードにかかる時間が若干伸びましたが（サブセット化してるのでしょうがない？）、記事にあったようなエラーは特に出なかったので、まあいいかな、ということで。


# 参考
- [DOMPDFでPDFファイルサイズを小さくする　http://madroom-project.blogspot.com/2012/12/dompdfpdf.html](http://madroom-project.blogspot.com/2012/12/dompdfpdf.html)
- [本家　https://github.com/FriendsOfCake/CakePdf](https://github.com/FriendsOfCake/CakePdf)
Gitで特定フォルダの差分ファイルを抽出する

[gitで差分ファイルを抽出する](https://qiita.com/kaminaly/items/28f9cb4e680deb700833) を参考に関数化してみたんだけど、特定フォルダの差分を抽出することができず結局コマンドを入力して行ったので備忘録として書いておく。

なので、基本的には上記記事を参考にするのがよい。

## 差分を抽出する
`git diff` を使う。

```shell
git diff --diff-filter=d --name-only コミット2 コミット1
```

指定するコミットの順番は、**コミット1からコミット2までの差分**をみるという意味です。なので今の状態からあるコミット(hoge123)をみたい場合、

```shell
git diff --diff-filter=d --name-only hoge123 HEAD
```

と書きます。ちなみに現在の位置(HEAD)から比較する場合はコミット1の部分を省略できます。

```shell
git diff --diff-filter=d --name-only hoge123
```

`--name-only` は差分のあったファイルのパスのみを出力。`--diff-filter=d`は削除した差分だけ除外できるオプション。大文字と小文字で出力結果が変わってくるので注意しましょう。

**参考**
[git diff --diff-filterが地味に優秀（削除ファイルのみ／変更ファイルのみにフィルター）](https://qiita.com/FumiyaShibusawa/items/acc04055b1c9e03cce8a)

### 特定のフォルダの差分を抽出するには
`--`のあとにフォルダを指定してあげます。

```shell
git diff --diff-filter=d --name-only hoge123 -- deploy
```
こうすると`deploy/`直下の差分が抽出できます。

## 差分を抽出しzip圧縮する
先程の`git diff`と`git archive`を組み合わせます。

```shell

git archive --format=zip --prefix=root/ HEAD `git diff --diff-filter=d --name-only hoge123 -- deploy` -o archive.zip
```

### ちょっと注意点
あまりないことですが、パスにスペースが含まれているとエラーになるようです。

**参考**
[Git で差分ファイルを抽出する時にパスにスペースがあるとエラーになる](https://va2577.github.io/post/61/)

## Git拡張コマンド
[gitで差分ファイルを抽出する](https://qiita.com/kaminaly/items/28f9cb4e680deb700833)の記事ではzsh/bashのコマンドとして関数化していますが、自分は`git-diffa`というシェルスクリプトを作成しGitの拡張コマンドとして使っています。

```shell
#!/bin/sh

diff=""
  h="HEAD"
  if [ $# -eq 1 ]; then
    if expr "$1" : '[0-9]*$' > /dev/null ; then
      diff="HEAD~${1} HEAD"
    else
      diff="${1} HEAD"
    fi
  elif [ $# -eq 2 ]; then
    diff="${2} ${1}"
    h=$1
  fi
  if [ "$diff" != "" ]; then
    diff="git diff --diff-filter=d --name-only ${diff}"
  fi
  git archive --format=zip --prefix=root/ $h `eval $diff` -o archive.zip
```
↑を`git-diffa`という名前で保存。パスを通します。macを使っているので、`/usr/local/bin/`に設置しました。

実行権限を付与するのも忘れずに。

```shell
chmod +x /usr/local/bin/git-diffa
```

**参考**
[Git オリジナルのコマンドを作成する](https://qiita.com/icoxfog417/items/1d3ccec32d32bdaadc92)
docker の healthcheck でコンテナのサービスが開始されるのを待つ

# Overview

docker-compose の `depends_on` でコンテナの依存関係を指定すると、コンテナの起動順序が制御できるけど、
立ち上がったコンテナがちゃんと動いてるか？までは担保してくれないので、
「ミドルウェアのコンテナがちゃんと起動してるかどうかのチェックは、wait-for-it とかでアプリケーション側で頑張ってね」的なお困り事案よくあるじゃないですか。
https://docs.docker.jp/compose/startup-order.html

で、 docker に healthcheck 機能があって、
https://dev.classmethod.jp/articles/docker-healthcheck/
これを使うと依存してるコンテナが healthy になるまで起動を待たせられるっていう話。

## 試してみる

alpine に redis 入れて試してみます。

```Dockerfile:Dockerfile
FROM alpine:latest

RUN apk add make redis
```

```Makefile:Makefile
node1:    # 待たされる側
	@ echo "$@ is running!"
	redis-cli -h node2 ping

node2:    # 待たせる側
	@ echo "$@ started!"
	sleep 3    # 3秒待ってから
	redis-server --protected-mode no    # redis-server を起動
	@ echo "$@ ended!"
```

```yaml:docker-compose.yml
version: '3'

services:
  node1:
    image: hoge
    build:
      context: .
    command: make -f /mnt/Makefile node1
    depends_on:
      node2:    # node2 の healthcheck が通るまで起動を待つ
        condition: service_healthy
    volumes:
      - .:/mnt

  node2:
    image: hoge
    build:
      context: .
    command: make -f /mnt/Makefile node2
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 1s
      timeout: 30s
      retries: 30
    volumes:
      - .:/mnt
```

これで

```bash:bash
$ docker-compose build
```

して

```bash:bash
$  docker-compose up
```

すると、 node2 側で redis の起動前に 3秒 sleep してる間は healthcheck の `redis-cli ping` が通らないので、
node1 の起動も待たされる挙動が確認できます。

```bash:こんな感じ
$ docker-compose up
Creating network "docker_default" with the default driver
Creating docker_node2_1 ... done
Creating docker_node1_1 ... done
Attaching to docker_node2_1, docker_node1_1
node2_1  | node2 is started!
node2_1  | sleep 3    # 3秒待ってから
node1_1  | node1 is running!
node1_1  | redis-cli -h node2 ping
node2_1  | redis-server --protected-mode no    # redis-server を起動
node2_1  | 22:C 22 Dec 2020 09:38:25.036 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
node2_1  | 22:C 22 Dec 2020 09:38:25.036 # Redis version=5.0.9, bits=64, commit=869dcbdc, modified=0, pid=22, just started
node2_1  | 22:C 22 Dec 2020 09:38:25.036 # Configuration loaded
node1_1  | PONG
node2_1  | 22:M 22 Dec 2020 09:38:25.039 * Running mode=standalone, port=6379.
node2_1  | 22:M 22 Dec 2020 09:38:25.039 # WARNING: The TCP backlog setting of 511 cannot be enforced because /proc/sys/net/core/somaxconn is set to the lower value of 128.
node2_1  | 22:M 22 Dec 2020 09:38:25.039 # Server initialized
node2_1  | 22:M 22 Dec 2020 09:38:25.039 # WARNING you have Transparent Huge Pages (THP) support enabled in your kernel. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo never > /sys/kernel/mm/transparent_hugepage/enabled' as root, and add it to your /etc/rc.local in order to retain the setting after a reboot. Redis must be restarted after THP is disabled.
node2_1  | 22:M 22 Dec 2020 09:38:25.040 * Ready to accept connections
docker_node1_1 exited with code 0
```

っていう話。

## cf.

https://til.codes/health-check-option-in-docker-to-wait-for-dependent-containers-to-be-healthy/
MATLABで裸眼立体視

　MATLABの3D図は、マウス操作でグリグリと回せるので、そのままでも立体感は得られます。しかし、静止したままの図を立体感を感じながらじっくりと観察できれば、また別の発想が湧いてきそうな気もします。ということで、左右像で裸眼立体視できる3Dグラフを作ってみました。MATLABが描く画像の大きさは、自分のPC上で最適になるような設定にしています。皆さんの環境に合わせて適宜調整してください。左右のz軸の間隔が60～65mm程度になるようにするのが最適です。

　しかし、この下のスクリーンコピーした画像は、ブラウザの横幅を変えるだけで間隔の調整は自在です。適当に調整してご覧になってください。予想外の立体感に感動します。

　プログラムは長々と続いていますが、前半はごく普通の作図処理です。裸眼立体視に必要なのは最後の１９行だけです。

![stereo01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/932484/351c0020-a1a3-d0cc-637f-421a2053310a.jpeg)

```stereo01.m
clear
close all

o=[0 0 0];         % 原点
ex=[1 0 0];        % x軸頂点のx,y,z座標
ey=[0 1 0];        % y軸頂点のx,y,z座標
ez=[0 0 1];        % z軸頂点のx,y,z座標
p=[0.7 1 1]*0.9;   % 任意ベクトルの頂点p
xp=[p(1) 0 0];     % p点のx軸への垂直投影点xp
yp=[0 p(2) 0];     % p点のy軸への垂直投影点yp
zp=[0 0 p(3)];     % p点のz軸への垂直投影点zp
p0=[p(1) p(2) 0];  % p点のxy平面上への垂直投影点p0

figure(1)
plot3([0 ex(1)],[0 ex(2)],[0 ex(3)],'b','LineWidth',2);    % x軸

view(130,12);                        % ここの一連のコマンドは、
axis equal                           % 　記述位置を変えると、
axis([-0.2 1.2 -0.2 1.2 -0.2 1.2]);  % 　期待に沿わない表示に
grid on                              % 　なるので、要注意。
hold on                              % 　原因は未確認。

plot3([0 ey(1)],[0 ey(2)],[0 ey(3)],'b','LineWidth',2);    % y軸
plot3([0 ez(1)],[0 ez(2)],[0 ez(3)],'b','LineWidth',2);    % z軸

plot3([0 p(1)],[0 p(2)],[0 p(3)],'r','LineWidth',2);       % 任意ベクトル

text(ex(1)+0.1,ex(2),ex(3),'x','FontSize',18);             % x軸の先端文字
text(ey(1),ey(2)+0.1,ey(3),'y','FontSize',18);             % y軸の先端文字
text(ez(1),ez(2),ez(3)+0.1,'z','FontSize',18);             % z軸の先端文字
text(p(1)+0.057,p(2)+0.057,p(3)+0.057,'p','FontSize',18);  % 任意ベクトルの先端文字

plot3([p(1) xp(1)],[p(2) xp(2)],[p(3) xp(3)],'k','LineWidth',0.75);     % p-xp線
plot3([p(1) yp(1)],[p(2) yp(2)],[p(3) yp(3)],'k','LineWidth',0.75);     % p-yp線
plot3([p(1) zp(1)],[p(2) zp(2)],[p(3) zp(3)],'k','LineWidth',0.75);     % p-zp線
plot3([p0(1) p(1)],[p0(2) p(2)],[p0(3) p(3)],'k','LineWidth',0.75);     % p-p0線
plot3([p0(1) xp(1)],[p0(2) xp(2)],[p0(3) xp(3)],'k','LineWidth',0.75);  % p0-xp線
plot3([p0(1) yp(1)],[p0(2) yp(2)],[p0(3) yp(3)],'k','LineWidth',0.75);  % p0-yp線
plot3([p0(1) o(1)],[p0(2) o(2)],[p0(3) o(3)],'k','LineWidth',0.75);     % o0-p0線

xlabel('X');
ylabel('Y');
zlabel('Z');

h1=get(gca,'Children');  % figure(1)をコピーする。

% 裸眼立体視用の左右２つの画像を入れる窓を作る。
figure('Position',[250 200 800 400]);  % 指定サイズの新figureを作る（figure(2)となる）

% 新figureの中に左目用の画像を描く。
axes('Position',[0.18 0.2 0.3 0.6],'Projection','perspective');  % 第１の座標面を作る。
copyobj(h1,gca);                                                 % figure(1)を貼り付ける。
title('裸眼立体視（左目用）')

view(130,12);                        % 貼り付けても、視点などの属性は無視されるので、
axis equal                           % 元の属性と同じものを再設定する。
axis([-0.2 1.2 -0.2 1.2 -0.2 1.2]);
grid on

% 新figureの中に右目用の画像を描く。
axes('Position',[0.50 0.2 0.3 0.6],'Projection','perspective');  % 第２の座標面を作る。
copyobj(h1,gca);                                                 % figure(1)を貼り付ける。
title('裸眼立体視（右目用）')

view(135,12);                        % 右目用に、左目用とはazimuthだけが異なる属性を設定する。
axis equal
axis([-0.2 1.2 -0.2 1.2 -0.2 1.2]);
grid on
```
【Java】標準入力で空白で区切られた数値データを受け取る方法

#プログラミング勉強日記
2020年12月22日
昨日に引き続きJavaでの標準入力について扱う。入力された空白で区切られえた数値をデータで受け取る方法を示す。

#ScannerのnextIntメソッドを使う方法

```java
import java.util.*;

public class Sample {
	public static void main(String[] args) {
		int[] points = new int[5];
		Scanner scan = new Scanner(System.in);
		
		for(int i = 0; i < points.length; i++) {
		    points[i] = scan.nextInt();
		    System.out.println(points[i]);
		}
	}
}
```


#キャストする方法

```java
import java.util.*;

public class Sample {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		String[] pointsStr = scan.nextLine().split(" ");
		int[] points = new int[pointsStr.length];

		for(int i = 0; i < points.length; ++i) {
		    points[i] = Integer.parseInt(pointsStr[i]);
		    System.out.println(points[i]);
		}
	}
}
```



#参考文献
[【Java】標準入力を取得・出力する方法](https://qiita.com/mzmz__02/items/3e4c0a7ccbf3bae6f5d3)