OmniAICreator/Qiita-1.07M huggingface dataset:
UiPathでExcelファイルに罫線を引く

* UiPathでExcelファイルに罫線を引く方法。

![実行前.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184967/2444f3e9-a9fa-29e5-95d1-1fb9b6bdfd4d.png)

# 手順
### １．アクティビティ「Excelアプリケーションスコープ内」に「VBAを呼び出し」を配置
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184967/93e47429-a420-e5c8-022b-bbb437be5fc4.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184967/321f0597-e50e-47b0-8981-792b0e273e3a.png)

### ２．任意の場所にVBAコードを記載したファイルを配置
拡張子はなんでもいいみたい

```vb:keisen.txt
Sub DrawOutlineCell(argRowIndex as Integer)
	Dim rng as Range
	Dim rngStr as String

	rngStr = "A1:A" + CStr(argRowIndex)
	Set rng = Range(rngStr)

	With rng.Borders
		.LineStyle = xlContinuous
		.Color = vbBlack
		.Weight = xlThin
	End With
	
	Columns("A:A").EntireColumn.AutoFit
End Sub
```

### ３．「VBAを呼び出し」アクティビティを編集

* 呼び出すメソッド名だけ記載する。引数はプロパティのエントリメソッドのパラメータで設定する。{}付きで記載すること。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184967/8f558180-9141-6198-0cbe-5d0eb3824edc.png)

【実行フロー】
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184967/c7026478-78d9-dec2-3cef-aa5d90086a52.png)


### ４．実行後

* ↓のようなエラーが出た場合はExcelの設定を変更する必要がある。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184967/72be9cd0-9150-c3fb-3050-576a8b98953d.png)


* Excelを開き、ファイル→オプション→トラストセンター→トラストセンターの設定→マクロの設定　から「VBAプロジェクト オブジェクトモデルへのアクセスを信頼する」にチェック。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184967/1a9b0ef0-bc5b-43c1-9c20-8c5febeb2e92.png)

* この設定で正常に実行される。



![実行後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184967/dfd7b5bb-f965-96a9-6068-61db8b5446e9.png)


###　(追記)
引数は使わなくてもできますね。

【汎用的なマクロ】

```vb

Sub DrawOutlineCell()
    Dim rng As Range
    Dim rngStr As String

    Set rng = Range("A1").CurrentRegion

    With rng.Borders
        .LineStyle = xlContinuous
        .Color = vbBlack
        .Weight = xlThin
    End With

    rng.Columns.EntireColumn.AutoFit
End Sub

```
Ruby はすべてがオブジェクト，は本当？

Ruby は JavaScript などと違い，整数のような基本的な型もオブジェクトとして扱われます。
また，クラスという〈オブジェクトの振る舞いを規定する仕組み〉さえもオブジェクトです。

そのため，初心者向けの記事でよく

> Ruby ではすべてがオブジェクトです。

と書かれます。本当でしょうか？
この問いの答えは，「すべて」という言葉の意味によって変わります。

メソッドやブロックはオブジェクトではありません。

「ええ〜？　すべてがオブジェクトって嘘だったのかよっ？！」

いえいえ，これは，Ruby のメソッドやブロックはデータとして扱えないというだけです。Python や JavaScript なんかと違うところですね。

「ええ〜？　Ruby ショボイじゃん」

いえいえ，そういうわけではありません。メソッドそのもの，ブロックそのものはデータではないのですが，それをデータ化することはでき，それぞれ Method オブジェクト，Proc オブジェクトと呼ばれます。その名のとおり，それぞれ `Method` クラスと `Proc` クラスのインスタンスです。当然オブジェクトです。
Method オブジェクト，Proc オブジェクトはデータなので，当然，変数に代入したり，メソッドに実引数として渡したり，そいつが持っているメソッドを呼び出したり，といったことができます。

Proc オブジェクトは，メソッドに実引数として渡せるだけでなく，ブロックとして渡すこともできます。
Method オブジェクトは Proc オブジェクトに変換することもできます。

例を見ましょう。

```rb
# 「ブロックパラメーターを 2 乗して返すブロック」を用いて
# 2 乗する Proc オブジェクトを生成
square = proc{ |x| x * x }

# Proc オブジェクトを呼び出す例
p square[3] # => 9

# Proc オブジェクトを map にブロックとして与える例
p (1..3).map(&square) # => [1, 4, 9]
# → 映画「2001 年宇宙の旅」に出てきたモノリスの辺の比率

# 「13 に対する to_s メソッド呼び出し」を表す Method オブジェクトを生成
thirteen_to_str = 13.method(:to_s)

# 引数無しで呼び出すと 10 進で文字列化
p thirteen_to_str[] # => "13"

# 8 進で文字列化
p thirteen_to_str[8] # => "15"

# 2 進，8 進，10 進，16 進で文字列化
# map に & 付きで Method オブジェクトを渡すと，Proc に変換されたうえ，
# ブロックとして渡される。
p [2, 8, 10, 16].map(&thirteen_to_str)
# => ["1101", "15", "13", "d"]
``` 

冒頭の問いに戻ります。
「Ruby はすべてがオブジェクト」は，「すべて」の意味合いによっては間違いではないものの，誤解を招きます。
「Ruby はすべて**のデータ**がオブジェクト」と表現すべきでしょう。

Ruby では，変数・定数も演算子も制御構造もデータではないので，オブジェクトではありません。
プログラムもそれ自体はオブジェクトではありません。もちろんプログラムは文字列として表現できるので String オブジェクトで表すことはでき，`eval` メソッドによって実行することはできます。
Reactで表現するUIモーションデザイン【マウス & タッチパネルジェスチャー】

以下記事の続きとなります。

> [Reactで表現するUIモーションデザイン【モーションスタイリング】](https://qiita.com/stranger1989/items/842816b6e0e4de1fff34)

前回の記事でモーションスタイリングによりどのような表現が可能になるのかについて学びました。

これまでの記事ではどちらかといえば、モーションの役割は単純に動いているものをみるだけの「動画（アニメーション）」に近かったものが、今回からユーザーの入力を受け付ける事により「インターフェイスとしての機能」の役割を持つようになります。

車でいうところの「アクセル」「ブレーキ」「ハンドル」などの機能を動作させるためのトリガーと同義となっており、車においてもブレーキの効きが悪かったり、ハンドルの操作性が悪いと著しくユーザー体験が悪くなってしまうように、UIインターフェイスの動作が悪いとユーザーに対して使いにくさを感じさせてしまいます。


## <font color="LightSeaGreen">マウスジェスチャー手法</font>

`react-spring`と`react-use-gesture`を使用しながら、マウスからの入力を受けてモーションを変化させる一般的な方法について検証を行っていきます。

> https://use-gesture.netlify.app/

ここでは、スニペットとして活用できるように単純な例をサンプルとして上げていますが、モーションスタイリングやSVGイラストと組み合わせることにより多彩なインターフェイスを実現することも可能です。

### クリック/ダブルクリック

https://codesandbox.io/s/click-doubleclick-i9iru

![b5bef464bb8d2b4b7086490f4762ac85.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498345/0ebb3218-0d6e-a5a8-ad16-50d3e609ff3f.gif)

### ホバー

※ マウスジェスチャーのみの動作

https://codesandbox.io/s/hover-pwsuh
![b629e91186cc3cecb1f685d368453b99.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498345/32bce00f-2150-1d72-ffec-c3dc9c37775f.gif)

### ドラッグ & ドロップ
https://codesandbox.io/s/drag-8bzyb
![54784d23e654719d25c657a51a627bf1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498345/99349cfa-0c2e-7140-b320-042eae612b02.gif)

### マウス移動
https://codesandbox.io/s/mouse-move-ci8ku
![6a4f8bd36b3bce06a6b8dc3b7fce0c15.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498345/2f14ec46-62df-fbbd-ac9c-bdc6529e9e8f.gif)


### マウスホイール
https://codesandbox.io/s/wheel-ww5bv
![a3dc6d0ef92bb57d89894b80ac1dcb5c.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498345/4a24946a-3650-8a71-3fe1-3f556ea80b34.gif)


### ピンチ

※ タッチパネルジェスチャーのみの動作

https://codesandbox.io/s/pinch-b1dmb

![5a9b01d0bfd6b211a3b702e1273064b1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498345/f5251893-b779-96fd-083c-3696da94262e.gif)
left4dead2サーバー用のDockerイメージを作り、GCE上で動かしてみた #3（サーバー構築までで苦労したこと）

　[前回の記事](https://qiita.com/ekaru/items/201250bbb3def0dbe8eb)で今回作成した、l4d2 dedicated serverを構築用のDockerfileの悪い点を示しました。
　最後に、Dckerfileを作成する過程で躓いた点２つ（些細なことですが）を残します。

##1. Docker Toolboxのdefaultマシンのディスク容量が足りなくなった
　私が使用していた環境はDocker Toolbox (version 19.03.1)なのですが、```docker build```をする際にdockerのディスク容量が足りないことを示す```no space left on device```が出てしまいました。
　[類似した症状に関する記事](https://qiita.com/shione/items/dfa956a47b6632d8b3b3)を参考に```docker system prune -a --volumes```で不要なコンテナ・ネットワーク・イメージ・ボリュームを一括削除してみましたが、それでも解決しませんでした。

　作成しようとしているコンテナイメージは前回の記事で述べていたように10GB程度と大きいですが、Docker Toolboxのdefaultマシンのディスク容量は20GB（disk.vmdkは19.53GB）あるため、ディスク容量に問題はないと思い込んでおりました。
　しかし、（想像ですが）今回のコンテナは大半の容量をdedicated serverが占めているため、仮に```docker build```がこれをイメージ内でコピーするような動作をしているとしたら、ディスク容量が不足している可能性もあると思い、一回defaultマシンを削除してディスク容量を増やして再作成しました。

```docker
# defaultマシンを削除
$ docker-machine rm default
About to remove default
WARNING: This action will delete both local reference and remote instance.
Are you sure? (y/n): y
Successfully removed default

# defaultVM（50GB）を作成
$ docker-machine create -d virtualbox --virtualbox-disk-size "50000" default                
...
```

この上で再度ビルドしたところ、問題無く動作することを確認出来ました。
ディスク容量が足りないわけではないだろうという思い込みで躓いておりました。

##2. GCEのポート設定が上手くできているのか分からなかった
　これはGCE側の仕様というよりは```nmap```の仕様かと思うのですが、ファイアウォール設定をした後にちゃんとポート設定が出来ているのかを確認するため、```nmap```を使ってポートスキャンをしました。すると、5桁以降のポートはスキャン対象から除かれるようで、それに気づかず躓いてしまいました。
（この際、実際にファイアウォール設定をしててもサーバーに接続できない事象が発生していたため、勝手にポートの設定が出来ていないものとばかり思いこんでいたのですが、実態は```docker run```の際にUDPの27015をポートフォワードし忘れていたことに起因しており、このことに気が付くのに時間がかかってしまいました……。）

　上記を実際に見ていきます。例えば、ファイアウォール設定で22(SSH), 443(HTTPS), 8080, 9000, 10000, 11000, 27015(l4d2 dedicated serverのデフォルト), 27016を許可した上で、```nmap```でオプションをつけずにスキャンをすると下記のようになります。

```console
xxx@instance-1:~$ nmap 34.84.27.167
...
Not shown: 994 filtered ports
PORT      STATE  SERVICE
22/tcp    open   ssh
443/tcp   closed https
3389/tcp  closed ms-wbt-server
8080/tcp  closed http-proxy
9000/tcp  closed cslistener
10000/tcp closed snet-sensor-mgmt
Nmap done: 1 IP address (1 host up) scanned in 4.60 seconds
```
　確かに11000以降はスキャンされていません。私はこれを勝手に10000以降は許可できていないと勘違いして混乱してしまいました。
　しかし（当然ですが）、例えば上記の条件の下スキャンするポートを27015-27018に制限すると、下記のように27015と27016はclosed（受信待機中のアプリケーションはないが、プローブは届いている）となっており（当然17, 18はプローブが到達していない）、しっかり機能していることが分かります。

```console
xxx@instance-1:~$ nmap -p 27015-27018 34.84.27.167
PORT      STATE    SERVICE
27015/tcp closed   unknown
27016/tcp closed   unknown
27017/tcp filtered mongod
27018/tcp filtered mongod
Nmap done: 1 IP address (1 host up) scanned in 1.32 seconds
```

##まとめ
　蓋を開けてみるとなんてことない話かもしれませんが、実際こういうところで躓いてしまったので、今後のために残しておきます。

　これで「left4dead2サーバー用のDockerイメージを作り、GCE上で動かしてみた」の一連の話は全てとなります。今後はまた勉強を進め、本件のバージョンアップ版やその他の新しいアウトプットが出来たら積極的に記事化していきたいと思います。
　今回も最後まで読んでいただきありがとうございます。
Rails：refileを使って画像表示されなくなってしまった時（fill→sizeにするだけだった話）

# 最初に

**カレンダー企画2020の20日目**
プログラミングの勉強を始めて3ヵ月程経ったので学んだことのメモをアウトプットとして記事に残します。
これからプログラミングの世界に入る人の手助けになれたら嬉しい限りです。
間違っていたり、言葉が違っていたり、誤解されるような言葉があったら教えてください^^
言葉を長々と読みづらかったら申し訳ありません。少しずつなれてがんばります。

## gemのrefileを導入して、attachment_image_tagを使った時に画像が表示されなくて困った件

これは実際にWEBアプリケーションを作成していた時に起こったことをメモとして残します。

## 事の成り行き

最初作成した時は画像が表示されていたのですが、ある日突然表示されなくなりパニックたということです^^;

## 環境

```ruby:環境

Rails 5.2.4.4
ruby 2.6.3
gem "refile", require: "refile/rails", github: "manfe/refile"
gem "refile-mini_magick"

```


## 起きた時の画面の表示

![スクリーンショット 2020-12-20 11.25.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838465/23aeaa81-1582-33cd-a8e3-fe6f3af4daac.png)

こんなやつ


## 改善後

![スクリーンショット 2020-12-20 11.25.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/838465/bc05cab5-b162-a465-e3e7-39d087fca537.png)



## どう解決したのか？

```html:実際のコード（問題が起きた時）

<%= attachment_image_tag @member, :profile_image, :fill, 60, 60, format: "jpeg", fallback: "no_image.jpg", class: "img-circle" %>

```

```html:実際のコード（解決後）

<%= attachment_image_tag @member, :profile_image, format: "jpeg", size: "60x60", fallback: "no_image.jpg", class: "img-circle" %>

```

原因はどうも
`:fill, 60, 60`←これだったみたい
↓
`size: "60x60"`←これに変更（英小文字のxを使っています。）

`fill`を`size`に変更して解決しましたよ。って話です


## 最後に

色々調べてみると
formatと順番を入れ替えているものしかなかったので入れ替えたけど、入れ替えなくても一応表示さはされました。
理由はまだ調べても分からないので分かったら更新します。

こういうのは実際に作っていかないと分からないものなので実践って大切だな〜と改めて感じました。
Firestore ルールが勝手に書き換わってしまう現象

Firebase を使った Web アプリで、Web UI にアクセスしたユーザーが Firestore のデータにアクセスするため ルールを設定してアクセス管理をしていたのだけど、ルールがデフォルトの状態に戻ってしまう現象が度々発生。

結論としては、firebase コンソール上で変更したものを、きちんとローカルの開発環境にある firestore.rules にも適用して直しておけ、というだけのことでした。

# firestore.rules のデフォルト設定
```firstore.rules
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write;
    }
  }
}
```
これだと、Web UI 上の Javascript からアクセスすると誰でも読み書きできてしまうので、Firebase Console 上で以下のように設定して、認証されたユーザーIDを持つユーザーが自身のデータだけにアクセスできるようにしたい。

# firestore.rules の変更後

```firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /users/{userId}/{documents=**} {
      allow read,write: if request.auth.uid == userId;
    }
    
    match /hp2fitconfig/client_id {
      allow read: if request.auth.uid != null;
    }
  }
}
```
OAuth のトークン交換の際に必要となる、自身のアプリケーションの ClientID など共通の設定値にも Read 権限でアクセスできるようにしている。

# 不思議な現象
この設定でデータを保護しているつもりだったが、時たまこんなメールがくることがあって、そのたびに書き直すということをしていた。

>[Firebase] Cloud Firestore データベースに安全でないルールがあります

なんとなく、開発作業中にデータの削除だったりを Firebase Console 上で操作したあとに来るような気がしていたので、Firebase Console 上でデータの削除とかをするとルールが変わってしまう仕様なのかと疑ったが、どうやらそうでもない。

最終的にたどり着いたのは、firebase Hosting の静的ファイル（HTML、Javascript、CSS）をアップロードするタイミングで発生していることがわかった。

```
firebase deploy
```

よくみたら、ローカルの firebase プロジェクトディレクトリに `firestore.rules` があって、それが deploy されるタイミングでアップロードされて更新されていた、というオチだった。

# 結論
**ローカルにある `firestore.rules` で変更管理しましょう**
gatsby-theme-i18n-react-i18next: 初回アクセス時にブラウザの言語によって自動的に表示言語を変えたい

https://github.com/gatsbyjs/themes/tree/master/starters/example-react-i18next
↑のスターターでアクセスしたときにブラウザの設定言語によって、表示言語を自動的に変わるようにしたい。  

```gatsby-browser.js  
const i18nConfig = require("./i18n/config.json");

exports.onClientEntry = () => {
    const langs = i18nConfig.map(c => c.code);
    const userLang = navigator.language.substr(0, 2);
    if (langs.includes(userLang) && 
        !window.location.pathname.startsWith(`/${userLang}/`)
    ) {
      window.location.pathname = `/${userLang}${window.location.pathname}`;
    }
  }
```
```i18n/config.json
[
  {
    "code": "en",
    "hrefLang": "en-US",
    "name": "English",
    "localName": "English",
    "langDir": "ltr",
    "dateFormat": "MM/DD/YYYY"
  },
  {
    "code": "de",
    "hrefLang": "de-DE",
    "name": "German",
    "localName": "Deutsch",
    "langDir": "ltr",
    "dateFormat": "DD.MM.YYYY"
  }
]
```
Eclipseでリモートペアプロを実現する

# Eclipseでリモートペアプロを実現する

リモートワークではかどってますでしょうか？

[ドリーム・アーツ](https://recruit.dreamarts.co.jp)でもフルリモート、フルフレックス環境でチーム開発を行っています。リモートワークになって困ったことの筆頭がペアプログラミングです。

我々のプロダクトのサーバーサイドは Java で作成されており、標準の開発環境として Eclipse を使っています。

Teams や Zoom で画面を共有しながらやってみたりしたのですが、ナビゲーターからドライバーにコードスニペットを伝えたりするのに「XX行目のところ、違うもっと上！ そこに入れる！」とかかなりストレスフルなやりとりに辟易していました。

Visual Studio Code の Live Share と同じことを Eclipse でもやりたい！を実現してみました。（だいたい同じ手順で IntelliJ でも可能です）

## ペアプロの様子

まずはペアプロの様子をご覧ください。Eclipse でのコード編集がリアルタイムに双方向に同期しています。

![20201220_saros.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131496/37e533df-29a3-f6bd-47ed-b0dbf9ad06ed.gif)

これを実現するのが、Saros (https://www.saros-project.org) です。

## XMPPサーバーの構築

Saros は、Eclipse間のソースツリーや編集状態の同期に XMPP を利用します。

すでにどこかのサーバーの XMPP のアカウントを持っている場合はそれをそのまま利用できますが、アカウントを持っていない場合、またセキュリティ上の理由でプライベートな環境が必要な場合は、自前で XMPP サーバーを構築することができます。

今回は、XMPP サーバーの実装の一つである ejabber を用いて XMPP サーバーを構築します。

ejabber は標準で Docker のコンテナイメージが提供されているのでそれを用います。

```
docker run --name ejabberd -d -p 5222:5222 ejabberd/ecs
```

コンテナが起動したら以下のコマンドでアカウントを作成していきます。

```
docker exec -it ejabberd bin/ejabberdctl register {ユーザー名} localhost {パスワード}
```

Saros を試すには少なくとも２人のアカウントが必要なので必要に応じて作成していきます。

## Eclipse Saros プラグインのセットアップ

Eclipse マーケットプレースからインストールできるので、Saros という文字列で検索してインストールします。
![Eclipseマーケットプレース](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131496/49fb8a82-bfe2-932a-bc98-fcfa6a0d9f26.png)

インストールして Eclipse をリスタートすると、XMPPのアカウントの設定画面が開きます。
![XMPPアカウントの設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131496/8deb1d37-d144-0cff-f083-6ab09fff649b.png)

JID には先ほど作成したユーザーを `ユーザー名@localhost` として指定します。

Advanced Options を開き、ejabberd を起動したサーバーのホスト名を入れ、Port には 5222 を指定します。
ここで Eclipse を再起動しておきます。

別のコンピューターの Eclipse にも同様に別のユーザーでセットアップします。

## Saros によるプロジェクトの共有

プロジェクトに招待する側から、別のユーザーをコンタクトに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131496/902dd908-af4b-9021-5932-52cd1d064f6a.png)

招待を受けた側の Eclipse では、招待を受け入れるかどうかの確認がでるので OK を押してXMPPで通信できるようにします。
![Screen Shot 2020-12-20 at 11.39.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131496/358d97b0-779a-3ada-cea9-9fff6bae053c.png)

あとは共有するプロジェクトを右クリックして「Share Proejct(s)」を選択。共有するユーザーを選択すると共有が始まります。
![スクリーンショット 2020-12-20 10.50.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131496/e355ac94-1ff8-e961-c513-4c0ac00ee864.png)
![スクリーンショット 2020-12-20 10.50.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131496/8fd137cc-847d-cae6-5c39-d553dae2fdb2.png)

これで Eclipse でもライブ共有しながらコーディングが可能になるというわけです。

Let's enjoy hacking!
enebular を改良提案してみる


enebularがより広まるために、抱えている課題に対しての提案をしてみます。

# 解決したいこと

* 課題：enebularで開発したフローをGW(Gateway)デバイスにデプロイする際、同じフローを他の環境（他のGWデバイス）にデプロイすると、環境の違いによって動作しないことがある
* 原因：環境ごとに、センサー用nodeの利用可否が変わる
* ゴール：同じフローがどのGWデバイスでも動作出来るようにする
* 解決方法：GW上でWSS（後述）を動かし、enebularのフローとセンサーとの間の処理を抽象化する

# WSS

* Web Sensor Server の略
	* センサー/ アクチュエータとのやりとりををWeb APIを通して読み書きするためのサーバ
	* HTTPのGETリクエスト、WebSocket通信ができる
* 実装例：[kikoriPi+](https://github.com/uhuru-yokota-eiji/kikoripi/)

## システム概要図 

※社内用資料から抜粋

![systemflow_kikoriPi+.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1533/d1a0916d-9054-695d-f1de-4a6497ac2647.png "systemflow_kikoriPi+.png")

## 解決したこと

以下の2環境で、同じフローが動作することを確認しました。（※社内資料から抜粋）

![スクリーンショット 2020-12-20 11.39.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1533/4b8e14a7-bce1-1986-ce03-eff4d24bbbfc.png "スクリーンショット 2020-12-20 11.39.40.png")


手元の開発環境（Mac + Groovy IoT） でも、ラズパイ上でも同じフローが動作することが確認できました。これによって、開発も捗ります。

# 理想の未来

* WSSという概念とそれを実装したGWが広がり
* それらに対応するDeviceDriverが広まれば
* enebularのフローがどのGWでも同じ用に動作する

このような未来になるといいですね。
enum 定義

### なんでENUMを使いますか。
→コーディングが分かりやすくなる

### コード例）
①ENUMの定義

```java
import java.util.HashMap;
import java.util.Map;

public enum FLAG {
    YES("1", "YES", "はい"),
    NO("2", "NO", "いいえ");

    public String v;
    public String nE;
    public String nJ;

    private FLAG(String v, String nE, String nJ) {
        this.v = v; this.nE = nE; this.nJ = nJ;
    }

    private static Map<String, FLAG> vMap = new HashMap<String, FLAG>();

    static {
        for(FLAG e : FLAG.values()) {
            vMap.put(e.v, e);
        }
    }

    public static FLAG vToE(String value) {
        return vMap.get(value);
    }

    public String getV() { return this.v; }
    public String getNE() { return this.nE; }
    public String getNJ() { return this.nJ; }
}
```


②機能にはENUMの値を呼び方法

```java

    FLAG.YES.getV()   // 結果："1"
    FLAG.NO.getV()    // 結果："2"

    FLAG.YES.getNJ()  // 結果："はい"
    FLAG.NO.getNJ()   // 結果："いいえ"
```


③ENUMの比較
比較の時、文字列の比較の代わりに、ENUMを比較したの方が分かりやすい

```java
    // ENUMに変換する
    ENUM YES_FLAG = FLAG.vToE("1"); // "1" : はい
    ENUM NO_FLAG  = FLAG.vToE("2"); // "2" : いいえ
```

```java
    // ENUMの比較
    if(YES_FLAG == FLAG.YES) {
        // todo
    }

    if(NO_FLAG == FLAG.NO) {
        // todo
    }
```
```jsp
    // JSPの場合、値の比較
    <c:if test="${FLAG.YES.getV() == '1'}">
    <c:if>

    // または
    <c:if test="${FLAG.NO.getV() == '2'}">
    <c:if>
```

以上
CLS対策としての画像の高さ指定

GoogleのCore Web VitalsがSEO評価の指標となるようですが、CLS (Cumulative Layout Shift)の調整でハマったところを解決策を書きます。(WordPressを使ったサイトの話です)

## 背景
`img`タグに高さが指定されていない場合、画像が読み込まれた時点で下のコンテンツの位置に変更が発生し、CLSが加算されてしまいます。そのため画像の高さを指定する必要があります。

あらかじめ`img`タグに`height`が指定されていたり、CMSの投稿画像のサイズルールが定められていればこの問題は簡単に回避できます。しかし、長年運用されているサイトで、投稿画像のサイズがばらばらだったりすると「困った！」となるわけです。さらに添付画像のように画像が100%幅のときは、__ウィンドウサイズを変更するたびに画像の高さが変わるため__「高さ指定無理じゃね？」となりました。

![Screen_Shot_2020-12-20_at_11_12_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230009/27cd46af-b52f-e9e7-1b93-77218146c099.png)





## 解決策
結論から言えば、CSSの`100vw`を使います。

WordPressの`wp_get_attachment_image_src`では、画像の幅、高さを取得できます。

```php
$featured_image = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ) , 'thumbnail' );

// $featured_image[0]: 画像のURL
// $featured_image[1]: 画像の幅
// $featured_image[2]: 画像の高さ
```

そこで画像の縦横比を取得します。

```php
$ratio = $featured_image[2] / $featured_image[1];
```

あとは`img`タグに指定するだけです。

```php
<img 
    src="<?php echo $featured_image[0]; ?>"
    style="
        width: 100%;
        height: calc(100vw * <?php echo $ratio ;?>);
    "
/>
```

以上。

追記: DevToolで確かめた限りだと、CLSに関しては`img`への`height`指定ではなく、CSS側の対応でもCLS加算は発生しませんでした。
C/C++のヘッダーをJSONにまとめてくれるc2ffiをUbuntuにインストールする

## c2ffiとは

C言語のバインディングを作成していると、CやC++のヘッダーファイルを自動的に解析してくれるツールがあったらなと思うことがあります。c2ffiはLLVMを利用したツールで、CやC++のヘッダーファイルを解析して、メタデータのjsonファイルを作成してくれる便利なツールです。

この記事ではc2ffiをUbuntuでc2ffiを利用するまでに行った手順を記録しています。

* https://github.com/rpav/c2ffi

## ソースコードを入手する

```
git clone https://github.com/rpav/c2ffi
```

LLVMのバージョンに合わせてブランチを切り替えます。ここではUbunutu groovyの配布しているパッケージのLLVMはversion11であるため、11に切り替えます。

```
sudo apt install llvm-dev libclang-dev
```

```sh
git branch -a # ブランチ一覧を表示
git checkout -b llvm-10.0.0 refs/remotes/origin/llvm-10.0.0
```

## cmake(3.17〜)のインストール

ここで、公式READMEの言うとおりに、`build` ディレクトリを作って `cmake ..` を実行するとcmakeが古いと言われました。

```sh
mkdir build
cd build
cmake ..
```

エラーが発生する

```error
CMake Error at CMakeLists.txt:1 (cmake_minimum_required):
  CMake 3.17 or higher is required.  You are running version 3.16.3


-- Configuring incomplete, errors occurred!
```

そこで、仕方ないのでcmakeの最新版をインストールします。

* https://github.com/Kitware/CMake

```
cd ../../ # c2ffiのディレクトリの外へ
git clone https://github.com/Kitware/CMake
cd CMake
git checkout -b v3.19.2 refs/tags/v3.19.2 # 最新のリリース版
./bootstrap && make # -j8
```

数分待ちます。
CMakeは恐らく色々なツールで使われるので、あとからトラブルになる可能性も十分にあります。あとから簡単にアンインストールできるように`make install`ではなく`checkinstall`しておきます。

```
sudo checkinstall
```

適当にオプションとかを修正してインストールします。cmakeが大きいので、この工程もそこそこ時間がかかります。終わったら一旦シェルを起動し直すとcmakeが使えるようになります。cmakeが使えるか確認します。

```
# シェルの再起動
cmake --version
# cmake version 3.19.2
```

最新版のCMakeがインストールされました。c2ffiのディレクトリに戻ります。

```
cd ../c2ffi
```

## makeする時に環境変数の設定が必要

今度こそうまくいくかとおもいきや

```
cd build
cmake .. # cmake -DBUILD_CONFIG=Release ..
make # -j8
```

`/usr/bin/ld: -lclang-cpp が見つかりません` というエラーメッセージが出ます。

```
sudo apt install libclang-cpp10-dev
```

をして、以下のissueを参考に

* https://github.com/rpav/c2ffi/issues/59

```
LIBRARY_PATH=/usr/lib/llvm-11/lib/ make
```

とします。これで最後までいきました。このissueの記事を読むと、Macでも別の環境変数が必要になる場合があるようです。
checkinstallします。そのままだとSummaryやNameが正しく指定されないと思うので、c2ffiに書き直します。

```
sudo checkinstall
```

こちらはすぐに終了します。`c2ffi` とタイプして、c2ffiが正しく使えるか試してみましょう。

```
c2ffi: unrecognized option '--version'
Usage: c2ffi [options ...] FILE

Options:
      -I, --include        Add a "LOCAL" include path
      -i, --sys-include    Add a <system> include path
      -D, --driver         Specify an output driver (default: json)

      -o, --output         Specify an output file (default: stdout)
      -M, --macro-file     Specify a file for macro definition output
      --with-macro-defs    Also include #defines for macro definitions

      -N, --namespace      Specify target namespace/package/etc

      -A, --arch           Specify the target triple for LLVM
                           (default: x86_64-pc-linux-gnu)
      -x, --lang           Specify language (c, c++, objc, objc++)
      --std                Specify the standard (c99, c++0x, c++11, ...)

      -E                   Preprocessed output only, a la clang -E
```

このように表示されればOKだと思います。

あとはc2ffiをバインディング作成のお供に使っていきましょう。

公式ではcommon-lispとRuby用のバインディグ生成ツールを提供していますが、Rubyの方は古いので今でも動くかどうかはわかりません。

* https://github.com/rpav/cl-autowrap/
* https://github.com/rpav/c2ffi-ruby

この記事は以上です。
20H1以降のMicrosoft IMEでDvorakJを動かす

# 新IMEでDvorakJを動かす！
Windows10 20H1以降の新しいMicrosoft IMEで、正しくDvorakJを動かすための設定を紹介します。

## DvorakJの設定
* DvorakJの設定ウィンドウ→「キーボード」→「入力全般」→「IME関連」の、「Google日本語入力を使用している」にチェックを入れる![googleIme.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293884/89d76ed5-30fb-11b4-2f94-7b9c7de122cc.png)

## Microsoft IMEの設定
* Microsoft IMEの「かな入力」を「無効」にする（ローマ字入力にする）![microsoftIme.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293884/def0dfca-72da-453b-9c9c-85e263767de5.png)

## 以上！
これだけで、期待通り動作します！

## 参考
[DvorakJ:レファレンスマニュアル](https://blechmusik.xii.jp/dvorakj/wiliki.cgi?DvorakJ%3A%E3%83%AC%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB%3A%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%3A%E5%85%A5%E5%8A%9B%E5%85%A8%E8%88%AC%3AIME%E9%96%A2%E9%80%A3)
[Rails] authenticate_user! の使い方

authenticate_user!
===================
・deviseで使えるヘルパーメソッド
・コントローラーの先頭に記述
・そのコントローラー内で行われる処理はログインユーザーによってのみ実行可能

---下記の場合---
`編集はログインユーザーのみ実行可能
一覧・詳細ページ閲覧は未ログインユーザーでも実行可能`

```videos_controller.rb
class VideosController < ApplicationController
  before_action :authenticate_user!, only: [:edit]

  def index
  end

  def show
  end

  def edit
  end
end
```
---
---下記の場合---
`意味は上記と同じになります
記載の処理はログインユーザーのみ実行可能
ただし一覧・詳細ページ閲覧の処理は除くよー`

```videos_controller.rb
class VideosController < ApplicationController
  before_action :authenticate_user!, except: [:index, :show]

  def index
  end

  def show
  end

  def edit
  end
end
```
-----------------------------------------------------------------------------------
この記事は、下記の記事を参考させていただきました
https://qiita.com/gogotakataka1234/items/c7d5c0b3d8953216259e
【Rails6】ページネーション機能実装（kaminari）

#はじめに

記事の検索・閲覧アプリの作成中です。今回は、検索結果一覧表示が1ページで膨大な量になってしまうため、ページネーション機能を実装し、1ページに表示する数を制限して、スッキリとした見た目を実現したいと思います。

#環境

Ruby on Rails '6.0.0'
Ruby '2.6.5'

#前提

ユーザーが記事の検索などを行い、記事一覧が表示され、閲覧できる。

#①Gemの導入

ページネーション機能を簡単に実装できるgem「**kaminari**」を導入します。

```ruby:Gemfile
gem 'kaminari'
```

```ruby:ターミナル
% bundle install
```

#②コントローラーにてページネーションを定義する

```ruby:app/controllers/articles_controller.rb
  def index
    @articles = Article.page(params[:page]).per(8).order('created_at DESC')
  end
```

「page」と「per」というメソッドがkaminariで定義されているメソッドです。perメソッドの引数にどれだけの記事（レコード）が表示されたら、ページを増やすのかを指定しています。

#③ビューファイルの編集

```ruby:app/views/articles/index.html.erb
(省略）
 <%= paginate @articles %>
```

表示したいビューファイルに上記を記述するだけで完了です！！！

#おまけ(ページネーションのカスタマイズ)

上記の3工程でページネーション機能は導入できますが、ビューファイルはdefaltで決まっています。それを修正する方法について記述します。

```ruby:ターミナル
% rails g kaminari:views default （①）

              or

% rails g kaminari:views bootstrap4 （②）
```

①のコマンドで、app/views配下にkaminariが追加されるため、そこで変更を行うことができます。
②のコマンドでbootstrapなどのCSSフレームワークを適用できます。

また、デフォルトで英語表記になっているため、日本語表記に変更するためには、config/locales以下にkaminari_ja.ymlというファイルを作成し、以下のように記述すれば適用できます。

```ruby:config/locales/kaminari_ja.yml
ja:
  views:
    pagination:
      first: "&laquo; 最初"
      last: "最後 &raquo;"
      previous: "&lsaquo; 前"
      next: "次 &rsaquo;"
      truncate: "..."
```

#おわりに

https://pikawaka.com/rails/kaminari
上記の記事を参考にしました。ありがとうございました！！
[Android]プレビューに便利なDataBindingのデフォルト値

DataBindingを使ってレイアウトを組む時、`data`で定義したパラメータを指定しても、情報が空なので、プレビューで確認しづらいという問題がありました。

調べたところ、デフォルト値（Placeholder）が設定できるとのことだったので、まとめてみました。
公式には書いてなかったので、ぜひ書いて欲しいところです。

## レイアウトファイルで、DataBindingデータのデフォルトを設定

```layout.xml

<TextView android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:text="@{user.firstName, default=Placeholder}"/>

```

このように、@で囲んだ中に`default`で設定できます。
クォーテーションで囲む際には注意が必要です。

```layout.xml

android:text='@{user.firstName, default="Placeholder text"}'
android:text="@{user.firstName, default=`Placeholder text`}"
android:text="@{user.firstName, default=&quot;Placeholder text&quot;}"
android:text="@{user.firstName, default=@string/placeholder_text}"

```

私は2つ目をよく使っています。

このデフォルト値を使うことで、プレビューが断然しやすくなりました。

## 参考
https://stackoverflow.com/questions/34252516/android-studio-design-time-data-binding-fallback-default-value
アナログ回路 その13

# 概要

circuit sandboxをplunkerでホスティングした。
アナログ回路をシュミレーションで、説明してみる。

# トランジスタ・スイッチング回路

![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/9487607c-8ec3-cb34-29a9-2c434242d883.jpeg)


# 結果
![無題.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/40818476-4aaf-db55-de6a-23f884fea537.jpeg)


# 説明

arduinoなどのGPIOの出力バッファです。



# 成果物

https://embed.plnkr.co/plunk/hq5vWyhF2KdtJeuI


以上。
技術に熱心でない私が３つのGCP認定資格を取得出来たので学習方法を語ります

趣味は音楽、格闘技、フットサルです。
プライベートでは出来れば技術の勉強をしたくありません。
尊敬する人物は島田紳助さん、hydeさん、キングコング西野さんです。
尊敬するエンジニアは特にいません。(もちろん出来るエンジニアをすごいとは思います)
Qiitaを書くようになりましたが、実は本心はこんなところです。
しかしこんな私ですが、Professional Cloud Architect, Professional Data Engineer, Associate Cloud Engineerという3つのGCP認定資格を持っています。
全て一発合格です。
技術に強い関心がなく、そんなに勉強に時間を使わない私が取れたということは、私が実践した学習方法はかなり効率的なのかもしれないと勝手に自負しております。
だから今回、私が資格試験を受験した当時実践していた学習方法についてお伝えしたいと思います。
あくまで学習方法について語ります。
試験問題については触れません(試験のポリシーで試験問題を公開出来ません)のでご了承ください。
この記事が少しでもGCP認定資格試験を目指す方々のお役に立てば幸いです。

## 学習方法
早速ですが、学習方法について解説したいと思います。
私が実践した試験勉強は至ってシンプルです。

- 模擬試験(例. [Professional Cloud Architectの模擬試験](https://cloud.google.com/certification/sample-questions/cloud-architect?hl=ja))を受けて問題の傾向を掴み、模擬試験の問題と関連する[公式ドキュメント](https://cloud.google.com/docs?hl=ja)を読む
- 各試験の試験ガイド(例. [Professional Cloud Architectの試験ガイド](https://cloud.google.com/certification/guides/cloud-architect/casestudy-terramearth-rev2/?hl=ja))と関連する[公式ドキュメント](https://cloud.google.com/docs?hl=ja)、(自分が分かりやすいと思った)ネット上の記事を探して読む
- [Google Cloud Platform エンタープライズ設計ガイド](https://www.nikkeibp.co.jp/atclpubmkt/book/18/265910/)を読む(今は内容が古くなっているかもしれません)
- ケーススタディのある試験については、事前にそのケーススタディを確認してどのGCPサービスを使うか考えておくこと

以上です。
3資格とも、この対策でした。
全て「読む」が勉強方法になりますが、強いてポイントだけ挙げるとすると、読んでる途中に出てくる分からない単語は分かるまで調べましょうというぐらいです。調べる際、私は[こちら](https://wa3.i-3-i.info/)のサイトに大変お世話になりました。
「えっ、それだけ？」、「手を動かさなくて良いの？」と思った方いらっしゃると思いますが、本当にこれだけで十分でした。

## そもそもどういう試験なのか？
GCP認定資格試験は選択式で2時間以内に50問回答する試験です。
選択式なので、手を動かしてGCPのサービスを操作する試験ではありません。
内容としては、`各サービスの特徴を理解しているかを問う試験`です。
つまり、試験勉強のために手を動かす必要はなく、試験ガイドに関連するドキュメント、記事を読むだけで対策は十分可能ということになります。
試験範囲も問われるサービスも幅広いです。
それら全てを触って学習するのは時間もそうですが、何よりお金が相当掛かりますので試験対策としては非効率です。
**「GCP王に、おれはなる!!!!」**という方以外に、触って学習することはあまりおすすめしません。
試験に合格したいというだけであれば、私が実践した学習方法だけで対策は十分出来ると思います。

## それでも不安だという方へ
これから紹介する学習方法は私も実践しましたが、受けた後の私の感想としては、それほど試験対策として重要ではないかなという意見です。
おそらく先述の学習方法で紹介した対策で十分ですが、念には念をという方のために紹介致します。

**Professional Cloud Architect, Associate Cloud Engineer向けの追加の学習方法**
・[プログラマのためのGoogle Cloud Platform入門 サービスの全体像からクラウドネイティブアプリケーション構築まで](https://honto.jp/netstore/pd-book_28412895.html)を読む
・[Kubernetes完全ガイド](https://book.impress.co.jp/books/1119101148)を読む

**Professional Data Engineer向けの追加の学習方法**
・[ゼロから作るDeep Learning
――Pythonで学ぶディープラーニングの理論と実装](https://www.oreilly.co.jp/books/9784873117584/)を読む
・[ビッグデータを支える技術
――刻々とデータが脈打つ自動化の世界](https://gihyo.jp/book/2017/978-4-7741-9225-3)を読む

試験対策としては重要ではありませんが、本としては大変実践的で素晴らしかったので読むこと自体はかなりおすすめします。

## 余談
GCPの認定資格は私が取得しているもの以外にも、いくつか追加されています。
追加された試験を私はまだ受験していませんが、おそらくこの記事で記載している学習方法で概ね対策出来ると思っています。

## 最後に
資格と言えば「実際の現場で役に立たない」、「広く浅い」など、ネガティブなイメージが持たれがちです。
かくいう私も同じ意見でした。
しかし実際、GCP認定資格の勉強を通して得た知識は現場で課題や問題が発生した時に、私を助けてくれています。
例えば、「ある課題を解決したいがGCPのどのサービスをどのように使えば良いのか分からない」、「この要件の場合どのGCPサービスを使ってシステムを構築すれば良いのか分からない」、「お客様にサービスの特徴を説明しないといけない」といった時に役立ちます。
このような問題を検索してすぐに解決するのは意外と難しいと思います。
広く知っていなければ解決出来ないからです。
しかし、広く知ってさえいれば解決出来ます。
また私の場合、GCP認定の3資格を取得したことで周囲の評価が変わりました。
おかげで技術に熱心でない私でも、技術者としての自分に自信を持つことが出来ましたので、私はGCP認定資格の勉強を頑張って本当に良かったと思っています。
この記事を読んでくださる方々も是非、興味があればGCP認定資格取得を目指してみてください！
中国でカレンダーPlusを使ってみた

[カレンダーPlus Advent Calendar 2020](https://adventar.org/calendars/5414) の 21日目の記事です。

#内容
中国でカレンダーPlusを使ってみます。
中国は国策としてネットワークの安全を保持するために、国全体がファイアーウォールで覆われており、海外のサービスを使うと、正常に動作しないことがあります。
中国から見ると、日本も海外なので、同様な現象が起きる事があります。

そこで、今回はカレンダーPlusを中国で動かしたときに、ちゃんと動くのかについて検証したいと思います！

#結論
**めっちゃ普通に動きました！すばらしい！**
「上手くうごかないので、そこをどうやって動かすかみたいな記事」を書こうと思っていたのですが、普通にさくさく動いたので、本当困りました。

#なんでこんなにさくさくと動くのかを確認
*JSやCSSの外部参照関連
　中国で日本のサービスが動かない、或いは遅延する要素の一つとして、JSやCSSを外部サーバー参照しており、その外部サーバーが中国国内からアクセスできないため、想定外の動作をするというケースがあります。
　カレンダーPlusは、下図の様に、基本、cybozu.com への参照に絞られている様で、これも安定の要因だと思います（下図全てがカレンダーPlusが参照しているものかはわかりませんので、ご注意）。

![060.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79724/99d1536a-e44c-707d-7050-3b34afd755d1.png)

　現状でも十分安定していますが、稀に、中国から、js.cybozu.com への接続に遅延が生じます。その場合でも、URLをjs.cybozu.cn に変更してもらえば、さらに安定度が増すだろうと思います。

*認証サーバー
　遅延要素のもう一つの代表的な要因としては、「認証」があります。
　認証サーバーへとの通信が遮断、或いは遅延することで、画面が開かないというパターンですね。ところが、このカレンダーPlus。

![050.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79724/0b391807-3f56-e5b3-da5c-f7397095434b.png)

　このアラートが、遅延を感じさせることなく、秒速で表示されます。まじで秒速です。
　通信が発生していないんじゃないかというくらい高速。認証確認行為に時間も通信負荷もかけない、ユーザビリティ重視の開発者様のこだわりが感じられる速度です。　
　
#使ってみた感想
　今回カレンダーPlusをさわるのははじめてなのですが、サンプルアプリも提供されておりすごく親切でした。
　一番好きなのは、カレンダー月表示で、予定をドラッグ＆ドロップできるところ。
　元々はガルーンのスケジュール機能の置換のイメージでとらえていたのですが、それよりも、kintoneで構築する業務システムの日程管理機能強化で使うと、すごく効果が発揮できそうですね。

　なにより、前述のとおり中国で使用するに大変優しい作りになっているので、もっといろいろと触ってみたいと思います！
JavascriptのES6以降のクラスでイミュータブルプロパティを定義

# Object.definePropertyを利用

- Object.definePropertyメソッドを使って、読み込み専用のプロパティを定義する。
- writableはデフォルトはfalseなので、設定がなくてもいい。明示するのはコードリーディング上はありかも。

```security.js

export default class Security {
  setCsrf(value) {
    //第１引数は自身のインスタンス、第２引数はプロパティ名
    Object.defineProperty(this, "csrf", {
      //値を設定
      value: value,
      //読み込み専用
      writable: false,
    });
  }
}

````

- 利用は以下。

```run.js

import Security from "[任意のパス]/security";

const s = new Security();
//プロパティを設定
s.setCsrf("A");

//プロパティから値取得
console.log(s.csrf); // "A"を表示

//setを試みる
s.csrf = "B" //readOnlyの例外発生

```

# 複数のプロパティをインスタンス時に設定する


- Object.propertiesを使う方法もあるが、オブジェクトリテラルの値をすべてする場合は、以下のようにするのもありかと思う。
- オブジェクトリテラルをモデルクラスにするときに以下のようにすると良いかもしれない。

```model.js

export default class Model {

 /**
  * 初期化
  */
 constructor(dataSet) {
   this._setProperties(dataSet);
 }

 /**
  * オブジェクトリテラルの値をプロパティに設定
  */
 _setProperies(dataSet) {
   for(const [key, value] of Object.entries(dataSet)) {
     this._setProperty(key, value);
   }
 }

 /**
  * プロパティ設定
  */
 _setProperty(name, value) {
    Object.defineProperty(this, name, {
      value: value,
      writable: false,
    });
  }
}


````

- 利用は以下。

```run.js

import Model from "[任意のパス]/model";

//オブジェクトリテラルを作成
const dataSet = {"key1": "val1", "key2": "value2"};

//インスタンス化
const m = new Model(dataSet);

console.log(m.key1); // val1を表示
console.log(m.key2); // val2を表示

```

# 継承によりプロパティ定義を隠蔽

- 設定処理を他のクラスで利用する場合は継承で設定を隠蔽する。


```extended.js
import Model from "[任意のパス]/model.js"

export default class Extended extends Model {

  constructor(dataSet) {
    super(dataSet);
  }

}

```

# 指定名のプロパティを必ず定義する

- 指定のプロパティを必ず定義し、undefinedエラーを防止する。
- 可変引数で必ず設定したいプロパティ名を設定。
- オブジェクトリテラルにプロパティがあるかを判別してない場合は、nullを設定。(初期値は任意のものでよいと思う。空文字や-1などプロパティの性質に合わせる）

```model.js
export default class Model {

 /**
  * 初期化
  */
 constructor(dataSet, ...names) {
   this._setProperties(dataSet, names);
 }

 /**
  * オブジェクトリテラルの値のうち、指定名を必ずプロパティに設定
  */
 _setProperies(dataSet, names) {
   //指定のプロパティ名でプロパティを設定。
   // 値が無い場合はnullを設定
   for(const name of names) {
     const value = (name in dataSet) ? dataSet[name] : null;
     this._setProperty(name value);
   }
 }

 /**
  * プロパティ設定
  */
 _setProperty(name, value) {
    Object.defineProperty(this, name, {
      value: value,
      writable: false,
    });
  }
}

```

- 上記の定義を継承により隠蔽。

```extended.js
import Model from "[任意のパス]/model.js"

export default class Extended extends Model {

  constructor(dataSet) {
    super(dataSet, "prop1", "props2", "prop3");
  }

}

```
Spigotに外部プロセスからコマンド送信

プロセス間通信でSpigotのコンソールにコマンドを送る必要があったのでその方法を残しとく

```Server.java
public class Server {

    private Process process = null;
    private BufferedWriter commandLine;
    
    public void boot() {
        ProcessBuilder pb = new ProcessBuilder("java","-jar","~.jar");
        pb.directory(folder);

        try {
            process = pb.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
        commandLine = new BufferedWriter(new OutputStreamWriter(process.getOutputStream()));
    }

    public void sendCommand(String command) {
        try {
            commandLine.write(command + "\n");
            commandLine.flush();
        } catch (IOException e){
            e.printStackTrace();
        }
    }

    public void stop() {
        if (process == null) return;
        sendCommand("stop");
        try {
            commandLine.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
```
結構適当なコード

BufferedWriterを用いてプロセスのOutputStreamに書き込むことでコマンドを送信することができる
これは外部でサーバーを起動しているが、既に起動中のプロセスに対してもできる~~はず~~
注意点は改行しないと実行されない
Macの画面共有で、Ubuntu DesktopにVNC接続する。

# Interaction

追加ソフトなしで簡単にVNC接続できます。(Ubuntu DesktopにはVNC serverは既に入っています）
検索するとみなさん面倒なことやってるみたいなので書いときます。


# Ubuntu 側

1. 設定 → 共有 → 画面共有 → パスワード設定
2. パスワード暗号化解除

```
gsettings set org.gnome.Vino require-encryption false
```

![スクリーンショット 2020-12-20 10.35.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154910/081e4a90-f37b-c70f-1b1a-5ca520261a0b.png)


# Mac 側

1. ファインダー → 移動 → サーバーへ接続... → vnc://hostname.local で接続

![スクリーンショット 2020-12-20 10.32.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154910/e9f16f77-ca91-066e-646d-372e2e28f0a5.png)

※ IPアドレスを調べる必要はありません。


# 姉妹品

- [Macの画面共有で、Raspberry Pi OS (Raspbian)にVNC接続する。](https://qiita.com/kose3/items/0a3a67caae31344ae0d2)
AWS Storage Gateway ってどういうサービス？

## 勉強前イメージ

全然わからん・・・
でもstorageのgatewayだから、オンプレとデータをやり取りしたりするんかな？

## 調査

### AWS Storage Gatewayとは？

オンプレのサービスと密に連携したストレージサービス
オンプレにあるファイルサーバなどのストレージとS3のストレージを連携させ構築することが可能になる

### Storage Gatewayの機能

#### ファイルゲートウェイ

- オンプレに保存しているデータをs3のオブジェクトとして保存する
- ファイル1つ = 1オブジェクト
- 直近のファイルはゲートウェイ上にあるので、低遅延でのアクセスが可能

![ファイルゲートウェイUntitled Diagram.drawio - diagrams.net - Google Ch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/3f65eb9e-dae2-db63-4a5c-101c6e1f37ec.png)


#### ボリュームゲートウェイ

- オンプレのデータの `スナップショット` をs3に保存する
- 保存される際に仮想アプライアンスにマウントされている `Cache Volumes` に一時的に保存される
- 2つの方法がある
- キャッシュボリューム
	- プライマリデータをS3に保管しなおかつスナップショットを保存する、頻繁にアクセスするはキャッシュしてローカルに保持する
	- まず、アクセスされたらキャッシュストレージにアクセスされ、なければs3に行く

![キャッシュボリューむUntitled Diagram.drawio - diagrams.net - Google Ch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/afc15dac-160f-ab33-5cf0-9d783b332e51.png)


- 保管型ボリューム
	- プライマリデータをローカルに保存し、非同期でAWSにスナップショットを保存する
	- データがローカルに有るので、低遅延でアクセスできる

![保管型ボリュームUntitled Diagram.drawio - diagrams.net - Google Ch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/eb8b8c02-2917-5870-e825-1ef7455ad8c2.png)



#### テープゲートウェイ

- iSCSIベースの仮想テープライブラリ(VTL)として使用することができる
- S3 もしくは Gracier に保存することができる
- ゲートウェイはそのデータをローカルに保存した後、S3に非同期でアップロードする

## 勉強後イメージ

どうもテープゲートウェイがしっくりこないなー理解できてないかも。
上2つはなんとなくイメージ分かった。
実際のアクセスをどこで受けるとかいろいろ考えないといけない....

## 参考

- [AWS Storage Gateway（1）Storage Gatewayの概要](http://tech.blog.surbiton.jp/aws-storage-gatewa-1-get-started/)
- [AWS Storage Gateway](https://docs.aws.amazon.com/ja_jp/storagegateway/latest/userguide/StorageGatewayConcepts.html#volume-gateway-concepts)
- [AWS Storage Gatewayの種類とDR対策](https://www.acrovision.jp/service/aws/?p=1359)
- [Storage gatewayについて概要を調べてみた](https://recipe.kc-cloud.jp/archives/9180)
- [AWS Storage Gateway について知ってることをまとめてみた](https://qiita.com/MayForBlue/items/ce0d915ffdda11ffffe2)
- [AWS Storage Gatewayでできること、使いどころのポイント](https://codezine.jp/article/detail/7782)
- [AWS Storage Gateway とは](https://qiita.com/fjisdahgaiuerua/items/cbd384a108c53e791776)
Rails内にVueを導入した時のviewはどう書く?

## まずはvueをrailsのvueに表示させてみる。


controllerとviewを作る

```bash
rails g controller Pages home
```


下のコードで、app/javasript/packs配下にあるファイルを読み込むことができる。CSSも

```erb
<%= javascript_pack_tag 'hello_vue' %>  
<%= stylesheet_pack_tag 'hello_vue' %>   
```
↓

```erb:app/view/application.html.erb

    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
    +<%= javascript_pack_tag 'hello_vue' %> 
    +<%= stylesheet_pack_tag 'hello_vue' %> 
  </head>

  <body>
    <%= yield %>
  </body>
</html>
```

ブラウザを確認して見ると、、、
[![Image from Gyazo](https://i.gyazo.com/3777a9de2ef72d7c3f89b46a32a9d8f2.png)](https://gyazo.com/3777a9de2ef72d7c3f89b46a32a9d8f2)



## 次は、railsのviewからvueを操作するプロセス


```vue:app/javascript/packs/hello_vue.js
import Vue from 'vue'
import App from '../app.vue'

document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    render: h => h(App)
  }).$mount()
  document.body.appendChild(app.$el)

  console.log(app)
})


// The above code uses Vue without the compiler, which means you cannot
// use Vue to target elements in your existing html templates. You would
// need to always use single file components.
// To be able to target elements in your existing html/erb templates,
// comment out the above code and uncomment the below
// Add <%= javascript_pack_tag 'hello_vue' %> to your layout
// Then add this markup to your html template:
//
// <div id='hello'>
//   {{message}}
//   <app></app>
// </div>


// import Vue from 'vue/dist/vue.esm'
// import App from '../app.vue'

// document.addEventListener('DOMContentLoaded', () => {
//   const app = new Vue({
//     el: '#hello',
//     data: {
//       message: "Can you say hello?"
//     },
//     components: { App }
//   })
// })
```
中央のコメントアウトされている文章を読んで見ると、上をコメントアウトして、下のコメントアウトを外してくれ。そして、下のコードをerbにペースとしてくれと書かれている。


```vue:app/javascript/packs/hello_vue.js
import Vue from 'vue/dist/vue.esm'
import App from '../app.vue'
import Home from './pages/Home.vue'


document.addEventListener('DOMContentLoaded', () => {
  const app = new Vue({
    el: '#hello',
    data: {
      message: "Can you say hello?"
    },
    components: { App }
  })
})
```
ブラウザ側

```erb:home.html.erb
<div id='hello'>
  {{message}}
  <%# ↓app.vueの読み込み %>
  <app></app>
  <h1>Pages#home</h1>
</div>
```

Hello.vueとcan you say hello?が表示されて入れば完了です。


終わりです。
































参考:
https://qiita.com/cohki0305/items/582c0f5ed0750e60c951
IDE上からユニットテストをサクッと実行して開発効率化（IntelliJの場合の例）

# はじめに

皆さん、開発の時にユニットテストは書いているでしょうか。

ユニットテストを書いていたらどのように実行しているでしょうか。

ユニットテストはコードの保守性を上げるのに重要ですが、ユニットテストを実行するのにコストがかかっていると、時間ももったいないし、テストを書くのも面倒になります。

* 新しく実装したクラスのテストを実行したいけど、特定のテストだけ実行するコマンドがぱっと書けない
  * かといって、とりあえず全部のテストを実行させると時間がかかる
* 毎回 GitHub に Push して CI にまかせているけど、時間がかかる

僕は、会社の人から教えてもらって依頼 IntelliJ （IDE） 上でテストを実行できるようにしています。

このようにコードの左側に実行ボタンが出現し

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/94705a7a-bfe2-48a4-dc1c-16e7bf7d7991.png)

ワンクリックで実行できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/2b7774ba-3f85-0dd2-c2b0-6bab1dc8d540.png)

これで開発効率は劇的にアップします。

もちろん、PHP以外の言語でも可能ですし、おそらく IntelliJ 以外の IDE でも可能かと思います。VSCode も対応しているようでした。Docker上で実行することもできるし、リモートのサーバーにSSHさせて実行することもできます。

Visual Studio CodeがJUnitに対応。エディタ上で単体テストの実行、テストのデバッグなどが可能に － Publickey
https://www.publickey1.jp/blog/17/visual_studio_codejunit.html

↓ go の場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/a46bc469-fa36-5ee6-a4ef-f3e1238b8173.png "goの場合")

# IntelliJ PHP の設定方法

IntelliJ の Preferences を開きます。 PHP のインタプリタは設定しておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/dcadc541-ef9d-e0ae-b3eb-fe7360591ef8.png)


Composer の設定をします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/b82eac87-bbf6-253d-e0a0-a7929e867197.png)

PHPUnit の PATH を設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29024/884b0861-1945-e18b-950c-b54818103309.png)

これだけで実行ボタンが出てきます。

# まとめ

これだけで IDE 上でユニットテストが実行できて、開発効率が格段に上がります。

IDE は高機能で何でもできるので、あらゆる機能を IDE 上に乗せていくのが開発効率アップのコツだと思っています。

僕は以下のようなことをすべて IDE で行っています

* ユニットテストの実行
* DB のデータ確認
* HTTP リクエストを送って動作確認

HTTP リクエストの動作確認を IntelliJ 上で行う方法は別の記事にも書いてあります。

CURL の代わりに IntelliJ でカンタン API の動作確認【JetBrains IDE】 - Qiita
https://qiita.com/yoshikyoto/items/39a40c1b59e2bcba8c7f

VSCode でも IntelliJ でもいいですが、せっかくの IDE を最大限活用して効率の良い開発を。
Macの画面共有で、Raspberry Pi OS (Raspbian)にVNC接続する。

# Interaction
追加ソフトなしで簡単にVNC接続できます。
検索するとみなさん面倒なことやってるみたいなので書いときます。

# Raspberry Pi 側

1. メニュー → 設定 → Raspberry Piの設定 → タブ：インターフェース → VNCを有効に。
2. ツールバーにあるVNC → メニュー → Options... → VNC password

![スクリーンショット 2020-12-20 10.17.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154910/7a60a917-62d3-2ecc-0fcc-677561ac48cd.png)
![スクリーンショット 2020-12-20 10.17.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154910/d5d8fcb3-dc09-b68f-c9fd-1c526cb9f0f0.png)

VNCパスワードに変更し、そのパスワードで Mac から画面共有します。

# Mac 側

1. ファインダー → 移動 → サーバーへ接続... → vnc://hostname.local で接続

![スクリーンショット 2020-12-20 10.22.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154910/d7c5ef10-f99f-0394-9dee-88e73912d311.png)

※ IPアドレスを調べる必要はありません。

# 姉妹品
- [Macの画面共有で、Ubuntu DesktopにVNC接続する。](https://qiita.com/kose3/items/0fc037871916625903ea)
「箇条書きを含む段落」をMarkdownするとアレ

:::note info
これは「<a href="https://adventar.org/calendars/4964)">Markdown Advent Caleandar 2020</a>」の19日目の記事です。
:::

※この記事は[「『箇条書きを含む段落』をMarkdownする話」][qiita-p1]の続編です。

## 前回のおさらい

[前回の記事][qiita-p1]では、図1のような**「箇条書きを内部に含む<ins>段落</ins>」**がMarkdown（元祖MarkdownおよびCommonMark）で表現できるかについて考えました。

※前回の記事に引き続き、「文章構成上の段落」のことを「<ins>段落</ins>」と下線付で表記します。

---

![箇条書きを内部に含む段落](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14550/67525338-5542-ec48-73c0-59dd5b9e8990.png)
<font color="#3F9200"><b>図1：箇条書きを内部に含む<ins>段落</ins></b></font>

---

そして、**「箇条書きを内部に含む<ins>段落</ins>」はMarkdownで表せる**という結論を出しました。例えば、図1の文書は次のようなMarkdownコードで表せます。

```markdown:例1
この方法には

  - ほげほげ
  - ふがふが
  - ぴよぴよ

の3つの利点がある。なんとかかんとか。なんとかかんとか。なんとかかんとか。なんとかかんとか。なんとかかんとか。なんとかかんとか。
```

この結論はある意味で「多くの人の期待通り」です。ところが、記事の最後で私は“ちょっと気になる”ことを書きました。

> ところが、「箇条書きを含む<ins>段落</ins>」を含む文章をMarkdownで実際に扱おうとすると、文章のスタイルによってはレンダリングに関して問題が生じることがあります。

この記事ではこの「問題」について述べることにします。

## 「箇条書きを含む<ins>段落</ins>」のMarkdownに潜む問題

### 含むか、含まざるか、それが問題だ

端的にいうと、「箇条書きを含む<ins>段落</ins>」のMarkdownの問題は、**「実際に箇条書きが<ins>段落</ins>に含まれているのか否かが、コードを見てもわからない」**ということです。例えば例1のコードの場合、そのMarkdownの表記を見ただけでは、箇条書きのブロックの周りにある（Markdownの）段落要素が「箇条書きと合わせて1つの<ins>段落</ins>を成しているのか」が判別できません。これは、「箇条書きを<ins>段落</ins>が含んでいない」ような場合と対照してみればよくわかります。

---

![箇条書きを内部に含まない段落](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14550/4a5db56e-a2b2-f5a2-b03c-77ccbf154464.png)
<font color="#3F9200"><b>図2：箇条書きを内部に含まない<ins>段落</ins></b></font>

---

図2の文章では、箇条書きの部分は前後の<ins>段落</ins>からは独立していることが、内容から判断できます。つまり、この文章では「この方法には……ある。」の部分と「次に、……かんとか。」の部分はどちらも<ins>段落</ins>を成しています。ところが、図2の文章をMarkdownで表すとなると、「<ins>段落</ins>」はそのまま「HTML5・Markdownの段落」となるので、結局以下のようになってしまいます。

```markdown:例2
この方法には以下に挙げる3つの利点がある。

  - ほげほげ
  - ふがふが
  - ぴよぴよ

次に、素敵な☃の回し方に関して考察してみる。なんとかかんとか。なんとかかんとか。なんとかかんとか。
```

明らかに、例1と例2はMarkdownとして「段落→箇条書き→段落」という全く同じ構造になってしまっていて、「全体が1つの<ins>段落</ins>であるか」が**Markdownの構造を見るだけでは判断できません**。

### 構成変われば、「外形」変わる

一方で図1と図2については事情が違います。これらの図は「文章構造を“書籍のような外形”（以下では『**書籍風**』と呼ぶことにします）で表現（レンダリング）した結果」といえますが、この書籍風の表現においては「箇条書きを<ins>段落</ins>が含むか否か」は「外形」の差となって現れます。箇条書きの直後にある行の先頭を見てください。

![段落には段落下げがある](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14550/861acccf-7baa-8038-2a1d-a2966a7c21cc.png "段落には段落下げがある")

このように、文のブロックの先頭に**「段落下げ」があるかどうか**で、当該の文ブロックが<ins>段落</ins>を成すかどうかを判別できるわけです。

### 「文章構成上の段落」が効いてくる場合

先述の「外形の違い」の話は、Markdownが「箇条書きを<ins>段落</ins>が含むか否か」の違いを表現できないことが、**実世界の応用において問題になる**場面があることを示しています。すなわち、「書籍風の表現」が関わってくる場合です。

例えば、「技術同人誌のMarkdown形式の原稿を入力としてPDF形式に変換する」というシステムを考えてみましょう。対象が技術同人誌であるため書籍風（つまり図1・図2のような外形）で表現する仕様が採用されているでしょう。

この場合、例1のMarkdownの原稿は図1、例2のMarkdownの原稿は図2のように表現され、段落下げの有無という外形の違いを実現することが求められます。しかし、例1と例2のMarkdownの構造を読んだだけでは「箇条書きを<ins>段落</ins>が含むか否か」が判断できず、従って「段落下げを入れるべきか否か」の判断もできない、ということになってしまいます。これが「現実に起こりうる問題」であることは言うまでもないでしょう。

---

<font color="#0033FF">（後日に加筆します…:bow::bow::bow:）</font>

---

## 現状のまとめ

アドベントカレンダーの記事は**遅刻せずに早く書きましょう！**:bow:

[qiita-p1]: https://qiita.com/zr_tex8r/items/95822fb19bee698c0f17
リアルタイム通信周りの技術を調べてみた

# 目的
ほぼリモートになり、頻繁に使うようになったリアルタイム通信
どういった経緯で、そうなったのか歴史を見つつ、今は何を使ったら良いのか
ほぼ参考になったサイトのメモですが、時系列っぽく順にまとめております。

# ポーリング
基本的にAjaxでURL単位にサーバへリクエストを送り、レスポンスを確認する
サーバ側にリクエストをしてデータを取ってくる
ヘッダーとか余計な通信があって効率が悪い

# SSE
Server-sent events
サーバーからクライアントへの単一方向通信
https://en.wikipedia.org/wiki/Server-sent_events

# SPDY（HTTP/2）
Googleが提唱、後のHTTP/2
ヘッダーの圧縮、不要な部分を削除
サーバプッシュ通信なのでサーバからクライアントへ送信できる
https://ja.wikipedia.org/wiki/SPDY
https://builder.japan.zdnet.com/html-css/35013644/

# WebSocket
クライアント側からもサーバ側からも送信できる、双方向通信
ヘッダーが不要
https://ja.wikipedia.org/wiki/WebSocket
https://www.slideshare.net/mawarimichi/websocketwebrtc

# Socket.IO
WebSocketが対応していないブラウザでも対応する
[WebSocketとの違い](https://stackoverflow.com/questions/10112178/differences-between-socket-io-and-websockets)

## WebSocketとSocket.IOをherokuで動かす
触ってみました
https://devcenter.heroku.com/ja/articles/node-websockets

# WebRTC
P2P通信
MediaCaptureでカメラやマイクの入力ができる
WebでRTC通信を行う仕様郡
https://ja.wikipedia.org/wiki/WebRTC
https://www.slideshare.net/mawarimichi/websocketwebrtc

# おまけ

## WebSocketはHTTP/2に置き換わるのか？？
HTTP/2 では SSEを使って実装するのがよい？
https://www.infoq.com/articles/websocket-and-http2-coexist/
https://stackoverflow.com/questions/28582935/does-http-2-make-websockets-obsolete

## FirebaseとSocket.IOの違い
FirebaseはGoogleが提供するサービスで実装なのでその範囲内で実装できる（有料だが責任が少なくなる）
Socket.IOは詳細に実装ができる（無料だが責任が大きくなる）
https://stackoverflow.com/questions/28676586/what-is-the-difference-between-socket-io-and-firebase

# まとめ
テキストでのやり取り、共同編集については Firestoreだけあれば良さそう
ビデオや音声の入力が必要だと追加でWebRTCを利用する必要がありそう
ここはもう少しまとめます
Content-Security-Policy(CSP) 概要


* Content-Security-Policy(CSP) の概要をまとめる。

## Content-Security-Policy(CSP) とは？

* サーバーが、ブラウザに対して自身のセキュリティポリシーを表明するための仕組みを指す。
  * スクリプトや画像の実行可能範囲を指定する。

## 導入が必要な理由

* **クロスサイトスクリプティング(XSS)対策**
  * XSSを目的とした外部のスクリプトコードが埋め込まれた際の影響を軽減する。
![content-security-policy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/a8d026ae-9fa8-3d82-cf93-e70415519d2a.png)



## 構文

```http
Content-Security-Policy: <policy-directive>; <policy-directive>
```

* `<policy-directive>` = `<directive> <value>` 内部の句読点なし

  * `directive`種別 : 許可するリソースの種類([参考](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Security-Policy#Directives))
  * `value` : `'self'(同一ドメイン、同一ポート※サブドメイン除く)`や特定のドメインを指定

* 例1：自ドメインリソースのみを読み込み許可する場合

  ```http
  Content-Security-Policy: default-src 'self'
  ```

* 例2 : 自ドメインと指定ドメインのリソースのみを読み込み許可する場合

  ```http
  Content-Security-Policy: default-src 'self' *.example.com
  ```

   

## 設定の流れ

1. Web アプリが利用する各リソースについて、許可するオリジンのリストを定義する。

2. サーバーから1.で定義した制御設定を `Content-Security-Policy`HTTP ヘッダーに設定してを返却させる。
   ※`meta`タグに指定することも可能。



## Apacheでの設定方法

* 設定ファイル(`.conf`ファイルなど)に以下のように、記載を追加する。

```http
Header set Content-Security-Policy "default-src 'self'; script-src 'self' *.example.com"
```



## 参考情報

* [コンテンツセキュリティポリシー (CSP)](https://developer.mozilla.org/ja/docs/Web/HTTP/CSP)
* [Content-Security-Policy](https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Content-Security-Policy)
* [Content Security Policy の導入](https://dev.mozilla.jp/2016/02/implementing-content-security-policy/)
* [Content Security Policy Reference](https://content-security-policy.com/)
* [Content Security Policy (CSP)](https://qiita.com/nyamage/items/677ec6828818461f3e84)