OmniAICreator/Qiita-1.07M huggingface dataset:
Edge,IE11だけFileListにevent.dataTransfer.filesが入らない


# 経緯
ドラッグ&ドロップ式 ファイルアップロード画面のIE対応でハマった話
モダンブラウザではきちんと動くのに、edgeとIE11だけドロップしても動かない。

```js
// input要素
const fileInput = document.getElementById("fileInput")
// ファイルをdropする要素
const dropTarget = document.getElementById("dropTarget")

function hoge(event) {
  event.preventDefault()
  event.stopPropagation()
  event.dataTransfer.dropEffect = 'copy'
}

function fuga(event) {
  event.stopPropagation()
  event.preventDefault()
  fileInput.files = event.dataTransfer.files; //今回問題の部分
}

dropTarget.addEventListener('dragover', e => {
  hoge(e)
})
dropTarget.addEventListener('drop', e => {
  fuga(e)
})

```

よくあるドラッグ&ドロップでフォーム実装する時の処理ですね。
`<input type="file">`のFileListオブジェクトに対して、
なぜかIE系だけ`event.dataTransfer.files`が入らない。
これに結構ハマりました。

# 対応
何やらIEからは「厳密モードのFileListは読み取り専用なので代入できません」って怒られます。
babelが吐き出してくれるソースにはデフォルトで`use strict`が付くので、取っちゃおうかと考えました。

```json:.babelrc
{
  "sourceType": "script"
}
```

`"sourceType": "script"`を`.babelrc`に追加することで、
バベられた後のソースから`use strict`を取っ払うことができます。

**しかしこの対応でも動かない。**

しかも`"sourceType": "script"`を指定すると
import/exportがつかえなくなります。(しんどい)
**何より`use strict`を取るって対応そのものが単純に敗北感が強い。**

# 解決

色々調べましたが、結局あまりスマートな解決の糸口が見つからず、
`event.dataTransfer.files`を`<input type="file">`の
FileListオブジェクトに突っ込まない方法で解決。

```js

// input要素
const fileInput = document.getElementById("fileInput")
// 画像をdropする要素
const dropTarget = document.getElementById("dropTarget")

function piyo(data) {
  const formData = new FormData(document.getElementById("form"))
  formData.append('image', fileData[0])
  //APIコール用のロジック
}

function hoge(event) {
  event.preventDefault()
  event.stopPropagation()
  event.dataTransfer.dropEffect = 'copy'
}

function fuga(event) {
  event.stopPropagation()
  event.preventDefault()
  piyo(event.dataTransfer.files);
}

dropTarget.addEventListener('dragover', e => {
  hoge(e)
})
dropTarget.addEventListener('drop', e => {
  fuga(e)
})

```

`event.dataTransfer.files`を引数で渡していって
formdataに突っ込んでAPIに投げてあげる形に。
formdataがFilelistオブジェクトしか受け付けない。
みたいになってたら詰んでました。

`File()`で新しくインスタンス生成する方向でも考えたものの、
第二引数に渡すBlob型のデータをdropで取得する方法がわからないのと、
普通にクリック処理でファイルを受け取る場合は
`<input type="file">`のデフォルトの挙動に頼っていたので断念。

これ上手なやり方ご存知の方はぜひ教えてください。
VIVE Pro でハンドトラッキング

# はじめに

VIVE Proでハンドトラッキングしたので，やり方を残しておきます．
同様の内容の記事を僕の[Scrapbox.io/7cancer](https://scrapbox.io/7cancer/HTC_VIVE_Pro_%E3%81%A7%E3%83%8F%E3%83%B3%E3%83%89%E3%83%88%E3%83%A9%E3%83%83%E3%82%AD%E3%83%B3%E3%82%B0)にも残してあります．

# 環境
- Windows10
- Unity 2018.3.12f1
- SteamVR 1.9.16

# 手順

## Unity側の設定
- 以下のurlから**Vive Hand Tracking SDK**をダウンロード．
  - https://developer.vive.com/resources/knowledgebase/vive-hand-tracking-sdk/
- 解凍すると**Vive Hand Tracking Unity.unitypackage**があるので，Unityでインポート．

## SteamVR側の設定
- **設定**から，VIVE Proのカメラが有効になっているかを確認する．

![sukusyo2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390881/44735e2f-e8d6-e0ef-5fd6-376f33564740.png)

- この画面の設定から．

![camera.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390881/09eb3d72-f933-a8e9-ca71-bd19e01a41b4.png)

- この画面を開いて確認．

# 動かしてみる
- Unityで動作確認をしてみる．
- `Project > ViveHandTracking > Sample`にあるSampleシーンを実行してみる．

![handTracking.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390881/f1cda0b5-c2c8-1794-0768-83d972d440b1.gif)

動作した．
なにかあればコメントを下さい．
年末まで毎日webサイトを作り続ける大学生 〜69日目 オブジェクト指向とマウスと円〜

##はじめに
こんにちは！@70days_jsです。
昨日に引き続き円で遊びました。
昨日は自動でしたが、今日はマウスに合わせて円が作られます。(gif)↓
![test3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/ad575d64-eccc-0c50-dcdc-5d7a97413040.gif)

今日は69日目。(2019/12/26)
よろしくお願いします。

##サイトURL
https://sin2cos21.github.io/day69.html

##やったこと
マウスに合わせて円を作ります。
cssなし。

html↓

```html
  <body>
    <canvas id="canvas"></canvas>
  </body>
```

JavaScript↓

```javascript
let canvas = document.getElementById("canvas"),
  ctx = canvas.getContext("2d"),
  canvasW = (canvas.width = window.innerWidth),
  canvasH = (canvas.height = window.innerHeight),
  circles = [];

function Circle(ctx, x, y, size) {
  this.ctx = ctx;
  this.x = x;
  this.y = y;
  this.size = size;
  this.r = Math.random() * 256;
  this.g = Math.random() * 256;
  this.b = Math.random() * 256;
  this.a = Math.random() * 11;
  this.v = Math.ceil(Math.random() * 3);
}

Circle.prototype.render = function() {
  this.draw();
  this.statusChange();
};
Circle.prototype.draw = function() {
  let color = this.r + "," + this.g + "," + this.b + "," + this.a;
  let ctx = this.ctx;
  let random = Math.ceil(Math.random() * 2);
  ctx.beginPath();
  ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
  if (random > 1) {
    ctx.strokeStyle = "rgba(" + color + ")";
    ctx.stroke();
  } else {
    ctx.fillStyle = "rgba(" + color + ")";
    ctx.fill();
  }
  ctx.closePath();
};

Circle.prototype.statusChange = function() {
  this.size += 1;
  if (this.size > canvasW / 3 || this.size > canvasH / 3) {
    this.size = 0;
  }
};

document.body.addEventListener("mousemove", createCircleObject);

function createCircleObject(e) {
  let x = e.pageX;
  let y = e.pageY;
  let size = Math.random() * 10;
  let circle = new Circle(ctx, x, y, size);
  circles.push(circle);
}

function render() {
  ctx.clearRect(0, 0, canvasW, canvasH);
  circles.forEach(function(obj) {
    obj.render();
  });

  requestAnimationFrame(render);
}

render();
```


大部分は昨日と同じなので、違うところを解説していきます。

まずオブジェクトの作成はイベントリスナーでマウスの移動で取っています。

>document.body.addEventListener("mousemove", createCircleObject);

オブジェクトはマウスの通った位置にできます。

>function createCircleObject(e) {
  let x = e.pageX;
  let y = e.pageY;
  let size = Math.random() * 10;
  let circle = new Circle(ctx, x, y, size);
  circles.push(circle);
}

昨日はsizeがもっと大きかったのですが、今回は小さめに微調整しました。

円はだんだん大きくなっていくのですが、昨日より最大の大きさを低めに設定しました。
また、最大限大きくなっても位置は変わらず、サイズのみ0から始めることで、z軸の移動もしているような視差効果が得られます。

>  if (this.size > canvasW / 3 || this.size > canvasH / 3) {
    this.size = 0;

gifを見ているとなんとなく奥から手前に移動しているように見えませんでしょうか？


##感想
オセロ作らねば。

最後まで読んでいただきありがとうございます。明日も投稿しますのでよろしくお願いします。
NginxのリバプロでCORSとサヨナラする

# はじめに
いなたつアドカレの二十六(ry

はい、アドカレロスなので勝手に26日目書きます。

docker-composeを用いてフロントエンドとバックエンドを分離して開発するなんて場合は最近多々あるのではないでしょうか？
CORSに悩まされますよね。つらい。解決しましょう。

# リバプロってなんだ？
リバースプロキシの略称ですね。
HTTPからアプリケーションサーバにリクエストを飛ばしたりするやつです。

# Nginxの設定

```default.conf
server {
    listen 80;
    root /usr/share/nginx/html;
    error_page 500 502 503 504 /error.html;
    location /error.html {
        internal;
    }

    location /api/ {
        proxy_pass http://[CONTANER_NAME]:8000;
        proxy_set_header Host $host:$server_port;
        proxy_set_header X-Forwarded-Host $server_name;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
    
}
```
このように設定ファイルを書くことで/api/へのリクエストを任意の場所へアクセスを飛ばすことができます。
ここで、任意のCONTAINER_NAMEで任意のポート番号`backend:8000`みたいな感じバックエンドへと飛ばします。

/api/以外から始まるものは普段通り `root /usr/share/nginx/html` を参照してファイルを返却してくれ、かつ/api/のアクセスはapiにアクセスするといった感じです。

nginxでファイルを返したい時も、リバースプロキシでapiを叩きたい場合も`hoge.com/hoge` or `hoge.com/api/hoge`を叩くかで振り分けているため、オリジンが同一になるため、CORSにかかりません。

これで、あなたもCORSとはぐっばいです。
コマンドラインでdockerに入門

```bash
// install
$ brew cask install docker

$ docker --version
Docker version 19.03.5, build 633a0ea

// これは自動でよしなにイメージをとってきてコンテナを作ってくれる
$ docker run hello-world

// Docker Hubからimageをとってくる
$ docker pull alpine

// とってきたimageがある
 $ docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
alpine              latest              965ea09ff2eb        4 weeks ago         5.55MB

// コンテナを作る
 $ docker create -it alpine

// コンテナがある
 $ docker container ls 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
e1dd4b1c20a6        alpine              "/bin/sh"           43 seconds ago      Up 19 seconds                           charming_gates

// コンテナ起動
$ docker start e1d(コンテナID、ほかとかぶってなければ3文字ですむ)
e1d

// コンテナストップ
$ docker stop e1d

// 消えてる
 $ docker container ls 
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES

// 動いてないものも見たいとき
$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                            PORTS               NAMES
e1dd4b1c20a6        alpine              "/bin/sh"           2 minutes ago       Exited (137) About a minute ago                       charming_gates

// コンテナ名を変えられる
$ docker rename sleepy_chatelet hoge

$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                            PORTS               NAMES
e1dd4b1c20a6        alpine              "/bin/sh"           3 minutes ago       Exited (137) About a minute ago                       charming_gates

// alpineの中に入る
docker run -it alpine bin/sh

// exitで出れる。

// コンテナを消す
$ docker rm e1d

// 消えてる
$ docker container ls -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
```

参考文献
すごく参考になりました。これがなければ、dockerに入門してみようということにならなかったかもしれません。スタートのハードルが下がりスタートできました。
[\#マンガでわかるDocker ① 〜概念・基本コマンド編〜 【ダウンロード版】 \#技術書典 \- 湊川あいの、わかば家。 \- BOOTH](https://booth.pm/ja/items/825879)

参考サイト

[p17\-p31 PHPのローカル開発環境をサクッと作ってみよう \- マンガでわかるDocker サポートサイト](https://scrapbox.io/docker/p17-p31_PHP%E3%81%AE%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E9%96%8B%E7%99%BA%E7%92%B0%E5%A2%83%E3%82%92%E3%82%B5%E3%82%AF%E3%83%83%E3%81%A8%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86)

[dockerコマンドの使い方を学ぼう！dockerコマンドチートシート](http://exrecord.net/how-to-use-docker-command)

[Dockerコマンドメモ \- Qiita](https://qiita.com/curseoff/items/a9e64ad01d673abb6866)

[Dockerコマンド](http://www.tohoho-web.com/docker/command.html)
初学者によるプログラミングMemo　#2　開発前の準備知識

# はじめに
開発前の準備知識として記述します
今回も相変わらずざっくりですので、理解の一助になればと思います
なお、本記述はMacにおいて、Railsでの開発を前提としています
また、まだまだひよっこですので、不備等ございましたらご指摘いただけると幸いです


# 目次
- terminal
- ディレクトリ
- パス
- Linuxコマンド




# terminalとは
PCに命令をすることができるアプリケーション
MACにデフォルトでインストールされているコマンドライン

## コマンドラインとは
プログラムを記述したファイルを読み込み、プログラムとして実行するためのツール
コマンドラインインターフェース（CLI）とも言う
対照的に、グラフィックを用いて操作を行う仕組みを、グラフィカルユーザインタフェース（GUI）と言い、代表的なものは"マウスでクリックする"が当てはまる
コマンドラインの方が、操作の数が圧倒的に多いため、コマンドラインになれておく方がいい

# ディレクトリとは
ファイルを管理するフォルダのこと
階層構造になっている
ルートディレクトリやカレントディレクトリ、ホームディレクトリなど

## 階層構造とは
写真のように、１つのディレクトリの中に複数のファイルとディレクトリがあり、そのディレクトリの中にも同様に…と言うこと
<img width="218" alt="スクリーンショット 2019-12-26 20.10.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522204/2fc116f6-f091-182e-5254-344fc8f5d354.png">

## 各ディレクトリについて
- ルートディレクトリ
その階層構造の一番上にあるディレクトリのこと
前出の写真で見ると一番上の"VUE_TEST"と書いてあるものがそれに当たる

- カレントディレクトリ
ターミナルで現在作業中となるディレクトリのこと
命令を出すときの基準点

- ホームディレクトリ
新規にターミナルを立ち上げた場合に作業中となるディレクトリのこと
Macでのデフォルトのホームディレクトリは"/Users/ユーザ名"となり、ターミナル上では"~"で表示される

<img width="492" alt="スクリーンショット 2019-12-26 20.21.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522204/da98879b-26d5-d1fd-c124-c1a77f076b77.png">

# パス
ディレクトリやファイルの所在を示すもの
わかりやすく言えばそれぞれの住所のこと
階層ごとに"/"で区切り、絶対パスと相対パスの二つがある

## 絶対パス
ルートディレクトリから指定するパス
Macの全ディレクトリにおけるルートディレクトリは"/"なので、前述した区切りの"/"と間違えないように
パスのはじめに"/"をつける
##### 表示方法
/Users/ユーザ名/hoge
または、ホームディレクトリ以下であれば
~/hoge
でも可能
## 相対パス
カレントディレクトリから指定するパス
##### 表示方法
＊今"projects"というディレクトリにいるとして
projects/our_blog/Gemfile

## 絶対パス・相対パスまとめ
絶対パスは、郵便を送る時の住所
大阪府枚方市〜…
相対パスは、道案内
そこまっすぐ行って、左曲がってだーっと行ったら右に見えてくるわ

# Linuxコマンド
ターミナルからのPC操作をするために入力するコマンド
LinuxとはOSと呼ばれるPCの中身の種類となるもの…ですが難しいので割愛します
とにかく、コマンド打ったら動くから、そのコマンドのことをLinuxコマンドって言うよってこと
代表例は"ls"と"cd"
<img width="569" alt="スクリーンショット 2019-12-26 20.47.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522204/9d9eef2f-9d39-d3a6-ae76-cfcb781a310e.png">
"ls"と打ち込めば、そのディレクトリ直下のファイルとディレクトリを表示できる
"cd"はディレクトリの移動
"cd"の後に、行きたいディレクトリ名を入力すると移動できる
写真では"ls"コマンドでホームディレクトリで一覧を確認し、"cd"コマンドで"projects"へ移動した
＊タイポは無視してね

# まとめ
ディレクトリは階層構造
絶対パスは郵便の住所
相対パスは道案内
LinuxコマンドはterminalからPCを操作するコマンド

##### putit情報
- カレントディレクトリのパス表示は"pwd"と入力するだけ
- ファイル名等の入力の際、途中まで入力してからTabキーを押すと残りを自動入力してくれる
該当が複数ある場合はもう一度Tabキーを押せば候補リストを出せる
「リファクタリング 第2版」Swiftでコーディング その1

# 2頁 第1章 statement関数
## Swift版 main.swift

データ生成、結果表示付き。

```swift
import Foundation

makeData()

func statement(invoice:Invoice, plays:Dictionary<String, Play>) -> String {
    var volumeCredits = 0
    var totalAmount = 0
    var result = "Statement for \(invoice.customer)\n"
    let format = NumberFormatter()
    format.numberStyle = .currency
    format.locale = Locale(identifier: "en_US")

    for perf in invoice.performances {
        let play = plays[perf.playID]!
        var thisAcmount = 0

        switch play.type {
        case "tragedy":
            thisAcmount = 40000
            if perf.audience > 30 {
                thisAcmount += 1000 * (perf.audience - 30)
            }
        case "comedy":
            thisAcmount = 30000
            if perf.audience > 20 {
                thisAcmount += 10000 + 500 * (perf.audience - 20)
            }
            thisAcmount += 300 * perf.audience
        default:
            print("error")
        }

        volumeCredits += max(perf.audience - 30, 0)
        if "comedy" == play.type {
            volumeCredits += Int(perf.audience / 5)
        }
        result += "  \(play.name): " + format.string(from: NSNumber(value: thisAcmount / 100))! + " (\(perf.audience) seats)\n"
        totalAmount += thisAcmount
    }
    result += "Amount owed is " + format.string(from: NSNumber(value: totalAmount / 100))! + "\n"
    result += "You earned \(volumeCredits) credits\n"
    return result
}

let result = statement(invoice: invoices[0], plays: plays)
print(result)
```

## データ生成 data.swift

```swift
import Foundation

let json_plays = """
{
"hamlet": {"name": "Hamlet", "type": "tragedy"},
"aslike": {"name": "As You Like It", "type": "comedy"},
"othello": {"name": "Othello", "type": "tragedy"}
}
"""

let json_invoices = """
[
{
"customer": "BigCo",
"performances": [
{
"playID": "hamlet",
"audience": 55
},
{
"playID": "aslike",
"audience": 35
},
{
"playID": "othello",
"audience": 40
}
]
}
]
"""

struct Play: Codable {
    let name: String
    let type: String
}

struct Plays: Codable {
    let hamlet: Play
    let aslike: Play
    let othello: Play
}

struct Performance: Codable {
    let playID: String
    let audience: Int
}

struct Invoice: Codable {
    let customer: String
    let performances:[Performance]
}

let json_plays_data: Data =  json_plays.data(using: String.Encoding.utf8)!
let json_invoices_data:Data = json_invoices.data(using: String.Encoding.utf8)!

var plays:Dictionary<String, Play> = [:]
var invoices:[Invoice] = []

func makeData() {
    let decoder: JSONDecoder = JSONDecoder()

    do {
        let json: Plays = try decoder.decode(Plays.self, from: json_plays_data)
        plays["hamlet"] = json.hamlet
        plays["aslike"] = json.aslike
        plays["othello"] = json.othello
        
    } catch {
        print("error:", error.localizedDescription)
    }

    do {
        let json = try decoder.decode([Invoice].self, from: json_invoices_data)
        invoices = json
    } catch {
        print("error:", error.localizedDescription)
    }

//    print(plays)
//    print(invoices)
}
```
パスワード変更ではまったお話

#このパスワードはドメインで要求される長さ、複雑さ、または履歴の条件を満たしていません

Set-ADAccountPasswordが何度やっても↑のエラー

[複雑さの要件を満たす必要があるパスワード - Microsoft Doc](https://docs.microsoft.com/ja-jp/windows/security/threat-protection/security-policy-settings/password-must-meet-complexity-requirements)

↑読んで、ちゃんと要件満たしてるよなぁ、と思ってたら

>英数字以外の文字 (特殊文字): (~! @ # $% ^& * _-+ = ' | \ \ (){}\ []:; "'<>,.?/) 
>このポリシー設定では、ユーロや英国ポンドなどの通貨記号は特殊文字としてカウントされません。

ん？もしかして特殊記号の一覧の中に「\$」は入ってるけど、**「\$」も通貨記号だし特殊文字扱いされない**とか…？

**ビンゴでした。「$」は記号扱いされません**
SQLSERVERのDBにXML型を含む新規ストアドをバッチ適用したらエラーになった

# はじめに
ストアドプロシージャを新規に作成してDBに適用したところエラーになりました。
そのときの対応内容をメモしておきます。

# 環境
Windows10
SQLServer 2017
Management Studio 17

# 再現手順
新規のストアドプロシージャを作成して開発環境にリリース。
ストアドプロシージャにはXML型の記述が含まれています。
DBモジュールリリース用のバッチがあるので実行したところ下記のエラーがでました。

「SELECT INTOが失敗しました。
次のSETオプションには不適切な設定'QUOTED_IDENTIFIER'があります。
SETオプションが、インデックス付きビュー、計算列のインデックス、フィルター選択されたインデックス、クエリ通知、XML型データ型のメソッド、空間インデックスの操作で使用するのに適切であることを確認してください。」

なお、リリースバッチを使用せずにプログラムを直接SSMSで開いて適用したところ正常に適用されました。

# 原因
エラー内容に記載のとおり、QUOTED_IDENTIFIERというSETオプションの設定が不足していました。
ストアドプロシージャ内で一時テーブルへデータをSELECT INTOしているのですが、
一時テーブルのQUOTED_IDENTIFIERがONの設定になっていないためエラーになったと思われます。

# QUOTED_IDENTIFIER
予約済キーワードを使用できるようにするオプションのようです。
"SELECT"や"ORDER"といった予約済キーワードをオブジェクト識別子(テーブル名、カラム名等)として使用できるようになります。
そして、XML型を使用する場合はこのオプションをONにする必要があります。
以下、公式からの引用です。

https://docs.microsoft.com/ja-jp/sql/t-sql/statements/set-quoted-identifier-transact-sql?view=sql-server-ver15
>XML データ型のメソッドを呼び出す場合は、SET QUOTED_IDENTIFIER を ON に設定する必要があります。

# おわりに
QUOTED_IDENTIFIERオプションはONが規定値のようです。
SSMSから直接ファイルを開いて単独実行した場合には成功したのはこのためと思われます。
外部からsqlcmd実行する際は明示してあげる必要があるのでしょうか。

QUOTED_IDENTIFIERオプションはインデックス付きビューで効果を発揮するらしいです。
インデックス付きビューの効果についてもう少し知りたくなりました。

# 参考
https://docs.microsoft.com/ja-jp/sql/t-sql/statements/set-quoted-identifier-transact-sql?view=sql-server-ver15
https://social.msdn.microsoft.com/Forums/ja-JP/30ffa085-04fd-4e67-8466-05b2fc65e852/microsoft-sql-server-management?forum=sqlserverja
https://qiita.com/maaaaaaaa/items/4653d610c0925504b10a
Docker+nginxでTimeZoneをAsia/Tokyoにする

dockerでnginx 1.17.6の環境を構築したときに、TimeZoneがUTCとなっていたため、ログに出力される時間などがおかしい状態があり、JSTにするのにちょっとてこずったのでメモを残します。

```shell-session
.
├── docker-compose.yml
└── web
    ├── build
    │   └── Dockerfile
    └── conf
        └── default.conf
```

php-fpmの環境構築用にnginxを用意していたため、default.confは余計な設定が入っています。

```config:default.conf
server {
  listen 80;
  server_name 127.0.0.1;

  #ドキュメントルートの設定
  root  /var/www/;
  index index.php index.html index.htm;

  location / {
    # 指定された順序でfileやdirの存在を確認し、最初に見つかったものを返却する。
    # いずれも無かった場合は、最後に指定されたパスに遷移する。
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    # php-fpmのコンテナである「app」のポート9000に対してリクエストのパスを設定
    fastcgi_pass   app:9000;
    # 1台のサーバーでnginx+php-fpmを動作させる場合、Unixソケットの方が高速に動作するため、
    # 以下の設定をするが、今回はnginxとphp-fpmを別のコンテナにしているため、ポートでの接続となっている。
    # fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
  }

  access_log /var/log/nginx/access.log;
  error_log  /var/log/nginx/error.log;
}
```


```yaml:docker-compose.yml
version: '3'
services:
  web:
    build: ./web/build
    ports:
      - "80:80"
    depends_on:
      - app
    volumes:
      - ./web/conf/default.conf:/etc/nginx/conf.d/default.conf
```

```dockerfile:./web/build/Dockerfile
FROM nginx:1.17.6

# TimeZoneをAsia/Tokyoに設定する
ENV TZ Asia/Tokyo
RUN echo "${TZ}" > /etc/timezone \
   && dpkg-reconfigure -f noninteractive tzdata
```

これでコンテナを起動してnginxのコンテナにアクセスし、`date`コマンドで時間を確認すると以下のようになる。

```shell-session
$ docker-compose exec web bash

root@0eb5b274bc8d:/# date
Thu Dec 26 20:33:06 JST 2019 ← JSTになっている。
```
Google Nest Hub に草を表示

Pixel 4 を買ったら Google Nest Hub が届きました。デジタルフォトフレームとしてもいい感じに使えそうです。せっかくなので、GitHub の草画像を表示させてみることにします。

![nesthub.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123106/2bd0bd55-4959-7f82-6e20-e4e4a352a9c6.jpeg)

# Google Nest Hub の設定
購入直後の Nest Hub は、Google が用意したアートギャラリーを表示するようになっています。これを、好きな画像を表示できる設定に変更します。

1. iOS または Android 端末で Google Home アプリを起動
  * Nest Hub を買ったら、インストールしているはず
2. Nest Hub > フォトフレーム に移動
  * 表示する画像の設定を Google フォトに変更
3. 「個人的な写真の整理」の設定を「リアルタイム共有アルバムのみ」に変更
  * この設定をしないと、GitHub の草画像などはフォトフレームに不向きと判定され、表示されないことがある

フォトフレームに表示する Google Photos アルバムは適当に選んでください。草画像を保存するアルバムは、後で紹介するスクリプトが自動で作成します。

# Google Photo API のアクセストークン取得
これから、草画像を生成して Google Photo API にアップロードする python スクリプトを動かします。そのためには、デフォルトでは無効化されている Google Photos API を有効化し、OAuth 2.0 のトークンを取得する必要があります。

今回は、こちらの Qiita 記事を参考にしてトークンを取得しました。

* https://qiita.com/shin1ogawa/items/49a076f62e5f17f18fe5

Client ID, Client Secret および Refresh Token を後で使います。これらは公開してはいけないものなので、くれぐれも管理に気を付けてください。

# 草画像の作成とアップロードを行うスクリプト
以下のリポジトリに、GitHub の草画像を生成して Google Photos にアップロードする python スクリプトを用意しました。

* https://github.com/fjt7tdmi/grass-photo

草画像の生成にあたっては、https://grass-graph.moshimo.works/ を参考にさせていただきました。

スクリプトを実行すると、草画像保存用の Google Photos アルバムが自動作成されます。デフォルト名は "GitHub grass" です。このアルバムを表示するように、Google Nest Hub の設定を行ってください。

# 自動化
リポジトリには GitHub Actions の設定が含まれています。以下のシークレットを設定しておくと、草画像の生成・アップロードを自動で毎日行ってくれます。

* GITHUB_CLIENT_ID
* GOOGLE_API_CLIENT_ID
* GOOGLE_API_CLIENT_SECRET
* GOOGLE_API_REFRESH_TOKEN

# Nest Hub に草画像を表示してみたい方へ
私の作ったスクリプト群は Apache 2.0 ライセンスで配布しています。GitHub リポジトリをフォークしていただくことで、自動化機能も含めてご利用いただけます。

* https://github.com/fjt7tdmi/grass-photo

ただし、以下の点に注意してください。

* OAuth 2.0トークンの流出を避けるため GitHub のプライベートリポジトリを使ってください
  * GitHub のシークレットを使ってはいますが、これだけでは安全とは言い難いです
  * トークンが流出した場合、草画像と関係ないデータも第三者が閲覧・操作できるようになります
* 拙作のスクリプトは草画像の削除は行わないので、Google ドライブの残り容量には注意してください
  * Google Photos にアップロードした画像を削除する API は、現在 (2019/12/26) のところ提供されていないようです
* 本スクリプトを利用したことによる、利用者に生じた直接的・間接的な損害について、私 @fjt7tdmi は一切の責任を負いません

# おわりに
今回多くの助言をいただいた @u_akihir0 に感謝します。
それでは皆様良い Nest Hub ライフを！
deviseをi18nを使って日本語化する

#環境
Ruby 2.5.1
Rails 6.0.2

# devise.ja.ymlの導入

[こちら](https://qiita.com/you8/items/921e0dd1210eb0d158df)を参考にさせてもらってdeviseを日本語化した際に、いくつか違ったので、メモ書きしておく

## gemを導入

```
gem 'devise-i18n'
```

上記のgemを導入した後に、

```
$rails g devise:views:locale ja
```
これを実行。

>Running via Spring preloader in process 70886
Deprecation warning: Expected string default value for '--controller'; got false (boolean).
This will be rejected in the future unless you explicitly pass the options `check_default_type: false` or call `allow_incompatible_default_type!` in your code
You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.
Could not find generator 'devise:views:locale'. Maybe you meant "devise:i18n:locale"?
Run `rails generate --help` for more options.

Maybe you meant "devise:i18n:locale"?

とのことだったので、改めて
```
$rails g devise:i18n:locale ja
```
こいつを実行した。

これによってdevise.ja.ymlが自動生成された。

#参考文献
[Deviseを日本語化する](https://qiita.com/you8/items/921e0dd1210eb0d158df)
初心者によるプログラミング学習ログ 195日目

#100日チャレンジの195日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

195日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>195日目<br><br>udemyでjquery<br>アコーディオンメニュー作成<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1209927900234838016?ref_src=twsrc%5Etfw">December 25, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Rails6 Lost connection to MySQL server during query というエラーが出て困った話

# 目的

- ローカル開発環境にてRailsアプリをブラウザから確認したところ`Lost connection to MySQL server during query`のエラーが出て困った話をまとめる

# 結論

- mysqlの再起動、Railsアプリの再起動を実施したところ正常に戻った。

# エラーまでの経緯

1. ローカル開発環境での確認をしたくてコマンド`$ mysql.server start`を実行した。
1. Railsのアプリを起動するためにコマンド`$ rails s`を実行した。
1. ブラウザにてアプリを確認したところ下記のエラー発生。

    ```terminal
    Lost connection to MySQL server during query
    ```

# 原因究明

- 公式ドキュメントを閲覧したところ下記の内容を発見した。 
   - [https://dev.mysql.com/doc/refman/5.6/ja/packet-too-large.html](https://dev.mysql.com/doc/refman/5.6/ja/packet-too-large.html)
   - `MySQL 8.0サーバーまたはクライアントとの間で送受信できる最大のパケットは1GBです。`とあった。
   - パケットのやりとりで許容範囲を超えたことによるエラーだった。

# 解決

1. Railsアプリの再起動を実施した。
    - 改善せず。
1. mysql とRailsアプリの再起動を実施した。
    - 正常にブラウザで表示できた。
Smalltalkでスターリンソート

Smalltalkの練習がてら、かなり賞味期限が切れたネタですが[スターリンソート](https://qiita.com/Tatsuki-I/items/380d6bd06515b872b2b2)を実装してみました。
Advent Calendarの期限は過ぎていますが、賑やかしにスターリンの誕生日である12月18日のSmalltalk Advent Calendarに載せてみます。

### 実装内容
immutableなArrayの場合は自身を変えられないので`stalinSort`ではなく`stalinSorted`というメソッド名にしています。

```SequencableCollection.st
stalinSorted
	^ self copy stalinSorted: [ :a :b | a <= b ]
```

```SequencableCollection.st
stalinSorted: aBlock
	| result |
	result := self copyFrom: 1 to: 1.
	(self copyFrom: 2 to: self size) doWithIndex: [ :each :index |
		(aBlock value: result last value: each)
			ifTrue: [ result := result copyWith: each ]
			ifFalse: [ ]
	].
	^ result
```
いまだにSmalltalk的な書き方がよくわかりません……。

### 実行結果
```Playground
#(6 2 5 7 3 8 8 4) stalinSorted. "#(6 7 8 8)"
#(1 2 1 3 2 3 4) stalinSorted. "#(1 2 3 3 4)"
```
一応期待通り（？）粛清できているようです。
エクセル統計を騙した話

...タイトルがなんかぶっそうですが、大した話ではないですm(_ _)m。

統計処理に使うソフト、いろいろありますが、うちではエクセル統計(英語名BellCurve for Excel)を導入することにしました。Excelの
アドインとして動くタイプのソフトですね。

![コメント 2019-12-26 185812.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547444/db393be0-d11b-da02-a7d5-99f88c1f9957.jpeg)
↑順番前後して、これはアップデータですがイメージってことでｗ

さあ、インストーラーを立ち上げて...

![コメント 2019-12-26 185845.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547444/9b143b7d-3f64-6b24-3c6e-77db38cf824f.jpeg)

？

####？？？？？

##！！！！！！！！！！！？

何故だ。なぜExcelアドインとして働くソフトにAcrobatReaderが必要になるのだ...。（おそらくだが説明書等を見る場合はPDFが必要でインストール後に文句を言われないためにこうしているのでしょう）

そうなると、絶対やりたくなることがあります。

そう。
####エクセル統計のインストーラーを騙して、Readerが無くてもインストールを完了させる！

いったいどこで判別しているのだろうか？
・ProgramFiles　＞　違った
・CommonFiles　＞　違った
・ProgramData　＞　違った

とするとレジストリだろうか？

とりあえず、adobeで検索。関連付けのキーがいくつも...いあいあこれじゃあキリがない、Classisはパスして、と、となって、割とすぐにわかりました。

![コメント 2019-12-26 190000.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547444/5a81b510-26ba-1ae8-2c32-c1e2341e8cdb.jpeg)

software\microsoft\windows\currentversion\app paths\acrord32.exe
どうやらキーがあれば、中に何も書いてなくてもいいようです。

![コメント 2019-12-26 190128.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547444/ee25bb91-1cdf-72de-9d56-1b98fd9c4773.jpeg)

まだアクティベーションしていないので体験版となっています。
めでたしめでたし、無事に起動できましたとさ♪
computedで動的なプロパティを使って表現する ❏Vue.js❏

3より大きいか小さいかを判断します。
その際、`computed`という新たなものを使います。

[![Screenshot from Gyazo](https://gyazo.com/f0921c0019666c7bc0aea080bcdda78f/raw)](https://gyazo.com/f0921c0019666c7bc0aea080bcdda78f)

開発環境はJSFiddle
https://qiita.com/ITmanbow/items/9ae48d37aa5b847f1b3b

```html:html
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
  <p>{{ counter }}</p>
  <button @click="counter += 1">+1</button>
  <p>{{ lessThanThree }}</p>
</div>
```

```javascript:javascript
new Vue({
  el: "#app",
  data: {
    counter: 0
  },
  computed: {
    lessThanThree() {
      return this.counter > 3 ? "3より上" : "3より下"
    }
  }
})
```

【解説】
`{{ lessThanThree }}`と二重中括弧の中にプロパティを入れます。
JS側で`computed`を記述し、`lessThanThree`や`return`などメソッドのようにその後を書きます。

メソッドとの違いは、
`computed`: this.counterの値が変わった時にだけ反応する。
`methods`: ページの描画が少しでも変わった時に反応する。

`counter`の値のみに注目したいので`computed`を使います。

<br>
ではまた！
Redundant alt attribute. Screen-readers already announce `img` tags as an image. 

Gatsby.jsでホームページを作ろうとしていた時のこと。なんか警告を出してきた。

```zsh
warn ESLintError: 
<JavaScriptファイルの絶対パス>.js
  5:5  warning  Redundant alt attribute. Screen-readers already announce `img` tags as an image. You don’t need to use the
words `image`, `photo,` or `picture` (or any specified custom words) in the alt prop  jsx-a11y/img-redundant-alt
```


# この警告は何

[gatsby@2.18.8](https://www.npmjs.com/package/gatsby)には[eslint-plugin-jsx-a11y@6.2.3](https://www.npmjs.com/package/eslint-plugin-jsx-a11y)が依存パッケージとして入っている。

```zsh
% npm ls eslint-plugin-jsx-a11y
<プロジェクトのpackage名>@<プロジェクトのバージョン> <プロジェクトのルートディレクトリパス>
└─┬ gatsby@2.18.8
  └── eslint-plugin-jsx-a11y@6.2.3 
```

これが警告を出してくれている。

「スクリーンリーダーは「img」タグを画像として認識しています。<img>のalt属性に「image」、「photo」または「picture」という単語を使用する必要はありません」らしい。



# そもそも <img> タグに入れる `alt` 属性とは

画像の説明。アクセシビリティとして用意する他に、画像が取得できなかった際、代わりに表示するものでもある。
必須ではない。

```html
<img src="./hogepage.png" alt="ほげぱげ">
```


装飾の場合は空文字列で良いらしい。

```html
<img src="./hogepage.png" alt="">
```



# 参考

* [eslint-plugin-jsx-a11y/img-redundant-alt.md at v6.2.3 · evcohen/eslint-plugin-jsx-a11y](https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/v6.2.3/docs/rules/img-redundant-alt.md)
* [[翻訳] Airbnb React/JSX Style Guide - Qiita](https://qiita.com/yamadashy/items/e64762e407b8dd5e0247)
* [&lt;img&gt;: 埋め込み画像要素 - HTML: HyperText Markup Language | MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Element/img)

* [html - accessibility in decorative images or repetitive information images - Stack Overflow](https://stackoverflow.com/q/44677529)
* [javascript - What does this warning message mean? &#39;img elements must have an alt prop, either with meaningful text, or an empty string for decorative images&#39; - Stack Overflow](https://stackoverflow.com/q/43812733)
画像ファイルの形式をHEICからJPGにしたい

## 状況

スマホのiOSの画像のデフォルトの保存形式がどうやらHEICになったようでより画質が上がったようだ。しかし、いまだにjpgなどのファイル形式を使ってるところが多く、画像提出時などでHEICだと弾かれることがあった。今回はHEIC→jpgの画像形式の変換方法をまとめておこうと思う。

## 動作環境

Mac OS Catalina 10.15.1

## 変換方法

コマンドラインで以下のコードを打つだけ

```
sips --setProperty format jpeg input.heic --out output.jpg
```

input.heicの部分に変換前の画像

output.jpgに変換後の画像の名前をそれぞれ当てはめる

また対象画像が存在するディレクトリに移動する必要がある
Raspberry Pi で .Net を使う

[Download .NET 6.0](https://dotnet.microsoft.com/en-us/download/dotnet/6.0)　から SDK をダウンロードします。

```text
dotnet-sdk-6.0.302-linux-arm.tar.gz
```

解凍します。

```bash
mkdir dotnet
cp dotnet-sdk-6.0.302-linux-arm.tar.gz dotnet
cd dotnet
tar xvfz dotnet-sdk-6.0.302-linux-arm.tar.gz
```

PATH の設定を .bashrc に加えます。

```bash:.bashrc
#
export DOTNET_ROOT=$HOME/dotnet
export PATH=$PATH:$HOME/dotnet
```

ログインし直してバージョンの確認

```text
$ dotnet --version
6.0.302
```

プロジェクトの作成

```bash
mkdir Test01
cd Test01
dotnet new console
```

次のようなファイルが出来ます。

```text
$ ls
Program.cs  Test01.csproj  obj
```


Program.cs を次のように改造します。

```cs:Program.cs
Console.WriteLine("Hello, World!");
Console.WriteLine("This is a Test!");
```

コンパイルと実行


```text
$ dotnet run
Hello World!
This is a Test!
```

再実行

```text
$ bin/Debug/net6.0/Test01
Hello World!
This is a Test!
```

次の環境で確認しました。

```text
$ uname -a
Linux violet 5.15.32-v7l+ #1538 SMP Thu Mar 31 19:39:41 BST 2022 armv7l GNU/Linux
```
実装力があるとはどういったことか説明する

#はじめに
エンジニアたるもの、誰しもが早くコーディングしたいし、実装力が高くなりたいと思っているはずです。

しかしながら、実装力が高い人がなぜ実装力が高いのか案外説明されないと思ったので、説明したいと思う。
（私は、実装力が高くない。）


#1.実装力が高い人はデバッグ力が高い

一部を除いては、基本的にはそこまで難しいことを実装しているケースはとても稀であると思う。
すなわち、基本手には普通のことを実装しているのである。
普通のことを実装するのにそこまで時間の差が生じるわけではないはずである。
そうなると実装する以外の時間、すなわちデバックの時間が実装力が高いかどうかの大きな判断基準になると思う。

#2.では、デバッグ力が高いとはどういうことか。
![Untitled 3.001.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/0e962427-de6a-5204-26b8-757a8bcb851e.jpeg)

可能性がある幅がこれだけあるとする。

![Untitled 3.002.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/1f7ddf8d-d12c-934d-0fa5-501f17c9afa7.jpeg)

この時、バグを特定するフラグのたて方が上手い。

![Untitled 3.003.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/80aa03d4-bc30-9b5a-8c75-5aa24135a79a.jpeg)

なので、すぐに特定できる

![Untitled 3.004.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/68f9820e-8796-f905-54bd-e2af59b29532.jpeg)
![Untitled 3.005.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/9881c198-8f72-fac5-59da-fa5e19b077b2.jpeg)
![Untitled 3.006.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/95aeacb3-e999-c898-0658-f68b23f8c512.jpeg)


#3.では、デバッグ力が低いとはどういうことか。
![Untitled 3.007.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/76044c0b-ee17-daf9-28e9-f675197c0c17.jpeg)
想定範囲が狭い。この場合一生バグに辿り着けない。

![Untitled 3.008.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/242700/add025f1-95c1-6d36-63fb-86182f80f160.jpeg)
フラグのたて方が非効率である。時間がかかる。


#4.デバッグ力を高くするにはどうすればいいか。

####「全体から押さえる」

これに尽きる。

一生懸命コツコツと勉強することが奨励されやすい日本の教育感においては皮肉だが、
プログラミングに関してはコツコツとやることが必ずしも正解ではない。
全体を理解しないと、デバックできないし、フラグをいい感じに立てることができない。

全体像を理解して、コツコツとしたから積み上げるのではなく、上から全体を見下ろした方がいい。

#あとがき
qiitaの猛者達にマサカリを投げられそう。
こんなふんわりしたことを書くなみたいな。
Scratch Link と Edge の注意事項

義務教育でのプログラミング教育必修化を目前に控え、各小学校などで、Scratch や micro:bit の活用が増えてきそうな今日この頃。

皆様いかがお過ごしでしょうか？

わたくしめは、Edgeの不具合なのか独自仕様かに、本日は、少々振り回されておりました。

小学校などでは、こどもたちが、変なコンテンツをみないように、Proxy が設定されていることも多いかと思います。

すると、Scratch link が、うまく動かないのです。

ところで、マイクロビットのWEBサイトにて、回避方法は見つかりました。

https://support.microbit.org/support/solutions/articles/19000026080-using-the-micro-bit-with-scratch

しかし。しかしです。。。

Edge は、この設定をしても、動きませんでした。

Chrome と Scratch Desktop は、同じ設定で動いたので、たぶん、Edge 特有の仕様ではないかと思います。
※雰囲気、websocket まわり？

もしかしたら、当方のProxyサーバーのクセとの関係もあるのかもしれませんが、

みなさま、同じような境遇にあわれたら、お気をつけいただければと思います。

あ、Proxyの例外には、device-manager.scratch.mit.edu だけでなく、scratch.mit.edu も指定して、試してました。

scratch.mit.edu が必要かどうかまでは、作業時間などの関係もあり、詳しく調べられてませんが、クロスサイトほげほげに、ひっかかったりしてたので、念の為の設定です。こちらも、当方のProxyサーバーのヘッダー上書き具合との関係があるやもしれません。

あ、Edge で、Scratch link は、いったんあきらめ、Scratch Desktop で、Scratch link 経由で、micro:bit することにしました。

（蛇足）

だって、ぼくは、Windowsの管理者権限もらえてないんだもの。
間接的にしか状況とらえられないし、がちの担当者さんをないがしろにしすぎてもあかんし、みなれぬ学校用ぽいセキュリティシステムも混在してたり、調査や対応むずかったっす。
初学者によるプログラミングMemo　#1　Ruby/Railsとは

# はじめに
今回はRubyとRailsの特徴を簡単にまとめました
これから勉強される方の助けになればと思います
まだまだひよっこですので、間違っている点等ありましたらご指摘いただければ幸いです

# Rubyとは
スクリプト言語と呼ばれるプログラミング言語
プログラミング言語には、「コンパイラ言語」と「スクリプト言語」と言われる部類の言語がある
また、オブジェクト指向言語でもあるため、記述量が少なくすんだり、コンパイルの時間がかからない
だから生産性が高いと言われている

## 「コンパイラ言語」と「スクリプト言語」って？
- コンパイラ言語
コード実行に事前に全てを翻訳してから実行する
主に　C,C++,Java,C#等

- スクリプト言語
各コード実行時に、随時翻訳しつつ実行する
主に　Ruby,JavaScript,Python,PHP等

上記のような違いがありますが、そもそも、人間が書いたコード（わかりやすく言うと人間語）はそのままでは機械には伝わらない
機械が実行するには（機械語に）翻訳する必要がある
コンパイラ言語はコンパイラーを使用してコンパイル（翻訳）する必要がありますが、スクリプト言語はその必要がない
そのため、開発がしやすいですが、実行速度は遅めと言う特徴がある

## オブジェクト指向とは
オブジェクト指向プログラミング（Object Oriented Programming: OOP）
オブジェクト、つまり”物”として考えようってこと
概念だからあんまり「これが答えだ！」ってものはないようで、概念は概念なんです
愛とか心とかそんなんと一緒
でもそれだと説明にならないので…
オブジェクト指向とは→（近日公開）

## 

# Railsとは
Ruby on Rails のこと
RubyのWeb開発フレームワーク
開発を効率化する仕組みが多数用意されている為生産性が高いと言われる
例えば、"rails new"と言うコマンドを入力するだけで、雛形を作成できたり、ActiveRecordによってSQL操作ができるなどの仕組みが標準で組み込まれている（この辺りは実装段階で解説したいと思います）

## フレームワークとは
言語に対する枠組みのこと、プログラムとかの雛形となるもの
こちらも概念っぽいので、ざっくりと覚えてください
フレームワークをわかりやすく言うと…ブログが当てはまるでしょうか
ある程度の形は決まっていて用意はしてくれている状態（フレームワーク）で、中身の記事（プログラム）に関しては用意した機能を使って好きなように記入してねって感じです
あるいは（私みたいな年齢高めの人はわかりやすいか…）家の柱とか壁とかのそもそもの構造（フレームワーク）のことで、壁紙とか含めた内装（プログラム）に関しては好きに決めてねって感じです


# まとめ
Rubyはコンパイラ（翻訳）作業が不要なスクリプト言語で生産性が高いと言われている
RailsはRubyのフレームワークで、開発を効率化する仕組みが多数用意されている便利なもの

本当にざっくりなので、詳しくは下の参考記事先をご覧いただけるといいかと思います


##### 参考記事
https://www.ruby-lang.org/ja/about/
https://railstutorial.jp/
https://wa3.i-3-i.info/word12470.html
https://eng-entrance.com/what-oop
php 連続 文字 一つに




# やりたいこと

ABBCCCAAのような文字列をABCAにしたい


# これでおｋ

PHP

```php
>>>  preg_replace('/(.)\1+/', '\1', 'ABBCCCAA')
=> "ABCA"
```

JS

```javascript
'ABBCCCAA'.replace(/(.)\1+/g, '$1')
=> "ABCA"
```

ruby

```ruby
"ABBCCCAA".gsub(/(.)\1+/, '\1')
=> "ABCA"
```

python

```python
import re
print(re.sub(r'(.)\1+', '\\1', 'ABBCCCAA'))

=> "ABCA"
```

おわり

類似記事

https://qiita.com/nena3/items/b5fec48c8eecb2353ab1
[C#] テストデータファイルをテストケースごとにディレクトリ分けして管理する

# [C#] テストデータファイルをテストケースごとにディレクトリ分けして管理する

C#でUnitTest(MSTest)を書いていると、テスト用のデータファイルが必要な場合がある。
(画像を読み込んでなにかするとか、ヒアドキュメントで書くのは厳しいサイズのJSONがあるとか)

テストケースごとに必要なファイルが異なるので、"テストクラス/テストケース"という名前のディレクトリに分けて管理することにした。
(DeploymentItemAttributeはいまいち便利さが分からない…)

テストデータはVisualStudioから簡単に表示したいので、プロジェクトに登録し、ビルド時にデータファイルとして出力フォルダにコピーするよう設定した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426308/0137b166-febb-8b11-4d61-d23a210efc68.png)

テストの実装側ではこうした。

```cs
[TestClass]
public class SomeTestClass {

  [TestMethod]
  public void SomeTest(){
    // テストクラスやテストメソッドのリネームに追随できるよう、nameofを使ってパスを定義
    var testDataDir = Path.Combine(nameof(SomeTestClass), nameof(SomeTest)); // <- テストケースごとに書きかえる必要がある

    // ディレクトリ内のテストデータを読んでテストする
    var imgPath = Path.Combine(testDataDir, "foo.png");
  }

}
```

## 問題

nameof(SomeTestClass)のところを書き換えるのがとても面倒くさい。

## 対策

こんなクラスを作った。

```cs
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Diagnostics;
using System.Linq;

internal class TestHelper
{
    /// <summary>
    /// テストデータ格納ディレクトリへのパスを取得する。
    /// </summary>
    /// <returns>テストデータ格納ディレクトリへのパス。</returns>
    public static string GetTestDataDir()
    {
        var testMethodStackFrame = new StackTrace()
            .GetFrames()
            .First(x => Attribute.GetCustomAttribute(x.GetMethod(), typeof(TestMethodAttribute)) != null);
        if (testMethodStackFrame == null) throw new InvalidOperationException("This method must be called from a test method with the TestMethodAttribute attribute.");
        var testMethod = testMethodStackFrame.GetMethod();
        return $@"TestData\{testMethod.ReflectedType.Name}\{testMethod.Name}";
    }
}
```

### なにこれ

この関数を呼び出すと、以下が行われる。

1. スタックトレースをたどって、TestMethod属性がついてるメソッド(= テストケース)を探す
1. メソッド名とそのメソッドが定義されているクラス名を取得する
1. "TestClass\TestMethod"形式のパス文字列を生成して返す

### 結果

全テストケースで、以下をコピペするだけで、対応ディレクトリを取得できるようになった。

```cs
var testDataDir = TestHelper.GetTestDataDir();
```

## ほか

テストフレームワークがNUnitの場合は、TestMethodAttributeをTestAttributeに変えればそのまま動くはず。
5G

# 5G

## 5Gとは

Gは"Generation"の略で、第5世代目の通信方式のこと。

* 1G　・・・　1980年代、アナログ方式、ショルダーフォンとかの時代
* 2G　・・・　1990年代　デジタル方式、音声以外にも文字データなどの通信もできるようになる
* 3G　・・・　2000年代　インターネットが使用できるようになる（iモードとか）
* 4G　・・・　2010年代　3Gを更に発展させて高速化した、ガラケーからスマホに変わってく

大体10年ごとに進化してる。

## 5Gでどうなるの？

### ・高速・大容量
4Gでは1Gbpsであったが、5Gでは20Gbpsと<b>20倍</b>に

### ・低遅延
4Gでは10msであったが、5Gでは1msと<b>1/10</b>に

### ・多接続
4Gでは接続するデバイス数が1平方キロメートルあたり10万であったのが、5Gでは100万と<b>10倍</b>に

## 5Gで伸びそうな分野

* AI
今まではデータの大量送信・受信にタイムラグがあったが、5Gになることで膨大なデータの送受信が可能になるため、発展していきそう。
例：自動運転、交通状況のモニタリング
https://time-space.kddi.com/au-kddi/20190322/2603

* VR/AR
高速・大容量な通信ができるようになるため、膨大なVRデータの送受信が可能になるため、発展していきそう。
例：VRライブ配信、VR会議、VRオンラインゲーム
https://casamia.trust5.co.jp/blog/post_6694/

* IoT
ここ最近も話題になっていますが、5Gの実現によりさらに発展しそう。
例：無人コンビニ、自動運転

* クラウド
上記サービスを実現させるための基盤として発展していきそう。

## ITエンジニアとして

上記はあくまで「伸び<b>そう</b>な分野」ですが、もし伸びてきたらこれらの分野のITエンジニアの需要が上がってきそうですね。

5Gの波に乗ってより高い報酬を望むなら、これらの分野について勉強しておいたほうがいいかもしれません。

## まとめ

時代に取り残されないよう頑張ろう！！
cssうんちにこっちみんなさせてみた

# こっちみんな
今回はうんちの目をマウスの動きに合わせて動くようにしたぞ！

# Let's Try
<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="result" data-user="petapetapeta" data-slug-hash="RwNgyLE" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="kocchiminna-unchi">
  <span>See the Pen <a href="https://codepen.io/petapetapeta/pen/RwNgyLE">
  kocchiminna-unchi</a> by petapetapeta (<a href="https://codepen.io/petapetapeta">@petapetapeta</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

# ポイント
## html(pug)& css(stylus)
左右の目を動かしたいので、黒目はそれぞれ要素を作成して中央に配置します。

## javascript
今回もvue.jsを使ってます。
mousemoveイベントで座標を取得し、その座標によって目の位置を変えてやります。
白目をはみ出さないように注意しましょう！

いつでもうんちに見られてる感じがして良いですね💩
Linuxで認識しないNICのドライバをインストールしてみた

#はじめに
新しい機種のサーバーを買って、
CentOSの6をインストールさせた時、
OSが古いせいかNICを一つ認識しなかった。

NICのドライバをIntelとかからダウンロードしなくてはいけないが、
ちょっと手間がかかったため、
記録に残しておく。

流れとしては、
OSビルドと同じkernel-develをインストールして、
ドライバインストール用のモジュールをインストールして、
サーバーに搭載されているNICの情報を取得して、
Intelから該当のドライバをダウンロードしてインストールする。

#手順
##kernel-develのインストール
OSのビルドを確認して変数へ入れておく

```
# KERNEL_VERSION=`uname -r`
# KERNEL_DEVEL_EXPECTED_VERSION=kernel-devel-${KERNEL_VERSION}
# echo ${KERNEL_DEVEL_EXPECTED_VERSION}

# cd /usr/local/src
```

下記サイトからOSビルドのkernel-develを探してrpmファイルのURLをコピーする
http://rpm.pbone.net/

```
# wget "コピーしたURL"
# ls ${KERNEL_DEVEL_EXPECTED_VERSION}.rpm

# rpm -ivh ${KERNEL_DEVEL_EXPECTED_VERSION}.rpm

##インストールしたものの確認
# rpm -qa | grep kernel-devel
# ls -l /usr/src/kernels/

##リンクが通ってることを確認
# ls -l /lib/modules/${KERNEL_VERSION}/build/
```

#インストール用モジュールの準備

```
# yum -y install "Development Tools"
# yum -y install man
```

下記コマンドでデバイスがちゃんといることを確認する

```
# lspci | grep Ethernet
00:1f.6 Ethernet controller: Intel Corporation Ethernet Connection (6) I219-V (rev 30)
01:00.0 Ethernet controller: Intel Corporation I211 Gigabit Network Connection (rev 03)
```

デバイス情報取得ツールを下記サイトから入手する
https://downloadcenter.intel.com/ja/download/17289

```
# chmod 777 netdriverinfo.sh
# ./netdriverinfo.sh
eth1 : 00:1f.6
    Make/Model = Intel Corporation Device 0000
    Ethernet controller = Intel Corporation Ethernet Connection
    VenID:DevID = 8086:15be
    Driver name = e1000e
    Driver version = 3.5.1-NAPI
eth0 : 01:00.0
    Make/Model = Holco Enterprise Co, Ltd/Shuttle Computer Device 4076
    Ethernet controller = Intel Corporation I211 Gigabit Network Connection
    VenID:DevID = 8086:1539
    Driver name = igb
    Driver version = 5.3.5.39
```

ここで出てきた、現在認識していないNICの「Driver name」及び「Driver version」をググると、
すぐにダウンロードページが出てくるため、サーバーへコピーする

##ドライバのインストール
メーカーからダウンロードしたドライバを解凍し、
インストールする

```
//ファイルの解凍(例)
# tar zvxf e1000e-3.5.1.tar.gz

//解凍後にディレクトリ内のsrcディレクトリに移動してインストール
# make install

//NICドライバがインストールされたことを確認する
# ifconfig -a
```

NICが認識された後はサーバーを再起動し、
NICの設定ファイルから好きにできる

#参考にしたページ
[Install Linux kernel-devel](https://qiita.com/metheglin/items/60261f474ccdfb467574)
[10Gigabit Ethernet NICドライバをインストールする](https://codezine.jp/article/detail/7194)
プログラミングの変数名、関数名を命名する際に役立つこと

#はじめに

開発プロジェクトを標準化させようと日々色々と考えております。
そんな中、コーディング規則の一つである命名規則を決めるうえで役立つ方法・ツールなどなど
記事にまとめてみます。（備忘録も含め）


新規で追加する関数名に悩むとき、通常の翻訳サイトだと物足りないこともあります。（そもそも思いつかないこともある。）


#ステップ1：既存プロジェクトの開発ならプロジェクトの規則・文化を考慮する
もし既存プロジェクトにおいて新規関数や変数を作ろうとしている場合、以下は最低限意識した方が良いと思います。

・そのプロジェクトでの命名規則
・「こういった機能ではこの単語を使いましょう！」というような暗黙の文化

既存プロジェクト内のソースコードと全然異なる命名をすると、同一機能のgrepで引っかからなくなる等デメリットが発生します。
必ず確認しましょう。


#ステップ2：命名

命名する際の参考サイト・記事

・[プログラミングでよく使う英単語のまとめ【随時更新】](https://qiita.com/Ted-HM/items/7dde25dcffae4cdc7923)
⇒基本となる単語情報は対義語や意味合い、ユースケース付きでシンプルかつ丁寧に説明されています。記事内の検索性もよく、非常に便利なサイトといえるでしょう。
また、単語の話だけでなく、使わない方がいい単語や記法の説明、命名に対する考え方等の説明もされており、タイトルとなっている英単語に留まらない「命名」に関する参考資料です。


・[Codic](https://codic.jp/)
⇒プログラマ向けの辞書サイトです。
UIはこんな感じになっており、翻訳時の記号 "_"を使うのか"userAccount"のように大文字区切りにするか等の記法も設定出来ます。

![codic.jfif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482202/2491cbae-daaf-7ec0-279c-193a5ea57f0d.jpeg)


デフォルトでも参考になりますし、ログインすれば辞書をカスタマイズすることも出来るので、自分やプロジェクト内での開発用辞書として育てていくことも出来そうです。
関数や変数のネーミングに悩んだら「codic」に日本語名を入力するとある程度解決するかも知れません。

[プログラミングで変数名や関数名のネーミングに迷ったときに便利なカンニングペーパーまとめ](https://nelog.jp/programming-words)
「命名」という観点で色々なサイトを紹介しており、かなり勉強になります。上記codecの使い方もガイドされてます。




#ステップ3：見直し


一般的な翻訳サイト
翻訳サイトを使ってスペルミスやそもそも単語の意味が違っていないかチェックしましょう。

・google翻訳
⇒google検索で「XXX(日本語名)　英語」検索すると自ずとgoogle翻訳が開かれるのが便利。違和感あれば別のサイトをチェックしましょう。

・[Weblio辞書](https://ejje.weblio.jp/)
⇒意味合いが似た単語の候補をいくつか挙げてくれるので、プログラミングとして、プロジェクトとして違和感のないものを選ぶことが出来ます。（何故か検索候補に上がり易い。）

・[アルク](https://www.alc.co.jp/)
⇒使いやすいが、Weblioでよいかも。（Weblioのほうが検索上位に来やすい）



その他命名に関する参考サイト・記事

・[[ソフト開発]きれいなソースコードを書くために必要な、たったひとつの単純な事](http://d.hatena.ne.jp/r-west/20090510/1241962864)
⇒「プログラミングでよく使う英単語のまとめ【随時更新】でも取り上げられた参考リンク記事の一つ


・[クラスの命名のアンチパターン](https://qiita.com/magicant/items/8134edf969f9629fa66e)
⇒アンチパターンをまとめたもの。良記事です…！

・[プログラミングの英語表現 / 文章作成に迷ったら「クオートで囲ってGoogle検索」](https://qiita.com/YumaInaura/items/76f8242ae58d017d69f6)
⇒命名の妥当性を確認するひとつの指標として、簡単に実践できるgoodアイディア。自分も実践しています。







#まとめ

これらに則り、プロジェクトごとにしっかり命名ルールを書いて「暗黙の」ルールまでなくせたらかなり標準化が進みそうです。
まず現状、習慣として少なくともスペルミスはしっかり見直しましょうっていう部分が必要そう。（自分含め）


参考：
・[プログラミングでよく使う英単語のまとめ【随時更新】](https://qiita.com/Ted-HM/items/7dde25dcffae4cdc7923)
・[[ソフト開発]きれいなソースコードを書くために必要な、たったひとつの単純な事](http://d.hatena.ne.jp/r-west/20090510/1241962864)
・[クラスの命名のアンチパターン](https://qiita.com/magicant/items/8134edf969f9629fa66e)
・[プログラミングの英語表現 / 文章作成に迷ったら「クオートで囲ってGoogle検索」](https://qiita.com/YumaInaura/items/76f8242ae58d017d69f6)
NFT（Non-Fungible Token ）の概要と発行方法を学んで実際にトークンを作ってみよう！

#はじめに
ブロックチェーンの仕組みを学ぶ中で、NFTトークンの発行に関する実装をする機会に恵まれたので、Solidityを用いたNFTの発行方法についてまとめていきたいと思います！

##NFTとは？
NFT（Non-Fungible Token ）はブロックチェーン上で取引される、架空のトークンであり、直訳すると「代替性のないトークン」という意味になります。
簡単にいうならば、発行されたトークンの一つ一つが我々人間のように固有の容姿や名前を持つように、完全なる独自性を備え持っています。

現在VR世界での決済の方法の一つとして注目されているだけでなく、既にゲームの世界でアイテムとして取引されたり、最近では[フォーブズ](https://www.coindeskjapan.com/31860/)の事例のように一般社会でも活用される事例が目立つようになりました！

円やドルのような貨幣と異なり、誰でも発行することが出来るので、自分で発行したトークンに価値が生まれたら、大金持ちになることも可能かもしれません・・・！

##NFTの発行のためのソースコード
NFTはERC721(Ethereum Request for Comments 721)という規格を採用しています。
ここには[様々なメソットやイベント](https://aire-voice.com/blockchain/4587/)が用意されており、それら（リンク先）を組み合わせることによって、生成や焼却、他者へ送信することが出来ます。

今回は、[OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts)というNFTの発行を補助してくれるライブラリを用いて、テストをしていきます。

```javascript:testToken.sol

//バージョンを指定
pragma solidity ^0.5.0;

//テストをするRemixでは簡略的にGitHubのURLを指定
//もちろんファイルのパス指定も出来る
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC721/ERC721Full.sol";

contract testToken is ERC721Full {

//トークンの名前と最小単位を定義
  constructor() public ERC721Full("testToken", "hoge") {}

//トークンの情報をstructで定義
    struct Token {
        string name;
        string description;
    }

//トークンを保管するために定義
Token[] public tokens;

//mint関数でトークンを発行
  function mint() external {
   uint256 id = tokens.push(Token('name','description')) - 1;
   super._mint(msg.sender, id);
  }

}
```

##試験的にトークンを発行してみる
テストには[Remix](https://remix.ethereum.org/#optimize=false&evmVersion=null&version=soljson-v0.5.12+commit.7709ece9.js)というブラウザー型のエディターを使います。
インタラクティブにバグを検知してくれるだけでなく、試験的にトークンを発行することが出来ます。
本記事を読んで、テスト実装をされる方は事前に[MetaMask](https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=ja)のインストールをお勧めします。（使い方に関しては最後にまとめます）


好きな名前でファイルを作ったら、先ほどのコードをそのままコピペしてください！
入力を終えたら、写真の中で「黄色い数字の１」が表示されてるボタンをクリックし、黒のボタン（コンパイル）を押します。
<img width="1280" alt="スクリーンショット 2019-12-26 18.32.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357734/e187bddf-a01b-4e72-875b-59f712269c72.png">

左下にオレンジ色で表示されている項目は、トークンの鋳造や送信に使われる関数です。この記事では取り扱いませんが、興味のある方は調べてみてください！通常トークンの生成にはGasと呼ばれる所謂コストが発生しますが、今回はMetamaskを利用したテストネットワークを使用したため、無料で試すことが出来ます。
<img width="305" alt="スクリーンショット 2019-12-26 18.34.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357734/4a97bfbc-f7bc-e2f3-9ce3-dd400db7ce07.png">

実行結果を更に下へスクロールすると、無事にトークンが発行されたことを確認できます！
nameの項には先ほど定義したこのトークンの名前である「testToken」、
symbolの項には「hoge」が反映されています！
<img width="297" alt="スクリーンショット 2019-12-26 18.36.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357734/0d7f4545-4f85-11b5-de69-00ddd8e90518.png">

以上、概念的に難解なブロックチェーンですが、本記事で紹介させて頂いたように思いの外、簡単にトークンを発行することが出来ます。

宜しければチャレンジしてみてください！！

###参考にさせて頂きました。ありがとうございます！
[NFTについて](https://aire-voice.com/blockchain/4587/)
[トークンの発行について](https://qiita.com/kolife/items/8bc7316d25a24db08ceb)
[MetaMaskの使い方](https://kasobu.com/metamask/)
Ruby silverに10日で受かった

##Ruby技術者認定試験Silverに合格した(2019/12/26)

今回、実施した勉強法や期間等をまとめたいと思います。

誰かの参考にでもなればいいなと思いつつ。


###前提
まだまだ駆け出しでRubyは業務で4ヶ月程触ったレベル。
最近はどちらかというと上流の方にいて、コード読むことはあっても、あまりコードを書いてない。
ので、コードをもっと読めるようになりたいと思いチャレンジ。


##学習期間
学習期間 ： 10日
学習時間 : 30時間

上記は試験に特化した学習時間です。
よくよく、考えると短期集中過ぎますね。朝夜、昼休み、移動の電車で学習


##学習方法
とりあえず、Rubyの技術書を最低1冊は読んでおかないと問題の内容もキツイと思います。
####公式模擬問題集
無料です。解説もついてる。ブラウザ2画面に分けて問題と回答を交互に見れるようにすると便利。
[https://gist.github.com/sean2121/945035ef2341f0c39bf40762cd8531e0](https://gist.github.com/sean2121/945035ef2341f0c39bf40762cd8531e0)

####REx
こちらも無料。スマホでもできるので移動中や昼休みはお世話になりました。受けるごとに問題内容が少し変わる。解説もついてる。あと、点数も記録してくれる。Githubのアカウントが必要です。合格教本とも内容が被る部分もあるんですが必須だと思います。
[https://www.ruby.or.jp/ja/certification/examination/rex](https://www.ruby.or.jp/ja/certification/examination/rex)

####[改訂2版］Ruby技術者認定試験合格教本（Silver/Gold対応）Ruby公式資格教科書
実際の試験の6割程はこちらの模擬問題等から出ていました。(もちろんそのまま出題されない)模擬問題をメインに使っていました。
[https://www.amazon.co.jp/dp/B0756VF9Y3/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1](https://www.amazon.co.jp/dp/B0756VF9Y3/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

学習のやり方としては、模擬問題を1回やって、答え合わせの時に実際にコードを打って、問題の選択肢の全パターン試してみたり、問題と正反対のパターンも試して挙動の違いを見てみたりした。解説もしっかり読む。そして全部の問題に対して何故そうなるのかの解説ができるレベルにまでやる。

それぞれの問題集で9割以上とれてないと本番はキツイと思います。実際、模擬問題で平均88点だった自分は本番で78点というギリギリ合格でした。
不明点は公式リファレンス、合格本や技術書で調べたりしましょう。
本当ひたすら問題解くって感じでした。それまで手をつけてこなかった例外処理、n進数、IOクラスの勉強もしました。


####やってよかった
今回の試験勉強をやったおかげでコード読むのが前より楽しくなってきた気がします。初学者の方には、オススメな資格だと思います。
次はGold目指してがんばります。


####参考にした合格記事

[Ruby Silverに合格したので、勉強方法をまとめてみた(2019年2月版)](https://qiita.com/jonakp/items/7f7550eeea78973a0a7f)

[Ruby技術者認定試験 Silverに合格した話](https://mon-sele.com/post21/)