OmniAICreator/Qiita-1.07M huggingface dataset:
FormRequestのバリデーションエラー時のリダイレクト先をカスタマイズする

LaravelにはFormRequestというクラスがあり、これを継承したクラスにルールを指定しておくと、うまいことバリデーションをしてくれます。

```php:StoreBlogPostRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreBlogPostRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ];
    }
}

```

通常、バリデーションに引っかかると、リクエストを送ってきた前のURLにリダイレクトされますが、ここをカスタマイズすることが出来ます。

FormRequestクラスを読んでみると、getRedirectUrlという関数がありそこで呼ばれているプロパティを設定する、もしくはその関数自体をオーバーライドすることでリダイレクト先を変更することが出来ることがわかります。

```php:FormRequest.php
<?php

namespace Illuminate\Foundation\Http;

use Illuminate\Http\Request;
use Illuminate\Routing\Redirector;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Validation\Validator;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Validation\ValidatesWhenResolvedTrait;
use Illuminate\Contracts\Validation\ValidatesWhenResolved;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;

class FormRequest extends Request implements ValidatesWhenResolved
{


... 省略 ...


    /**
     * Get the URL to redirect to on a validation error.
     *
     * @return string
     */
    protected function getRedirectUrl()
    {
        $url = $this->redirector->getUrlGenerator();

        if ($this->redirect) {
            return $url->to($this->redirect);
        } elseif ($this->redirectRoute) {
            return $url->route($this->redirectRoute);
        } elseif ($this->redirectAction) {
            return $url->action($this->redirectAction);
        }

        return $url->previous();
    }


... 省略 ...


}

```


よって、以下のようにすればリダイレクト先をカスタマイズできます。

```php:StoreBlogPostRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class StoreBlogPostRequest extends FormRequest
{
    protected $redirect = 'リダイレクトさせたいパス';
    protected $redirectRoute = 'リダイレクトさせたいroute';
    protected $redirectAction = 'リダイレクトさせたいAction';

    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'title' => 'required|unique:posts|max:255',
            'body' => 'required',
        ];
    }

    protected function getRedirectUrl()
    {
        return 'リダイレクトさせたいURL';
    }

}

```
CodePenとGistとCacherでコードスニペットを管理する

ブラウザ上でさくっとコードを書いて実行できるCodePen。
せっかく使うならGistとCacherを一緒に使ってコードスニペットを管理しよう。という話です。

# 知らない人のためにサービスの紹介

## CodePen

[CodePen - Front End Developer Playground & Code Editor in the Browser](https://codepen.io/)

ブラウザ上でHTML、CSS、JSを書いて、その場で実行、確認できるWebサービス。
人の書いたコードに「いいね」やForkができたり、ブログやQiitaにも貼り付けることができるのでSNS的側面が強いです。
Babelや主要なフロントエンドライブラリ（自作ライブラリも可）、CSSプリプロセッサ、HTMLテンプレートエンジンがオプションで選べるようになっているため開発環境を構築せずにコードを試せます。

<img width="1089" alt="img01.png" src="https://qiita-image-store.s3.amazonaws.com/0/45634/987287dd-ad9a-ccdd-387a-9b1b14088d26.png">

使い方はこちらが参考になります。

> [codepenでウェブ開発入門 - Qiita](https://qiita.com/InoueDaiki/items/1ee988d8e1f43bc205de)

## Gist

[Discover gists · GitHub](https://gist.github.com/discover)

GitHubが提供するファイル管理サービス。
GitHubはプロジェクト（ディレクトリ）を管理するものですが、Gistはファイル単体を管理します。

こちらの記事が参考になります。

> [GitHubについてもう少し知ってみる。その5（Gistでお手軽コード管理）](http://www.paka3.net/github05/)

## Cacher

[Cacher](https://www.cacher.io/)

旧サービス名GistBox。コードスニペット管理ツールです。
100以上の言語をサポートし、Gistとの連携、チーム共有などの機能があります。
メーラーのようなUIやラベル、言語別での管理、検索ができます。
Webアプリケーションの他にデスクトップアプリがあります。

<img width="1055" alt="img02.png" src="https://qiita-image-store.s3.amazonaws.com/0/45634/a0991e3b-f70b-11c2-8416-5e120b7fdbdb.png">

ぶっちゃけて言うとCodePenだけでスニペット管理はできるのですが、動作が軽快なのとコードの見やすさや検索のしやすさはCacherの方が優れていると思います。

# サービスの連携

## 準備

まず、[こちら](https://codepen.io/accounts/signup/user/free) からGitHubアカウントでCodePenにサインアップ。
つぎに、[こちら](https://www.cacher.io/) からアプリをインストールしGitHubアカウントでサインイン。もしくは[こちら](https://app.cacher.io/sign-up)のWebアプリからサインインしてください。

## 使ってみる

CodePen上でCreateからNew Penを選択しエディタ画面を開きコードを書きます。
書き終わったら右下の `Export` から `Save as GitHub Gist` を選択します。

<img width="1181" alt="img03.png" src="https://qiita-image-store.s3.amazonaws.com/0/45634/c75d9e25-c340-e7e0-b0ca-b9f09d0680c2.png">

別ウィンドウでGistの画面が開きます。

<img width="1045" alt="img04.png" src="https://qiita-image-store.s3.amazonaws.com/0/45634/9fc3df37-61fc-1d55-7640-65036d1b1fa5.png">

概要が書かれたMarkdown、HTML、CSS、JS、それと読み込んだライブラリのリンクが出力されました。

Cacherアプリを開いてみます。

<img width="741" alt="img05.png" src="https://qiita-image-store.s3.amazonaws.com/0/45634/8acc2262-89c8-cb3d-6166-c3ba53b2a8b3.png">

自動でコードが同期されています。

## コードの編集

保存されたコードはCodePen、Gist、Cacherのどこからでも編集することができます。しかし、Gist、Cacher間は同期していますが、CodePen、Gist間はCodePenからの出力のみで一方通行です。なので、3つのサービスでコードを揃えたい場合はCodepenで編集後 `Save as GitHub Gist` でGistを上書きする必要があります。

以上、CodePenでコードを試す -> Gist に保存する -> Cacherから参照する。の流れでスニペット集を活用すると便利。という話でした。
CS-Cart：商品の返金申請をするとエラーが表示される。

### 再現手順（返金申請が可能な商品）
1. 商品を注文する。
2. 注文後、"注文詳細"ボタンをクリック。
3. "商品の交換または返金を申請"をクリック。
4. 対象の商品と返金申請の理由を選択する。
5. コメントを入力し、"返品"をクリックする。
6. エラーが表示される（返金申請メールは送信される）。

```
Warning: Illegal string offset 'status' in
/app/addons/mail_tpl_jp/tpl_variants/addons_rma_slip_notification.php on line 45
```

### 対象ファイル
/app/addons/mail_tpl_jp/tpl_variants/addons_rma_slip_notification.php

### 修正方法
45行目の`$tpl_return_status = $return_statuses[$tpl_return_status_info['status']]['description'];` を `$tpl_return_status = $return_statuses[$tpl_return_status_info]['description'];`に変更する。

※$tpl_return_status_infoには、ステータスを表す文字（例 'R'）がセットされるが、その文字列に対しインデックス'status'を取得しようとしてエラーになる。

![bug_fix.png](https://qiita-image-store.s3.amazonaws.com/0/235517/eba0b4a1-c4d9-7f8f-f982-d35289f581ac.png)


### 重要度
エラーメッセージは表示されるが、返金申請事態の処理は正しく行われているように見えるため（申請受付メールも送信される）、絶対に修正しないといけないレベルの問題ではない。

現に、最新バージョンの *cscart_v4.7.2_JP_1patched_20180427* でも、このエラーは修正されていない。
データベースからデータを取得する際のカラム数が可変のときの対処(Go言語)

## データベースからデータを取得する際のカラム数が可変の場合の対処

Go言語でデータベースからデータを取得する際にカラムの数がわからない場合に
どうやってとればいいのか悩んだのでメモを残します。

今回はPostgreSQLを使用していますが他のデータベースでも同じかなと。

``` sample.go

import (
	"database/sql"
	"fmt"

	_ "github.com/lib/pq"
)

func main() {
	db, err := sql.Open("postgres", "user=postgres password=secret port=5432 host=loacalhost dbname=sample sslmode=disable")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer db.Close()

	rows, err := db.Query("SELECT * FROM sample")
	if err != nil {
		fmt.Println(err)
		return
	}
	defer rows.Close()

	// カラム情報を取得する
	types, _ := rows.ColumnTypes()
	// カラム数分だけポインターを保管するinterfaceを用意
	dataPtrs := make([]interface{}, len(types))

	for rows.Next() {
		// カラム数分だけデータ保管用のinterfaceを用意
		data := make([]interface{}, len(types))
		// ポインターを入れる
		for i := range data {
			dataPtrs[i] = &data[i]
		}
		if err := rows.Scan(dataPtrs...); err != nil {
			fmt.Println(err)
		}
		fmt.Printf("%+v\n", data)
	}
	return
}
```

ポイントとしてはinterfaceのポインターをinterfaceのデータにそれぞれ入れるところ。
こうすることでポインターの個所にデータをうまい具合に保存してくれます。

どのようにデータの変換や保管が行われているかについては
database/sql/convert.goのconvertAssign関数を読んでいただければと思います。

もっといい方法があればコメントいただけると助かります。
macOS High Sierra（OSX）のOpenSSLをデフォルトのLibreSSLからOpenSSLに変更する

MacのHigh Sierraから、デフォルトのOpenSSLがOpenSSLからLibreSSLになっているそうで、OpenSSLの諸々の問題を鑑みれば英断らしいのですが、そうはいっても開発環境の様々なツールがOpenSSLに依存しておりアレコレと新たな問題を引き起こすため、様々なツールのほうがLibreSSLに対応するまでさくっとOpenSSLに出戻る方法が下記です。

# 使用されているSSLをみる

```
$ openssl version
LibreSSL 2.2.7
```

やっぱりOpenSSLじゃない。

# HomebrewでOpenSSLをインストール

```
$ brew install openssl
```

インストールしたOpenSSLの詳細をみる。

```
$ brew info openssl
openssl: stable 1.0.2o (bottled) [keg-only]
SSL/TLS cryptography library
https://openssl.org/
/usr/local/Cellar/openssl/1.0.2o_1 (1,791 files, 12.3MB)
  Poured from bottle on 2018-05-08 at 15:22:23
From: https://github.com/Homebrew/homebrew-core/blob/master/Formula/openssl.rb
==> Dependencies
Build: makedepend ✘
==> Options
--without-test
	Skip build-time tests (not recommended)
==> Caveats
A CA file has been bootstrapped using certificates from the SystemRoots
keychain. To add additional certificates (e.g. the certificates added in
the System keychain), place .pem files in
  /usr/local/etc/openssl/certs

and run
  /usr/local/opt/openssl/bin/c_rehash

This formula is keg-only, which means it was not symlinked into /usr/local,
because Apple has deprecated use of OpenSSL in favor of its own TLS and crypto libraries.

If you need to have this software first in your PATH run:
  echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile

For compilers to find this software you may need to set:
    LDFLAGS:  -L/usr/local/opt/openssl/lib
    CPPFLAGS: -I/usr/local/opt/openssl/include
```

> If you need to have this software first in your PATH run:
> （意訳：もしあなたがこのソフトウェアを優先したい場合は実行）

地味に悩んだのにすべてここに書かれていた……。

```
$ echo 'export PATH="/usr/local/opt/openssl/bin:$PATH"' >> ~/.bash_profile
```

ターミナルを再起動してできあがり。

```
$ openssl version
OpenSSL 1.0.2o  27 Mar 2018
```
Windows 10 > ウィンドウの整列 > 手順 > 4つのウィンドウのGrid(2行2列)表示

```txt:動作環境
Windows 10 Pro (64bit) バージョン 1803 (April 2018 Update)
Google Chrome バージョン: 66.0.3359.170（Official Build） （64 ビット）
```

### やりたいこと

- Google Chromeの4つのウィンドウのGrid表示 (2行2列)

### 手順

1. Chromeの起動
2. [Ctrl + n] x 3    
    - >> 計4つのウィンドウがある状態になる
3. タスクバー右クリック
4. ウィンドウを上下に並べて表示(E)
    - 「ウィンドウを左右に並べて表示(I)」でもいい


手順3の前に一つのウィンドウをクリックしておくと、そのウィンドウが左上に来る。
(つまり、ウィンドウ位置の指定ができる)。
WKWebView でローカルファイルにアクセスできないとき

cordova-plugin-camera などで取得した画像を読み込もうとすると「Origin null is not allowed by Access-Control-Allow-Origin.」のようなエラーが発生することがある。

```javascript
// エラーが発生するコード
let img = new Image()
img.crossOrigin = 'anonymous'
img.onload = () => {

}
img.src = /* ローカルから読み込んだファイルパス */
```

色々と試したがプラグインをインストールするだけで簡単に解決することができた。

```
cordova plugin add https://github.com/TheMattRay/cordova-plugin-wkwebviewxhrfix
```
https://github.com/TheMattRay/cordova-plugin-wkwebviewxhrfix
reactでDOM要素のサイズを知りたい


[react-measure](https://www.npmjs.com/package/react-measure)を使う

# 背景

- `svg`タグや`canvas`タグ等で、`width`、`height`属性を設定したい
- けれど、それらをレンダリングする場所は、固定サイズでないため（CSSで`width: 100%`等）レンダリングするまで具体的なサイズが不明
- そのほか、コンテナー要素のサイズに応じて、自前でレイアウト計算したいことがある

# 解決策

- [react-measure](https://www.npmjs.com/package/react-measure)のコンポーネントのchildrenでサイズを計測したい要素をレンダリングする
- childrenとしてFunctionを設定すると、`measureRef`(サイズ計測対象の`ref`をreact-measeureに渡すためのもの)が引数で渡されてくる
- サイズ計測したい要素の`ref`に`measureRef`を設定する。

## 例

SVGで指定の間隔の罫線を描くコンポーネント。DIV(.grid-inner)のサイズを計測し、その中にDIVと同サイズのSVGを生成し、SVGで罫線を描く


- 要素のサイズはstateで持つ
- サイズ変化時に`onResize: (contentRect) => void`が呼ばれる。`contentRect`に計測したサイズが入ってくるので、サイズをsetStateして再レンダリングさせる

``` tsx

import * as React from "react";
import _ = require("underscore");
import Measure from "react-measure";

export interface GridProps {
    size: number;
}

export class Grid extends React.Component<GridProps, {}> {
    state = {
        width: 0,
        height: 0
    }

    render() {
        const { size } = this.props;
        const { width, height } = this.state;
        return <div className="grid">
            <Measure bounds onResize={(contentRect) => { this.setState({ ...contentRect.bounds }) }}>
                {({ measureRef }) =>
                    <div ref={measureRef} className="grid-inner">
                        <svg width={width} height={height}>
                            <g>
                                {_.range(size, height, size).map((y) => {
                                    return <line x1={0} y1={y}
                                                 x2={width} y2={y}
                                                 className="grid-line" />
                                })}
                            </g>
                        </svg>
                    </div>
                }
            </Measure>
        </div>
    }
}
```

``` css
.grid {
    width: 100%;
    height: 100%;
}

.grid-inner {
    width: 100%;
    height: 100%;
}
```
ハンズオンで学ぶ、Azureのサーバーレスアーキテクチャ 

<p>この投稿は東京渋谷ヒカリエ 8 階にある <a href="http://aka.ms/aajp" target="_blank">Azure Antenna</a> で実施された「ハンズオンで学ぶ、Azureのサーバーレスアーキテクチャ」で使われた資料のご案内です。</p>

- <strong>ハンズオンで学ぶ、Azureのサーバーレスアーキテクチャ</strong><br />
https://www.slideshare.net/KazuyukiNomura/azure-96771125
<p>:satellite:&nbsp;&nbsp;新しいイベントの情報は、Connpass の <a href="http://aka.ms/aajp" target="_blank">Azure Antenna サイト</a>よりご確認いただけます。</p>

<p>:arrow_backward:&nbsp;<a href="https://qiita.com/AzureAntenna/items/71f394c100fbfa8ddcc8">「Azure Antenna 実施イベント資料（カテゴリ別）」に戻る</a></p>
SUI Credit Service 月額課金が停止されているか




# 単発決済時の取り消し

・トランザクションを選択
・期間を選択
・検索をクリック
・虫眼鏡アイコンをクリック

![1.png](https://qiita-image-store.s3.amazonaws.com/0/31338/2e43f0a4-db3b-57ae-40b6-37185ca15129.png)


###ログ情報が表示される

・VOIDREQ を選択して 更新をクリック

![2.png](https://qiita-image-store.s3.amazonaws.com/0/31338/82570ac3-e844-a6e1-64c1-1a4f5a1e93b1.png)


#継続決済の取り消し

上記の単発決済時の取り消しを行った後、

・トランザクションを選択
・期間を選択
・検索をクリック
・カードアイコンをクリック

![3.png](https://qiita-image-store.s3.amazonaws.com/0/31338/142286a8-284c-3664-d894-f01c5448b41c.png)


###顧客詳細が表示される

・退会をクリック

![4.png](https://qiita-image-store.s3.amazonaws.com/0/31338/39234f0a-4ad2-e6a5-24ab-0b54a9d34b1b.png)



#注意

継続決済の場合は単発決済の取り消しと継続の取り消しの両方をしなくてはいけないので注意すること。




# 2018年9月に切り替わりました。以下古い管理画面


クレジットカード決済の
http://www.shimatomo.com

を使っている。
ここは、一般決済で通らないようなサービスでも通るしサポートも良い。
料金が安いので、おすすめ。

で、今回は月額課金を停止しているかどうかをチェックする方法。

# 管理画面にログインしてから

トランザクションをクリック。
顧客を絶対にクリックしない。すると、単発決済の取り消しになってしまう。

![1.png](https://qiita-image-store.s3.amazonaws.com/0/31338/ed2092b5-9098-01e8-45b7-92566cfae201.png)


![2.png](https://qiita-image-store.s3.amazonaws.com/0/31338/2746d691-10df-77a6-a8e7-c7e064acd726.png)
laravel5.4でconst.phpに定義した定数の値を.envで環境ごとに変える

##はじめに
今回は、画像のパスを本番環境だけcdnに、他の環境では相対パスでの指定にする、という場合に行った一例を記述します。

##/config/const.phpに定数を定義する
```const.php
return array(
    'cdn'=> env('cdnPath', '//cdn.net/img'),
);

```
``env()``というのが.envファイルの設定を利用する際の関数で、第1引数がキー、第２引数が「デフォルト値」です。
.envファイルに``cdnPath``というキーの環境変数が存在しなかった場合、この第２引数の値が返されます。
参考：[Laravel 5.4 設定
](https://readouble.com/laravel/5.4/ja/configuration.html)

##本番環境以外の.envに設定を書く
```　.env
cdnPath=/img
```
ファイル内に設定を書きます。
本番環境ではデフォルト値にしたいので、何も書きません。
``cdnPath``の設定を.envに記述した場合のみ、.envに設定した値が返されます。

##テンプレートで使う
```sample.blade.php
<img src="{{Config::get('const.cdn')}}/sample.png">
```
上記のようにした場合、以下のような表示になります。

####本番環境
```
<img src="//cdn.net/img/sample.png">
```

####.envに設定したその他の環境
```
<img src="/img/sample.png">
```

.env便利:cat::dash:
Google Chrome @ Windows > 間違って閉じたブラウザの復帰 > Ctrl + Shift + T > 間違って閉じたタブの復帰と同じキー

```txt:動作環境
Windows 10 Pro (64bit) バージョン 1803 (April 2018 Update)
Google Chrome バージョン: 66.0.3359.170（Official Build） （64 ビット）
```

### 状況

- 間違ってGoogle Chrome閉じてしまった

### 対処

1. Google Chromeを起動する
2. <kbd>Ctrl</kbd> + <kbd>Shift</kbd> + <kbd>T</kbd>

閉じる前のタブを復帰できる。

複数タブも復帰できた。


### 備考

同じショートカットは「間違って閉じたタブ」を復帰するときに使っていた。

ブラウザを閉じたときも使えるのは知らなかった。
【CSSフレームワーク】BULMAのnavbarを学ぶ(執筆中)

[公式のドキュメンテーション](https://bulma.io/documentation/components/navbar/)を翻訳しつつ、機能を抑えていきます。

###Navbar
BULMAのナビゲーションバーはレスポンシブな水平のナビゲーションバーです。**イメージリンク・ボタン・ドロップダウンをサポート**しています。

####navbarのコンポーネント

BULMAにおけるnavbarのコンポーネントはレスポンシブに対応しており、多様性があります。

`navbar`はメインのコンテイナーです。

`navbar-brand`は、ナブバーの左側に位置する要素です。いつでも可視化されています。`navbar-brand`には通常はロゴを含み、リンクやアイコンを付与することができます。

`navbar-burger`はハンバーガーアイコンを表します。これはタッチデバイスにおいてトグル（開いたり閉じたり）します。

`navbar-menu`はナブバーの右側に位置します。タッチデバイスでは隠れ、デスクトップでは現れます。
PHPでASCIIコードから文字表示

『プログラミングPHP』で、識別子の1文字目について以下のように書かれていた。

> PHPでは、変数名や関数名、定数名、クラス名として識別子を使用します。識別子の最初の文字として使用できるのは、アルファベットの大文字と小文字、アンダースコア、そしてASCIIコードで0x7Fから0xFFまでの文字のいずれかのみとなります。

なんで前半は文字の種類を羅列しているのに、後半はASCIIコードなんだろう、全部ASCIIコードで説明できないの？と思って、調べてみた。


### 参考
> ASCII文字テーブル
http://www.asciitable.com/
ASCII - Wikipedia
https://ja.wikipedia.org/wiki/ASCII

### 確認

以下を実行してみた。

```php:ascii.php
$code = 0x80;

while ($code <= 0xFF) {
    printf('%s', chr($code));
    $code++;
}
```
```
$ php ascii.php
	


!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
```

文字としては表示されないのもあったりするんですね。
0x80以降は表示方法がわからず・・・。

0x20以前は「制御文字」だから表示はされないみたい。
このへんで何をやってるのか、wikipedia見てもいまいちよくわからなかった。

> 制御文字 - Wikipedia
https://ja.wikipedia.org/wiki/%E5%88%B6%E5%BE%A1%E6%96%87%E5%AD%97


### 結論

ASCII文字には、表示できない文字もたくさんある。（制御文字）
アルファベットの大文字と小文字の間に記号が入っていたりして、連続的にグルーピングできない。

### 課題

制御文字はそれぞれ何をしているのか？
0x80以降の文字をどうやって表示する方法？
フォーム以外の要素でキーボードイベント（keydown/keypress/keyup）やfocus疑似クラスを使う方法

# TL;DR
要素にtabindex属性をつける

# 全ての要素でキーボードイベントが発生するわけではない
WindowsのエクスプローラーやMacのFinderのファイルリストのように、クリックするとアイテムがアクティブになり、カーソルキーの上下で選択位置を移動するUIを作ろうとして、下記のようなマークアップをしたのですが、LI要素でkeyupなどのイベントが取得できませんでした。

```html
<ul>
  <li class="list-item is-active">foo</li>
  <li class="list-item">bar</li>
  <li class="list-item">baz</li>
</ul>
```

調べてみたら、キーボードイベントは「**フォーカスが当たっている要素でないと発生しない**[^1]」とのこと。
試しに次のようなCSSを追加してみましたが、クリックしても太字になりませんでした。

```css
.list-item:focus {
  font-weight: bold;
}
```

# フォーカスさせるには
次に任意の要素をフォーカス可能にする方法を調べたら、[こちらのページ](https://allyjs.io/data-tables/focusable.html)を見つけ、tabindexを設定すればよいことが分かりました。

- タブキーでフォーカスを移動したい場合は、0以上の数値
- クリックでのフォーカスのみを有効にしたい場合はマイナスの数値
- `tabindex=""`は意味がない（Firefoxでは有効）


自分のマークアップにtabindexをつけたところ、`:focus`のスタイルが適用され、キーボードイベントも発生するようになりました。

```html
<ul>
  <li tabindex="-1" class="list-item is-active">foo</li>
  <li tabindex="-1" class="list-item">bar</li>
  <li tabindex="-1" class="list-item">baz</li>
</ul>
```



[^1]: ブラウザの履歴を確認したのですが、情報元のサイトを見つけられませんでした。ちなみに[W3CのKeyboardEvent](https://www.w3.org/TR/uievents/#interface-keyboardevent)には`Keyboard events are commonly directed at the element that has the focus.`とだけ書かれています。
PHPの正規表現の書き方

#記述方法
正規表現のパターンをデリミタ(区切り文字)で囲う
通常はスラッシュだが、英数字とバックスラッシュ以外であれば何でも良い

```php
/[0-9]/
```
#エスケープ
正規表現では特殊文字を通常の文字として認識させる時はバックスラッシュを使い
エスケープを行う
スラッシュを文字として認識させる場合

```php
/\//
```

#正規表現の種類
[?]直前の表現を0回または1回繰り返す　例ab?→a,abとマッチ

#URIの前後の スラッシュ / を取り除く方法

```php:test.php
  $patterns = array(
    '/\/?$/',
    '/^\/*/',
  );

  //URIの取得
  $param = preg_replace($patterns,'',$_SERVER['REQUEST_URI']);
```
Qiitaの様なサービス作成中 ユーザー認証 連載(2)

## 基本情報

* [次に作りたいQiita、dev.toの様なサービスについて](http://alphabrend.hatenablog.com/entry/2018/05/07/090803) で書いたサービスを開発中です。
* [前回の記事](https://qiita.com/dala00/items/963a8f65a7730ede8f3b)

## 最初に作るところ

記事投稿サービスですので、何はともあれ記事を投稿できなければ何も始まりません。そして、記事を投稿するためにはユーザー認証が必要なので、まずはそこを作っていきます。

## Laravel Socialite

現在Laravel Socialiteというものがあり、OAuthを利用した認証はこれを使って簡単に実装することができるようになっています。これを使ってGitHub認証を作成していきます。

以下解説ですが基本的にはマニュアル通りです。

### Socialiteをインストール

```sh
composer require laravel/socialite
```

### 設定する

```php:config/services.php
'github' => [
    'client_id' => env('GITHUB_CLIENT_ID'),
    'client_secret' => env('GITHUB_CLIENT_SECRET'),
    'redirect' => env('GITHUB_AUTH_CALLBACK_URL'),
],
```

※実際の値を`.env`に追加する必要があります。

### ルーティング

ここはちょっと本家マニュアルとは変えていますが、URLでログインするサービスを変更できるようにしているだけです。

```php
Route::get('login/{provider}', 'Auth\LoginController@redirectToProvider');
Route::get('login/{provider}/callback', 'Auth\LoginController@handleProviderCallback');
```

### コントローラ

上記ルーティングに伴いこちらも少し変えています。UserSocialはユーザーにhasManyで持たせている、OAuthプロバイダ毎のデータ保存テーブルを作成しました。アバター画像などもUserではなくこちらに入れて切り替えられるようにしたりします。

```php:Auth/LoginController.php
    public function redirectToProvider(string $provider)
    {
        return Socialite::driver($provider)->redirect();
    }

    public function handleProviderCallback(string $provider)
    {
        $providerUser = Socialite::driver($provider)->user();

        $userSocial = UserSocial::firstOrNew([
            'provider' => $provider,
            'provider_id' => $providerUser->getId()
        ]);

        if ($userSocial->id) {
            $user = User::find($userSocial->user_id);
        } else {
            $user = new User;
        }

        User::setSocialInfo($user, $userSocial, $providerUser);
        $user->save();
        $userSocial->user_id = $user->id;
        $userSocial->save();
        Auth::login($user, true);

        return redirect('/');
    }
```

setSocialInfo内でuserやuserSocialに色々値を代入しています。ここではswitchなどでプロバイダ毎に代入処理を変えなければならないので、無性にElixirのパターンマッチを使った関数呼び出しが恋しくなります。

ちなみに上記のコードはまだ作成途中で複数のプロバイダ登録に対応できていないので、実際にちゃんと作るときはelse内を調整したり、`__construct`内の`except`指定で上記２つのメソッドにログインしていてもアクセスできるようにしておく必要等があります。

## まとめ

非常に短い記事になってしまいましたが、つまりはこれくらいの感じで認証ができてしまうので非常に簡単でした。他のサービスの認証も追加したり、前述の通りログイン中に他のサービスの連携追加も行う必要があるのでそれも作成はする必要がありますが、とりあえずそれは一旦置いておきます。

これで記事投稿を作成する準備が整いました。認証のところをずっといじっているより、とりあえずどんどん先に進めて見る方が最終的に効率も良いし達成感が得られ飽きにくくなりますのでどんどん次に行きます。

## 次回

多分マークダウンエディタを導入して記事を投稿できるようにする
もしくは豆腐をつなぎに使った低アレルゲンハンバーグの作り方
ConstraintLayoutのMarginsの基本

# 検証環境
この記事の内容は、以下の環境で検証した。
* Android Studio 3.0.2
* constraint-layout 1.0.2

# はじめに
ConstrantLayoutには様々な設定項目があります。
下記の記事で記述したように、今回は「Margins」のみについて説明します。

[ConstraintLayoutを理解する前に・・・](https://qiita.com/naoi/items/aedc985e49669f8fff110)

また、レイアウトの配置やViewの基礎知識は下記を参照してください。

[ConstraintLayoutのRelative positioningの基本](https://qiita.com/naoi/items/79416483cce89c058a95)


# 設定出来る項目とその見た目
Marginを設定する項目は下記のとおりです。
基本的には、「layout_ **[gone]** margin **POSITION** 」の構成をとっています。
「gone」のついている項目は、相対的な位置を示すために設定しているViewのVisivility属性の値によって、有効・無効が決まります。

* android:layout_marginStart
* android:layout_marginEnd
* android:layout_marginLeft
* android:layout_marginTop
* android:layout_marginRight
* android:layout_marginBottom
* layout_goneMarginStart
* layout_goneMarginEnd
* layout_goneMarginLeft
* layout_goneMarginTop
* layout_goneMarginRight
* layout_goneMarginBottom

それでは、説明をしていきます。

## android:layout_marginStart・android:layout_marginLeft・layout_goneMarginStart・layout_goneMarginLeft
配置するときのポジションにおける「start」と「left」は同じ部位を指すため、この記事では一気に説明してしまいます。
この項目を設定した時の見た目は下図のとおりです。

![start_left_margin.png](https://qiita-image-store.s3.amazonaws.com/0/99960/18f352e8-44ed-3056-d397-a00fbe2164e9.png)

Designタブでの見た目は下図のとおりです。
Designタブで「gone」の場合、見た目は変わるのですが、数値が100のままになっています。実際に動作させると期待通りの動きをしているので、IDEの不具合ではないかと思います。特に木にしなくても大丈夫です。

![start_left_margin_design.png](https://qiita-image-store.s3.amazonaws.com/0/99960/0939dd7d-2d8f-3ef2-bb61-8c91c9abfac9.png)


## android:layout_marginEnd・android:layout_marginRight・layout_goneMarginEnd・layout_goneMarginRight
配置するときのポジションにおける「end」と「right」は同じ部位を指すため、この記事では一気に説明してしまいます。
この項目を設定した時の見た目は下図のとおりです。

![end_right_margin.png](https://qiita-image-store.s3.amazonaws.com/0/99960/f6adfc0a-fd6d-a7b4-74d7-99f0d7367791.png)

Designタブでの見た目は下図のとおりです。

![end_right_margin_design.png](https://qiita-image-store.s3.amazonaws.com/0/99960/12a74906-40ef-dea3-52fa-2a344c3478b2.png)


## android:layout_marginTop・layout_goneMarginTop
この項目を設定した時の見た目は下図のとおりです。

![top_margin.png](https://qiita-image-store.s3.amazonaws.com/0/99960/fcba90f6-aa18-01bd-bdbb-8c18f7bc4061.png)


Designタブでの見た目は下図のとおりです。

![top_margin_design.png](https://qiita-image-store.s3.amazonaws.com/0/99960/e997e266-da56-c19c-3507-0cb68e7a5d95.png)


## android:layout_marginBottom・layout_goneMarginBottom
この項目を設定した時の見た目は下図のとおりです。

![bottm_margin.png](https://qiita-image-store.s3.amazonaws.com/0/99960/7c3ed8e8-257f-bb84-e1f3-c96167a73e0d.png)


Designタブでの見た目は下図のとおりです。

![bottom_margin_design.png](https://qiita-image-store.s3.amazonaws.com/0/99960/41182f93-49c3-f5cd-59b4-80a9ec26a2e0.png)


# まとめ
Marginsはそこまで難しい内容ではないように感じます。startとleftの様に同じ動きをする項目はあるものの、配置と同じように捉えれば問題なさそうです。

# 参考
今回使用したアイコンはIcons8を使用しています。
Icons8のライセンスは、 CC BY-ND 3.0です。
https://icons8.com/

ConstraintLayout
https://developer.android.com/reference/android/support/constraint/ConstraintLayout.html
【PHP5】uniqid()関数を使用して、ユニーク（一意）なIDを生成する

```php5:uniqid.php

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>ユニークなタイトルIDを生成</title>
	<!-- emmet->meta:vp -->
	<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>
	<?php 
	// ユニークIDは、マイクロ秒（100万分の1秒）単位で変化。

	// ユニークな13桁のIDを出力する
	// 出力結果「5af8cdbe59ff3」
	// 出力結果「5af8cdbe5a019」
	echo uniqid()."<br>";
	echo uniqid()."<br>";
	// 先頭に「test_」とついたユニークなIDを作成する
	// 出力結果「test_5af8cdbe5a03e」
	// 出力結果「test_5af8cdbe5a062」
	echo uniqid('test_')."<br>";
	echo uniqid('test_')."<br>";
	// より推測の難しい文字列を生成
	// この場合、23文字
	// 出力結果「5af8cdbe5a07e9.81077980」
	// 出力結果「5af8cdbe5a09e0.53166384」
	// 出力結果「5af8cdbe5a0b92.42877045」
	echo uniqid('',true)."<br>";
	echo uniqid('',true)."<br>";
	echo uniqid('',true)."<br>";
	// 頭に「test_」のついたユニークなIDを生成
	// 出力結果「test_5af8cdbe5a0d39.05814345」
	// 出力結果「test_5af8cdbe5a0ee7.93872758」
	echo uniqid('test_',true)."<br>";
	echo uniqid('test_',true)."<br>";
	// mt_rand()で乱数を生成->同じマイクロ秒でも異なる文字列を生成できる
	// md5()->md5ハッシュ値を計算。パスワードのハッシュ化には向いていない
	// 出力結果「4020dd107cffde2aa9b8e52787b98b13」
	// 出力結果「27a5a8778381c73817d5ffc3215a4073」
	echo md5(uniqid(mt_rand(),true))."<br>";
	echo md5(uniqid(mt_rand(),true))."<br>";

	// uniqid()関数は、暗号学的に安全な文字列ではない。
	// 暗号学的に安全な値が必要な場合は、openssl_random_pseudo_bytes()関数を使う。
	 ?>
</body>
</html>
```
###参考書籍
PHP逆引き辞典
Slerが製品（パッケージ、Webサービス）開発した結果

# 概要

　私はSlerで受託開発とパッケージ開発の双方を体験したことをもとに、アンチパターンとして残したいと思います
誰が悪いとかではなく、私も含めて製品開発を理解していなかったゆえに起こる事象になります
なので、**あくまでも私が体験した環境のみの話であって、業界を代表したものではありません**
なお、これらの体験には何年か前の話も含まれているので、現状とは異なる場合もあります


# 前提条件

下記の「製品開発」はパッケージ製品およびWebサービスの双方を指しています

# アンチパターン

## 人がいなくなる

開発が終わった途端、メンバーが他のプロジェクトに放出される
その理由は売り上げがないから人員を維持できないとか・・・
そもそも継続的に製品を改善していこうという姿勢ではない

### 対策

- 製品開発のライフサイクルを理解すること
- 長期的なロードマップを立てる

## 安易な機能実装

要望に対して安易な機能実装を行うことで、顧客によっては無駄な機能だったり、使いづらかったりする
また、持続的に保守をしなければないため、場合によっては運用負担が大きくになる
実装が悪かったり、仕様がわるかったりすると後の機能拡張にも影響を及ぼす

### 対策

- 特定の顧客のニーズに捉われず、製品全体にとって有意義な実装を目指す
- 製品ビジョンにあった機能実装

## 安易なカスタマイズ

売り方や契約によりけりですが、顧客別にカスタマイズを行うことでそれらをすべて保守していかなければならない
製品バージョンアップ時にそれらがバージョンアップできるかの保証もしなければならないので、運用コストが大きくなる

### 対策

- カスタマイズをしない
- CI環境を整え、運用コストを抑える
- 製品と切り離した売り方や契約にする

## ニーズをすべて実装しようとする

顧客に言われるがままに機能実装する（使われもしない機能も含めて）
それと同じ感覚でニーズと思われる機能をすべて実装しようとする

### 対策

- 製品のビジョンを立てる
- スモールバッチで実装（仮説検証も含めて）

## ビジョンなし

機能的な要素でしか、製品を捉えていない
製品に目的がなく、「〇〇ができる製品です」としか言えない

### 対策

- 製品の目的を明確にすること（会社の将来像や経営方針と合わせて考えるのがいいかもしれない）

## 儀式

製品のバージョンアップをしたい時に、都度バージョンアップするためのプロジェクトを作らなければならない
プロジェクト開始レビューこそはないが、リリース前にリリースレビューを都度役員にしなければならない
こうした儀式をしているだけで精神がすり減っていくし、スピードも遅くなる
場合によっては頓珍漢な意見を言ってくる・・・

### 対策

- 儀式を無せる（軽減できる）ように、事前にネゴる
- 製品のライフサイクルをプロダクトマネージャーに一任してもらう
- 都度見に来てもらえる、意見交換できる環境を整える

## 作ったらおしまい

受託開発の契約によりけりですが、作っておしまいという雰囲気になる
一度作ったのであとは売れるのを待つというスタンス

### 対策

- 製品のロードマップを立てる
- ニーズや製品のビジョンに合わせて、製品をアップデートし続けていく

## プロダクトオーナー不在

プロダクトオーナーという役割を担う人がいない
なので、みんなが好き勝手に意見を言い、それらをひっくるめた製品や機能になる


### 対策

- プロダクトオーナーを明確にする
- 意見を交わすのはいいが、だれが責任をもって最終決定をするのかを明確にする


## 掛け持ち

受託開発のプロジェクトと製品開発のプロジェクトの双方を掛け持ちしている状況
結果として受託優先にされるのが落ち目

### 対策

- どっちかにしてもらうｗ
東大　創造情報学　院試 2017 プログラミング


# 東大創造情報解答
(合っている保証なし)
USBのデータはこのファイルと同階層にあることを仮定しています.

## 1
2nm^2

## 2


```python
txt_path = "./mat1.txt"
MAT1 = []
with open(txt_path) as f:
    mat = f.read()
    mat = mat.split(".")[0]
    mat1 = mat.split(",")
    print(len(mat1))
    print(len(mat1[0].split()))
    
    for i in mat1:
        MAT1.append(i.split())
print(MAT1)        
```

    3
    4
    [['0', '1', '2', '3'], ['4', '5', '6', '7'], ['8', '9', '10', '11']]


## 3


```python
txt_path1 = "./mat2.txt"
MAT2 = []
with open(txt_path1) as f:
    mat = f.read()
    mat = mat.split(".")[0]
    mat1 = mat.split(",")    
    for i in mat1:
        MAT2.append(i.split())
print(MAT1)
print(MAT2)

d = 0

m =[]

for i in range(len(MAT1)):
    a = []
    for j in range(len(MAT2)):
        d = 0
        for k in range(len(MAT1[i])):
            d += float(MAT1[i][k])*float(MAT2[k][j])
        a.append(d)
    m.append(a)
    
print(m)

trace = 0

for i in range(min(len(m),len(m[0]))):
    trace += float(m[i][i])
    
print("トレースは" + str(trace))
```

    [['0', '1', '2', '3'], ['4', '5', '6', '7'], ['8', '9', '10', '11']]
    [['1', '2', '3', '4'], ['5', '6', '7', '8'], ['9', '10', '11', '12'], ['13', '14', '15', '16']]
    [[62.0, 68.0, 74.0, 80.0], [174.0, 196.0, 218.0, 240.0], [286.0, 324.0, 362.0, 400.0]]
    トレースは620.0


## 4

まずs > m*nの場合は何も変わらない.

プログラムの順番的にmat1の行をキャッシュに格納できたら良さそう。  
つまりn <= s で場合分けを考える. 


```python
m = 3
n = 4
s =5
if s >= m*n:
    print(n*(m**2))
if s < m*n:
    if s >= n:
        print(n*(m**2))
```

    36


わからん、ギブ。 どうもキャッシュブロッキングという手法らしい。
### 誰か教えて

## 5

1:u, 2:s, 3:v. 4:s, 5:w, 6:s

## 6
ZPOOL の異常時にメールするシェルスクリプト

ZFS の ZPOOL の状態を監視して異常時にメールするシェルスクリプト。ただそれだけ。

```sh:/etc/cron.hourly/zpool_satatus
#!/bin/sh

status=$(zpool status -x 2>&1)
host=$(hostname)
if [ 'all pools are healthy' != "$status" -a 'no pools available' != "$status" ]; then
    zpool status | mail -s "[ACTION REQUIRED] zpool satus on ${host}" root
fi
```
Googleのテキスト読み上げ機能がデフォルトで使用できない端末への対処法

#背景
googleのテキスト読み上げ機能(TextToSpeech)を利用しているandroidアプリに関してユーザーからテキスト読み上げが再生されないという問い合わせがあり、ユーザーの端末をきいて見たらFireタプレットにでGoogle Playアプリをインストールして、そこからアプリをインストールしたらしい...
参考:[FireタブレットにGoogle Playをインストールする方法【2017年版(第7世代)】](https://ygkb.jp/6312)

#対応
正直、サポート外です...で済ませてもよかったのですが、少し調べてわかったのでメモ

Google Playストアにある[Googleテキスト読み上げ](https://play.google.com/store/apps/details?id=com.google.android.tts&hl=ja)のアプリをインストールすることで音声が再生されました。

これまで4系のデフォルトの音声読み上げが音が酷すぎたのが、このアプリを入れて、テキスト読み上げ音声の設定をすることで解消できることがわかったのでよかったです。
Excelの日付に関する書式とTEXT関数

# 今回のケースについて
あるシート上で関数を入力しても正式に動作しないという事象を確認したとき、書式が原因であるというケースがありました。
そこで今回は日付の値である「#2018/5/14#」、式としては「=TODAY()」を様々な書式で見た場合どうなるかという点について調べてみました。

## 標準（yyyy/m/d）
> 2018/5/14

あくまで平常通り。
月と日の部分は2文字にすると2桁表記になります。

## 文字列（@）
> =TODAY()

シートの計算が有効になっていても計算が正常に行われない場合、書式が文字列になっている可能性があります。
大体の理由としてはExcelは自動的にゼロ抑制を行います。
そこで、0から始まるIDなどの入力を要求する際に不都合が生じるため明示的に文字列として入力を行うシングルクォートを入力せず入力させたい場合はこの書式を用いています。

## 数値（表示形式は<0_);[赤](0)>）
> 43324（※1は1900/1/1）

なんの値だよ！ということで上に注釈をつけています。


# 何が問題か
問題はExcelの関数で発生します。
＆演算子による文字列結合やCONCAT、CONCATENATE関数を使用した時において数値をベースとして変換します。
そのため、この場合だと43324として出力されます。

## 解決法
Excelシート上ではTEXT関数を使用します。（VBAについてはFormatメソッドで解決可能です。）
TEXT関数は第2引数で入力された書式にそって第1引数に入力された値を文字列型に変換して返します。

たとえば、TEXT(DATE(2018,5,14),"yyyy-m-d")の戻り値は"2018-5-14"として帰ってきます。
DATE関数は年月日をそれぞれ入力した時、日付型の値として帰ってきます。

# 最後に
よくわかんないけど日付が変な値になったとか、式がそのまま出てくるとかいう場合は書式を疑うのが先決だと思いました。
開発者アカウント(AppleDeveloper)を取得する手順についてまとめてみた

個人的に開発者アカウントを取得する手順の学習をしたため、
備忘録としてまとめてみました。

#AppleDeveloperProgramとは
**AppStoreにアプリをリリースするために登録する必要**がある。
　-年間¥11,800。
　-解約するとリリースしているアプリのダウンロードができなくなる。
　-元々いくつか種類がありiOSDeveloperProgram等が統合。

#必要なもの
**①AppleDeveloperで使用するためのAppleIDを作成する。**
　-既にAppleIDを持っている場合でも新たに作成した方が良い。
　【AppleDeveloperに使用するAppleIDは全て英語で登録したアカウントでないといけないため。

**②AppleDeveloperProgramでMembership for one yearを購入する。**
　-参加費用(メンバーシップ)の購入をする必要がある(税込：¥11,800)
　-**アクティベートに48時間程度**かかるそうなので余裕を持った作成が必要
　-アクティベートが完了後、AppleDeveloperProgramが利用可能であるメールが送られてくる。
　-**審査中は「Pending」の表示**、審査中はもちろんAppleDeveloperProgramを使用できない。
　-クレジットカード会社の情報等に1つでも相違があればアクティベートが失敗してしまうので注意が必要。

#補足：AppleDeveloperProgramの解約について
登録はめんどくさい割に解約はあっさりさせてもらえるようです。
勉強のために1年だけ登録したりするのにありがたいですね。

メンバーシップの有効期限が更新前に切れてしまった場合、
期限切れの間だけアプリがダウンロードできなくなるというペナリティがあるそうです。
しかし、メンバーシップの期限が切れてしまった場合でも更新は可能なようです。
また、メンバーシップは都度購入しなければならず、
都度購入したくなければ自動更新設定に変更する必要があります。
つまり**自動更新は設定を変更しないとできないようなので、
そのまま期限まで放置しておけば解約になる**ということです。

#参考
http://unitynightowlgames.hatenablog.com/entry/2016/09/23/110949
http://naouniverse.com/blog/2015/08/apple-developer-program-activation.html/
https://developer.apple.com/jp/support/renewal/
転職を機にリハビリも兼ねたWebサイト開発

※2019/04/22
諸事情でサイト公開を停止しました。すみません。

---

　おはこんばんにちわ。初めてのQiita投稿です。

　しばらく開発から離れてなんちゃってマネジメントをしていたため、リハビリを兼ねてPHPとYoutube API, Qiita APIを使ったツール開発をしてみました。

#作ったものの概要
###[QiitaTube](http://camp-life.jp/)

　Qiitaに多く関連付けられているタグをYouTubeで検索し、解説動画を再生リストごとに表示するツールです。
　思いつきと勢いで作ったのでかなり雑な作りです。（ゴメンナサイ）

　Qiitaで投稿された記事から関連付けられたタグを抽出し、関連付けれた数が多い順にタグを出力しています。
　そのタグでYouTubeで再生リストを取得し、解説動画をパパっと見られるようにしています。

　開発にはphp、apacheが使える無料レンタルサーバを使い、ほぼphpで実装。かなり昔にLAMPでWebアプリを作ったくらいの知識しかなかったので、レガシィな感じに。。。今の流行りって何ですかね？

　作ってみてQiitaで関連付けられているタグはWeb系が多いなぁというのと、機械学習関係がそれに負けないくらい多いというのが分かりました。
　また、解説動画を流したいけど、言語とかで中国語のものがヒットしたり、解説動画とは無関係の動画が出てくることもあります。（タイトルと内容が合致していないようなノイズ）
　まだまだ改善すべきポイントはあるので、これからも育てていきたいです。

###背景
　作ろうと思ったきっかけは以下の2点
1. 個人的に開発言語や技術系の解説動画をYouTubeで見ることがあるため、サクッと見られるツールが欲しかった
2. @jabba さんの『[技術書ランキングサイトをQiita記事の集計から作ったら、2700冊の技術本がいい感じに並んだ](https://qiita.com/jabba/items/edefda09121877b79760)』に感化された

###環境
1. 開発環境はCentOSにphp, apacheをインストールしたものを使いテスト。
2. 本番はphp+apacheが実行できる無料レンタルサーバにPHPファイルをアップ。
3. コーディングはIDEは使わず、viでゴリゴリ。理由はIDEを探すのと慣れるのに時間がかかると思ったから。あとはコンソールの使い方を思い出すためです。

###WEBページの構成
1. トップページ
　ここではQiitaのAPIを使い、Qiitaに投稿された記事に関連付けられているタグを多い順に取得しています。
　タグを検索キーワードとして、タグ毎にリンクを作り、リンクを踏むと次のページに移動します。

2. 選択したタグで検索した再生リストの一覧 
　トップページで選択したタグを使ってにYouTubeAPIで再生リストを取得しています。APIの仕様で再生リストは5つずつの取得のため、pageTokenを使って5つずつ再生リストを表示するようにしています。
　タイトル、サムネイルにリンクを張り、リンクをクリックすると再生ページを表示します。

3. 再生リストを再生するページ
　再生リストの動画を再生するページです。PlayerはYouTube APIを使うことでiframeで取得できる便利仕様でした。

　取り敢えずこれでQiitaのタグをもとにYouTubeの動画検索をするWebアプリ？ができました。

###作ってみてわかったこと、今後の課題
　まず作ってみて、インフラ系に比べてWeb系の言語の記事が多いのだと実感。
　最近ホットな機械学習系のタグはもっと少ないかと思っていたが、以外にもそうでもなかったので、今後も増えてきそうだなと思いました。
　
　今後の課題としては下記の点を改善していきたいなと思っています。
1. デザイン。スマホ、PCに対応したレスポンシブデザインにしたい。
2. 検索精度の向上。キーワードを単純にタグにしているため、中国語の解説動画などが出てきたり、内容とタイトルが合わない再生リストが出てきたりします。ここはキーワードをいろいろ絡めてみてチューニングしていくか、ユーザが選択できるようにしたいですね。（入門or解説or講座などなど）

###謝辞
　きっかけを作っていただいた @jabba さんに感謝申し上げます。
CentOS7にPostgreSQLをインストールする

# はじめに
これまでMySQLしか触ったことがありませんでしたが、PostgreSQLを勉強する必要が出てきたため、その環境準備からです。

# OS準備
ローカル開発環境（Vagrant等）があれば良いですし、少々のお金を払っても良いならクラウドもお手軽です。今回はクラウドに作ったCentOS7サーバを使うことにしました。ということでOS準備までは割愛します。

# PostgreSQLのインストール
[公式ドキュメント](https://www.postgresql.org/download/linux/redhat/)にもある通り、yumで一発です。CentOS7の場合は、PostgreSQLの9.2がインストールされるようです。

```
# yum install postgresql-server
# psql --version
psql (PostgreSQL) 9.2.23
```

続いてDBの起動です。これも公式の手順通りに。

```
# postgresql-setup initdb
# systemctl enable postgresql.service
# systemctl start postgresql.service
```

一行目の`initdb`はまだ意味が分かっていません。これから勉強していきます。

（9/24追記）
initdbコマンドによって、データベースの実体となる単一のディレクトリが作成されます。
この例ではデフォルトでは`/var/lib/pgsql/data`に作成されます。



# データベースの確認
データベースの確認をしようとしたところ、以下のエラーが出ました。

```
# psql -l
psql: FATAL:  ロール"root"は存在しません
```

PostgreSQLサーバではrootユーザでのログインを禁止しているようです。これも公式のドキュメントに頼ると、「postgresというユーザ名がよく使われる」との記述があったので、それに倣おうと思います。

```
# grep postgres /etc/passwd
postgres:x:26:26:PostgreSQL Server:/var/lib/pgsql:/bin/bash
```

インストール時にpostgresユーザが作成されていました。今後はこれを使っていきましょう。

```
# su - postgres
$ psql -l
                                         データベース一覧
   名前    |  所有者  | エンコーディング |  照合順序   | Ctype(変換演算子) |      アクセス権       
-----------+----------+------------------+-------------+-------------------+-----------------------
 postgres  | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       | 
 template0 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       | =c/postgres          +
           |          |                  |             |                   | postgres=CTc/postgres
 template1 | postgres | UTF8             | ja_JP.UTF-8 | ja_JP.UTF-8       | =c/postgres          +
           |          |                  |             |                   | postgres=CTc/postgres
(3 行)
```

無事データベースの確認ができました！
Vsftpd + MySQLでユーザーをデータベースで管理するFTPを作ってみる


```shell
apt-get install vsftpd libpam-mysql libpam-ldap

☆質問はこう返しなさい☆
LDAP server Uniform Resource Identifier: <--  エンター
Distinguished name of the search base: <-- エンター
LDAP version to use: <-- 3　と入力
Make local root Database admin: <-- Yesを選択
Does the LDAP database require login?  <-- Noを選択
LDAP account for root: <-- エンター
LDAP root account password: <-- ldaprootpw　と入力
・・・・・・


mysql -u root -p
```


#DB作成
```shell
mysql> 
create database ☆データベース名☆;

CREATE USER '☆DB管理のユーザー名☆'@'localhost' IDENTIFIED WITH mysql_native_password AS '☆DB管理のユーザのパスワード☆'; GRANT USAGE ON *.* TO '☆DB管理のユーザー名☆'@'localhost' REQUIRE NONE WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0;

GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, INDEX, ALTER ON `☆データベース名☆`.* TO '☆DB管理のユーザー名☆'@'localhost';


use ☆データベース名☆;

CREATE TABLE `accounts` ( `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY , `username` VARCHAR( 30 ) NOT NULL , `pass` VARCHAR( 50 ) NOT NULL , UNIQUE ( `username` ) ) ENGINE = MYISAM

quit;
```

#Linuxユーザーの作成
nogroupにvsftpd用のユーザーを作ってやります。
 /home/vsftpd 下に(例 /home/vsftpd/user1, /home/vsftpd/user2, ....)という感じでできます。

```shell
useradd --home /home/vsftpd --gid nogroup -m --shell /bin/false vsftpd
```

#設定ファイルの作成
```shell
vi etc/vsftpd.conf
///
listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
nopriv_user=vsftpd
chroot_local_user=YES
secure_chroot_dir=/var/run/vsftpd
pam_service_name=vsftpd
guest_enable=YES
guest_username=vsftpd
local_root=/home/vsftpd/$USER
user_sub_token=$USER
virtual_use_local_privs=YES
user_config_dir=/etc/vsftpd_user_conf
listen_port=8021
///
```
読解して、適宜変えてください。

#MySQL設定
MySQLのライブラリを読み込むようにして、データベースのカラム等を設定します。

```shell
mkdir /etc/vsftpd_user_conf

cp /etc/pam.d/vsftpd /etc/pam.d/vsftpd_orig
cat /dev/null > /etc/pam.d/vsftpd
vi /etc/pam.d/vsftpd
///
auth required pam_mysql.so user=☆DB管理のユーザー名☆ passwd=☆DB管理のユーザーパスワード☆ host=localhost db=☆データベース名☆ table=accounts usercolumn=username passwdcolumn=pass crypt=2
account required pam_mysql.so user=☆DB管理のユーザー名☆ passwd=☆DB管理のユーザーパスワード☆ host=localhost db=☆データベース名☆ table=accounts usercolumn=username passwdcolumn=pass crypt=2
///
```

```shell
service vsftpd restart
```
これで動くはず。

#ユーザーの新規追加
```shell
MySQLで
USE ☆データベース名☆;

INSERT INTO accounts (username, pass) VALUES('ユーザー名', PASSWORD('パスワード'));
quit;

コンソールで
mkdir /home/vsftpd/testuser
chown vsftpd:nogroup /home/vsftpd/testuser
chmod a-w /home/vsftpd/testuser
```


これでFTPアクセスできます！！！

SSL対応はまた今度の話。

#Reference
https://www.howtoforge.com/virtual-hosting-with-vsftpd-and-mysql-on-ubuntu-12.04
http://e-garakuta.net/techinfo/doku.php/linux/vsftpd_mysql
http://park1.wakwak.com/~ima/centos4_vsftpd0006.html
CloudFormationのvim snippetを作ってみた

AWSを触り始めて、CloudFormationのtemplateをvimで書きたかった。
けど、既にあるsnippetがしばらく更新されてないようなので公式docからコード部分を抜き出してsnipファイルにしました。

[aws-cfn-snippet](https://github.com/lunarxlark/aws-cfn-snippet.vim)

ex) AWS ResourceのAWS::EC2で展開した時
![sample1.png](https://qiita-image-store.s3.amazonaws.com/0/222199/1483b0b6-bafa-15b5-a276-23046f60b6ec.png)

ex) Resource PropertriesのStageDescriptionで展開した時
![sample2.png](https://qiita-image-store.s3.amazonaws.com/0/222199/73b91110-d5ee-73b4-0f66-bfdf2de82cd3.png)


[Shougo/neosnippet](https://github.com/Shougo/neosnippet.vim)前提です。
vimのプラグインとしてインストールしてsnippetを読み込ませるやり方を知らないので、ひとまず手動でsnipファイルを配置してください。
vimrcに自前snippetファイルの場所を書いてそこにsnipを置くことでsnippetに追加されます。
solaris10でネットワークの帯域を制御する

通信量に上限を設定したい場合、色々な仕組みがあります。NW機器で経由する通信を制御するのがわかりやすいですが、今回はOSの機能で実装します。

# やりたいこと
利用する通信量に上限を設定して帯域制御する

（参考）IPQoS
https://docs.oracle.com/cd/E24845_01/html/819-0380/ipqos-intro-1.html
（参考）実現したいことと同事象
https://serverfault.com/questions/265084/solaris-express-11-ipqos-how-to-set-up?utm_medium=organic&utm_source=google_rich_qa&utm_campaign=google_rich_qa

## 設定を追加する
**OSの確認**

```bash
$ cat /etc/release
Oracle Solaris 10
・・・略
```
**QoSの設定が入っているか確認する**

```bash
# rootユーザで実施
$ ipqosconf -l
$ 
```
**設定を記載したテキストファイルを作成**

```bash:/var/ipqos.qos
fmt_version 1.0
action {
    module ipgpc
    name ipgpc.classify

    params {
        global_stats TRUE
    }
    class {
        name hlimit
        next_action check
        enable_stats FALSE
    }
    filter {
        name hlimit
        if_name {インターフェースの名前}
        class hlimit
    }
}
action {
    module tokenmt
    name check
    params {
        committed_rate 102400
        committed_burst 102400
        peak_rate {通信量の上限をbpsで入力する}
        peak_burst 102400
        red_action_name drop
        green_action_name continue
        yellow_action_name continue
        global_stats TRUE
    }
}
```

**設定の反映**

```
# rootユーザで実行
$ /usr/sbin/ipqosconf -a /var/ipqos.qos
$ ipqosconf -l
→設定値が標準出力に出る
```

**動作**
制御を掛けたインターフェースを使って通信した場合
peak_rateの設定値を上限として通信量が制御できます。

solaris10は2005年にリリースされたとのことで、2018年現在利用する状況は非常に少ないかと思いますが、solaris10で稼働しているホストにおいてOS層で帯域制御したい場合は利用できる機能です。
Kotlinでprivateメソッドをテストする

# ０.はじめに
基本はJunitのソースコードの置き換え
Junit同様にリフレクションを使用

# １.テストしたコード

Sample001クラス
　・privateメソッドを持つテスト対象のクラス

``` Sample001.kt
class Sample001 {
    private fun privateMethod () : String { return "I am private"}
}
```

Sample001Testクラス
　・privateメソッドのテストコード

``` Sample001Test.kt
import org.junit.Test
import java.lang.reflect.Method
import kotlin.test.assertEquals

class Sample001Test {
    @Test
    fun privateTest () {
        // テストクラスのインスタンス生成
        var sample001 = Sample001()
        // メソッド格納用
        var method : Method
        // テストクラスからprivateメソッドの取り出し(リフレクション)
        // 今回はSample001.privateMethod()を取得する
        method = sample001.javaClass.getDeclaredMethod("privateMethod")
        // privateメソッドをアクセス可能に変更
        method.trySetAccessible()

        // 実行
        assertEquals("I am private", method.invoke(sample001) as String)
    }
}
```

# ２.引数を指定する

Sample001クラス
　・エコー(引数をそのまま返す)メソッドの実装

``` Sample001.kt
private fun privateMethodB (v :String) : String { return v }
```

Sample001Testクラス
　・引数付きprivateメソッドの指定部分を次の記述に変更

``` Sample001Test.kt
// 引数の型(String)を String::class.java で指定する
method = sample001.javaClass.getDeclaredMethod("privateMethodB", String::class.java)

// 実行
assertEquals("BBB", method.invoke(sample001, "BBB") as String)
```

# ３.感想とか
　String::class.java って書くところを String.javaClass ってずーっと書いてて詰まった
10分でVuePressをGitHub Pagesで公開できる雛形作った

紆余曲折あって気づいたら作ってました。
5ステップでmarkdownで作るちょっとリッチなWebサイトが作れます。

[VuePressで作ったこの雛形を使って10分で公開する方法](https://fruitriin.github.io/VuePressOnGithubPageTemplate/)
[リポジトリ](https://github.com/fruitriin/VuePressOnGithubPageTemplate)

## 必要環境
- git
- shell上からgitコマンドでgithubに書き込み（push）できること  
`sh git@github.com` コマンドで確認することができると思います。
- yarn （VuePressが必要とする間はnpmではインストールできません）


## 公開に必要な5ステップ

- githubでリポジトリを作る
- 雛形をコピーしてyarn installする
- .env ファイルを修正する
- deploy.sh を実行する
- 公開するリポジトリでGithub Pagesを有効にする

これだけでサイトを作って公開できます！
あとは.mdファイルをdocs配下にぽいぽい放り込んでいくだけ。


## 何が違うの？
- github公開のためにちょっとだけ最適化してます
- サイドバーをdocs配下のファイル名とディレクトリ名から自動的に作ります。  
- (ファイル名/ディレクトリ名でソートされます)
- そして手順のドキュメントがありますよ！


もしよかったら使ってみてください。
.mdをリポジトリに置くだけでプレゼンできるGitPitchに挑戦してわかったことまとめ


markdownでスライドが作れる[GitPitch](https://gitpitch.com/)に挑戦してみました。
いやーいいですねこれ。とにかくmarkdownだけでスライド作れるのめっちゃ楽です❗

挑戦してみてわかったこといくつか。

## 基本仕様
- スライドは1ブランチにつき１つ。ファイル名はPITCHME.mdのみ
- 複数のスライドを公開するときはブランチを分ける。  
→雛形を作ってそこからブランチを生やせばマスタースライド的なことができる？
- MarkdownのrenderはGithub Flavor+α？makrdown-it？  
まあどっちでもいいか。
- [font-awesome](https://github.com/gitpitch/gitpitch/wiki/Font-Awesome-Icons)がスライドの中で簡単に使える。大きさも変えれる。おおー

## レイアウトについて
- htmlタグやcss（！）が有効。  
JavaScriptは試してないからわからない。
- レイアウトはデフォルトですべて縦軸横軸両方センタリング。
- 縦方向センタリングは見出しがガタガタするし、  
横方向センタリングは箇条書きなんかがガタガタするので、  
それら用のクラスを作ってdivで囲むといいかも。
- [ページ番号を打ちたい](https://github.com/gitpitch/gitpitch/wiki/Slide-Number-Setting)とか[フッターを設定したい](https://github.com/gitpitch/gitpitch/wiki/Footnote-Setting)とかもできる。


## コードとの親和性
- コードブロックはシンタックスハイライトされる。やったぜ。
- [Code Presenting](https://github.com/gitpitch/gitpitch/wiki/Code-Presenting)が激アツの予感😍  
ベタっとコードブロックを貼って重要なところだけを強調するスライドが簡単に作れる  

## プレゼンテーション
- デフォルトでトランジションがついてる。リッチで素敵。  
---で横方向、+++で縦方向。
- [スピーカーノート](https://github.com/gitpitch/gitpitch/wiki/Speaker-Notes-Window)も使える。  
パワポとかKeynoteとかにもあるけど、時間の進みとか測れて時間が限られてるときの強い味方

## 総評
markdownでスライド作れるのめちゃくちゃ楽‼️（大事なことなので2回

めちゃくちゃイケてるけど、かなりサービスにロックインされる感があるので、うっかりポシャったりしないといいな。
お布施すればいいのか？ローカルのmarkdownがGitPitch上でリアルタイムに確認できてお値段12$？
ふむ🤔 ←真面目に検討している

とりあえずこれから作るスライドは全部GitPitch向けの.mdでいいや。
GitPitchはいいぞ💪

この記事は[私のブログ](https://www.riinswork.space/2018/05/try-gitpitch.html)からの寄稿です。
窓使いがMacに入信したけど発狂したのでやっぱりWindowsっぽく操作したい

15年ほど窓使いだった私が、Macに宗旨変えしたものの発狂した結果、
Windowsっぽい操作に寄せていったり諦めた方法のまとめです。

## Windowsでいう「スタート」ってどれ
LaunchPadでリストから選択/Finderのアプリケーションから選択
もしくはSpotlightでキーボード検索。

Spotlightはショートカットのキーバインドを使いやすいように変えてやるとキーワード検索型のタスクランチャーみたいでいいぞ。
[Mac Spotlightをすぐに起動するキーボードショートカット / Inforati](http://inforati.jp/apple/mac-tips-techniques/system-hints/how-to-activate-mac-spotlight-with-keyboard-shortcuts.html)

## マウスのスクロール操作が逆
トラックパッド→スクロールとズーム→スクロールの方向→オフにする

「タッチパッドでのスクロールはいいけどマウスは逆」のときは[Scroll Reverser for macOS](https://pilotmoon.com/scrollreverser/)をインストールする

## コピペ、戻るのキーボードショートカット is どれ<br>WindowsでいうところのCtrl、Altキーにあたる操作が逆でつらい
だいたいMacではCommandキーがWindowsでいうところのCtrlキーに相当するキーバインドになっている。
AltはOption。なんと配置が逆である。嫌がらせか。

Capsを何かと入れ替えるついでに適当にごにょろう。

 キーボード→キーボード→修飾キー
（もしくはここでは設定しないでKarabinerをインストールする）

CapsLock→Command
Option→任意
Command→Option

## 半角全角キーで入力が切り替わらない
諦めて英数キーとかなキーに慣れよう。
最初は違和感あるけど慣れるとむしろこっちのほうがイイかも。 

外付けキーボードを使っているときに、Karabinerで半/全キーにIMEのトグルを設定できるけど、挙動が微妙に違って地味にイライラしたので結局やめた

## IME(ことえり)がうざい
ことえりに違和感があるならGoogle日本語入力はいいぞ。Atokでもいい。   
サード制のIMEインストールしたら、システム環境設定→キーボード→入力ソースからことえりを抹殺しよう。

## F5でブラウザが更新できない<br>F12で開発者ツールが開かない

更新はCmd+Rに慣れる。

開発者ツールはCmd+Shift+I だと思うんだけどメーラーとバッティングしてる？
とりあえず右クリックして検証を押すと開くのでそれでいいかなと思っている


もしくはキーボード→ショートカット→アプリケーションに下記の設定を加える
[Mac の Chrome に F5 と F12 のショートカットキーを割り当てる設定方法 \| ウエツハラ](https://uetsuhara.com/articles/2013/12/mac-chrome-shortcutkey.html)


## タスクバーがほしい
[uBar](https://brawersoftware.com/products/ubar)はいいぞ（有料）  
[Windows派の私がMacを使い始めてタスクバーを求めてuBarに出会った話 \- Qiita](https://qiita.com/fruitriin/items/3def5cdbcb0461f47b25)

## Finder
未だに慣れないのでいい情報求む。
~~いっそのことElectronとかで作ったほうが速いのかもしれん。~~

コメント欄で[PATH FINDER](https://cocoatech.com/#/)をおすすめされました。
ちょっと使ってみたいと思います！

とりあえずFinderについて気をつけること。
- 関連付けで開くはEnterではなく Cmd+↓
- Enterはリネーム
- 同じ名前のディレクトリをコピーすると **マージではなく上書き** される

## ダイアログの はい/いいえ、保存/キャンセルが逆
This is Mac. damit.
スクロールといいCtrl/AltにあたるCmd/Optキーの配置といいダイアログといい嫌がらせか！

## お前それWSLでよくね？ 
- TerminalいいよTerminal
- Unix系のコマンドがネイティブに動いてGUIが綺麗っていうちょうどいい塩梅  
（WSLでいいって怒られそうだけど）
- AppStoreかわいいよAppStore
- brewかわいいよbrew
-  周りの開発者みんなMacだし
- 会社がMacなんで
- iOSアプリビルドできるようになってから言えよ(´・ω・｀)


この記事は[私のブログからの寄稿](https://www.riinswork.space/2018/05/mac-windows.html)です。
nodejsのpm2、linuxの環境変数が反映されるタイミングは？

以下の環境。
```plaintext
[ec2-user@ip-172-31-26-74 ~]$ pm2 --version
2.10.3
[ec2-user@ip-172-31-26-74 ~]$ node --version
v10.1.0
```

` pm2 restart 0  --update-env & pm2 save`でおｋ。

もっと複雑な条件だと思ってたのでオチはないです

メモ。jsonのオブジェクトをキーでソートしてNormalizeする処理

```

k=JSON.stringify(JSON.parse(v),(key,val)=>{
  if( typeof val == "object" && val != null && Array.isArray(val) == false){
    const keys = Object.keys(val);
    if(keys==null){debugger;}
    const keysSort = keys.sort();
    const r = {};
    for(let v of keysSort){
      r[v] = val[v];
    }
    return r;
  }else{
    return val;
  }
},"  ");copy(k);

```
OUTPUT"May 14 days"

<h2 id="Rubyの開発者を目指し基礎を学んでいる:relaxed:">Rubyの開発者を目指し基礎を学んでいる:relaxed:初心者の私がつまづいたところを簡単にまとめてみました。</h2>


<p>つまづいたところ:runner_tone3:(May 14 days)</p>
<ul>
<li>eachメソッド</li>
<li>initializeメソッド</li>
<li>ハッシュ</li>
</ul>

<h2>
<span id="code---コードの挿入" class="fragment"></span><a href="#code---%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%8C%BF%E5%85%A5"><i class="fa fa-link"></i></a>eachメソッド</h2>
<p><strong>こ</strong>のスクリプトでのつまづきポイントは「puts animal」を「puts animals」と誤記していたために出力された結果が配列ごと出力されたしまったことです。出力結果がanimalsの中身の値の文字列"いぬ","ねこ","ねずみ"を三回出力してしまいました。eachメソッドは変数を定義してその中身を全て出力しています。それと同時に本来であれば１要素づつ出力しなければいけないところ、"いぬ","ねこ","ねずみ""いぬ","ねこ","ねずみ""いぬ","ねこ","ねずみ"とくどいくらい出力されてしまいました。。
</p>


```ruby:sample.rb
animals = ["いぬ","ねこ","ねずみ"]

animals.each do |animal|
puts animal
end
```

<h2>
<span id="code---コードの挿入" class="fragment"></span><a href="#code---%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%8C%BF%E5%85%A5"><i class="fa fa-link"></i></a>initializeメソッド</h2>
<p><strong>こ</strong>のスクリプトでのつまづきポイントはまず読み方。「いにてぃあらいず？」　「イニシャライズ」が正しいようです。謎の名前のせいで何がすごいのだかわかりませんが、今はインスタンスというものを生成した時に呼び出されるメソッドと認識して良いそうです。また、initializeの綴りが誤っていたためメソッドが呼び出されませんでした。正しい読み方を知る必要があるみたいです。:ghost:
</p>


```ruby:sample.rb
class Hoge
  def initialize
    puts "Hogeクラスのインスタンスが生成されました"
  end
end

hoge = Hoge.new
```


<h2>
<span id="code---コードの挿入" class="fragment"></span><a href="#code---%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%8C%BF%E5%85%A5"><i class="fa fa-link"></i></a>ハッシュ</h2>

<p><strong>こ</strong>のスクリプトでのつまづきポイント：「puts movie[data]」が「puts movie[:data]」じゃないの？と思い悩まされました。解決はメソッドの変数を取り出しているで解決しました。ハッシュはhash[:hash]でも値を取り出せるが、今回の場合は引数プラスハッシュみたいな考え方があるようで、dataにはユーザが入力した文字列「movie["title"]」が入るイメージで理解しました。ハッシュは難しいぞ、、、:thinking:</p>

```ruby:sample.rb
def movie_info(movie, data)
  puts movie[data]
end

movie = {"title" => "ハリーポッター", "genre" => "ファンタジー", "year" => "2001年"}

puts "以下から一つを選んで入力してください。
  ・title
  ・genre
  ・year"

info = gets.chomp

movie_info(movie, info)
```

<h2>
<span id="code---コードの挿入" class="fragment"></span><a href="#code---%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%8C%BF%E5%85%A5"><i class="fa fa-link"></i></a>さいごに</h2>
<li id="fn2">
<p>概要の理解は本当に頭を悩ませます。さっさとものを作ったほうがいいのかも。でもそができていないと。。。時間をかけずに作業を進めたいですが効率の良い勉強は結局回り道な気がします。<a href="#fnref2"></a></p>
</li>
nodistで管理しているnpmのバージョンが上がらない

## 事象

nodistでNode.jsのバージョン管理を行っている時に、npmのバージョンをアップデートしようと思って下記コマンドを実行した。


```
npm update -g npm
```

その後`npm -v`でnpmのバージョン確認をしたが、バージョンがアップデートされていなかった。

## 解決策

nodistのGitHubの`README.md`に記載されている下記コマンドを実行すればnpmのバージョンがアップデートされた。

```
nodist npm global match 
```

**match**は[リリース一覧 Node.js](https://nodejs.org/ja/download/releases/) のnpmの欄に記載されているバージョンがインストールされる。
※Node.jsが8.11.1の場合は5.6.0のnpmがインストールされる。

## 

## 参考サイト
- https://github.com/marcelklehr/nodist
    - nodistのGithub