OmniAICreator/Qiita-1.07M huggingface dataset:
【個人的】駆け出しエンジニア向け参考書

# 初めまして
SESや特定派遣でインフラエンジニアとして働いてきました。
IT業界の仕組みをようやくざっくりと理解し、
やりたいことも定まってきた社会人5年目の若手です。

# 目的
自身が読んだ本の要約を人にオススメする形でアウトプットしたい。
読み終えた本は随時更新する。

# 内容と対象者
これまで私が読んできた中で初学者向けの参考書を要約と共に紹介します。
これからエンジニアを目指す駆け出しの方向けで、
コンピュータって普段使ってるけど何者？
サーバってなに？コンピュータと何が違うの？
ネットワークとかNEに任せればいいよね！
という方にオススメです。インフラ部門に特化する気がなくても概念として知っておくことは重要です。どんなアプリケーションもインフラの上で成り立っています。

# [痛快！コンピュータ学/坂村 健 著](https://www.amazon.co.jp/%E7%97%9B%E5%BF%AB-%E3%82%B3%E3%83%B3%E3%83%94%E3%83%A5%E3%83%BC%E3%82%BF%E5%AD%A6-%E9%9B%86%E8%8B%B1%E7%A4%BE%E6%96%87%E5%BA%AB-%E5%9D%82%E6%9D%91-%E5%81%A5/dp/4087474283)
- 技術書ではありません。小説のような読み物です。これからエンジニアになろうとしてる方に是非とも読んでいただきたい一冊。コンピュータサイエンスの概念は、どれだけITが発達しようと変わりがありません。コンピュータ誕生の背景、コンピュータができることなど普段何気なく利用しているコンピュータについて体系的に学ぶことができます。n進数の話からアルゴリズムなど基本情報技術者試験に通ずる内容もあります。私はこれを読んで***コンピュータは目的達成のためのツール***であることを再認識させられました。
文庫本のため本のサイズも小さく通勤中でもさくっと読めておすすめです。

# [小悪魔女子大学生のサーバエンジニア日記/aico 著](https://www.amazon.co.jp/%E5%B0%8F%E6%82%AA%E9%AD%94%E5%A5%B3%E5%AD%90%E5%A4%A7%E7%94%9F%E3%81%AE%E3%82%B5%E3%83%BC%E3%83%90%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E6%97%A5%E8%A8%98-%E2%80%95%E2%80%95%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%BC%E3%83%8D%E3%83%83%E3%83%88%E3%82%84%E3%82%B5%E3%83%BC%E3%83%90%E3%81%AE%E3%81%97%E3%81%8F%E3%81%BF%E3%81%8C%E6%A5%BD%E3%81%97%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8B-aico/dp/477414522X/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E5%B0%8F%E6%82%AA%E9%AD%94%E5%A5%B3%E5%AD%90%E5%A4%A7%E7%94%9F&qid=1559016536&s=gateway&sr=8-1)
- 可愛い？文字とイラストでサーバやネットワークについての基本について学ぶことが出来ます。
サーバ？ネットワーク？ナニソレワカンナイを日常生活で普段利用しているものに例えて説明してくれるので内容がスッと入ってきます。ネットワークの仕組みを郵便配達に例えたイラストはとてもわかりやすく、私も新卒エンジニアにサーバやネットワークの仕組みを説明するときに使わせて頂いています。（私なりの説明例：ファイルサーバは図書館。その地区に住んでいる人しか図書館内のファイルを閲覧、編集することができない（ネットワークアドレス、IPアドレス））

# [イラスト図解式 この一冊で全部わかるサーバーの基本/きはし まさひろ 著](https://www.amazon.co.jp/%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88%E5%9B%B3%E8%A7%A3%E5%BC%8F-%E3%81%93%E3%81%AE%E4%B8%80%E5%86%8A%E3%81%A7%E5%85%A8%E9%83%A8%E3%82%8F%E3%81%8B%E3%82%8B%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AE%E5%9F%BA%E6%9C%AC-%E3%81%8D%E3%81%AF%E3%81%97-%E3%81%BE%E3%81%95%E3%81%B2%E3%82%8D/dp/4797386665/ref=pd_lpo_sbs_14_t_1?_encoding=UTF8&psc=1&refRID=GQGS8KJJCC0XQ5NTQPSP)
- システムを構成するうえでサーバって色々あるけれど、何のために必要で何が出来るのかをイラスト多めで解説してくれます。ページ数も多くなくサクッと読めるため復習にも使っています。

# 番外編
参考書ではありませんがネットワークに関してはこちらのサイトがおすすめです。

### [3分間ネットワーキング](http://www5e.biglobe.ne.jp/aji/3min/)
- ネットワークとは何かを博士とネット君の二人がコミカルに説明してくれます。二人のやりとりとは裏腹に内容が深いので意外とがっつり学ぶことができます。基本的なネットワークの知識はこのサイトで網羅できるんじゃないでしょうか。
私は利用したことがありませんが、書籍化もされています。

[[改訂新版] 3分間ネットワーク基礎講座]
(https://www.amazon.co.jp/%E6%94%B9%E8%A8%82%E6%96%B0%E7%89%88-3%E5%88%86%E9%96%93%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E5%9F%BA%E7%A4%8E%E8%AC%9B%E5%BA%A7-%E7%B6%B2%E9%87%8E-%E8%A1%9B%E4%BA%8C/dp/4774143731)


### [ネットワークエンジニアとして](https://www.infraexpert.com/)
- ネットワークを志すものなら避けては通れないCisco製品の資格取得に大いに役立つサイト。
ネットワークを学ぶというよりはCisco資格のCCNA、CCNP、CCIE取得にフォーカスを当てている。
ネットワークどこまでできますか？と聞かれても証明しずらいものがあるので、ネットワーク？ならCCNAは必須だね！と言われる。個人的には資格がすべてじゃないと思ってます。
Gradleを使ったbuildで『Runtime JAR files in the classpath should have the same version』がでた時の備忘録

# 発生した問題
Gradleを使ってbuildしたところ、警告が表示された。

# 表示された警告
```
taniguchieinoMacBook-Pro:blackberry taniguchiakira$ ./gradlew clean build

> Task :compileKotlin
w: Runtime JAR files in the classpath should have the same version. These files were found in the classpath:
    /Users/hogehoge/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.3.30/459999be0d6ac844dd3d2ca85c2daf14deb5f7f0/kotlin-stdlib-jdk8-1.3.30.jar (version 1.3)
    /Users/hogehoge/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-jdk7/1.3.30/bf0edcf669e446e0d903a0681190d1e3df969ac4/kotlin-stdlib-jdk7-1.3.30.jar (version 1.3)
    /Users/hogehoge/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-reflect/1.2.51/36b719a7b84452dd13eeec979d8c82bfb765c57d/kotlin-reflect-1.2.51.jar (version 1.2)
    /Users/hogehoge/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib/1.3.30/9ea98e65c246d34de9af59c104ad9bdea4908ee/kotlin-stdlib-1.3.30.jar (version 1.3)
    /Users/hogehoge/.gradle/caches/modules-2/files-2.1/org.jetbrains.kotlin/kotlin-stdlib-common/1.3.30/989a125fdb6e4d0d75a016032e03e1e3b57a13d/kotlin-stdlib-common-1.3.30.jar (version 1.3)
w: Consider providing an explicit dependency on kotlin-reflect 1.3 to prevent strange errors
w: Some runtime JAR files in the classpath have an incompatible version. Consider removing them from the classpath

BUILD SUCCESSFUL in 14s
7 actionable tasks: 7 executed
taniguchieinoMacBook-Pro:blackberry taniguchiakira$
```

# 解決方法
build.gradleの
>implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.9.7'

を
>implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.9.8+'

に修正した

# 気づいたこと
>implementation 'com.fasterxml.jackson.module:jackson-module-kotlin:2.9.7'

とすると、他のライブラリとの兼ね合いで、「kotlin-reflect」のバージョンの1.2.51と1.3.10が混在していた
diff(3) する際に RCS ヘッダを無視して比較したい

```text:こーんな感じ
/usr/bin/diff -udpwNBI '# \$FreeBSD' src/ RELENG_12.2/
```

毎度スイッチを忘れるけん、忘備録じゃ。

2021/12/3 diff の変更に対応
~~diff -EwBI '\$FreeBSD: ' src/ RELENG_9.1/~~
fontAwesomeのアイコンにバッジをつける方法

<img width="228" alt="スクリーンショット 2019-05-28 10.30.57.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72150/d2ca672d-4d0c-d881-b8d8-0caa669618a1.png">
通知があった時に右上に通知マークを表示するカスタマイズについて。

```
<i class="fas fa-bell badge"></i>
```
badgeというclassを設定します。

あとはCSSを追加。

```:css
.fa-bell{
  position: relative;
}

.badge:after{
  content:"";
  position: absolute;
  background: #fff;
  height:6px;
  width:6px;
  top:-2px;
  right:-5px;
  text-align: center;
  border-radius: 50%;
  color:white;
}
```

通知があった時だけ、badgeを追加すればいいですね。
Geo Library for Amazon DynamoDB for JavaScriptを使ってみた

# 概要

## Geo Library for Amazon DynamoDBとは？

[AWS公式ブログのこの記事](https://aws.amazon.com/jp/blogs/mobile/geo-library-for-amazon-dynamodb-part-1-table-structure/)で解説されているJava用のライブラリ。[リポジトリはこちら](https://github.com/amazon-archives/dynamodb-geo)。
DynamoDBで緯度経度、半径で絞り込んでクエリできる。ただし、プライマリキーの構造はライブラリが規定する形になるので、既存のテーブルに対してクエリできるわけではなく、テーブル作り直しが必要になる。

[dynamodb-geo.js](https://github.com/rh389/dynamodb-geo.js)はそれを有志がJS用にポーティングしたもの。本記事ではこちらのJS版を使ってみた。


## テーブルの構造

- プライマリキーはハッシュキー＋レンジキーになる
- ハッシュキーの値はライブラリによって自動的に埋められる
- レンジキーの値は自分で決められる。このライブラリを使う場合、レンジキーだけでテーブル内でユニークにしなければいけないので、レンジキーに実質的なIDを入れることになる
- `geoHash`というカラムが作られ、`6924445843714161599`のような値で埋められる
    - Geohashとは言ってもこの[ジオハッシュ](https://ja.wikipedia.org/wiki/%E3%82%B8%E3%82%AA%E3%83%8F%E3%83%83%E3%82%B7%E3%83%)とは別物っぽい
- `geoJson`というカラムが作られ、`{"type":"POINT","coordinates":[139.697004,35.755606]}`のような値で埋められる
- ハッシュキー＋geohashに対してインデックスが作られる
 

## クエリ

矩形範囲を取ってくる`queryRectangle`と半径内を取ってくる`queryRadius`がある。

約1400件のアイテムを入れて`queryRadius`をやってみたところ、

- 1000メートル以内のアイテムを取ってくると約600msかかった
- 10000メートル以内のアイテムを取ってくると約1200msかかった

1000メートル以内のとき、下記のようなクエリが8回投げられて、

```
{ TableName: 'geoPorts_hash1',
  KeyConditions:
   { hashKey:
      { ComparisonOperator: 'EQ', AttributeValueList: [ { N: '6' } ] },
     geohash:
      { ComparisonOperator: 'BETWEEN',
        AttributeValueList:
         [ { N: '6917783255345266689' }, { N: '6917783289705005055' } ] } },
  IndexName: 'geohash-index',
  ConsistentRead: false,
  ReturnConsumedCapacity: 'TOTAL',
  ExclusiveStartKey: null }
```

消費キャパシティはこんな感じだった。

```
Count=19, ScannedCount=19, ConsumedCapacity=2
Count=4, ScannedCount=4, ConsumedCapacity=0.5
Count=1, ScannedCount=1, ConsumedCapacity=0.5
Count=3, ScannedCount=3, ConsumedCapacity=0.5
Count=2, ScannedCount=2, ConsumedCapacity=0.5
Count=2, ScannedCount=2, ConsumedCapacity=0.5
Count=4, ScannedCount=4, ConsumedCapacity=0.5
Count=2, ScannedCount=2, ConsumedCapacity=0.5
```

## 感想

意外とクエリが遅かった。

AWSの元リポジトリはアーカイブされているし、スター数も多くないので、イマイチなのかもしれない。
[DynamoDB GeoLocation Lookup : aws - Reddit](https://www.reddit.com/r/aws/comments/9u8kqv/dynamodb_geolocation_lookup/)でもDynamoDBをGeoLocationに使うのは間違いだと言われているのでそうなのかも。というかAWSサーバーレスアーキテクチャで緯度経度による検索するベストな方法は何なんでしょうか？誰か教えてください…
Desktop : OpenCV Show Stylization By WebCam 

<h5>Goal</h5>
Test OpenCV show stylization by WebCam.

```OpenCV_ShowStylizationByWebCam.java
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.photo.Photo;
import org.opencv.videoio.VideoCapture;

import javax.swing.*;


public class OpenCV_ShowStylizationByWebCam {
    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    public static void main(String arg[]) {
        VideoCapture capture = new VideoCapture();
        capture.open(0);
        JFrame frame1 = new JFrame("show image");
        frame1.setTitle("從webcam讀取影像至Java Swing視窗1");
        frame1.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame1.setSize(640, 480);
        frame1.setBounds(0, 0, frame1.getWidth(), frame1.getHeight());
        Panel panel1 = new Panel();
        frame1.setContentPane(panel1);
        frame1.setVisible(true);

        JFrame frame2 = new JFrame("show image");
        frame2.setTitle("從webcam讀取影像至Java Swing視窗2");
        frame2.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame2.setSize(640, 480);
        frame2.setBounds(160, 0, frame1.getWidth(), frame1.getHeight());
        Panel panel2 = new Panel();
        frame2.setContentPane(panel2);
        frame2.setVisible(true);

        JFrame frame3 = new JFrame("show image");
        frame3.setTitle("從webcam讀取影像至Java Swing視窗2");
        frame3.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame3.setSize(640, 480);
        frame3.setBounds(280, 0, frame1.getWidth(), frame1.getHeight());
        Panel panel3 = new Panel();
        frame3.setContentPane(panel3);
        frame3.setVisible(true);
        if (!capture.isOpened()) {
            System.out.println("Error");
        } else {
            Mat webcam_image = new Mat();


            capture.read(webcam_image);
            frame1.setSize(webcam_image.width() + 40,webcam_image.height() + 60);
            frame2.setSize(webcam_image.width() + 50,webcam_image.height() + 70);
            frame3.setSize(webcam_image.width() + 60,webcam_image.height() + 80);
            while (true) {
                capture.read(webcam_image);
                //System.out.println("從webcam讀取影像至Java Swing視窗");

                Mat stylizationResult1=new Mat();
                Mat stylizationResult2=new Mat();

                Photo.stylization(webcam_image,stylizationResult1,50.0f,0.1f);
                Photo.stylization(webcam_image,stylizationResult2,200.0f,0.7f);

                panel1.setimagewithMat(webcam_image);
                panel2.setimagewithMat(stylizationResult1);
                panel3.setimagewithMat(stylizationResult2);
                frame1.repaint();
                frame2.repaint();
                frame3.repaint();
            }
        }
    }
}
```
<h5>Result</h5>
![擷取1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276243/95782a39-a230-40d3-57f2-4fe735e8d8e8.jpeg)
![擷取2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276243/dc62f239-8f9b-9706-60fe-2be08c225226.jpeg)
![擷取3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276243/bbad84c7-82c2-75ae-3049-2209bd7493d1.jpeg)
RubyonRailsでtwitter風webアプリケーションの作成

## はじめに
こんにちはジャムです。

Ruby on Railsを学習しております。

Railsを一通り学びましたので、復習と備忘録をかねてtwitter風のwebアプリケーションを作成しました。
簡単ではありますが紹介したいと思いますので、これからRailsを使ってWEBアプリケーションを作成する方の参考になれば幸いです。

## 完成版

herokuを利用してデプロイしました。

完成版のリンクは[こちら](https://jumtweet.herokuapp.com/)

herokuへデプロイするにあたっては[こちら](https://qiita.com/kazukimatsumoto/items/a0daa7281a3948701c39)の記事を参考にさせていただきました。


##実行環境
- サーバー：macOSにvagrantとvirtual box
- OS：CENTOS 6.10
- ruby 2.5.3p105
- Rails 5.2.3

## 作成の流れ


[STEP1：ユーザーの登録](https://qiita.com/JUM22676603/items/9c9793648661277a79d4)

[STEP2：ユーザーの編集、削除](https://qiita.com/JUM22676603/items/929113257bbb12d7008d)

[STEP3：ログイン、ログアウト機能](https://qiita.com/JUM22676603/items/f6b81a1422219cec275c)

[STEP4：投稿機能、投稿一覧の表示](https://qiita.com/JUM22676603/items/c02762182498a2f615f2)

[STEP5：おまけ機能](https://qiita.com/JUM22676603/items/6259000bbd2d64977b67)

##最後に

railsでwebアプリケーションの作成は楽しいですね

次は何作ろうかな
Excel で一行挿入するマクロ

Excelで「一行挿入」は「行を選択 → Ctrl+'+'」で可能で、または「Alt + I + R」でも可能ですが、
個人的には「行を選択」したり三回メニューを選んだりするのが面倒なのでマクロにしてショートカットを(Ctrl + Shift + I)を割り当てて使っています。

例えば「３行挿入したい」ときでも Ctrl + Shift + I を三回繰り返すだけです。

```VisualBasic

Sub InsertLine()
'
' InsertLine Macro
'
' Keyboard Shortcut: Ctrl+Shift+I
 
    Dim s As String
    s = Selection.Address
    Range(s).EntireRow.Insert
   
End Sub

```

「[Officeのアクセスキー](https://www.ex-it-blog.com/131021ExcelAccessKey)」によれば、Alt → __I__nsert __R__ow でも行挿入できます。
メモ

##事前知識　
JQuery + RailsのAjaxhttps://qiita.com/moriwm77/items/ea54c0f34da073801bf1
JavaScriptの基礎教材 https://jsprimer.net/

#サンプルコード
```javascript
$.ajax("/clients", params {
  name: name
  location: location
}).done(function(response) {
  // レスポンスからClientIdを取り出し
  // hiddenのinputにセットする(下のClientWorkから使えるように)
  // newClientのFormを一つ生成する
  // jQueryによる要素の生成　https://blog.toshimaru.net/jqueryhidden-inputjquery/
})

// Formを1つ生成する関数
function DrawClientWorkForm() {
  var form = `
    <div>
      <input />
    </div>
  `
  $("#clientForms").appendTo(form)
}
```
# もし理想の物(ページ遷移ゼロでぬるぬる動くページ)作る場合

* RailsでAPI / View側(Client側)をVue.js
* https://jp.vuejs.org/v2/guide/index.html
* https://qiita.com/naoki85/items/51a8b0f2cbf949d08b11
* Webpackというものもある程度理解する必要がある
import cv2 で謎の"ImportError"が出た...[OpenCV for Python3]

# Python3で"ImportError: numpy.core.multiarray failed to import"が出たら

解決策は、numpyをアップグレードすればいい。

```sh:ターミナル
pip install -U numpy
```

それでもダメなら、pipをアップグレードした後で、
もう一度、numpyをアップグレードしてみる。

```
pip install --upgrade pip
pip install numpy --upgrade
# or
pip install -U numpy
```

なお、それでもダメならば、再インストールすればいい。

[参照URL: ImportError: numpy.core.multiarray failed to import][so1]


<!-- Link's Set -->
[so1]:https://stackoverflow.com/questions/20518632/importerror-numpy-core-multiarray-failed-to-import
mecab-ipadic-neologd環境のMecabでユーザー辞書の作成につまずいた話

# はじめに
Mecab + mecab-ipadic-neologd環境の実装後、
ユーザー辞書の追加を行おうとすると

```bash
~/work# /usr/lib/mecab/mecab-dict-index \
        -d /var/lib/mecab/dic/ipadic/  \
        -u name.dic -u uft8 -t utf8 ./name.csv 

reading ./name.csv ... context_id.cpp(96) [it != left_.end()] cannot find LEFT-ID  for 名詞,固有名詞,人名,名,*,*,*
```

というエラーが表示され、うまく辞書の作成ができませんでした。

# 結論
システム辞書をmecab-ipadic-neologdのファイルパスに変更する。

```bash
~/work# /usr/lib/mecab/mecab-dict-index \
        -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd/ \ 
        -u user.dic -f uft8 -t utf-8 ./user.csv 
```

まあ言われてみれば当たり前なんですが、気づくのに30分以上かかったので投稿します。

## 余談
該当のエラーについて調べてみると、文字コードのエラーかLEFT-IDの指定が不十分である場合が多く記事になっていました。
文字コードはviで

```vim
:set enc?
```

とすると確認できます。
Gitでrevertしたmasterブランチをmergeしようとしてハマった

GitでRevertしたブランチに対して，操作しようと思うと大抵ハマってしまっている．今回はその対処方法をまとめて，同じような現象起こった際に対処できるようにしておく．

## 前提
今回の状況として

- master <- プロダクト環境のブランチ
- develop <- 開発環境のブランチ，ここからブランチを切って機能修正する
- feature/XXXX <- developブランチから作成した修正ブランチ

と3つのブランチがあるという前提のもとに行う．
尚，feature/XXXXブランチで機能修正を行い，developブランチにマージしてテストし，テスト後masterブランチにdevelopブランチをマージして，プロダクト環境に機能修正を行うという手順を踏んで，開発を行っている．
(多分，だいたいどこの現場でもこうだと思う)

## 問題
下記の問題の状況に陥ってしまった

1. developブランチからブランチをきってfeature/AAAという修正ブランチを作成
2. feature/AAAにて，コードを追加，修正する
3. developブランチにマージして，開発環境でテスト
4. masterブランチとdevelopブランチをマージしてプロダクト環境に機能修正を行う
5. が，しかし，feature/AAAの機能修正にバグが見つかる
6. masterブランチのdevelopブランチのマージコミットをrevertして対応
7. feature/AAAブランチにてバグを直して，developブランチにマージして再テスト
8. masterブランチにdevelopブランチをマージしようと思うとConflict
9. どうにかしようと思ってdevelopブランチにmasterブランチをマージしようと思うと修正箇所の一部が消える
10. さあ，どうしよう

と，まあ，文字に羅列したらめちゃくちゃわかりづらくなったw

## 対処
では，どうしたか．

1. masterブランチから修正用ブランチrelease/AAAをきる
2. masterブランチのrevertコミットを，さらにrevert
3. release/AAAブランチにfeature/AAAブランチをマージ
4. 色々コンフリクトとか起きるのでそれをよしなに直す(具体的にはfeature/AAAの機能修正部分が正常に作動するようにコンフリクトを直す)
5. masterブランチに直接relase/AAAをマージする

## 所感
Gitくらい何も考えず操作できろよ，俺
Rails6 のちょい足しな新機能を試す25（create_with 番外編）

# はじめに

Rails 6 に追加されそうな新機能を試す第25段。 今回は、 `create_with` **番外編** です。
`create_with` で nest したレコードが2件登録されてしまうバグの対応です。
Rails 5.2.1 に含まれていたバグが Rails 5.2.2 以降で fix されています。

Ruby 2.6.3, Rails 6.0.0.rc1 で確認しました。Rails 6.0.0.rc1 は `gem install rails --prerelease` でインストールできます。

```shell
$  rails --version
Rails 6.0.0.rc1
```

# Rails プロジェクトを作る

```shell
$ rails new rails6_0_0rc1
$ cd rails6_0_0rc1
```

# model を2つ作る

Author モデル と Book モデルを作ります。Author モデルは、Book モデルを複数持つことができます。

```shell
$ rails g model Author name
$ rails g model Book title author:references
```

# Author モデルを編集する

Bookモデルを複数持たせるため `has_many` を使います。
またネストしたレコードとして処理するため、 `accepts_nested_attributes_for` を使います

```ruby:app/models/author.rb
class Author < ApplicationRecord
  has_many :books, dependent: :destroy
  accepts_nested_attributes_for :books
end
```

# seed を作る

今回は、seed でデータを作ります。このとき、Bookのレコードが2件できてしまうというのがバグだったようです。

```ruby:db/seeds.rb
Author.create_with(
  books_attributes: [{ title: 'Programming Ruby' }]
).find_or_create_by!(
  name: 'Dave Thomas'
)
```

# db:migrate を実行する

```shell
$ bin/rails db:create db:migrate
```

# db:seed を実行する

```shell
bin/rails db:seed
```


# rails console で確認

rails console で確認すると Bookのレコードは1件だけになっています。

```irb
$ bin/rails c
Running via Spring preloader in process 475
Loading development environment (Rails 6.0.0.rc1)
irb(main):001:0> Author.all
  Author Load (0.3ms)  SELECT "authors".* FROM "authors" LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Author id: 1, name: "Dave Thomas", created_at: "2019-05-24 23:57:22", updated_at: "2019-05-24 23:57:22">]>
irb(main):002:0> Book.all
  Book Load (1.0ms)  SELECT "books".* FROM "books" LIMIT $1  [["LIMIT", 11]]
=> #<ActiveRecord::Relation [#<Book id: 1, title: "Programming Ruby", author_id: 1, created_at: "2019-05-24 23:57:22", updated_at: "2019-05-24 23:57:22">]>
```

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try025_fix_create_with

# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Make sure there are no duplicated nested records with create_with](https://github.com/rails/rails/pull/33639)
* [Duplicate nested records created with `create_with` & `find_or_create_by` for >= rails 5.2](https://github.com/rails/rails/issues/33610)
* [ActiveRecord の ChangeLog(Rails 5.2.2)](https://github.com/rails/rails/blob/5-2-stable/activerecord/CHANGELOG.md#rails-522-december-04-2018)
【Laravel】プレゼンターを使ってビューのロジックを分離する

# はじめに

この記事では、Laravelでプレゼンターを利用し、ビューのロジックを分離する実装例を解説します。

具体的にはモデルのプロパティに応じて画面の表示文言を切り替えるという要件を、ビュー側のif文ではなく、プレゼンターで実現します。

## Before

```html:
@if($member->gender === 1)
  <p>男性</p>
@elseif($member->gender === 2)
  <p>女性</p>
@elseif($member->gender === 3)
  <p>指定無し</p>
@endif
```

## After

```html:
<p>{{ $member->genderIndication()) }}</p>
```

# 環境

- Laravel 5.5.45

# 1. 事前準備

## 1.1. プレゼンターの新規作成

```php:app/Presenters/Presenter.php

<?php

namespace App\Presenters;

use Illuminate\Database\Eloquent\Model;

abstract class Presenter
{
    protected $model;

    public function __construct(Model $model)
    {
        $this->model = $model;
    }

    public function __call($method, $args)
    {
        return call_user_func_array([$this->model, $method], $args);
    }

    public function __get($name)
    {
        return $this->model->$name;
    }
}
```

## 1.2. traitの新規作成

モデルをプレゼンターでラップするため、traitを作成します。

```php:app/Traits/PresenterBuildable.php
<?php
namespace App\Traits;
use App\Presenters\Presenter;

trait PresenterBuildable
{
    public function presenter() : Presenter
    {
        $name = (new \ReflectionClass($this))->getShortName();
        $class = sprintf("App\Presenters\%sPresenter", $name);
        return new $class($this);
    }
}
```

## 1.3. モデルの編集

```php:app/Member.php
<?php

namespace App;

use App\Traits\PresenterBuildable; // 追加
use Illuminate\Database\Eloquent\Model; 

class Member extends Model
{
    use PresenterBuildable; // 追加

    protected $fillable = [
        'name',
        'age',
        'gender',
        'memo'
    ];
}
```

## 1.4. コントローラーの編集

ビューへ渡すモデルのインスタンスに対して、`->presenter()`を追加しています。

こうすることで、ビュー側で毎回`->presenter()`を記述することなく、プレゼンターのメソッドを使用できるようになります。

```php:app/Http/Controllers/MemberController.php
    public function show(Member $member){
        return view('members.show')->with('member', $member->presenter());
```

# 2. モデル別のプレゼンターの作成とビューの編集

## 2.1. モデルに対応するプレゼンターの作成

`genderIndication`メソッド内のロジックは、先ほどのビュー同様にif文での条件分岐でも構わないのですが、今回は連想配列を定義し、`gender`プロパティの値をキーとして、それを取り出すロジックとしました。

```php:app/Presenters/MemberPresenter.php
<?php

namespace App\Presenters;

class MemberPresenter extends Presenter
{
    public function genderIndication()
    {
        return [
            1 => '男性',
            2 => '女性',
            3 => '指定無し',
        ][$this->gender];
    }
}
```

## 2.2. ビューの編集

```html:resources/views/members/show.blade.php
<p>{{ $member->genderIndication()) }}</p>
```

# 最後に

`1.事前準備`に若干の手間はかかりましたが、以降は各モデルに対応するプレゼンターに随時必要なメソッドを作成していくだけとなります。

今回プレゼンターを利用することによって、以下の利点が得られたかと思います。

- ビューからロジックを分離し、再利用性を高める

- モデルとは別にプレゼンターを用意したことで、画面表示に関するメソッドをモデルから独立させられる

- モデルをラップするので、ビュー側からはモデルのメソッドと同様に使用できる

# 参考

- [View Presenters in Laravel - DAVID HEMPHILL](
https://davidhemphill.com/presenters-in-laravel/)
php-master-changes 2019-05-27

今日は opcache サポート対象への fpmi の追加、zend_lookup_class_ex() の引数修正、Windows でスキップしていたテストのスキップ外し、HugePage 境界に .text セグメントをアラインさせるようにする修正、expat 検出の pkg-config への移行、pcre での valgrind サポートを DEBUG ビルドでのみ有効にする修正、opcache の組み込み関数の情報取得処理の修正があった！

# 2019-05-27
## bukka: Add fpmi to the opcache supported sapis
- https://github.com/php/php-src/commit/8baf3ffde6211c9373ac7f812c2095b2a6426f78
- [7.2~]
- ext/opcache で、サポート対象の sapi に [fpmi](https://github.com/bukka/fpmi) を追加
- fpmi は bukka の人がやってる [fpm の開発版](https://externals.io/message/101893#101897)

## nikic: Accept flags argument in zend_lookup_class_ex()
- https://github.com/php/php-src/commit/e6fac86dc35b876d2958ce77c01bb05bd7068ac3
- [7.4~]
- zend_lookup_class_ex() で引数にオートロードを受け付けるかだけの真偽値でなく int のフラグ受け付けるよう修正

## carusogabriel: Make more tests run on Windows
- https://github.com/php/php-src/commit/4bb6f9ba99ac30d603118adc38790f3e72524d5e
- [7.4~]
- Windows でスキップしていたテストのスキップを外した

## dstogov: Align .text segment for better huge pages usage
- https://github.com/php/php-src/commit/62ded6efbcb41e24a505117f8de5b70d56a98f57
- [7.4~]
- リンカフラグで HugePage 境界に .text セグメントをアラインさせるよう修正

## hughmcmaster: ext/xml: Use PKG_CHECK_MODULES to detect the Expat library
- https://github.com/php/php-src/commit/a8f4e8fe7349f64c42bfb961de46bf66d7b1a96e
- [7.4~]
- ext/xml で、expat の検出を pkg-config へ移行

## dstogov: Enable pcre valgrind support only in DEBUG build (it affects performance)
- https://github.com/php/php-src/commit/6a4ec6c7e4382dcffe0f150468271299704cf4e3
- [7.4~]
- ext/pcre で、valgrind サポートを DEBUG ビルドでのみ有効にするよう修正

## nikic: Func info: Fix calls to zero-arg varargs
- https://github.com/php/php-src/commit/62f339c8d5071c46005a3fa1ee44563347bdc5c5
- [7.3~]
- ext/opcache で、引数なしでの可変引数関数呼び出し用に組み込み関数の情報取得処理を修正
- [PR:4175](https://github.com/php/php-src/pull/4175) の話の流れで直した奴
【Rails】Chrome Headless モード on HerokuCI エラー集

# はじめに
HerokuCIに関する記事は他のCIに比べ少なく、依存ライブラリの変化などによりドキュメント通りに実装しても動かなくハマったところをまとめておきます。
本記事は、2019年5月時点での実装になっています。内容の更新により随時更新予定ではありますが、間違っている点・古くなっている点などあればお気軽にお知らせください。

# エラー集
## 1. Session not created~~
### エラー詳細
```
session not created: Chrome version must be between 70 and 73
  (Driver info: chromedriver=2.45.615355 (d5698f682d8b2742017df6c81e0bd8e6a3063189),platform=Mac OS X 10.14.4 x86_64)
```

このようなエラーが出る場合には、 [chromedriver-helper](https://github.com/flavorjones/chromedriver-helper) をいまだに使用している可能性が高いです。 chromedriver-helperはサポートが終了しており、 `webdrivers` というGemに移行しましょう。

### 対処法
Gemfileを以下のように変更して `bundle install` しましょう。

```ruby:Gemfile
# gem 'chromedriver-helper' # この行を削除
gem 'webdrivers' # この行を追加
```

## 2. DevTools listening on ws://~~ とでてCIが動かなくなる
### エラー詳細
`1. Session not created~~` のエラー解決の通り、 `chromedriver-helper` を削除し、HerokuCIを回すと、 `DevTools listening on ws://127.0.0.1:9222/devtools/browser/ec46578f-304d-4a11-8441-fee4092aebac` と表示された状態からCIが止まったような状況に遭遇することがあります。

### 解決方法
`Webdrivers::Chromedriver` のバージョンを指定してあげましょう。

```ruby:spec/spec_helper.rb
require 'selenium-webdriver'
require 'capybara/rspec'
require 'webdrivers'
RSpec.configure do |config|
  config.expect_with :rspec do |expectations|
    expectations.include_chain_clauses_in_custom_matcher_descriptions = true
  end
  config.mock_with :rspec do |mocks|
    mocks.verify_partial_doubles = true
  end
  config.shared_context_metadata_behavior = :apply_to_host_groups
end

# この部分を指定
Webdrivers::Chromedriver.version = '2.46'

chrome_bin = ENV.fetch('GOOGLE_CHROME_SHIM', nil)

options = {}
options[:args] = ['headless', 'disable-gpu', 'window-size=1280,1024']
options[:binary] = chrome_bin if chrome_bin
Capybara.register_driver :headless_chrome do |app|
  Capybara::Selenium::Driver.new(
    app,
    browser: :chrome,
    options: Selenium::WebDriver::Chrome::Options.new(options)
  )
end

Capybara.javascript_driver = :headless_chrome
```

詳しくは、[こちらのIssue](https://github.com/titusfortner/webdrivers/issues/72)を参照してください。

# 参考
1. [Heroku CI: Browser and User Acceptance Testing (UAT)](https://devcenter.heroku.com/articles/heroku-ci-browser-and-user-acceptance-testing-uat)
2. [heroku-buildpack-google-chrome](https://github.com/heroku/heroku-buildpack-google-chrome)
2. [session not created: Chrome version must be between](https://stackoverflow.com/questions/55822969/session-not-created-chrome-version-must-be-between)
3. [Migrating from chromedriver-helper (Heroku production) #72](https://github.com/titusfortner/webdrivers/issues/72)
Javascriptファイルの順序問題

Javascriptはweb系では不可欠の存在です。
複数jsファイルがある場合静的ファイルとして配置すると書く順序で動作できるのはほとんどです。
しかし、jsファイルはサーバーのプログラムを経由してロードする仕組みだと、予想通りにならない場合があります。
理由はjsファイルサイズ、ネットワーク環境によって書いたjsの順序で実行しないからです。

ブラウザのコンソールにエラーがある場合は順序問題だと特定しやすいですけど、エラーでない場合は順序問題のせいだと仮説しないとわからないままで終わります。

scriptタグの仕様:
https://developer.mozilla.org/ja/docs/Web/API/HTMLScriptElement

defer 属性がありました。
内容を引用すると下記です。

> asyncとdefer属性はboolean属性です．スクリプトがどのように実行されるべきかを示します． defer および async 属性は，src 属性が無ければ指定してはならない．
> 
> これら2つの属性値を用いて選択可能な3つのモードがあります．async属性があれば，スクリプトは可能な限り非同期的に実行されます．async属性が無くdefer属性があれば. スクリプトはページのパースが完了した時点で実行されます．両方の属性があれば，スクリプトはユーザーエージェントによるページのパース完了を待つこと無く，フェッチ後，直ちに実行されます．

defer はページロード完了後、実行しますので、この属性の追加で順序問題は回避できます。

以上
rspec subjectの使い方

rspecのsubjectは `let`などと同じように、処理を変数に置き換えるものです。

```spec.rb
let(:params) do
  {
    fuga: 'hoge'
  }
  
subject { get '/hogehoge', params: params; response }
```

このように `subject`を定義することで、 `get '/hogehoge', params: param`というリクエストをDRYに書くことが出来ます。

```subjectがないとき.rb
context 'ログインしてるとき' do
  before { sign_in user }

  it do
    get '/hogehoge', params: params; response 
    expect(response).to have_http_status(:success)
  end
end

context 'ログインしてないとき' do
  before { sign_out user }

  it do
    get '/hogehoge', params: params; response 
    expect(response).to have_http_status(:redirect)
  end
end
```

```subjectがあるとき.rb
subject { get '/hogehoge', params: params; response }

context ' ログインしてるとき' do
  before { sign_in user }
  it { is_expected.to have_http_status(:success)
end

context ' ログインしてないとき' do
  before { sign_out user }
  it { is_expected.to have_http_status(:redirect)
end
```

全体の行数が少なくなって、記述もDRYになって読みやすくなりました。
PowerShellで印刷など

コマンドプロンプトから印刷だと`lpr`サービスが必要だが、うまく出来なかったためPowerShellの方法を調べた。

## 参考

* [【PowerShell】プロセスを開始する | ほそぼそプログラミング日記](https://hosopro.blogspot.com/2016/11/powershell-start-process.html)
* [Powershellでstart-processコマンドと-waitコマンドを使用する](https://stackoverrun.com/ja/q/11114122)

## 既定のプリンターで印刷

* a.txtを印刷(アプリケーションは表示、終了を待たない)

```sh
Start-Process "c:\a.txt" -Verb Print
```


* a.txtを印刷 (アプリケーションは非表示、終了を待たない)

```sh:非表示
Start-Process "c:\a.txt" -Verb Print -WindowStyle Hidden
```


* a.txtを印刷 (アプリケーションは非表示、終了を待つ)

```sh:非表示
Start-Process "c:\a.txt" -Verb Print -WindowStyle Hidden -Wait
```

* 管理者として実行 (hostsを編集)

```sh
Start-Process notepad.exe "c:\Windows\System32\drivers\etc\hosts" -Verb runAs
```


## 起動方法

* Start-Process
* saps

## オプション

* -WindowStyle
    * Hidden : 非表示で実行
    * Maximized : 最大化
* -Verb
    * runAs : 管理者として実行
    * Print : 印刷
* -Wait
    * プロセスの終了を待つ
* -WorkingDirectory
    * 作業場所となるディレクトリを指定

## その他PowerShellコマンド

* Start-Sleep -s 3
    * 3秒待つ

## 特権になる

* [コマンドプロンプトから管理者権限のコマンドプロンプトに切り替える - Qiita](https://qiita.com/fjtter/items/4b7fe797ae1155c69dd9)

```sh

PowerShell Start-Process "cmd.exe" -ArgumentList '/k "cd %cd%"' -Verb runAs
```

## 他のコマンド

* powershell_ise
    * 統合環境の起動
* alias
    * コマンドalias一覧表示
    * alias | findstr "select"
* dir | ogv
    * 結果をグリッド表示
* ii
    * ファイルを関連付けられたプログラムで実行
    * ii .
    * ii Readme.txt
* `Get-ChildItem -Path Cert:\CurrentUser\Root`
    * 証明書一覧(CA)を出力

## フルパスで取得

* [【備忘録】PowerShell　指定したフォルダ以下の全てのファイルの絶対パスを取得する - Qiita](https://qiita.com/gyokufoo/items/56ea98116f9e559126f0)
* dir -Recurse | Select-Object FullName
* dir -Recurse | select FullName
* dir -Recurse | Select-Object FullName | findstr "log"
継承について

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257568/f476c9ed-054f-d7ac-bcdb-7d93071961f5.png)

説明する時にいつも読むのでまとめ

## 継承とは
**共通点と相違点を体系的に分離して整理するもの**

- クラスの共通部分を親クラスにまとめる仕組み
- 親クラスに共通の性質を定義し、子クラスに固有の性質を定義するもの
- コードの重複を排除して汎用性の高い部品をつくる仕組みの1つ
- オブジェクト指向三大要素の1つ
- 全体集合と部分集合の関係性を表す(集合論でいうスーパーセットとサブセット)

## 特徴
### 概念的側面(現実世界)
**分類体系が説明できる**

- 例えば「動物」と「人間」と「鳥」
  - 「動物」(上位)の中の「鳥」
  - 「人間」(下位)は「動物」の1つ
  - 「鳥」は(下位)は「動物」の1つ

### 技術的側面(プログラミング)
**継承を宣言するだけで親クラスの変数とメソッドを全て定義したことになる**

- スーパークラスとサブクラスそれぞれのメソッドとして成立する
- 例えば「Animal」と「human」と「bird」
  - 「動物」は「人間」も「鳥」も「食べる」けど、「人間は歩く」し、「鳥は飛ぶ」
  - 「動物」は「人間」も「鳥」も「食べる」けど、「人間は飛ばない」し、「鳥は歩け、、る」(今回は歩けないとする)
  - 共通の性質だけまとめて同じクラスに定義する
  
### プログラミング技術における「抽象」を利用した場合

```java:Animal.java
public abstract class Animal {
    public void eat() {
        System.out.println("ぱくぱく");
    }
}
```
```java:Human.java
public class Human extends Animal {
    public void walk() {
        System.out.println("てくてく");
    }
}
```
```java:Bird.java
public class Bird extends Animal {
    public void fly() {
        System.out.println("ばさばさ");
    }
}
```

```java:Main.java
public class Main {
    public static void main(String[] args) {
        Bird bird = new Bird();
        bird.eat();
        bird.fly();

        Bird human = new human();
        human.eat();
        human.walk();
    }
}
```

### ポイント
- 子クラス内で継承を宣言(extends)しているので、子クラスをインスタンス生成(new)すると、子クラスにメソッドがなくても親クラスのメソッドが使える(eatメソッドが呼び出せる)
- 継承はポリモーフィズムを実現する機能の1つでもある

## 関連記事
[オブジェクト指向でなぜつくるのかまとめ](https://qiita.com/dich1/items/59c4f15c6dfb71e48c5e)

## 書籍情報
平澤 章  (著) オブジェクト指向でなぜつくるのか 第2版
https://amzn.to/2VSrzwe

## 雑感
そういえば鳥は歩ける。たまに飛べない鳥もいる。

こういうのも現実世界に当てはめようとするとあれれとなるので、あくまで仕様的に問題ないということで。
今回「技術的側面」の部分で満たしたい「要件」は「親のメソッドを子生成後に呼べることの説明」なので「鳥」が歩かないことは仕様的に問題ない
【Ruby】コミットする前に husky+lint-staged で、Rubocopの自動整形＆チェックを行う

# この記事なに？ :thinking: 

- [Qiita - コミット前に Lint を強制するなら lint-staged が便利](https://qiita.com/ybiquitous/items/553479cfcb2cee124ae0)
- [MANA-DOT - husky + lint-stagedでgitのprecommit時にimageminを行い、minifyした画像のみコミットされるようにする](http://blog.manaten.net/entry/precommit-imagemin)

上記記事を参考に`husky`+`lint-staged`を用いて、コミット前にeslintによるチェックを行う実装が行えました。

その仕組みを使って、Rubocopの自動整形＆チェックを行う環境を構築できましたので、その手順メモになります。

# この記事を一読してくださった方へ

- 「こんなのも書き留めておいた方が良いよ」
- 「それ、解釈間違ってるよ」

的なものがあればコメント等いただけると助かります。🙇‍♂️

## rubocopのオプション変更 2019.08.05追記

分報仲間の[aqui](https://twitter.com/aquitcd)さんから、フィードバックをいただけました！

- [RuboCopのオプションを再入門したら、pre-commitフック経由の問題も解決した](https://blog.solunita.net/relean-rubocop-options/)

こちらの記事を参考に、近々記事をアップデートさせていただきたいと思います。

# 環境

- macOS
- [Homebrew](https://brew.sh/index_ja)でインストールした`git`と`yarn`を用いる

# 手順

実際に設定した手順を記載していきます。

## 準備

必要なGemとnpmパッケージのインストールをします。

```bash
# Rubocopのインストール（or Gemfileへrubocopを追記して、bundle installする）
gem install rubocop

# npmパッケージのインストール
yarn add -D lint-staged husky
```

## `package.json`の設定

rb,rakeファイルを対象にRubocopによる自動整形とチェックを行うコマンドを記載します。

```json
{
  "husky": {
    "hooks": {
      "pre-commit": "lint-staged"
    }
  },
  "lint-staged": {
    "linters": {
      "*.{rb,rake}": [
        "rubocop -a",
        "rubocop",
        "git add"
      ]
    }
  }
}
```

`bundle install`したRubocopを使用したい場合は、以下コマンドを記載する方が良いかなと思います。（未検証ですが、おそらく問題なく動作するかと思います。）

- `bundle exec rubocop -a`
- `bundle exec rubocop`

これで、設定完了となります。

## 注意事項

チーム開発等で本設定を使用されたい場合、必ず最初に`yarn`して、npmパッケージをインストールするようにしてください。

※npmパッケージをインストールしておかないと、`lint-staged`と`husky`が動作しないので、注意が必要です。

# おわり

CircleCI側で、Rubocopの自動整形をおこなったPRを出してくれるGemもあるみたいです。

- [Qiita - rubocop --auto-correctの補正結果を自動でPRにする](https://qiita.com/rvillage/items/1e5fdb1bfccbe8a09592)
- [RubyGems - rubocop-automata](https://rubygems.org/gems/rubocop-automata)

自動整形をコミットに含めない運用としたい場合は、上記を活用した方がよさそうです。
RubyonRailsでtwitter風webアプリケーションの作成：STEP5おまけ機能


##ログイン時の成功、エラーの表示

Sessionコントローラーにflashの追記

```ruby:app/controllers/sessions_controller.rb
  def create
    @user = User.find_by(email: params[:session][:email]) 
    if @user && @user.authenticate(params[:session][:password]) 
    log_in @user
    redirect_to user_path(@user), flash: {success: "ログインに成功しました"} #追記
    else
      flash.now[:danger] = "入力に誤りがあります" #追記
      render "new"
    end
  end
```
ビューにflash表示用を追記

```erb:app/viewa/layouts/application.html.erb
  <body>
    <%= render "shared/header" %>
    <div class="container">
    <% flash.each do |message_type, message| %> <!--追記-->
    <div class="alert alert-<%= message_type %>"><%= message %></div> <!--追記-->
    <% end %>　#追記
    <%= yield %>
    </div>
  </body>
```

##アクセス制限、ログインしていないと新規投稿できないようにする

ログインしていなければ、ログイン画面に戻す処理を追加
（＠current_userがnilの場合、new_session_pathに飛ばす)

```ruby:app/helpers/sessions_helper.rb
  def authenticate_user
    if @current_user == nil
    redirect_to new_session_path
    end
  end
```

常にcurrent_userメソッドを実行する
sessionにidが入っていたら @current_userに現在のログインユーザーを代入

```ruby:app/controllers/application_controller.rb
   before_action :current_user
```

tweetsコントローラーのnewとcreateにアクセスしたら、authenticate_userメソッドを実行する。（ログインしていなければ、新規投稿urlに直接アクセスできないようにする）

```ruby:app/controllers/application_controller.rb
   before_action :authenticate_user,{only: [:new,:create]}
```

以上です。
PostgreSQLのICUコレーションを使った日本語辞書順ソート

# PostgreSQLのICUコレーションを使った日本語辞書順ソート

元になった情報は以下のURLです。

PostgreSQL 10のICUコレーションを使うと日本語を普通にソートでき、更に文字順序までカスタマイズできる
https://blog.ohgaki.net/postgresql-10-icu-locale-collation-enables-natural-japanese-sorting

SQLでの文字列比較、ソート順には「照合順序（Collation）というのが絡みます。

代表的なのがMSのSQLServerで日本語版をインストールした場合
デフォルトの照合順序は Japanese_CI_AS です。
CaseIgnore（大文字小文字を区別しない）

MySQLにも照合順序があり最近のように文字コードがutf8,utf8mb4などの環境だと
照合順序は
utf8_general_ci
utf_unicode_ci

例えばテーブルTBL(txt varchar(10)で

```
txt
---
a
A
b
B
c
C
は
ハ
```

のようなデータに対して

```
SELECT txt FROM TBL ORER BY txt
```

とすると結果は

```
txt
---
a
A
b
B
c
C
は
ハ
```

いい感じに見えますが、ここで

```
INSERT INTO t VALUES ('A');
INSERT INTO t VALUES ('a');
INSERT INTO t VALUES ('ハ');
INSERT INTO t VALUES ('は');
```

として再度SELECT txt FROM t ORDER BY txt

とすると


```
txt
---
a
A
A
a
b
B
c
C
は
ハ
ハ
は
```

とかに。
アルファベットの大文字・小文字、ひらがな・カタカナを区別しない。
注意が必要なのはこれらはソート順だけでなく文字比較にも影響があること

```
SELECT txt FROM t WHERE txt = 'a' OR txt = 'は'
```
で

```
txt
---
a
A
A
a
は
ハ
```

結局大文字と小文字、ひらがな・カタカナが同じものとして扱われます。
2017で試していますが以前のバージョンでは日本語のひらがなで清音、濁音、半濁音が同一視されていました（それなのに照合順序名はASがついているのも疑問ですが）。

同様なことはMySQLの照合順序。character_setがutf8の時にutf8_general_ciでも起きます。ひらがな・カタカナは同一視しませんが。
なので

WHERE ’A' = 'a'

は「真」になります

で本題です。

PostgreSQLの場合は基本OSのlocale設定で決まります。

SHOW LC_COLLATE;

 lc_collate　=> en_US.UTF-8

みたいになっていると日本語のソート順がおかしなことに。

 ja_JP.UTF-8

でもいろいろ面倒なことがあるようです。

https://hacknote.jp/archives/24914/

それが「ja-x-icu」を指定すると結構ましな結果になります。

```
 txt
-----
 a
 a
 A
 A
 は
 は
 ハ
 ハ
```

一方

```
SELECT txt FROM t WHERE txt = 'a' OR txt = 'は'
```

の結果は

```
 txt
-----
 a
 a
 は
 は
```

ソート順はよしなに並べてくれるが同一視はしない。

これは文字列の比較条件として抽出、結合にも影響するので普通望んでいる結果を実現できそう。
ただし、現在はPostgreSQL 11でもDATABASE, TABLEのデフォルト指定はできず、項目（列）に対してのみ指定ができるようです。

通常のプログラミング言語では 'a' != 'A' です.
PostgreSQLでもlocaleをCにする
SQL Server,MySQLでもjapanese_binのようにバイナリ比較の照合順序を使うというのもありますが、そうするとODER BYの並び順も文字コード順になるので、使い分けが必要かなと思います。

内部処理的にはバイナリ比較にしたほうが処理負荷は少ないでしょうけど。
Excelで条件にあった複数の文字列を連結して表示したい

## なにがしたいか

Excelの関数を使って条件に一致する複数セルを一気にもってきたい。
ないようでたまにあるケースです。

例えばこういう表があったときに「**NG**のIDの一覧が欲しい！」みたいなケースです。

| ID    | Status |
|-------|--------|
| 1     | NG     |
| 2     | OK     |
| 3     | NG     |
| 4     | NG     |
| 5     | OK     |

こういう文字列が取得できるとゴールです。

```text
1, 3, 4
```

## 答え

一覧を出したいセルに次の関数を入力します。

```
=TEXTJOIN(", ",TRUE,IF(B1:B5="NG",A1:A5,""))
```

そして「**Ctrl + Shift + Enter**」で決定します。
無事に `1, 3, 4` と出たと思います。

めでたしめでたし

---

## 解説

２つの関数（というか仕組み）を使っています。
1つ目は「TEXTJOIN」、2つ目は「配列数式」です。

### TEXTJOIN()

それほど難しい関数ではありません。
複数の文字列を渡すとjoin(結合)してくれるだけです。

```
=TEXTJOIN("/",TRUE,"1","2","3")
```

とすれば、

```
1/2/3
```

となります。
文字列は可変個でいくらでも指定できます。そして実はここには「配列」を指定することもできます（後述）。

### 配列数式

こっちが少しやっかいですので簡単にだけ。
データをいわゆる配列として扱うことができます。
今回の例で説明すると。


| ID    | Status |
|-------|--------|
| 1     | NG     |
| 2     | OK     |
| 3     | NG     |
| 4     | NG     |
| 5     | OK     |

という表で以下の関数を入力して

```
=IF(B1:B5="NG",A1:A5,"")
```

「Ctrl+Shift+Enter」で決定したあとにセルの数式を見ると

```
{=IF(B1:B5="NG",A1:A5,"")}
```

みたいに `{}` で囲まれたように表示されると思います。
これが配列数式になってるよという目印です。

そしてIF文の意味を見てみると、もし Status（B1～B5） にNGがあったら ID（A1～A5） の値を返してくださいもしNGじゃなかったら `""` にしてください、という意味です。 B1:B5 と A1:A5 の数（行の数）が同じなので対応する値を返すことができます。 VLOOKUPとかと同じ感じです。

さらに今回はここで「配列数式」というものを使っているので（Ctrl+Shift+Enterで決定しているので）、条件に一致したデータが複数あれば複数個を配列にしてそのまま扱うことができます。

なんとさらに`TEXTJOIN`は配列を引数として受け取って結合することが出来るのです。

つまり、

```
IF(B1:B5="NG",A1:A5,"") で StatusがNG の ID一覧 を配列にする

　↓

TEXTJOIN(", ",TRUE, ＊ID一覧の配列＊ ) で ID一覧の配列 を "," で結合している
```

ということで、

```
=TEXTJOIN(", ",TRUE,IF(B1:B5="NG",A1:A5,""))
```

これで条件にあった複数セルを（配列と言うかたちにして文字列を結合して）一気に持ってこれました。
Mac からのリモートデスクトップで日本語キーボードを使う

日本語キーボードのMac から [Microsoft のリモートデスクトップ クライアント](https://itunes.apple.com/jp/app/microsoft-remote-desktop-10/id1295203466?mt=12) を使って、Windows に接続すると、英語配列となってしまって、とても使いにくいという問題があります。

これをなんとか解決したいと思っていたのですが。

## 結論

無理ｗ (2019/05/28現在)

[Microsoft のリモートデスクトップ クライアント](https://itunes.apple.com/jp/app/microsoft-remote-desktop-10/id1295203466?mt=12) を使っている分には解決方法ありません。でも...

## 解決策

無料アプリ[Parallels Client](https://itunes.apple.com/jp/app/parallels-client/id600925318) を使います。
Microsoft 製のRDPクライアントとなんら遜色はありません。AppStore に載っていますし無料ですし。Parallels さんなら安心でしょう。

----
いろいろ調べました。ググると沢山の記事が現れますし、この問題が長年放置されてきているのもよくわかりました。ちょっと古い解決方法は試してみてもだめだったものばかりでした。
中には対象となる Windows マシンのレジストリをいじるという荒業も見かけましたが、お客さんのサーバーにそんなことできるわけがありませんねｗ。自分のマシンでも、このためだけにあまりしたくないです。

ということで Parallels Client を使うのが一番という結論です。
ゴミ記事ごめんなさい。
Rails link_to で別ページのセクションに飛ばす

あるプロジェクトでリンクをクリックすると、別ページのセクションAという部分に遷移するという実装をしたのでその備忘メモを残す。

```page_A.html.slim
section#hogehoge_id
  | ホゲパートです
```

```page_B.html.slim
= link_to 'hogehogeに遷移する', hoge_path(anchor: 'hogehoge_id')
```

`anchor`タグを使用することで、遷移先のsectionを指定できる。
初心者が学ぶべき【リクエストからレスポンス】の流れ

#Railsを使いこなすには、リクエストからレスポンスの仕組みを理解することが必須。
##主な流れ
①　Webブラウザ→Router→Controller→Model→データベース→Model
②　Model→Controller→View→Webブラウザ
Ubuntu19.04でdocker-ceのインストールでつまづくときのメモ(2019年の5月時点)

# 概要

docker-ceのインストールで、Dockerのサイトの手順にそってやったつもりでうまく行かないときのためのメモです。

# サイトからのインストールがうまく行かないとき

UbuntuにDockerを入れるとき、[Dockerのサイトの手順](https://docs.docker.com/install/linux/docker-ce/ubuntu/)に従ってインストールすると思いますが、
コピペだけで済ませていくと、以下のようになると思います。

```bash
$ sudo apt-get remove docker docker-engine docker.io containerd runc
$ sudo apt-get install     apt-transport-https     ca-certificates     curl     gnupg-agent     software-properties-common
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
$ sudo add-apt-repository    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
sudo apt-get install docker-ce docker-ce-cli containerd.io
```

が、この手順では、以下のエラーが出る場合があると思います。(パッケージが準備されない間の話。2019年5月ではこうなりました)

```
$ sudo apt-get install docker-ce docker-ce-cli containerd.io
パッケージリストを読み込んでいます... 完了
依存関係ツリーを作成しています                
状態情報を読み取っています... 完了
パッケージ docker-ce は使用できませんが、別のパッケージから参照されます。
これは、パッケージが欠落しているか、廃止されたか、または別のソース
からのみ利用可能であることを意味します。

E: パッケージ 'docker-ce' にはインストール候補がありません
E: パッケージ docker-ce-cli が見つかりません
```

これは、追加したUbuntuのリポジトリが「stable」だけであり、この中にはまだdockerのパッケージが含まれていないため起こります。

回避のため、下記のように「edge」「test」のリポジトリも追加した上で、apt-get installすると、インストールが正常に終了します。

```bash
 sudo add-apt-repository    "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable edge test"
```
【視聴メモ】Next-Generation 3D Graphics on the Web (Google I/O ’19)

この記事は Google I/O '19 のセッションの視聴メモです。
想定読者は自分なので正確性や網羅率には問題があるかもしれません。

---

## References

https://www.youtube.com/watch?v=K2JzIUIHIhc

Speaker(s): Corentin Wallez, Ricardo Cabello


## Abstract

> This talk will cover the latest updates for adding 3D to your web site. You'll learn how to use model-viewer and new features for rendering, AR, and interactivity. You'll also see some phenomenal sites created with three.js. Then you'll get an overview of the WebGPU API that will provide modern features such as “GPU compute” as well as lower overhead access to GPU hardware and better, more predictable performance. Expect performance gains in Tensorflow.js up to 10x.

訳

> このセッションはWebサイトに3Dグラフィックを追加するときの最新情報をカバーしています。また、このセッションではmodel-viewerの使い方、レンダリング、AR、インタラクティビティについての新機能も紹介します。また、three.jsを使ったすばらしいいくつかのサイトもご紹介します。これにより、WebGPU APIが提供する"GPU compute"などの機能についてなども知ることができます。これはGPUに少ないオーバーヘッドでアクセスでき、tensorflow.jsのパフォーマンスを10倍まで高速化したりできます。

## Contents

### WebGL

* WebGLの基本
    * canvasを定義してcontextでwebglを指定する
    * あとはゴリゴリ書いていくだけ！
* WebGLがどうやって使われているか
    * インタラクティブなビデオクリップ
    * ゲーム(Plumeというものが紹介されていた)
    * Storybook
    * インテリアなどのコンフィグレーション
    * three.jsやbabylon.jsのサイトで色々な実用例を確認できるよ
* もちろんWebページのデザインとしても使われている
    * すごい → https://bertrandcandas.com/
    * すげえ！ → http://taotajima.jp/
* canvasの中にDOM要素を入れて映像効果を足している
* three.jsのReact拡張なんかもあって書きやすい
* WebGL + Web Components
    * WebGLの大変さをコンポーネントに隠してしまえば簡単に再利用できる（下図）

```
<script src="webgl-globe.js"></script>
<webgl-globe src="myjson.json" format="magnitude"></webgl-globe>
```

* `model-viewer` というWeb Componentsが便利
    * glbファイルを指定すると3Dモデルがわかりやすく表示される
    * アクセシビリティ的にも丁寧に表示される
    * attributeにarを指定するだけでARに対応する

### WebGPU

* WebGLの新しいAPI
* babylon.js
    * WebGPUに対応して多くのオブジェクトを描画してもパフォーマンス（FPS)が落ちなくなった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3387/b7d554c8-855c-7e2f-3d64-89754ee7fc98.png)

* Post-processing filterが使える
    * カメラアプリなどで使われる色彩効果や深度表現が行える
* GPU Compute
    * 物理的なGPUの処理方法
        * 1つのGPUはたくさんのExecution Unitからなり、Execution Unit はたくさんのレジスタとALUからなる
        * 最近のGPUはALU同士が通信できるように共有メモリがある
    * WebGLでのイメージフィルタがGPU処理とどう結びつくか
        * 画像をすべてメモリに乗せて乗算を計算してる
        * 画像の分だけメモリを消費する
    * WebGPU
        * 計算結果を共有メモリにキャッシュするので速いしメインメモリもあまり消費しない
* MLの計算を効率化する目的でもよく使われる

## Memo

* WebGPU、すごいけどライブラリが勝手に対応していつの間にかサイトが速くなってる系の改善かな？
* `model-viewer` 便利
* TAO TAJIMA のページがすごい
新卒一年目で応用情報技術者試験に合格するためにやったこと

#初めに
私は大学時代にはほとんどキーボードを触ったこと無いような状態から
システム開発会社に新卒で入社した現在2年目のエンジニアです。

昨年の春基本情報に合格し、その後秋で応用情報に合格しました。
周りの同期は未だ基本情報取得に苦戦している人も多いので､
自分のやった方法が何か役立つかもしれないと思い投稿しました。

「一ヶ月で余裕っすよ。」みたいなよくある記事みたいなことは書きません。
未経験一年で取得するにはそれなりに努力が必要でした。

#応用情報取得に必要なこと
##①前提知識
 基本情報に合格している状態からスタートを想定しています。
 まだ基本情報を取っていない方は先に取ることをお勧めします。
私は春に基本情報を取得して、その後半年間の勉強で応用情報を取得したため、
前提知識が無い状態なら半年間では厳しく、私のやり方では難しいと思われます。

##②勉強方法
最初~2ヶ月 インプット + 現状の力を知る
基本情報で得た知識に+αで対応可能なので、まずはその+αをインプットする

テキストは何でも良いですが、私は有名な合格教本を使用しました。
平成31年【春期】/01年【秋期】応用情報技術者 合格教本
https://www.amazon.co.jp/%E5%B9%B3%E6%88%9031%E5%B9%B4%E3%80%90%E6%98%A5%E6%9C%9F%E3%80%91-01%E5%B9%B4%E3%80%90%E7%A7%8B%E6%9C%9F%E3%80%91%E5%BF%9C%E7%94%A8%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85-%E5%90%88%E6%A0%BC%E6%95%99%E6%9C%AC-%E5%A4%A7%E6%BB%9D-%E3%81%BF%E3%82%84%E5%AD%90/dp/4297101971/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E5%BF%9C%E7%94%A8%E6%83%85%E5%A0%B1&qid=1558913539&s=gateway&sr=8-2

まず一周ざっと読みます。
基本情報のテキストと被る内容も多いのでページ数の割にさくっと読めます。

その後は早速過去問演習です。

過去問道場で一年分の午前問題を解く。
https://www.ap-siken.com/apkakomon.php

基本情報の知識があれば大体4割位は取れると思います。

ここで大事なのは分野毎の得点率を出します。
全体で4割かもしれませんが、セキュリティに分野は7割取れているけど、ネットワークは2割しか取れない。
ということが起きていると思います。

そのため、二週目は一番得点率の低かった分野を重点的にテキストを読み込んでいきます。

一番低かった分野が一番低くなくなったら、新たに一番苦手になった分野を重点的にインプットしていく。

これらを繰り返していくと2ヶ月くらいで午前は6割(ギリギリ合格点)取れるようになると思います。

午前はこのくらいで十分です。
なぜなら、この後の午後対策を行えば更に知識が着いて1割くらいは得点が伸びます。

2ヶ月~5ヶ月 午後対策

午後対策はこの本一択です。
2019応用情報技術者午後問題の重点対策 (重点対策シリーズ) 
https://www.amazon.co.jp/2019%E5%BF%9C%E7%94%A8%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85%E5%8D%88%E5%BE%8C%E5%95%8F%E9%A1%8C%E3%81%AE%E9%87%8D%E7%82%B9%E5%AF%BE%E7%AD%96-%E9%87%8D%E7%82%B9%E5%AF%BE%E7%AD%96%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E5%B0%8F%E5%8F%A3%E9%81%94%E5%A4%AB/dp/4865751556/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=%E5%BF%9C%E7%94%A8%E6%83%85%E5%A0%B1+%E5%8D%88%E5%BE%8C&qid=1558914543&s=gateway&sr=8-1

まず初めに選択する問題を絞りましょう。
本番で難しい問題が出た場合のために選択する数+1くらいと良く言われますが、選択する数で十分です。
なぜなら、難問が出た場合は点数の補正が入るからです。

後は三ヶ月間ひたすらこの問題集を解きます。

ラスト一ヶ月
総仕上げで過去問を解き、苦手分野を見つけ、それをインプットする。
以上をひたすら繰り返していきます。

##③1日どのくらい勉強したか
ラスト一ヶ月は平日2時間休日4時間ほど勉強しました。
それ以外の期間は平均1時間くらいです。
少し早く出社すれば簡単に確保できる時間だと思います。
Docker上で環境を作るメリット

Docker上でミニマムPython環境を作ってみました。
その中で感じた、Docker上で環境を作るメリットを整理しました。

# 結論
 - pythonファイルを書いて実行するための超シンプルな環境が出来た。
https://hub.docker.com/r/rimacdocker/ubuntu_python

 - [dockerを使うメリット](#docker上で環境を作るメリット)を整理出来た。

# Dockerとは
ざっくり説明すると以下のような感じです。
・軽量で高速に起動、停止などが可能な仮想化基盤
・ミドルウェアのインストールや各種環境設定をコード化して管理できる

# 今回作った環境(DockerImage)

OSはUbuntu18.04を入れました。
dockerのubuntuイメージは本当に最低限のものしか入ってないので、
とりあえずvimをインストール。
(そのままだとviコマンドすら効きません…)

さらに、言語python3をインストール、
python3のパッケージマネージャとしてpip3も入れてます。

 - OS:
  -  Ubuntu18.04

 - インストールしたパッケージ:
  - Python 3.6.7
  - pip 9.0.1
  - Vim 8.0

#### コンテナ内で実行したコマンド一覧
```
apt update
apt upgrade
apt install vim
apt install python3
apt install python3-pip --fix-missing
```

# Docker上で環境を作るメリット
#### 移植が圧倒的に楽
もはや言い尽くされた感もありますが、
dockerコンテナとして構築することで
使用するPCにdockerさえ入っていれば
OSやライブラリ、ミドルウェアを意識せずにその環境を使えるのがメリットです。

やろうと思えば、
会社の端末、家の端末、出先の端末、
どこでも同じインフラ環境で作業出来るのはとても便利です。
マシンサーバーとしてのOSは意識しなくて良いのが嬉しいです。

docker cpコマンドでコンテナ-ホスト間のファイルのやりとりも簡単に出来ます。
(マウントポイントとか作らなくて良いんですね)

#### 環境構築のやり直しが出来る
環境作ってる時に想定外のエラーが起こることは多々あります。
・ ライブラリのインストールに失敗して中途半端に何かが入っちゃうとか…
・ パッケージが足りないと言われて、パッケージインストールしたのに結局上手くいかないとか…
・ 何かをインストールしたせいで、それまで上手くいってたものまで動かなくなったとか…
(考えただけで頭が痛くなりますね…。)

そんな時に、dockerであれば
exitコマンドでコンテナから抜けて、
ごちゃごちゃした環境をリセット出来るのはとても有り難いです。

ここでは説明を割愛しますが、
こまめにdocker commitしておけば、
exitしてもcommit時点の環境から作り直せるので
その点でも環境構築のコストは大幅に削減出来ます。

#### ~~不要なもの~~ 運用上必要なものを入れなくて良い
例えば、pythonをインストールして使うとき、
python自体のバージョン管理として
virtualenvとかpyenvを入れて運用することが多いですが、
docker上で環境を作る時はそれらのミドルウェアを入れなくて良いと(個人的には)思っています。

他のバージョンのpythonを入れたいときは
別のコンテナやイメージを作れば解決しますからね。

簡単な構成にしておくことは
環境を作る上でも、運用上でもメリットは大きいです。
(少なくとも、ある日突然、pyenvコマンドが効かない…みたいな絶望からは距離をおくことが出来るんじゃないですかね)

# まとめ
dockerコンテナ毎に様々な環境を、独立して作れるので
ややこしいライブラリを気にせず入れたり、
各言語、ライブラリの最適化環境を作ったりできるのが嬉しいですね。

環境構築コストも軽減できるので、気軽に試せて良いと思います。
オブジェクト指向でなぜつくるのかまとめ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/f6f3faf9-308b-9d06-19c9-fb9936d1b5ef.png)
重要だと思った部分を抜粋しつつまとめ

## 目的
「オブジェクト指向」そのものに対する視点と知識量を増やす。

## オブジェクト指向とは
無駄を省いて整理整頓するもの

## 理解が難しくなる理由
「汎用の整理術(システム設計上の共通理解)としての表現」なのか、「オブジェクト指向プログラミングとしての表現」なのかを意識して読み取る必要がある

- 混乱したまま理解しようとする為
- どう混乱しているかを上手く整理できない、もしくは説明者もどう混乱しがちかを把握していない為
- 現実世界と共通点ばかりにフォーカスしてしまう
- プログラミング言語的理解が先行すると、言葉が同じであるがゆえに概念的な説明に対して技術的な仕様レベルの話を持ち込んでしまう

## 混乱要因
1. 用語の洪水
オブジェクト指向を説明する対象とする分野の広さから、特殊用語のオンパレードすぎる

2. 比喩の乱用
比喩だけが強烈な印象としてのこってしまい、聞く側がそれぞれ解釈し、誤解を生みがち

3. なんでもオブジェクト症候群
「オブジェクト思考を使えば、現実世界をそのままプログラムに表現できる」という考え方を鵜呑みにしてしまい、オブジェクト指向という技術を説明する1側面である事を認識できない

上記3点が一度にきてしまう

## 混乱要因を排除する方法
1. 紹介する用語や概念は最小限にする。
2. 比喩による説明は最小限に抑える。比喩を使う場合にはその旨を明示する。
3. プログラミングの仕組みと、「モノ中心」で汎用的に物事をとらえる考え方は別物として、分けて説明する。

## オブジェクト指向の三大要素
- クラス(カプセル化)
- ポリモーフィズム
- 継承

## 概念とプログラミング技術の2軸で理解する
初学時はプログラミングにおけるオブジェクト指向技術を指す部分(コード)をはっきり認識できていないケースがある為、抽象表現との紐付けが上手くできずに混乱する

### 共通点
オブジェクト指向は現実世界をそのまま反映したものである

- 現実世界に存在する固有の物体を全てオブジェクトと考えること
- これがプログラミング技術におけるインスタンス化した実体と通じる

### 相違点
オブジェクト指向は現実世界と似て非なる部分がある

- 現実世界の人やモノはクラスから作らない(概念先行ではない)
- 現実世界の人やモノはメッセージだけでは行動しない(自立した行動もする)

### プログラミングのための仕組みという事を割り切って抽象表現とは別軸でも理解する
- クラスは変数と関数をひとまとめにして独立性の高い部品を作る仕組み
- ポリモーフィズムと継承はコードの重複を排除して汎用性の高い部品を作る仕組み

### プログラミングは現実世界全てではなく、一部が実現された世界であることを認識する
人間の仕事の一部の世界を実現している

- 覚える仕事
- 決まり切った仕事

## プログラミング技術の側面からみたオブジェクト指向の三大要素の利用
- クラス(カプセル化)
  - クラスからインスタンスを作成して、メソッドと変数定義をまとめて利用する
- ポリモーフィズム
  - 親クラスのインスタンス生成時のメッセージの変更によって、呼び出される側のロジックをアプリケーション固有の処理で置き換える
- 継承
  - クラス定義の共通部分を親クラスにまとめて、コードの重複を排除する

## 関連記事
[カプセル化について](https://qiita.com/dich1/items/90081bb765239366350b)
[継承について](https://qiita.com/dich1/items/2141f75062e5e5cfc509)
[ポリモーフィズムについて](https://qiita.com/dich1/items/6768b3c7df45676cfd21)

## 雑感
この本では「クラス」という言葉で他の2要素と並べているけど言葉の種類を揃えると「カプセル化」の方がしっくり自分はしてしまう