OmniAICreator/Qiita-1.07M huggingface dataset:
最短攻略 htmlspecialchars

PHPで生の式を関数で囲みたいときがよくあるんだけど、せっかく PhpStorm でやってるんだし、上下左右キーやマウスはできるだけ触りたくないですよね。

# 標準機能でできる範囲

![スクリーンショット 2019-12-27 18.24.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/b858a15d-c7fa-f0d9-f142-9f0996ad8bae.png)
`Alt` + `↑` 選択範囲拡張
![スクリーンショット 2019-12-27 18.15.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/da7ace72-deed-5b3f-bf29-6ed635af3594.png)
`(` 自動閉じカッコ
![スクリーンショット 2019-12-27 18.15.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/0141bba9-65c6-f6fb-8d4f-9afbeb1f2875.png)
`←` この
![スクリーンショット 2019-12-27 18.17.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/ab555442-6e10-4c64-6d73-b18d843fd4f1.png)
`←` 2回押すのがめんどいだけで
![スクリーンショット 2019-12-27 18.17.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/3935dea2-5692-7851-9e40-8f9bd60f9136.png)
`h` `t` `m` `l` あとは
![スクリーンショット 2019-12-27 18.16.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/50e45231-549b-1da4-edc1-2c05408f99c7.png)
`Tab` シュッとこうなる
![スクリーンショット 2019-12-27 18.16.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/d5099da6-4e24-f4ef-75fa-d52f5b3fe6eb.png)

# ユーザー定義ポストフィックス・コンプリションで

![スクリーンショット 2019-12-27 18.43.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/fa47feb5-93de-45ea-a9a3-71dff0ec3807.png)
定義する
![スクリーンショット 2019-12-27 18.24.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/b858a15d-c7fa-f0d9-f142-9f0996ad8bae.png)
`.arg1`
![スクリーンショット 2019-12-27 18.46.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/e5641edf-68d8-7055-ae2a-6eceb4bbbfb4.png)
`Tab`
![スクリーンショット 2019-12-27 18.17.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/3935dea2-5692-7851-9e40-8f9bd60f9136.png)
あとは同じ

# ライブテンプレートで

![スクリーンショット 2019-12-27 18.56.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/3fe9c5c4-4f27-5e65-952d-850bf05223c8.png)
定義する

![スクリーンショット 2019-12-27 18.24.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/b858a15d-c7fa-f0d9-f142-9f0996ad8bae.png)
`Alt` + `↑` 選択範囲拡張
![スクリーンショット 2019-12-27 18.15.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/da7ace72-deed-5b3f-bf29-6ed635af3594.png)
`Cmd` + `Alt` + `J` さらうんど うぃず らいぶてんぷれーと
![スクリーンショット 2019-12-27 18.54.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/9ce3cfc1-b9a2-7f8f-25ce-b2f139dc4f1d.png)
`Enter`
![スクリーンショット 2019-12-27 18.17.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11525/3935dea2-5692-7851-9e40-8f9bd60f9136.png)
あとは同じ


注: `htmlspecialchars` 専用じゃないです
brew caskで欲しいバージョンのfomulaがないのでtap自作する


Virtualboxの5.2をインストールしたいのですが、2019-12-27現在 `brew install virtualbox` すると 6.1がインストールされてしまいます。  
tapを自作して解決しましょう。

# 1. 公式のCask Codeを参照する
https://formulae.brew.sh/cask/virtualbox  
https://github.com/Homebrew/homebrew-cask/blob/master/Casks/virtualbox.rb  

# 2. Tapリポジトリを公開する

やり方はこちらを参考にしました。  
https://qiita.com/tarappo/items/8d6cb62be3b91f0be583

dmgファイルのダウンロードURLを公式サイトから控え、バイナリの SHA256を算出した後、公式のCask Codeをコピペして置換した結果がこちらです。  
https://github.com/hiroga-cc/homebrew-virtualbox-5.2

## ハマりどころ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/44f4285e-14c7-d79d-8fbc-3251082ddecf.png)

ルートディレクトリに .rbファイルを作成するのではなく、 `プロジェクトルート/Casks/***.rb` の構成で作る必要があります。  
誤ってルートディレクトリに作成した場合は以下のエラーが発生し、私は原因特定まで1時間を費やしました...。

```
$ brew tap hiroga-cc/virtualbox-5.2
==> Tapping hiroga-cc/virtualbox-5.2
Cloning into '/usr/local/Homebrew/Library/Taps/hiroga-cc/homebrew-virtualbox-5.2'...
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 0), reused 4 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.
Error: Invalid formula: /usr/local/Homebrew/Library/Taps/hiroga-cc/homebrew-virtualbox/virtualbox-5.2.rb
virtualbox: undefined method `cask' for Formulary::FormulaNamespacead380ff8d454670d2504ca62549826bd:Module
Error: Cannot tap hiroga-cc/virtualbox: invalid syntax in tap!
```

（Ruby分かる人だと即解決できたりするんですかね？）

# 3. インストールする

```
brew tap hiroga-cc/virtualbox-5.2
brew cask install virtualbox-5.2
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/1d4647ea-3134-aef8-8825-d7995c7064ed.png)
やったぜ！完了。
【rails】webサイトからスクレイピングしたデータをデータベースに保存する方法

#はじめに
初学者がポートフォリオ作成でハマったことをメモします。

今回はスクレイピングをする為にMechanizeというgemを使用しました。
Nokogiriというgemもスクレイピングに使われるみたいです。

##環境
Ruby 2.6.3 ,Rails 5.2.4


##やりたいこと
webサイト(単一のページ)から特定の要素を抜き出してデータベースに保存する。


##手順
<b>・</b> gemをインストール

```ruby:Gemfile
gem 'mechanize'
```
```ruby:ターミナル
$ bundle install
```
</br>
</br>
<b>・</b>クラスの作成  
スクレイピングを実行するコードを書く為にモデルクラスを作成。


```ruby:ターミナル
$ rails generate model Scraping
```

mechanizeをrubyファイルで利用するためにrequire 'mechanize' をファイルの先頭に記述。

```ruby:scraping.rb
require 'mechanize'
```

</br>
</br>
<b>・</b>クラス内にメソッドを記述
  
```ruby:scraping.rb
def self.scrape
      agent = Mechanize.new                  #agentは任意の変数
      page = agent.get("https://www......")  #pageは任意の変数 getの引数はサイトのURL
      elements = page.search('div.idxcol a') #div.idxcol aは取得したい要素  elementsは任意の変数
      elements.each do |element|
        fish = Fish.new                      #Fishは任意のクラス、fishは任意のインスタンス
        fish.name = element.inner_text
        fish.save
      end
    end
end
```
  
agentという変数にMechanizeクラスのインスタンスを代入。

ウェブサイトからHTML情報をgetというメソッドで取得し、pageという変数代入。

任意の変数elementsに、ページ内でほしい要素に付いているクラス名やタグ名を指定。

eachメソッドを使ってelementsから要素を一つづつ取り出だす。

Fishクラスからインスタンスを作成。

inner_textメソッドで要素からテキストのみを取得してしてfishテーブルのnameカラムに代入。
今回はFishクラスのnameカラムにスクレイピングした値を代入したい。
（Fishクラス、fishesテーブル、nameカラムは事前に作成しています。）

最後にsave。

</br>
</br>

<b>・</b>ターミナルで定義したクラスメソッドを実行

```ruby:ターミナル
$ bundle exec rails console
pry(main)>Scraping.scrape

```
これでデータが入っているはずです。
　　
以上

##最後に
誰かのお役にたてれば幸いです。
間違えている部分があればコメントお願いいたします。

参考にした記事
https://qiita.com/4npei/items/2dc18487d3103cb3e5a6
https://qiita.com/takuyanin/items/01256773e1cbfc84f51a
https://freesworder.net/ruby-on-rails-scraping/
読書メモ：実践ドメイン駆動設計（IDDD）3章

# はじめに

- 実践ドメイン駆動の読書メモです。簡単なまとめと、自身のコメントをまとめています。//から始まる行が私のコメントや考察。
- https://www.amazon.co.jp/dp/479813161X
- 狙い：本書を読んだものの、頭に入ったようでまったく記憶に残らなかったため、あとで自分の記憶を掘り起こすツールとして。

# 第3章 コンテキストマップ

- 2章の内容が「解決空間の評価」にあたるのに対し、本章が「問題空間の評価」にあたる

## 3.1 なぜそんなにもコンテキストマップは重要なのか

- DDDにとりかかる最、まずプロジェクトの現状をコンテキストマップに表す
- 解決空間の全貌を俯瞰できるようにするために行う
- 巨大な泥団子との統合が求められる時でも、関連をきちんとマップに反映させておくとよい
    - 可視化することで得られる知見
    - どこでチーム間コミュニケーションが必要になるかを判断できる
    - // 巨大な泥団子というのは、理解が難しく、レガシーで、巨大なサービスをイメージすると良さそう

- コンテキストマップを描く
    - コンテキストマップは現状を書くもので、将来像を描くものではない
    - 凝った作りにする必要はなく、ホワイトボードなどのマーカーで手書きするなどでよい
    - あまり細かく儀式的な作業をしても、チームの助けにはならない
    - コンテキストマップをオープンにして、議論の中から知見を見つけるためのツールとして使う

- プロジェクトと組織的な関係
    - 境界づけられたコンテキスト同士の関係にはパターンがある（説明は個人的に気になったポイントのみ）
        - パートナーシップ
            - 成功/失敗の運命を共にする。相互が密接に関わっている。
        - 共有カーネル
        - 顧客/共有者の開発
            - 上流/下流の関係で、下流の結果に上流の成否が左右される。  
        - 順応者
            - 上流/下流の関係だが、上流側が下流の要求に応える動機がなく、下流が上流に合わせる形。
        - 腐敗防止層
            - 上流の機能を下流のドメインモデルの用語で表現する、情報の変換インタフェースの層。上流の変更に対する防御層。
        - 公開ホストサービス
            - サブシステムにアクセスできるプロトコルを公開し、別のサブシステムから使えるようにするもの
            - RESTベースのリソースとして実現できる。RPC、メッセージング。
        - 公表された言語(Published Language)
            - コンテキスト間での共通の言語。コンテキスト間のれん系はPLを介して行われ、それぞれのコンテキストのモデルの言語へと変換して使用する。
            - XML、JSONなど
        - 別々の道
            - お互いにとって不可欠ではないなら、切り離す。
        - 巨大な泥団子
            - あるシステムの各部分がどれも大規模でモデルが混在しており、境界も辻褄が合わない。キレイにするのは諦めて、巨大な泥団子として扱い、その悪影響が他のコンテキストに及ばないようにする。
        - // コンテキスト間は「公開ホストサービス上」に流れる「公表された言語」でやり取りし、それぞれの受け口が「腐敗防止層」として働く、というイメージかなと思います。これによって、相対するサービスが巨大な泥団子のであったとしても、そのイケてない設計の影響を受けなくできる、ということかと。自分たちのサービスや主管組織、連携するサービス・企業などを上記の用語で整理することで、見えてくるものがありそう。この可視化による発見の創出こそが、コンテキストマップの役割なんでしょうね。

    - コンテキストマップにおける、上流・下流の意識は重要

- コラボレーションコンテキスト/アジャイルプロジェクト管理コンテキスト/認証・アクセスコンテキストとの統合
    - 自立性を確保するために、依存する別システムのオブジェクトの状態をキャッシュする。ただし、この時、まるごとキャッシュするのではなく、ローカルにドメインイブジェクトを作り、ローカルのモデルには必要最小限の状態だけを保持するようにして、別システムのオブジェクトを変換するようにするほうがよい。
    - コンテキスト間の連携の事例（バウンダリーオブジェクトや腐敗防止層についての例。各論なので記載しない）
    - RESTベースのリソースをローカルのドメインモデルのオブジェクトに変換するためのマップの作り方の例

## 3.2 まとめ
- 以下、本章を読んだ個人的見解のまとめです。
    - // 設計・実装状は、RESTであるとか、変換オブジェクトであるとか、色々あるが、「腐敗防止層」であるとか「公表された言語」であるとかの定義がなされた上で考えてみるのは面白いと思いました。
    - // コンテキストの関係を上流・下流を意識するのも良いですね。
    - // なお、割と具体的で各論的な内容が多かったので読書メモに書く内容が少なかった…。後で見返そう。
Raspberry Pi 2に日本語プログラム言語なでしこ3をインストールしてHello Worldする


Raspberry Pi 2に日本語プログラム言語なでしこ3をインストールして、 `こんにちは、世界` を出力してみました。

# 日本語プログラム言語なでしこ とは

[日本語プログラム言語なでしこ](https://nadesi.com/doc3/index.php?)(以下なでしこ)は、日本語でプログラミングできる言語です。
現在は2種類存在しており、Windowsで動くバージョン1と、Webブラウザ/Windows/Mac/Linuxで動作するバージョン3があります。今回はバージョン3を使います。

# 動作環境

今回使用したRaspberry Piは以下の通りです。

* モデル: Raspberry Pi 2 Model B
* OS: Raspbian 10 buster
* Linux カーネル: 4.19.75-v7+

# なでしこ3のインストール
なでしこ3の動作には、Node.jsとnpmが必要とのことです。
公式サイトのドキュメント [ラズパイで動かそう - なでしこ3](https://nadesi.com/doc3/index.php?%E3%83%A9%E3%82%BA%E3%83%91%E3%82%A4%E3%81%A7%E5%8B%95%E3%81%8B%E3%81%9D%E3%81%86) に従ってインストールしていきます。

まずはNode.jsをインストールします。この処理には6〜7分ほどかかるため気長に待ちましょう。

```bash

sudo apt-get install -y nodejs npm
```

インストールが終わったら、Node.jsを最新版に更新します。
画面にWARNが出力されてビビりますが、インストールされたバージョンが古いための警告ですね。

```bash
nakkaa@piwo1:~/nako $ sudo npm install n -g
npm WARN npm npm does not support Node.js v10.15.2
npm WARN npm You should probably upgrade to a newer version of node as we
npm WARN npm can't make any promises that npm will work with this version.
npm WARN npm Supported releases of Node.js are the latest release of 4, 6, 7, 8, 9.
npm WARN npm You can find the latest version at https://nodejs.org/
/usr/local/bin/n -> /usr/local/lib/node_modules/n/bin/n
+ n@6.1.3
added 1 package from 4 contributors in 4.452s
```
ドキュメントに従ってコマンドを実行していきます。

```bash
nakkaa@piwo1:~/nako $ sudo n stable

  installing : node-v12.14.0
       mkdir : /usr/local/n/versions/node/12.14.0
       fetch : https://nodejs.org/dist/v12.14.0/node-v12.14.0-linux-armv7l.tar.gz
   installed : v12.14.0 (with npm 6.13.4)

Note: the node command changed location and the old location may be remembered in your current shell.
         old : /usr/bin/node
         new : /usr/local/bin/node
To reset the command location hash either start a new shell, or execute PATH="$PATH"

nakkaa@piwo1:~/nako $ sudo ln -sf /usr/local/bin/node /usr/bin/node
nakkaa@piwo1:~/nako $ sudo ln -sf /usr/local/bin/npm /usr/bin/npm
nakkaa@piwo1:~/nako $ sudo npm update -g npm
```
いよいよなでしこをインストールします。

```
nakkaa@piwo1:~/nako $ time sudo npm -g install nadesiko3
/usr/local/bin/nako3server -> /usr/local/lib/node_modules/nadesiko3/src/nako3server.js
/usr/local/bin/cnako3 -> /usr/local/lib/node_modules/nadesiko3/src/cnako3.js
/usr/local/bin/nako3edit -> /usr/local/lib/node_modules/nadesiko3/tools/nako3edit/run.js
npm WARN css-loader@3.4.0 requires a peer of webpack@^4.0.0 || ^5.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN style-loader@1.1.2 requires a peer of webpack@^4.0.0 || ^5.0.0 but none is installed. You must install peer dependencies yourself.

+ nadesiko3@3.0.65
added 118 packages from 117 contributors in 37.128s

```

バージョン3.0.65が入りました。

# Hello Worldする
私はなでしこ1の文法しか知らないのですが、試しに文字を画面に出力してみましょう。

```bash

nakkaa@piwo1:~/nako $ cnako3 -e "「こんにちは、世界」と表示"
こんにちは、世界
```

動きましたね・・・！

次回はWebエディタを使ってみたいと思います。
Mysql8にデーター移行して行数取得でエラー

以下のソースをMysql5.6で実行してました。

```
select * from
(select id, @row:=@row+1 as row from tbl_a
where deleted_at is null or deleted_at <= '2019-12-28'
order by deleted_at desc
) st
where id = 12 limit 1
```

Mysql8で実行するとエラーが出てました。

```
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'row from tbl_a
where deleted_at is null or deleted_at <= '2019-12-28' at line 2
```

結論としてはMysql8からROW_NUMBER()関数が追加されて行数を簡単に取得できるようになったようです。だがそれでなんでエラーが出るのか「row」っていう予約語が追加されたのが原因でした。「ROWS」も追加されてますね。

参考：https://dev.mysql.com/doc/refman/8.0/en/keywords.html
参考：https://wpchiraura.xyz/mysql-80-reserved-word-list/
flutter iOSでビルドできない時の対処法

初めてQiitaに投稿してみます、、、

## 現象
* **flutter** と**Android Studio**を使い始めて数週間のペーペーです。
* simulator.appのiOSのシミュレータで、`run`を実行すると、以下のようなビルドの失敗が続くようになりました。

```
Launching lib/main.dart on iPhone Xʀ in debug mode...
Running Xcode build...
Xcode build done.                                           12.2s
Failed to build iOS app
Error output from Xcode build:
↳
    ** BUILD FAILED **

Xcode's output:
↳
    /build/ios/Debug-iphonesimulator/Runner.app: resource fork, Finder information, or similar detritus not allowed
    Command CodeSign failed with a nonzero exit code
    note: Using new build system
    note: Planning build
    note: Constructing build description

Could not build the application for the simulator.
Error launching application on iPhone Xʀ.
```

そこで、[こちらの記事](https://qiita.com/sakyoyuto/items/c109edcfbb5253b4227e) のように、iosディレクトリに移動して、

```
$ pod reset
```
を実行しても、同じエラーが出て解決せず。。。

## 解決方法
ターミナルで`flutter clean`を実行。

```
$ flutter clean
Cleaning Xcode workspace...                                         2.9s
Deleting build...                                                   17ms
Deleting .dart_tool...                                               1ms
```

## 感想
* これで、`run`が通ってビルドが成功したけど、一回切ってしまうと、次`run`する時にはこのエラーがまた出てきててしまい、毎回`flutter clean`するのは面倒だなぁ
* もっといい方法がありそう。。。
Poweredgeでメーカー調査に必要なログ収集の実施手順

#はじめに

以前の記事 (https://qiita.com/ydetectiveu007/items/f3c8913937771f2adb64) で，PSODを発生させてしまい，ベンダーに調査依頼をかけたところログを採取してくれと依頼されたので，そのログ採取の方法をメモしておく．

ベンダーからはiDRAC とESXi の双方からログを採取してくれと依頼されたので，その方法について記す．

#目次
- iDRAC からSupportAssit コレクション ログを採取する方法
- ESXi からvm-support ログを採取する方法
- おわりに
- 参考文献

#iDRAC からSupportAssit コレクション ログを採取する方法
iDRAC からSupportAssit コレクションのログを採取するには，iSMのVIBをホストにインストールする必要がある．iSMのインストールファイル自体は，DELLのサポートサイトからサービスタグを入力することで，該当のバージョンを入手することができる．

以下の手順にて，インストールする．

1. ESXiにssh にてログインする．
2. scpなどを用いて，ESXi にiSMのVIB ファイルをアップロードする．
3. 以下のコマンドにて，iSMをインストールする．

```:実行コマンド
# esxcli software vib install -d "【VIB ファイルのパスを指定する】"
```

以下のような出力結果が出れば，OKである．

```:インストール結果
Installation Result
   Message: Operation finished successfully.
   Reboot Required: false
   VIBs Installed: Dell_bootbank_iSM_3.2.0.ESXi6-1172
   VIBs Removed:
   VIBs Skipped:
```

インストール後，再起動の実施も必要ない．
次に，iDRAC のWeb インターフェースにログインする．
ログイン後，「メンテナンス」>「SupportAssist」>「収集の開始」を選択すると自動的にログの収集が開始される．ログの収集終了後，結果をまとめたファイルがダウンロードされるので，これでログの採取は完了である．

#ESXi からvm-support ログを採取する方法
最初に参考文献の2番目のサイトを勧められたが，諸事情によりvCenter Server とホストの連携前だったため，その方法を断念した．代わりに，3番目のサイトの方法を採用して，コマンドでログを取得することにした．

ESXi にssh でログインするところまでは同じで，ログ採取のために実行するコマンドは以下のとおりである．

```:実行コマンド
# vm-support
```

上記コマンドを実行すると，時間は要するが，自動的にログを収集し，一つのファイルにまとめてくれる．コマンドの実行終了後，当該ファイルのパスを"To see the files collected, run:" というメッセージとともに表示されるので，scpなどを用いて作業用のPCのローカルに保存すればよい．

# おわりに
はじめてやったことで，PSOD 発生からやや時間も経過しているので，ちゃんとログを採取できているかわからないが，とりあえず採取したログをベンダーに展開してみる．

#参考文献
- iDRAC 9を介して，PowerEdge 14Gを使用したSupportAssistコレクションとPERCログのエクスポート (https://www.dell.com/support/article/jp/ja/jpbsd1/sln306670/idrac-9%E3%82%92%E4%BB%8B%E3%81%97%E3%81%A6-poweredge-14g%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9Fsupportassist%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8perc%E3%83%AD%E3%82%B0%E3%81%AE%E3%82%A8%E3%82%AF%E3%82%B9%E3%83%9D%E3%83%BC%E3%83%88?lang=ja)
- vSphere Web Clientを利用したvm-support / vc-support取得手順 (https://www.dell.com/support/article/jp/ja/jpbsd1/how16880/vsphere-web-client%E3%82%92%E5%88%A9%E7%94%A8%E3%81%97%E3%81%9Fvm-support-vc-support%E5%8F%96%E5%BE%97%E6%89%8B%E9%A0%86?lang=ja)
- ftサーバ/VMware ESXi】ESXiホストのサポートログ採取方法 (https://www.support.nec.co.jp/View.aspx?NoClear=on&id=3150109801)
【Nuxt.js】SEO基礎編①：超簡単解説！5分でわかるSEO

# 前置き
**今回はSEO(検索エンジン最適化)について！**
Nuxt.jsと直接的な関係はありませんが、
Nuxt.jsで作ったwebサイトでも
SEOは大事ですからね🌟

超簡単に説明する、が当アカウントのモットー。
お猿さんでも分かるように書きました🍎🐒

# 1.心構え
**大事なのは
・ユーザーファーストの考え方と、
・価値あるページを作り、
・テクニカルなSEO対策をすること。**

閲覧数→CVRをあげることも必要だけど
そもそもの閲覧数がなければ繋がらない😞
検索順位の上位しか見られないし、、、

**とはいえ**
ただ検索順位を上げる手法だけ頑張っても×
閲覧数を上げても
ユーザーが求める物と違ったら意味がない。
ユーザーが求める物を価値あるサイトとして
見てもらえる土台が必要。

Google自体がユーザーファーストの考え方。
検索キーワードから
ユーザーが求めるものを把握し、
それに応えられるページを上位に出すよう日々改善。
これで順位が変わるようなら
それは良質なページとは言えません。
https://www.google.com/intl/ja/search/howsearchworks/mission/users/

**とはいえ**
良質なサイトでも
見てもらわなければ意味ない。
だから全部大事。

# 2.検索エンジンの仕組み
**検索順位を決める3step**
・クローリング
・インデックス
・ランキング

# 2-1.クローリング
**クローラーというロボットが
webサイト収集します👷‍♀️**
こいつに発見してもらわなければ
検索結果に載りません。
ただし全てのサイトを
常に収集してるわけではないです。
そんなことしたら過労で壊れる(?)

サイトができたからといって
すぐに発見してもらえるわけではない
クロールをするタイミングなど
Googleアルゴリズムは非公開なので、不明。

だから待つのではなく
こちらから気づいてもらうよう、
働きかけます💁
こういう手段があるんだ〜
と思ってもらえれば◎
**・見つけやすい動線を作る**
　ソーシャルメディアや
　他のwebサイトからの
　ナチュラルリンクを集める
**・収集して欲しいと通知する**
　サイトマップを送信をする
　 https://support.google.com/webmasters/answer/183668?hl=ja

# 2-2.インデックス
クローラーで集めたページを
データベースに登録することです。

そこでインデクサという
中間処理プログラムの出番。
生のHTMLデータを
検索順位と関連のある情報に整理して保存。
インデックスされてようやく
検索結果に表示されます🎈

超ざっくり言うと
こんな感じで情報を整理します。
「目次はこれか、
　リンクはこういうのが貼られてる、
　文章は単語に分けて
　キーワード解析しないと。
　どれどれ、ふうん。
　こんなことが書かれてますよ、っと。」

※インデックス確認検索コマンド
　site:ページのURL

# 2-3.ランキング
インデックスした情報を元にランキング。

# 3.SEOの要素
**これをやればユーザー満足度アップ！**
・コンテンツSEO🌟重要
・SEO内部対策
・SEO外部対策

# 3-1.コンテンツSEO🌟
コンテンツSEOが優れている
 = 良質な情報があるサイト

**良質なサイトにするための手順**
・検索キーワードを選定
・ロングテールSEO
・コンテンツデザイン
・モバイルフレンドリー

# 3-1-1.検索キーワードを選定
ユーザーが求める情報を
どんなキーワードにするか選定します。
検索キーワードと、
タイトルや内容が一致すれば満足度アップ✨

**Point!**
**・使用率が高いか**
　よく使われる馴染みのあるキーワードに。
　専門的な用語でも、
　より一般的な方が使われますね。
**・コンバージョンが期待できるか**
　売り上げに直接繋がるキーワードに。
　使用率がほぼ同じで
　異なる単語が2つあった場合
　当然コンバージョンが高い方が◎
**・関連性のあるキーワードも使用しているか**
　入り口を広げて流入数のアップに。
　関連キーワードは
　Googleオートコンプリートで確認できますね🌟

<img width="616" alt="スクリーンショット 2019-12-27 16.41.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/28cc9d6a-3f4d-dd07-50f3-c32362378271.png">


　
キーワードの効果はSearch Consoleで確認できます。
https://search.google.com/search-console/about?hl=ja

キーワードをピックアップに使えるサイト
こちらが参考になります！
https://keywordfinder.jp/blog/seo/tool10/

# 3-1-2.ロングテールSEO
2つ以上の単語で構成されるキーワード
検索率の高い一単語で上位表示を狙うのではなく
単語の組み合わせでニッチなキーワードを狙うこと。

**キーワードの種類**
**・ビッグキーワード**
　主に単体キーワード
　検索回数が多く、
　上位表示すれば多くの流入が期待できる
　 ＝競合も多く相対的に順位を上げにくい
**・ミドルキーワード**
　ビッグキーワードとスモールキーワードの中間
**・スモールキーワード**
　主に複数単語の組み合わせ
　検索回数、流入数は少ない
　 ＝競合性が低く相対的に順位を上げやすい

ニッチなキーワードの組み合わせで
結果的にビッグキーワードの流入数を
超えることもできます😲

**ロングテールSEOのやり方**
・そのキーワードを多く出現させる
・そのキーワードに対してページを分ける
　1ページに1テーマにする

# 3-1-3.コンテンツデザイン
主に文章の見た目を整えること。
検索エンジンとユーザーが
正しく文章を読めるように書きましょう✍️
**ユーザーが求める回答を、
簡潔に分かりやすい言葉で🍀**

# 3-1-4.モバイルフレンドリー
スマートフォンで正しく表示されるかどうか📱
簡単にいうと
レスポンシブ対応ができているかが基準です。

これによっても検索順位が変わります。
今やスマホは当たり前ですものね。
こちらでチェックが可能です。
https://search.google.com/test/mobile-friendly?utm_source=mft&utm_medium=redirect&utm_campaign=mft-redirect&hl=ja

評価はあくまでもページであり
サイト全体ではないようです。
サイトによって数ページのみ基準に満たない！
なんてことも。



今回はここまで。
大枠を捉えてもらえたら嬉しいです😄





このアカウントでは
Nuxt.js、Vue.jsを誰でも分かるよう、
超簡単に解説しています🎈😀
これからも発信していくので、
ぜひフォローしてください♪
https://twitter.com/aLizlab
【Nuxt.js】transition実践編：ページ遷移アニメーション

# 前置き
![picture_pc_0a2236abb0a08c9e71a0c46b6085fafd.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/469755/e0963c3e-1ac2-1b45-bc34-a8181972f2b9.gif)
ボタンだけのシンプルなページをほわっと表示。
今回の実践編では、
全てのページ遷移時でアニメーション🤗
これだけでもウキウキしますね🕺
基礎編もご覧ください。


# ページ遷移アニメーションを全体化しよう
【ディレクトリ の構造、ファイル名】
ページは下記の順番で遷移します。
index.vue → main.vue → sub.vue

```bash:file
assets/
--| scss
-----| common.scss

layouts/
--| default.vue

pages/
--| index.vue
--| main.vue
--| sub.vue

nuxt.config.js // common.scssを読み込ませる
```

【How to use】
基礎編でのtransitionの使い方を元に、
全てのページでアニメーションを適応するため
デフォルトレイアウトを使用します。
公式 pageTransition プロパティ参照です！
layoutTransitionはlayouts同士での
切り替えに使うので…
(layouts/default.vue → layouts/hogehoge.vue)
今回はpageTransitonのみです！
https://ja.nuxtjs.org/api/configuration-transition/

**v2.7.0〜**
nuxt.config.jsで
pageTransition記載が不要になりました！
超シンプルで簡単になりましたね🤗
デフォルトのname="layout"で反映させてます。

【layouts/default.vue】
PageTransitionを適応
・transitionタグに
　デフォルトのname="page"を記載
・<nuxt />をtaransitonタグで囲う

```layouts/default.vue
<template>
 <div>
   <transition name="page">
     <nuxt />
   </transition>
 </div>
</template>

<style>
</style>
```

【common.scss】
configで設定したnameを使って
アニメーションを設定するだけです🌟

```common.scss
 .page-enter {
   opacity: 0;
 }
 .page-enter-active {
   transition: opacity 2s;
 }
```

…終わりです😲
ページ遷移アニメーションと、
それを全体化させるだけならこれで終わり！
と〜〜〜っても簡単ですよね🍒
複雑なアニメーションをやるなら
CSSが1番大変ですよね…（ボソボソ）

あとはpagesにページ遷移を書き込みましょう✍️
スタイリングは省きます。
そのため遷移先のみ変えればOKです！


```index.vue
<template>
 <div class="container">
   <nuxt-link to="/main">MOVE</nuxt-link>
 </div>
</template>
```

```main.vue
<template>
 <div class="container">
   <nuxt-link to="/sub">MOVE</nuxt-link>
 </div>
</template>
```

```sub.vue
<template>
 <div class="container">
   <nuxt-link to="/">MOVE</nuxt-link>
 </div>
</template>
```

完成です🎉
意外とシンプルで簡単ですね♪

**このアカウントでは
Nuxt.js、Vue.jsを誰でも分かるよう、
超簡単に解説しています🎈😀
これからも発信していくので、
ぜひフォローしてください♪**
https://twitter.com/aLizlab
form_forで自動生成される<div class="field_with_error">を消す方法

## formへの入力でバリデーションエラーがあると自動生成される。

生成される位置

```html

<form>
 <input type="hidden">
 <input type="hidden">
 <div class="field_with_error">
  <input type="text">
 </div>
//以下略
```

でこいつの厄介なところはレイアウトに影響してくるというところで、

### これを

<img width="671" alt="スクリーンショット 2019-12-27 18.22.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553132/0b507f46-79a2-34b5-11a5-9774231af539.png">

### こんな風に崩してくる。

<img width="671" alt="スクリーンショット 2019-12-27 18.22.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/553132/3d0656ff-3974-7670-3bcb-905ec553e0e4.png">

で対処法を調べていたら

```rb:config/application.rb

module ChatSpace
  class Application < Rails::Application
    config.generators do |g|
    #中略
  end
```

ここに

```rb:config/application.rb

module ChatSpace
  class Application < Rails::Application
    config.generators do |g|
    #中略
    config.action_view.field_error_proc = Proc.new { |html_tag, instance| html_tag }

  end
```

これを記述すれば自動生成されなくなってレイアウト崩れも解決されます。
【HTML】spanとdivの違い

## span
:sunny: 文の中の一部分にCSSを適用させる
:sunny: ＜span＞～＜/span＞で囲った部分をインライン要素としてグループ化

:thinking: りんごの "ん" だけ文字を赤くしたい

```例.html
<p>り<span>ん</span>ご</p>
```

```例.css　
span {
  color: red;
}
```

<img width="70" alt="スクリーンショット 2019-12-27 17.31.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/67be2d2f-fedc-a877-c2cd-8d104c30bd72.png">

"ん"のみ赤くなりました:smile:

## span と div の違い
グループ化といえば div もそうだけど、何が違うかというと

span・・・＜span＞～＜/span＞で囲った部分をグループ化(インライン要素)
div・・・＜div＞～＜/div＞で囲った部分をグループ化（ブロックレベル要素）

イメージとしては・・・

div
↓
<img width="80" alt="スクリーンショット 2019-12-27 17.51.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/4bb3328e-0ce1-f878-3f9d-14815f91eb46.png">

span
↓
<img width="75" alt="スクリーンショット 2019-12-27 18.11.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/dfaa738c-0088-f89a-a604-3cfb3650a821.png">

div はブロックレベル要素をグループ化しているので、そのブロックにCSSを適用（赤文字）
span は囲った文字をグループ化して、その囲った部分にCSSを適用（赤文字）

div でフルーツという大枠のブロックに対して赤文字にするか、
span でみかんの "か" にのみローカル部分を赤文字にするか。
そんな感じ。


ちなみに span も div と一緒で class が使用できます:smile:
(随時更新) 役に立ったプログラミング＆技術書籍とサイト

#  役に立ったプログラミング＆技術書籍とサイト
タイトル通り、 役に立ったプログラミング＆技術書籍とサイトを随時更新、ご紹介させていただきます。ドットインストールから、NewsPicksまでいろんな角度から。

# 書籍、電子書籍
## AmazonWebServices基礎からのネットワーク＆サーバー構築改訂版
ハンズオン学習に最適で、無事にAWSを使って、webサーバーとデータベースサーバーをクラウド上で構築することが出来ました。HTTP、SSH接続、DNSといったWeb業界で必須の基礎知識も学べます。

(著者）玉川憲,片山暁雄,今井雄太,大澤文孝

## Python言語の基本から仕事のやり方まで独学プログラマー
Pythonをざっくりと学ぶのに役に立った本書。書店に寄ったところ、ベストセラーだったので即購入。
（著者）コーリー・アルソフ 

## PHPフレームワーク　Laravel入門
Laravel関連で有名な一冊。MVCモデルの詳しい説明あり。

## JavaScript本格入門

## HTML＆CSSとWebデザインが1冊できちんと身につく本

(著者）服部 雄樹

# webサイト、サービス
## ドットインストール
ど定番、ドットインストール。1本の動画が短いので、隙間時間に利用。まとめて動画を見るときは、倍速でイッキ見。

##Railsチュートリアル
日本語版です。
https://railstutorial.jp/
# 番外編
## NewsPicks
ニュースキュレーションの雄、Newspicks。シリコンバレー発の最新ITニュースだけでなく、金融、経済等、一歩先を行きたいビジネスパーソンにとって効率よく情報収集できる。公式アプリがオススメ。動画コンテンツも多く、落合陽一氏のweekly ochiaiも面白い。


### 学習の役に立った、オススメの書籍、webサービスのみ随時更新していきます！
簡単！jQueryでページ内リンクをスムーススクロールする方法

LPやページが長い時によく使われるページ内リンクをスムーススクロールさせる方法を備忘録もかねて書きます。
この記事のコードをコピペして実装してみてください！


早速、
##HTML
```html
 <ul>
    <li><a href="#section1">SECTION1</a></li>
    <li><a href="#section2">SECTION2</a></li>
    <li><a href="#section3">SECTION3</a></li>
    <li><a href="#section4">SECTION4</a></li>
    <li><a href="#section5">SECTION5</a></li>
  </ul>
  <div id="section1" class="box"><p>SECTION1</p></div>
  <div id="section2" class="box"><p>SECTION2</p></div>
  <div id="section3" class="box"><p>SECTION3</p></div>
  <div id="section4" class="box"><p>SECTION4</p></div>
  <div id="section5" class="box"><p>SECTION5</p></div>
```

各ボタンとリンク先のdivを記述しています。

##CSS
```css
ul{
  display: flex;
  padding:40px 0 0;
}
ul + div{
  margin-top:30vh;
}
ul li{
  list-style-type: none;
  padding-right:20px;
  padding-left:0;
}
ul li a{
  text-decoration:none;
}
div.box{
  height:300px;
  width:100%;
}
div.box p{
  font-size:24px;
}
.box:nth-child(2){
  background-color: #9FA1D9;
}
.box:nth-child(3){
  background-color: #CBB5DB;
}
.box:nth-child(4){
  background-color: #E3E4F5;
}
.box:nth-child(5){
  background-color: #8778D7;
}
.box:nth-child(6){
  background-color: #9B9BAB;
}
```
こちらのcssの記述は実装した時に分かりやすいように書いているだけなので、確認した後に消してください！！

##script
```js
 $(document).ready(function () {
      $('a[href^="#"]').click(function() {
        var offsetTop = 0;
        var scrollSpeed = 400;
        var href= $(this).attr("href");
        var target = $(href == "#" || href == "" ? 'html' : href);
        var scrollPosition = target.offset().top + offsetTop;
        $('body,html').animate({scrollTop:scrollPosition}, scrollSpeed);
        return false;
      });
    });
```

下記で簡単に解説をします！


###イベント発動
 ```js
$('a[href^="#"]').click(function() {
```
こちらはaタグがクリックされたらイベントが発動します。
対象要素の`$('a[href^="#"]')`と記述されている部分ですが、
「#から始まるhref属性を持つaタグ」をクリックしたらイベントが発動するという記述になります。


###変数に値を代入
```js
var offsetTop = 0;
var scrollSpeed = 400;
var href= $(this).attr("href");
var target = $(href == "#" || href == "" ? 'html' : href);
var scrollPosition = target.offset().top + offsetTop;
```

各変数に値を代入しています。

・`var offsetTop = 0;`
→リンク先の要素の画面上部からの位置を調節します。

・`var scrollSpeed = 400;`
→スクロール開始してから移動先までの時間を指定します。

・`var href= $(this).attr("href");`
→クリックされたaタグのhref属性の値を変数に代入します。

・`var target = $(href == "#" || href == "" ? 'html' : href);`
→これは三項演算子という条件分岐です。上記で`href`に代入された値によって、hrefの値が変わります。
hrefの値が`#`もしくは`'（空）'`の場合は`$('html')`を変数に代入
hrefの値が`#`もしくは`'（空）'`***以外***の場合は`$(href)`を変数に代入

・`var scrollPosition = target.offset().top + offsetTop;`
→移動先の位置を指定しています。

###スクロールのアニメーション
```js
$('body,html').animate({scrollTop:scrollPosition}, scrollSpeed);
return false;
```

`scrollTop`に値(scrollPosition)を指定してスクロールさせます。スクロールスピードは先ほど指定した400ミリ秒です。
そして`return false;`を指定することによってaタグのデフォルトの機能（リンク機能）を消しています。

##まとめ

scriptの説明では分かりづらい単語もありましたが、必要に応じて調べていただければと思います。
説明部分で足りないところや、scriptでもっとこうした方がいいよー！などお意見をいただけたら嬉しいです！
勉強一ヶ月で ISTQB Foundation Levelを通った話

# はじめに
皆さんこんにちは！ LIFULL SET(Software Engineer in Test)グループの@rueyjyeです。

最近はテスト関連の資格を受けようと思いまして、その際に[ピアソンVUE](https://www.pearsonvue.co.jp/)の存在を知りました。
ピアソンVUEは世界中の資格認定団体を提供したテストをピアソンVUEが契約したテストセンターで受けれるサービスです。

今回は実際にISTQBの資格試験の受け方法と、個人の勉強の仕方を紹介したいと思います。

# なぜISTQBを受けるか
SETと関わる資格といえば、自動テスト周りの[ISTQB Advanced Level Test Automation Engineer](https://www.istqb.org/certification-path-root/test-automation-engineer.html)だと思いました。
これを受験するためにはISTQBのFoundation Level資格が必要です。

日本にも[JSTQB](http://jstqb.jp/index.html)主催のFoundation Levelの試験もありますが、JSTQBではAdvanced Level Test Automation Engineer資格の試験は今の段階では受けられません。
※現時点JSTQBで受けられる資格はFoundation Level、Advanced Levelテストマネージャ、Advanced Levelテストアナリストのみです
※テストセンターでISTQBの受験可能日もJSTQBより多いです。(ほぼ毎日受けられる)

英語の方がもっと汎用的に使えるじゃないかなと思いましたので、ピアソンVUEを経由して先にFoundation Levelの試験を受けました。

# ISTQB試験を受ける方法
ピアソンVUEで試験を受ける流れについては下記の記事を参考すればいいと思います。
[ピアソンVUEでAWS認定試験を受けてきた](https://qiita.com/amamillen/items/79bcc20973afac94adeb)

この記事はISTQB試験を受ける方法を紹介します。
最初はピアソンVUEのサイト内でISTQB試験を見つからなくて詰まりました。
実はISTQB資格試験のプロバイダは[Brightest](https://home.pearsonvue.com/brightest)と[iSQI](https://home.pearsonvue.com/Clients/iSQI.aspx)二社でした。

1. [トップページ](https://www.pearsonvue.co.jp/)で「受験者ホーム」を選択
![スクリーンショット 2019-12-27 17.51.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189885/b6d3301f-6ce1-e0f6-116d-e1a63beed578.png)


2. [プロバイダ](https://www.pearsonvue.co.jp/test-taker.aspx)を「Brightest」を選択
<img width="1000" alt="スクリーンショット 2019-12-27 14.11.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189885/24f1abbf-203f-c9ba-43af-405cf11f6873.png">

3. [Brightest](https://home.pearsonvue.com/brightest)のページで受けれるISQTBの資格リストが書かれています
<img width="1000" alt="スクリーンショット 2019-12-27 14.18.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/189885/6fc95a2d-a06a-a657-18d4-114aff06653a.png">

4. 続けてはアカウントを登録し、試験別や試験日などの選択すればテストの予約ができます。

# 勉強の仕方
私が今回メインで勉強した方法は、Youtubeの動画を見ることです。
[ISTQB FOUNDATION 2018](https://www.youtube.com/playlist?list=PLj5VKaW115t1o1hk5ZbNWFr4sW5mBpvmv) このプレイリストがおすすめです。(全部英語です)

このプレイリストはNeeraj Kumar Singhという方の[チャンネル](https://www.youtube.com/channel/UCoFMLIAopJAUmYmiWKI7PXQ)から提供しているものです。
Neeraj Kumar Singh氏は様々な組織でテストのトレーナーをやっていたため、すごく教えるのが上手な方です。
1動画が10分前後の長さなので、見やすいし、ちょうどいい粒度で各章のポイントをスライドでまとめています。
全部英語ですが、字幕をオンにすれば停止して、聞き取れなくても簡単に調べられます。

私は動画を全部見まして、更に自分のノートに整理しました。
ノートは復習の時に見やすいので、個人的にはよかったと思います。

動画以外、公式の[練習問題](https://www.istqb.org/downloads/category/2-foundation-level-documents.html)の三回分もやりました。問題と答えを全部理解し、1時間で40問を解く試験時間にも慣れました。

私の場合はこれで十分でしたが
自分の英語レベルとテスト関する知識の習得具合を見て試験に挑戦しましょう！
※ 私は英語が第2言語、日本語は第3言語です。

# Foundation Level試験のTips
Tipsじゃないかもしれませんが、私が受けた時はこんな感じでした。（次も同じかは保証できません)

1.　練習問題とほぼ同じ問題がありました (ただし完全に同じではなく、選択肢の順序や説明は少しだけ違う)
2.　問題は第一章から第六章の順番でした
3.　第四、第五章の問題は20問ぐらいありました　(50%の問題はここですね)

# 最後に
テスト終了の時点ですぐ点数が分かります。無事に通りました！
認定証明書も翌日にメールで届きました。

テストセンターでいろんな試験が受けられるになりましたので、すごく便利だと思いました。
JSTQBの場合は年2回くらいしか受けられない試験でもISTQBをテストセンターで受ける場合は基本毎日受けられます。これが一番いいところだと思いました。
さらに、ISTQBでしか受けられない試験が受けられる点も良い点です。

今回はピアソンVUE経由して、 ISTQB Foundation Levelを受験する方法と勉強の方法を紹介しました。
この記事を読んで、同じISTQBを受けようとしている方の役に立てればと思います。
初心者がGitHubでJavaScriptのコードを書き換えるまでにやったこと

笹澤さんのところでプログラミング開発の練習をさせていただいている、茨城大学の浅野です。

GitHubなどは全くの初心者であった自分が、GitHubでJavaScriptのコードを書き換えるまでに至った流れを書いておきます。

可能な限りGitHub初心者の人にも伝わる言葉で書くことを目標に頑張ります。
#1. そもそもGitHubって何って話から
GitHub（ギットハブ）って何だろうというところから始めます。

GitHubとは...

「GitのHub」です。

怒らないでください。

でもこの認識結構大事みたいで、GitとGitHubってどうやら違うみたいなんです。
##1.1. Gitとは「みんなで編集しやすいシステム」
仕切り直して、Gitって何だろうというところから始めます。

Gitとは「みんなで一つのファイルを編集しやすいようにしてくれるシステム」のことです。

ファイルでは説明しづらいので、みんなで小説を書くことを考えてみます。

##1.2. 小説をみんなで書くことで考えるGit
Aさん、Bさん、Cさんの3人で一つの小説を書きあげることを考えます。

Aさんが導入の部分を書き上げたとします。

Aさんは「導入」と書かれた封筒に導入の原稿を入れておきました。

次の日にBさんが導入を少し書き直して、自分が書いた本文の原稿と一緒に封筒の中に入れておきました。Aさんが書いた導入は、Bさんによって書き直されてしまったので、もう読むことはできません。

Cさんがその封筒を見たとき、どう見えるでしょうか。

「Aさんが作った導入と書かれた封筒」の中に「Aさんが書き、Bさんが書き直した導入」と「Bさんが書いた本文」が入っていることは、なかなか伝わりにくいでしょう。

また、Aさんが書いた導入を復元することはBさんにしかできません。どこを書き換えたのかを知っているのはBさんだけだからです。

このような「集団で一つの文書を編集する」ことに対して、「誰が何をいつしたのか」を記録しつつ、取り組みやすくしてくれるのがGitという仕組みなのです。

##1.3. GitHubとは
改めてGitHubとは何かというと...

GitのHubなわけです。

Hubは「ハブ空港」とか「ハブ配線」とかいうときのハブです。

ハブは中心地とか結節点とかの意味ですね。

いろんな人たちのGitが集まっているWebサービスが「GitHub」なわけです。

#2. 開発環境を導入する
それでは早速GitHubを利用するときに使うものをインストールなどしていきます。

##2.1. 使うもの
###1.Node.js
Javascript プログラムを開発するのに必須なプログラムです。
https://nodejs.org/ja/
###2.Git
ソースコードを管理するのに必要なプログラムです。先述したGitという仕組みを利用するのに必要なものです。
https://git-scm.com/
###3.Visual Studio Code
ソースコードを書くエディタです。プログラミングを書く専用のメモ帳のようなものです。
https://code.visualstudio.com/
###4.Sourcetree
必ず必要ではありませんが、2のGitはそのままでは使いにくいので、簡単に作業を行うためのソフトです。（個人的には必須。）
https://www.sourcetreeapp.com/

#3. 実際にGitで作業する
さて、上記のソフトを用いてGitHubにあるJavaScriptのコードを書き換えてみたいと思います。

先に断っておくと、詳細な工程ではありません。あくまで「初心者がGitHubでJavaScriptのコードを書き換えるまでにやったこと」であることに注意です。
##作業の手順
###1.コードをGitHubから自分のパソコン内に複製する
![スクリーンショット 2019-12-27 17.43.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142847/7fabafd0-6396-b670-d5ec-43ab2b30f8f6.png)

①GitHubの「clone or download」のタブでURLをコピー
②コマンドプロンプトで「git clone -b develop ~~①のURL~~」と実行

これで自分のパソコン内に複製されます。

###2.自分のパソコン内でコードを書き換えてみる

①Visual Studio Codeで先ほど複製したフォルダを開く
②フォルダ内のコードを書き換えてみる

これで自分のパソコン内のコードを書き換えました。

###3.一時保存する

![スクリーンショット 2019-12-27 17.54.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142847/2ebcb394-a675-dee7-3b72-f9f1b1deab20.png)

①Sourcetreeで自分のパソコン内のフォルダをAddする
→Addすると、変更が加えられたときに「やらないといけないリスト」みたいな感じでまとめてくれます。

###4.変更した内容はどんな内容なのか記録する

![スクリーンショット 2019-12-27 17.56.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142847/42e3ee92-304e-32ff-4b7f-b2ac479614a6.png)

①作業ツリーの中からインデックスに追加（＋ボタン）
②下の空欄に変更内容を書いて、コミットする

###5.自分のパソコン内のコードでGitHubのコードを置き換える

①プッシュタブから、GitHubのコードを置き換える。

これで一連の流れは終わりです。

#4. さいごに

書いてみると全然分かりやすく書けなかったです。(笑)

でもこうして詳しいことがわからなくても、JavaScriptのコードをGitHubというWebサービスを通じて書き換えることができると、「分からないことが分かるようになる」と思います。

それであれば、あとは調べたり勉強するだけです。

環境の導入など、最初の第一歩の手助けになれば幸いです。
サインアップ　サインイン機能の実装

目標物はこちら

[![Image from Gyazo](https://i.gyazo.com/4f5e8518041822dea1742194425394f5.png)](https://gyazo.com/4f5e8518041822dea1742194425394f5)
↑サインアップ画面

[![Image from Gyazo](https://i.gyazo.com/95b26478d4f28981fd1495be1d0426ae.png)](https://gyazo.com/95b26478d4f28981fd1495be1d0426ae)

↑サインイン画面

目標物を作成するまでの流れ
１、DeviseのGemをインストール
２、Deviseのビューファイルをインストール
３、Userモデルを作成
４、Usersテーブルを作成
＊フラッシュメッセージ追加など必要に応じて行います

# 1、DeviseのGemをインストール
まず今回はDeviseを導入しますので　deviseの公式ドキュメントにアクセスします
公式ドキュメント）　https://github.com/plataformatec/devise
アクセスしたら「Getting started」の箇所を見る

[![Image from Gyazo](https://i.gyazo.com/5b59248b3983e461ff2e7eac7a07afbb.png)](https://gyazo.com/5b59248b3983e461ff2e7eac7a07afbb)

「Add the following line to your Gemfile」とあるので、まずGemfileの最下部に以下のコードを追加します。


```ruby:Gemfile
gem 'devise'
```
##### ターミナル

```
$ bundle install
```
次に「Next, you need to run the generator」と公式ドキュメントにあるように以下のコマンドを実行

##### ターミナル

```
$ rails generate devise:install
```
deviseを使う際はdevise用のコマンドを打つ必要があり、それが↑のコマンドです。
＊deviseで使用するモデルを作成するときは、rails g modelのような通常のモデル作成とはコマンドが異なります。
ターミナルに以下の表示が出てくるはずです。
こちらがdeviseを使う際の初期設定です
[![Image from Gyazo](https://i.gyazo.com/2122583884fdb175fdb39a6c1bd181c8.png)](https://gyazo.com/2122583884fdb175fdb39a6c1bd181c8)
１番　　→パス
２番　ルーティングの設定　→確認
3番　フラッシュメッセージを実装する場合　指示通り　app/views/layouts/application.html.hamlに修正を加えます。
#2、Deviseのビューファイルをインストール
４番　Deviseのビューファイルのダウンロードです。ターミナルで表示されている通り以下のコマンドを実行します。

```
$ rails g devise:views
```
[![Image from Gyazo](https://i.gyazo.com/e080ff5f2a8983d70e9e1a3b0d317085.png)](https://gyazo.com/e080ff5f2a8983d70e9e1a3b0d317085)
このようにビューファイルが生成されます。
# Userモデルを作成
devise用のモデルを作成します。名前は任意ですが今回はUserで作成します。
##### ターミナル
```
$ rails g devise User
```
[![Image from Gyazo](https://i.gyazo.com/8cd4466f36bdb841284088dd251fc078.png)](https://gyazo.com/8cd4466f36bdb841284088dd251fc078)

# ４、Usersテーブルの作成
Userモデルを作成した際にdb/migrateフォルダ内にマイグレーションファイルが生成されています。
とりあえず初期設定のまま　rails db:migrate を実施します

```
$ rails db:migrate
```
すると
[![Image from Gyazo](https://i.gyazo.com/88bb55d3119521598ffabbb033955a14.png)](https://gyazo.com/88bb55d3119521598ffabbb033955a14)

という画面になります
サーバーをcontroll+cで切って　rails s で再起動
http://localhost:3000/users/sign_up にアクセスして表示を確認します。
サインインの場合は
http://localhost:3000/users/sign_in で表示を確認します。
日報スプレッドシートにBacklogAPIから課題データを取得する

## はじめに

Backlogの課題と日報の紐付けをしたいという要望があり、作成しました。

## スクリプトエディタを開く

新しくスプレッドシートを作成し、
ツール > スクリプトエディタ からスクリプトエディタを開く

## プログラム作成

スクリプトエディタで下記プログラムを作成

```javascript

/**
 * 編集時に発動
 **/
function task_action() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
​
  // 日報以外のシートはスルー
  if (sheet.getName() != '日報') {
    return;
  }
​
  var range = SpreadsheetApp.getActiveRange();
​
  // A列目以外の編集はスルー
  if (range.getLastColumn() != 1) {
      return;
  }
​
  // 入力したキーからデータ取得
  var key = range.getDisplayValue();
  set_task_data(key, range);
}
​
/**
 * BacklogAPIからデータを取得して反映する
 **/
function set_task_data(key, range) {
  if (key == "") {
    return;
  }
​
  // B(作業日)
  var d = new Date();
  range.offset(0, 1).setValue(Utilities.formatDate(d, 'Asia/Tokyo', 'yyyy/MM/dd'));
  SpreadsheetApp.flush();
​
  // C(作業者)
  var username = get_name();
  range.offset(0, 2).setValue(username);
​
  try {
    // Backlog課題取得
    var data = get_api_data(key);
​
    // D(種別)
    range.offset(0, 3).setValue(data["issueType"]["name"]);
    // E(作業内容)
    range.offset(0, 4).setValue(data["summary"]);

  } catch(e) {
    Browser.msgBox(e.message);
    log(e.message + "\n" + e.fileName + ".gs : " + e.lineNumber + "\nstack:\n" + e.stack);
  }
}
​
/**
 * BacklogAPIデータ取得
 **/
function get_api_data(key) {
  var HOST = PropertiesService.getScriptProperties().getProperty("BACKLOG_HOST");
  var API_KEY = PropertiesService.getScriptProperties().getProperty("BACKLOG_API_KEY");
​
  var url = HOST + "/api/v2/issues/" + key + "?apiKey=" + API_KEY;
​
  var fetch = UrlFetchApp.fetch(url);
  var data = JSON.parse(fetch.getContentText());
​
  return data;
}
​
/**
 * 編集者のメールアドレスから名前を取得
 **/
function get_name() {
  var name = '';
  var email = Session.getActiveUser().getEmail();

  switch(email) {
    case 'testA@test.com':
      name = 'テストA';
      break;
    case 'testB@test.com':
      name = 'テストB';
      break;
    default:
  }
  return name;
}
```

## API情報の保持

ファイル > プロジェクトのプロパティ > スクリプトのプロパティ で下記保存

BACKLOG_HOST : [BacklogAPI]
BACKLOG_API_KEY : https://xxxxx.backlog.jp

## トリガー追加

編集 > 現在のプロジェクトのトリガー > トリガー追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536619/0618a74a-f41c-ed4b-380f-bd1f5eb550cd.png)

実行する関数を選択 : task_action
デプロイ時に実行 : Head
イベントのソースを選択 : スプレッドシートから
イベントの種類を選択 : 編集時
保存

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536619/a035c883-9479-3570-667c-8fba2cff7690.png)

## 実行

A列にBacklogのキーを入力すると、内容をAPIで取得して表示する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536619/2b2c1505-9766-794e-d947-92943fc674de.png)

## さいごに

毎日日報入れるの面倒だった。
引き継いで使ってくれるのかな。
もっと便利なツールがあればいいなと思った。
初心者でも簡単にわかる！Photoshop(フォトショップ)とIllustrator(イラストレーター)の違いや特徴と使い方

# あなたは、Photoshop(フォトショップ)とIllustrator(イラストレーター)の使い分けができますか？
## 初心者でも簡単わかる！Photoshop(フォトショップ)とIllustrator(イラストレーター)の違いや特徴と使い方
Webデザイナーが使用している有名なデザインツールに、Photoshop(フォトショップ)とIllustrator(イラストレーター)というものがあります。

Photoshop(フォトショップ)とIllustrator(イラストレーター)のどちらもアメリカの会社のアドビ社が提供している制作ソフトです。

特に初心者の方には、この二つの違いがよくわからず、混同されている人もいると思います。

初心者の方向けに、Photoshop(フォトショップ)とIllustrator(イラストレーター)の違いと特徴、簡単な使い方も説明します。
## Photoshop(フォトショップ)の違いや特徴と使い方
Photoshop(フォトショップ)は頭文字をとって「Ps」と呼ばれたりもしています。

Photoshop(フォトショップ)、通称「フォトショ」の特徴です
### Photoshop(フォトショップ)は写真や画像の加工が得意
フォトショップは写真加工・合成が得意です。

また、絵画や本格的なグラフィック制作も可能で、プロに愛用されています。
### Photoshop(フォトショップ)のデータはピクセル単位でのデータ処理
フォトショップのデータは、ピクセル単位でデータの処理されます。

点の集まりでできた画像を、ビットマップ画像と呼ばれています。

ラスター画像とも呼ばれています。

フォトショップは、ビットマップ画像を扱うソフトです。

ビットマップ画像の特徴は、細かい画像の切り抜きや色味の調整、形の変化をつけることが可能なことです。

また、ビットマップ画像は立体感のあるグラフィックも表現できます。

また、フォトショップは写真加工のソフトなので、写真を多用したデザインも得意としています。
### Photoshop(フォトショップ)を使う職業の一例
フォトショップを使う職業の一例として、Webデザイナー、フォトレタッチャー、グラフィックデザイナー、CGデザイナーなどがあります。
## Illustrator(イラストレーター)の違いや特徴と使い方
Illustrator(イラストレーター)は頭文字をとって「Ai」と呼ばれたりもしています。

Illustrator(イラストレーター)、通称「イラレ」の特徴です。
### Illustrator(イラストレーター)は製図・レイアウトが得意
イラストレーターは、ロゴやレイアウト、図表やグラフ作成に最高のツールです。

ポスターやチラシ作り、紙面デザインにも多用されています。

ポスターだけでなく、イラストを描く、Webページ制作用の素材を作る、アプリのグラフィックを描くことにも適しています。
### Illustrator(イラストレーター)のデータはベクターデータを利用
イラストレーターは、ベジェ曲線で描くパスでできたベクター画像を扱うソフトです。

言い換えると、画像を数値で記録し、図形をコードで表現したデータです。

ベクターデータのいい所は、どんなに拡大や縮小をしても綺麗に表現できる所です。
### Illustrator(イラストレーター)を使う職業の一例
イラストレーターを使う職業の一例として、イラストデザイナーやDTPデザイナーが代表的です。
眺めて覚えるGo言語 その6 可変引数

#Go言語で可変引数を使う。
### では、眺める例題

```main.go
ackage main
import(
	"fmt"
	"reflect"
)
func f(args ...interface{}){
	for i,arg:=range args{
		fmt.Println(i,reflect.TypeOf(arg),arg)
	}
}
func sum(a int,b int) int{
	return a+b
}
func main(){
	f(10.0/3,10,20,30,"Tokyo",sum,sum(5,10))
}

0 float64 3.3333333333333335
1 int 10
2 int 20
3 int 30
4 string Tokyo
5 func(int, int) int 0x4bb2a0
6 int 15
Process exiting with code: 0

```
###注目すべき書き方 
-**args ...interface{}**
可変引数
**f(10.0/3,10,20,30,"Tokyo",sum,sum(5,10))**

 - 10.0/3 実数を渡す
 - 10,20,30 整数を渡す
 - "Tokyo" 文字列を渡す
 - sumは、関数を渡す
 - sum(5,10)は、関数の答えを渡す

##変数の取り出し方

```f.go
func f(args ...interface{}){
	for i,arg:=range args{
		fmt.Println(arg)
	}
}
```
**for range で取り出す**

###応用問題　fmt.Printlnに書き疲れたら

```main.go
package main
import(
	"fmt"
)
func main(){
	for i:=0;i<10;i++{
		p(i,"hello world")
	}	
}
func p(a ...interface{}){
	fmt.Println(a...);
}

0 hello world
1 hello world
2 hello world
3 hello world
4 hello world
5 hello world
6 hello world
7 hello world
8 hello world
9 hello world
Process exiting with code: 0
```
#「いいね」ボタン押してね! :relaxed:
qiita2review 内部のスクリプトの解説

# qiita2reviewとは

複数の Qiita 記事から Re:VIEW経由で 書籍としての PDF を作成するためのプログラムです。
Web経由で動かすことができ、以下で紹介しています。

qiita2reviewの使い方
https://qiita.com/nanbuwks/items/5625acb49580084696c5
Re:VIEW を apache で動かす
https://qiita.com/nanbuwks/items/dd15819ec7798a9eca7b

# スクリプト

Web画面のうち、主要なものはcompile.phpですが、そこで以下の処理が行われます。

- qiitaからの記事のダウンロード
- 画像のダウンロード
- markdown から re ファイルへの変換
- pdfファイルへの変換

これを行うのは qiitaget.sh というシェルスクリプトです。

あらかじめ、著者名、Qiitaの記事のURLなどを yaml ファイルにして指定しておき、
アーティクル名を引数にして qiitaget.sh を呼ぶと以下のような処理が行われます。


```

URL=`ruby -Ku ../../makeurl.rb` # qiita記事のURLを取得する
echo $UR


rm qiita.md  # 前回実行時のテンポラリファイルを削除 デバッグのためにテンポラリファイルは削除されない
rm qiitaall.md  # 前回実行時のテンポラリファイルを削除 デバッグのためにテンポラリファイルは削除されない
wget $URL.md -O qiitaall.md # qiita 記事を取得する
# change qiita md old format 
sed -n 2p qiitaall.md | sed s/"title: "// > qiita.md # 記事からタイトル名を抜き出す
tail -n +7 qiitaall.md >> qiita.md # 記事から本文を抜き出し、タイトルと合体する

cd images # イメージ保存フォルダへ移動
# wget $URL -k -H -r -l 1 -nH -nd -A png,PNG,jpg,JPG,jpeg,JPEG,html  -R txt 
cat ../qiita.md | awk 'match($0, /!\[(.*)\]\((.*)\)/, a) {print a[2]}' > images.list # qiita記事からイメージ画像URLリストを作成
wget -N -i images.list # イメージ画像を取得
cd ..

# qiita md file to local md file.
# 4つのパイプをつなげ、qiita.mdからtemp.mdアーティクル名.mdを生成する
# パイプ1 記事段落レベルを全体に1つ下げる
# パイプ2 ![foo](https://a/b/c/d.jpeg) を ![foo](images/d.jpeg)に変換
# パイプ3 「```math」、「```」、「[:blank:]」の処理
# パイプ4 インラインTeX数式の処理
sed "s/^#/##/"  qiita.md | ruby -Ku ../../qiitamd.rb | ruby -Ku ../../texblock.rb | ruby -Ku ../../texinline.rb   > temp.md

# アーティクル名.md の作成
# タイトルを抽出して段落レベル1とする。
head -1 temp.md | sed "s/^/#/" > $1.md
# 著者をつける（コメントアウト中）
# Because single author case, to make author section is manually.
# ruby  ../../makeauthor.rb  >> $1.md
# 本文をつける
tail -n +2 temp.md >> $1.md

# extention markdown to review command
# 4つのパイプをつなげ、Markdown から review ファイルを生成する
# パイプ1 コードブロック中の「\@」、「\\」を処理
# パイプ2
#    [](review://pagebreak) →  //pagebreak
#    [](scale=0.5)![aaa](images/bbb.jpg) →  [scale=0.5]![](images/bbb.jpg)
#    ![aaa](imagesbbb.jpg) →  ![](images/bbb.jpg)
#    インラインコードを除外するのが大変！
# パイプ3 review付属のMarkdown → review コンバータ
# パイプ4 [scale=0.5]//image[bbb][]{\n//} → //image[bbb][][scale=0.5]{\n//} 

ruby ../../escapeincode.rb $1.md | ruby ../../preprocess.rb |  md2review | ruby -Ku ../../scalemd.rb > $1.re

rake pdf # pdf作成
mv book.pdf $1.pdf # アーティクル名.pdfにリネーム
```
Webプログラミング初心者が知っておくべきモダンな技術＆知識

# Webプログラミング初心者が知っておくべきモダンな知識
何から学習を進めていいかわからない初心者へ。
モダンなWebプログラミングに必要な知識をざっくり全体的にまとめて見ました。
内容はあくまでも、私の独断なので、皆様からのご指導、ご指摘お待ちしております！
# インプットとアウトプットのバランス
学習におけるインプットは言うまでもないですが、ハンズオンによるアウトプット学習を優先しましょう。イメージとしては、アウトプットするために、必要な知識をインプットする感じです。最速で効率よくアウトプットするため、漠然とインプットしないことも大事です。
ボトムアップよりも、トップダウン的な考え方です。
#Webプログラミングに必要な知識、ソフト、ツール等
##OS
Mac OS, Linux (Windowsでももちろんokですが、web系はMacユーザーが多いイメージです）
## フロントエンド言語(マークアップ言語含む)
HTML5,CSS3(可能ならSass),Javascript(ES6)
## バックエンド言語
PHPまたはRuby
## フロントエンドフレームワーク＆ライブラリ
Bootstrap4, JQuery, React.js(Vue.jsまたはAngular.js)
## バックエンドフレームワーク＆ライブラリ
Laravel(PHP)またはRails(Ruby)
## データベース
MySQL,SQlite
## Amazon web service
AWS EC2, AWS Lightsail, AWS S3, AWS Route53
## コミュニケーションツール
Slack,Zoom
## Webデザインツール
Adobe XD
## バージョン管理ツール
Git
## パッケージ管理ツール
Composer(PHP)またはGem(Ruby)
## IDE
AWS Cloud9
## ローカル開発環境
MAMP
## テキストエディタ
Atom,Sublime, VScode
##CMS(コンテンツ管理システム）
Wordpress,Webflow
## FTP
Cyberduck
## webサービス
Qiita, Teratail,　Stack Overflow, Github
## 開発方法
アジャイル方式
## etc
基本コマンド操作,基本Web知識,API知識,マークダウン記法,レスポンシブデザイン,Docker,CircleCI

# まとめ
最初は、覚えることだらけですが、一つづつ理解していけば学習は楽になっていきます。必要な知識や技術を、箇条書きにすることによって、学習内容の可視化、整理、順序立てが出来ます。必要知識、全て書くことは出来ませんでしたが、みなさんからのご意見、ご感想、ご指摘をお待ちしてます！！
Advent Calendar 2019をRevealで可視化！①


# はじめに

## Revealとは
[Reveal  ダッシュボードをアプリケーションに組み込み](https://www.revealbi.io/jp)
> Reveal Embedは、アプリケーションに組み込み可能なデータ可視化SDKです。シンプルな価格体系、組み込みの容易さでアプリケーションの価値を最大限向上することができます。

## この記事は
本記事は、Advent Calendar 2019 のランキングデータをRevealで可視化してみました！

公式のランキングページで見れる内容と被りもありますが、TOP30まで選出したこと。
また、他のグラフでも数値を表現していますので、お楽しみください！

(公式)カレンダー全体ランキング
https://qiita.com/advent-calendar/2019/ranking/subscriptions

# いいねランキング　TOP30
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48623/d79482a6-75c4-53f5-54ba-1f709a5801bd.png)

# 購読者ランキング　TOP30
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48623/39315ed1-5b30-d00b-40c0-554f04400795.png)

# "本番環境でやらかしちゃった人"が強すぎる！！
12月頭から"本番環境でやらかしちゃった人"が話題になり、私も見ていましたがこれほどとは...。
(筆者もsecret base ～君がくれたもの～、ドンピシャな世代です)
"いいね"も"購読者数"も桁違い...

続きまして、散布図で"いいね"と"購読者数"を見てみましょう。

# 散布図で見る"いいね"と"購読者数"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48623/203c42d1-b6d0-3019-a891-1e2fa18cd4b8.png)


縦軸をいいね数。横軸を購読者数で並べています。

一見、良い感じにばらけて見えますが、
"本番環境でやらかしちゃった人"はどこか？....


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48623/2b4bd396-1d86-7728-c262-65e44fc9d31f.png)

右上の隅っこに...
改めてグラフ化してみると数値の強さが一発で分かりますね...!


# まとめ
2019年アドベントカレンダー、今年も楽しませてもらいました！

データをまとめながら、この記事見たなー。だとか、この記事見たことないけど面白い！などの発見もあり、楽しみながらデータ可視化が出来ました。

本記事は、カレンダー別でのデータを紹介しましたが、
次(最後)の記事は、アドベントカレンダーの記事別のデータを可視化したいと思います！
AngularのGuard使用時に、MatDialogでユーザに通知する

#はじめに

権限を持ったユーザのみページアクセスの許可を出したいときに、AngularではGuardが提供されています。

[AngularでGuardの導入](https://qiita.com/daiki7nohe/items/ddeebad790ae4127d9a7)

Guardはページ遷移の直前に動作し、アクセス権限を持ったユーザの判断をします。
ログイン認証などで使われますが、例えば会員と非会員ごとにアクセス可能なページを切り分けたい場合などにも使えます。

その際に、アクセスできなかったユーザに対して「なぜアクセスできないのか」を通知するのは重要だろうと考え、MatDialogと組み合わせて実装してみました。

#アプリケーションの構成

この記事ではGuardとDialogをどのように組み合わせたのかを紹介するために、認証済みでないユーザに対し、ログインが必要である旨を伝えます。

以下が構成です。

<img width="657" alt="スクリーンショット 2019-12-27 16.53.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266563/231e724f-ef95-f31f-a377-8484787621b7.png">

このアプリケーションでは、AuthGardにSubjectを持たせて、ページ遷移に失敗した場合にnextでfalseを流します。

LoginComponent側ではsubscribeをしておき、Guadの結果を受け取ることでDialogを表示する、と言う流れにしています。

まずはGuadのコードです。

```typescript:auth-guard.ts


@Injectable({
  providedIn: 'root'
})
export class InitializeGuard implements CanActivate {

  private authenticationSubject = new Subject<boolean>();

  constructor(
    private session$: SessionService,
    private router: Router,
  ) {}

  canActivate(
    next: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {

      if () {
        // some code
      }

      // ページ遷移失敗時の結果を流す
      this.authenticationSubject.next(false);
      this.router.navigateByUrl('login');
  }

  get authentication$() {
    return this.authenticationSubject.asObservable();
  }
  
}

```

```typescript:login-component.ts

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss']
})
export class LoginComponent implements OnInit, OnDestroy {

  onDestroy$ = new Subject<any>();

  constructor(
    private initialGuard: InitializeGuard,
    private dialog: MatDialog
  ) { }

  ngOnInit() {

    // guard の結果を購読
    this.initialGuard
      .authentication$
      .pipe(takeUntil(this.onDestroy$))
      .subscribe( result => {

        if (!result) {
          const dialog = this.dialog.open(AlertComponent, {
            data: {
              title: 'ログインしてください',
              button: '閉じる',
            }
          })
          
          // 購読の破棄
          dialog.afterClosed().subscribe( result => this.onDestroy$.next());
        } 
      })
  }
```

今回はダイアログの表示とGuardからの結果を受け取る箇所のみ記載しています。
FormGroupなどは割愛しています。

また、AlertDialogはComponent間で使い回しをしており、Component側からメッセージを入力させるように設計しているため、このような実装になっています。

ログイン画面はこのようにしています。

<img width="562" alt="スクリーンショット 2019-12-27 17.10.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266563/50e0c714-dfd9-e8bc-1fdc-9f4d3b022ccb.png">

未認証アクセスボタンはHomeComponentへのリンクを埋め込んでいます。
認証が住んでいない状態でクリックすると、このようなダイアログが表示されます。

<img width="493" alt="スクリーンショット 2019-12-27 17.12.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/266563/caae3c06-eb4f-dbc4-0da0-65f10e121554.png">

今回のようにGuardからの結果を各コンポーネントで購読するのは冗長なので、共通コンポーネントを挟んでおくと良さそうです。

#まとめ
これを使えば、非会員ユーザなどに対しての通知も簡単に実装できそうです。

私はこの方法しか思いつきませんでしたが、他にも思いついた方がいらっしゃればコメントをお願いいたします。