OmniAICreator/Qiita-1.07M huggingface dataset:
[PHP]staticについて学習してみた

# はじめに
　業務でPHPを使うことが多いのですが、static変数をなんとなく使っていたり、他のメソッドとの違いがわからずずっとモヤモヤしていたので、この機会に学習しようと思いました。

　学習前は、staticをつけるとクラス内のどこからでもメソッドや変数を呼び出すことができるという認識だけです。グローバル変数と何が違う？使うメリットって？どういう場合に使う？など頭の中に？しか浮かばない状況です。

　学習用の備忘録として記事を残して行きます。間違ってるところがあれば指摘していただければと思います。

##クラスとインスタンス
　static変数を理解するにはクラスとインスタンスの概念を理解する必要があります。

> - クラスは、ある実体を生成するために定義された概念のようなもの。よく設計図に例えられる。
> - インスタンスは、クラス（設計図）を基に作られた実体のこと。

　僕は、クラスはたい焼きの型で、インスタンスはその型から作られたたい焼きと覚えています。一度設計図を定義してしまうと、再利用もでき、たい焼きの中身をあんこにしたりカスタードクリームにするなどカスタムすることもできます。

　実際に例としてクラスを基にインスタンスを生成してみます。

```
<?php
class A{
    public $b = 1;
    public $c = 2;
}
?>
```
上記のクラスAを呼び出すには、

```
$a = new A();
```
とするとそのクラスを使うことができるようになります。この状態をクラスがインスタンス化するといいます。通常はインスタンスを生成する時点で、必要な分のメモリが確保されます。

このメモリを確保するタイミングが、staticを理解する上で重要なポイントになります。

##なぜstatic変数を使うのか？
　基本はnew演算子を使うと、変数やメソッドを使うことができますが、インスタンスを生成することでいくつか困ることがでてきます。

>- クラスに定数を持たせた時に、インスタンスを生成するたびに同じデータなのにメモリがその分だけ消費されるメモリが無駄になること。
>- インスタンスを生成するたびにメモリを確保してしまうと、クラスで同じ変数を共有したくてもできない。

などの問題が出てきます。

これを解決してくれるのが、static変数です。

static変数は、基本的にプログラムが開始されるタイミングでメモリを確保します。

なので、最初に一度だけメモリを確保するだけでアクセスできるので、決まった値を参照するときなどにメモリを無駄にせずに使うことができます。

また、static変数は、インスタンスを生成しなくても直接、クラスの変数にアクセスすることができます。

これは、staticで変数を定義するとクラスそのものに属することになり、インスタンスとの依存関係がなくなるからです。

```
class A {
    public static $a = 1;
}
```

上記のstatic変数を使用するには、

```
$b = A::$a
```

とするとどこからでも変数を使うことができます。


# まとめ
　今回はstatic変数について学習しました。今までなんとなく変数やメソッドを使ってきましたが、どちらもそれぞれメリット・デメリットがあると思うので、それをしっかりと把握した上でなぜそこでstaticを使っているかなどを考えながらソースを書いていきたいと思います。
vistaでquartus その50

# 概要

vistaでquartusやってみた。
qsysでniosやってみた。
Lチカやってみた。

# サンプルコード


```
#include "sys/alt_stdio.h"
#include "system.h"

#define PIO_0_LED	 (*(volatile unsigned int *) PIO_0_BASE)

int main() {
	while(1)
	{
		PIO_0_LED = 0x00;
		usleep(500000);
		PIO_0_LED = 0x07;
		usleep(500000);
		alt_putstr(". ");
	}
	return 0;
}



```

以上。
技術備忘録（Docker）

自分自身の学習記録を残し、見直した際に素早く思い出すための記事投稿です。

記入日：2020年11月15日

今回は「Docker」についての記録を残していきます。
![horizontal-logo-monochromatic-white.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568321/31b62315-aad8-43a8-a316-c81f86d0585c.png)

それでは書いていきましょう。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
1.Dockerとは何か？

PC上でSwitchやLinuxを動かせるエミュレータのようなもの。
PCの中に別のマシンを作成・起動させるための仮想環境を作成するためのプラットフォームです。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
2.そもそもDockerを入れる理由は？

①エンジニアによって異なる開発環境を統一させ、開発効率をよくするため
　＝OSによる環境の違いや、使用しているマシンなどによる挙動を気にしくてよくなる

②開発環境と本番環境での違いをできるだけなくせる
　＝本番環境へのデプロイがしやすい（環境差分が完全になくなるわけでない？）
　＝サーバーへの環境設定なども不要になるので、リリースの速度も早くなる

つまりDockerを使用すると、チーム開発をする上での開発環境を統一させ、
本番環境へデプロイする上でのエラー等を最大限小さくすることができます！

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
3.Dockerの仕組みとは？

Dockerはイメージとコンテナが基本。イメージからコンテナを生成する。

【イメージとは】
コンテナの元となるテンプレート。
OSや実行するアプリケーションや様々な設定をまとめたもの（テンプレート）。

【コンテナ】
上記のイメージを元に作成される。
OSとアプリケーションが動く実行環境。
本番環境にコンテナをデプロイすることで、アプリケーションを本番環境上で動作させられる。

基本的には以上の２つから成り立っているのがDockerの基本です。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
4.具体的な操作手順は？

①イメージを取得/ビルドする
　❶オンライン上のDockerHubにある、Dockerレジストリからイメージを取得する。
　❷自分自身で作成する　※ベースのイメージはレジストリから取得し、それらに設定を加えたものビルドする
　　ビルド＝ベースとなるイメージに、自分自身の加工を加えたもの

　通常の開発では、自分自身でDockerfileを作ることの方が多い。

②コンテナを生成・起動する

　作成したイメージからコンテナを生成する　→　そしてそれを起動する　→　アプリケーションが動作する

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

以上が基本的な流れです。

ですが、アプリケーションの開発においては、大抵は複数のコンテナを扱い作業が行われるため、
１つ１つをイメージビルド、コンテナ作成等をすると手間です。

それでは複数のコンテナを動作させる場合はどうするか？

結論 「Docker Compose」　を使用する

Docker Composeは複数のコンテナを定義し実行するためのツールです。
ymlファイルというものに設定を記載する事で、コマンドでコンテナの生成や起動などをする事ができます！

ここで、Docker Composeにおけるコマンドの基本操作を記載しておきます。
※コンテナライフサイクルと言います

ビルド　　　$ docker-compose build
生成起動　　$ docker-compose up
停止　　　　$ docker-compose stop
削除　　　　$ docker-compose rm
再起動　　　$ docker-compose restart
停止削除　　$ docker-compose down

その他のコマンド

起動中のコンテナでコマンドを実行　　　　　　　$ docker-compose exec
コンテナの一覧を表示　　　　　　　　　　　　　$ docker-compose ps
ログの表示　　　　　　　　　　　　　　　　　　$ docker-compose  logs
使用していないコンテナやイメージなどを削除　　$ docker-compose prune 

他にも多くがありますが、その際はリファレンスを参考にしてください。

参考URL：https://docs.docker.com/reference/

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

5.Dockerをインストールする

公式HPのget-startedからダウンロードしましょう。
Desktop用の物をインストールしますが、
自身のOSのバージョンなどを事前に確認しておくと良いと思います。

URL：https://www.docker.com/

ダウンロードが完了し、アプリケーションを実行するとデスクトップ右上に、
Dockerのクジラのアイコンが出てきます。（可愛い）
クリックしていただき、runningの状態になるとアプリケーションを操作する事ができるようになります。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

6.Dockerでコンテナを起動させるには

公式ドキュメント：https://docs.docker.com/

公式ドキュメントないの「Quickstart」でPCにインストールできているかや
簡単な動作確認ができますので、参考にしつつ触りとして行うことをおすすめします。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

簡単ではありますが以上となります。
感想としてはモダンなWEB系企業では取り入れられており、
導入メリットを見れば「あぁなるほどな〜」と思いました。

WEB開発を進める上ではスピード感は大切ですし、
人を動かす分、お金がかかっていますので、
それらを迅速に活用するためにも、Dockerは合理的で
素晴らしいプラットフォームだと思いました。

学習を進める上で、追記事項があれば別記事にするか、
こちらに追記していくかで内容を濃くできるようにしていきたいと思います。

ご覧いただきありがとうございました。
【JavaScript】CSV 書き出しの際に必要なエスケープ処理と二次元配列→文字列変換の方法

# CSV 書き出しの際に必要なエスケープ処理と二次元配列→文字列変換の方法
こんにちは、ndj です。
二次元配列から変換した `CSV`(カンマと改行コードで区切ってあるアレです)をファイルなどに書き出す際に値にエスケープ処理を施す必要があったので、そのときの方法を記録しておきます。
また、合わせて二次元配列を `CSV` 形式の文字列へ変換する方法についても記録しておきます。

## なぜエスケープ処理が必要なのか
`CSV` 形式のファイルを作成する際、なぜエスケープ処理が必要なのかといいますと、値の中に**,**(カンマ)や**\n**(改行)が含まれてしまっていると、`Excel` や他のアプリケーションなんかで `CSV` を読み込んだときに値中に含まれている**,**(カンマ)や**\n**(改行)と区切り文字である**,**(カンマ)や**\n**(改行)を区別できないわけです。
なので、値は「**""**(ダブルクォーテーション)」で囲んで値であるということを明示する必要があります。

## エスケープ処理を行う方法

```escape.js
// エスケープ処理
const escapeForCSV = (s) => {
    return `"${s.replace(/\"/g, '\"\"')}"`
}
```

正規表現を用いて、引数として与えられた文字列をダブルクォーテーションで囲っています。
引数として与えられた文字列中に、「**"**」が含まれていると `CSV` に変換した際に値がずれてしまうため、「**""**」としてエスケープします。

## 二次元配列から CSV 文字列へ変換する方法

```convert.js
const arrToString = (arr, colDelimeter=',', rowDelimeter='\n') => {
    return arr.map((row) => row.map((cell) => escapeForCSV(cell)).join(colDelimeter)).join(rowDelimeter);
}
```

まず、二次元配列を `map()` メソッドで行(`row`)を取り出す。
`row` は一次元配列になっているので、さらに `map()` メソッドを用いてセル(`cell`)を取り出す。
このとき、各値にエスケープ処理を施す。
そして、`row` を区切り文字で連結(この場合は「**,**」)する。
最後に行区切り(この場合の区切り文字は「**\n**」)を行い、完了。

## サンプルコード
先述したように、`arrToString()` 内で各セルに対して `escapeForCSV()` を実行して、エスケープ処理を施しています。
`TSV` 形式にしたい場合は、`arrToString()` に引数を渡せばOK。

```sample.js
// エスケープ処理
const escapeForCSV = (s) => {
    return `"${s.replace(/\"/g, '\"\"')}"`
}
//二次元配列 -> CSV形式の文字列に変換
const arrToString = (arr, colDelimeter=',', rowDelimeter = '\n') => {
    return arr.map((row) => row.map((cell) => escapeForCSV(cell)).join(colDelimeter)).join(rowDelimeter);
}

// CSV 形式文字列に変換
let sample = [['a', 'b', 'c'], ['"a"', '"b"', '"c"']];
console.log(arrToString(sample));
// "a","b","c"
// """a""","""b""","""c"""

// TSV 形式にしたい場合
console.log(arrToString(sample, colDelimeter='\t'));
// "a"	"b"	"c"
// """a"""	"""b"""	"""c"""

```

## 最後に
どちらも汎用的な処理なので、おそらくライブラリがあると思いますが、手法を知っておくのは必要だと思ったので、残しておきます。
誤字脱字やアドバイス、ご指摘などございましたらコメントや編集リクエストなどくださると幸いです。
以上です。
ここまで読んでくださりありがとうございました。

[Twitter(@teqndj)](https://twitter.com/teqndj)

## 参考
### CSV について
[CodeZine: CSVファイルフォーマットの解説](https://codezine.jp/article/detail/2364)
### 正規表現について
[Qiita: JavaScript 正規表現まとめ @iLLviA 様](https://qiita.com/iLLviA/items/b6bf680cd2408edd050f)

非常に参考になりました。ありがとうございました。
nginxでのバーチャルホストの簡易設定

##そもそもバーチャルホストを一言で説明すると?
複数のドメインを一つのサーバに設定できる機能



##バーチャルホストを使うことによるメリット
- 一つのwebサーバ上で複数のドメインを運用するとき
- ipアドレスの節約
- バーチャルホストごとに設定を分けられる

簡単な設定例

```
server{
listen 80;
server_name www.pddaja.com;
root /usr/share/nginx/html;
access_log  /home/staising/access.log  main;
error_log /home/staising/error.log warn;
index  index.html index.htm index.php;
}
```

##一行ずつ解説すると
- apacheでバーチャルホストを設定する際は\<VirtualHost>とかで囲む必要があるけどninxはなんでもserverセクションで囲えばok
- listen80は待ち受けポート
- server_nameはドメインを置く
- rootはドキュメントルート(コンテンツを置く場所)
- access_logはアクセスログの出力先とmain形式のフォーマット指定
- error_logはエラーログの出力先とエラーレベルwarnの指定
- indexはこのドメインにアクセスした際にどこのコンテンツに飛ばすかの指定

##初投稿の感想と今後
次書くときはもっときれいに書けるように心がけたい
なんか勉強したときは定期的にアップロードしていきたい
決定性TMをシミュレートするシェルスクリプト 

この休日、シェルスクリプトの基本を勉強したので、その記録として、決定性TM $M=(Q,S,S,\delta,q_0,\\_,F)$ をシミュレートするシェルスクリプトを作りました。

```shell:TM.sh
#!/bin/bash

# Settings
Q=(0 1 2)
S=('_' 'a' 'b')
q0=0; F=(2); L=-1; R=1;

# delta: Q×S → Q×S×{L,R}
d0_=end;        d0a=(1 'a' $R); d0b=(0 'b' $R);
d1_=(2 'a' $L); d1a=(1 'b' $R); d1b=(1 'a' $L);
d2_=end;        d2a=end;        d2b=end;

# Controller
q=$q0; w="$1"; cur=0

echo "$w: "
while
	if [ 0 -le $cur -a $cur -lt ${#w} ]; then
		c=${w:$cur:1}
	else
		c='_'
	fi
	to=($(eval echo \${d"$q$c"\[\@\]}))
	echo '(q,w,cur): '"($q,$w,$cur)"
	if [ $to = end ]; then
		break
	fi
	q=${to[0]}
	if [ 0 -le $cur -a $cur -lt ${#w} ]; then
		w=$(echo "$w" | sed -e "s/./${to[1]}/$((cur + 1))")
	elif [ $cur -lt 0 ]; then
		for ((i=0; i < -cur - 1; ++i)); do
			w='_'"$w"
		done
		w="${to[1]}$w"
		cur=0
	else
		for ((i=0; i < cur - ${#w}; ++i)); do
			w="$w"'_'
		done
		w="$w${to[1]}"
	fi
	((cur += ${to[2]}))
	:
do :; done

for qf in "${F[@]}"; do
	if [ $qf -eq $q ]; then
		echo 'Accepted'
		exit 0
	fi
done
echo 'Rejected'
exit 1
```

この設定では次のようなTMを表しています:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311704/bbda604f-5be3-2e70-18ef-ebf18a862e76.png)
だから、例えば、

```shell:
$ bash TM.sh ab
ab: 
(q,w,cur): (0,ab,0)
(q,w,cur): (1,ab,1)
(q,w,cur): (1,aa,0)
(q,w,cur): (1,ba,1)
(q,w,cur): (1,bb,2)
(q,w,cur): (2,bba,1)
Accepted
```

とか、

```shell:
$ bash TM.sh ababa
ababa: 
(q,w,cur): (0,ababa,0)
(q,w,cur): (1,ababa,1)
(q,w,cur): (1,aaaba,0)
(q,w,cur): (1,baaba,1)
(q,w,cur): (1,bbaba,2)
(q,w,cur): (1,bbbba,3)
(q,w,cur): (1,bbbaa,2)
(q,w,cur): (1,bbaaa,1)
(q,w,cur): (1,baaaa,0)
(q,w,cur): (1,aaaaa,-1)
(q,w,cur): (2,aaaaaa,-1)
Accepted
```

とか、

```shell:
$ bash TM.sh bb
bb: 
(q,w,cur): (0,bb,0)
(q,w,cur): (0,bb,1)
(q,w,cur): (0,bb,2)
Rejected
```
など。深夜テンションで作ったので、間違い等あるかもしれません。

## 学べたこと
* bashがとても書きやすいこと(算術式のfor文など)。
* 多次元配列のサポートがないこと。
* 外部コマンドを使うよりも組み込みのコマンドで構成したほうが随分と速いこと。特にループ中のインクリメント をexprで行うとたかだか100回のループでも体感できる程度の遅延があった。
* 文字列の $n$ 文字目だけを置換するのが案外難しいこと。sedを使う方法しか思いつかなかった。
Unity Device Simulator のインストール方法


##背景
Device Simulatorのインストール方法が変わったようなので、忘却録として。。。

##開発環境
PC:macOS Catalina
Unity：2020.1.10f1

##内容
「Unity Device Simulator インストール」で検索すると、
同じような検索結果が出てくる。
メニューのwindowからPackage ManagerをクリックするとPackage Managerのダイアログが表示される。
ダイアログのAdvancedからshow preview pakagesにチェックを入れて、Device Simulatorで検索すれば見つかる、、、が肝心のAdvancedがない。

調べてみると、Unity 2020.1以降からインストール方法が変わったらしい。（参考のUnity 日本語ヘルプデスクに書いてあります）

書いてある通りにやれば、無事インストールでき、GameタブにGameとSimulatorを選択できるようになる。
Safe Areaを表示したり、回転することもできる。

![スクリーンショット 2020-11-16 2.17.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631339/1fac7984-e9ca-82a5-0094-3fc9812aa560.png)


###パッケージのインストール
[プレビューのパッケージ](https://docs.unity3d.com/ja/2020.1/Manual/com.unity.device-simulator.html)

###参考
[Unity 日本語ヘルプデスク](https://helpdesk.unity3d.co.jp/hc/ja/articles/900002171066-Unity-2020-1-%E3%81%8B%E3%82%89%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%81%A7%E7%99%BA%E8%A6%8B%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%96%B9%E6%B3%95)

[公式](https://docs.unity3d.com/Packages/com.unity.device-simulator@2.2/manual/index.html)
RSpecで「undefined method `create'」というエラーが出た



<a href="https://leanpub.com/everydayrailsrspec-jp" target="_blanck">Everyday Rails – RSpecによるRailsテスト入門</a>でコントローラーにおけるRSpecのテストを学んでいたときに、自分にとって新しい学びがあったのでアウトプットしたいと思います。

# 問題

本日もRSpecについて勉強していたところ、

```ruby:reviews_spec.rb
 review = FactoryBot.create(:review)
```

という記述を

```ruby:reviews_spec.rb
  review = create(:review)
```

という省略系にできることを知り、自分もやってみました。

しかし、「bundle exec rspec」を実行した後、以下のようなエラーが出てしまいました。

```html:ターミナル
Failure/Error: review = create(:review)
     
     NoMethodError:
       undefined method `create' for……（以下省略）
```

「セットアップがうまく行ってなかったのかなぁ…」
と思ったので、伊藤淳一さんのブログ(<a href="https://blog.jnito.com/entry/2019/10/25/053521">リンクはこちら</a>)を参考にさせていただきながらRailsのセットアップを見直したり、他にもいろいろ調べていました。

# 解決策

その結果、rails_helperに次のような記述が必要だったことを知りました。
（<a href="https://qiita.com/jonakp/items/0f70eece4fe7980f81a6" " target="_blank" rel="noopener noreferrer">参考にさせていただいた記事はこちら</a>）

```ruby:rails_helper.rb
　#一番下に記述してください

 RSpec.configure do |config|
    config.include FactoryBot::Syntax::Methods
  end
```

この記述が抜けていたために、今回のようなエラーが出ていたようです。

これにより、冒頭にあった

```ruby:reviews_spec.rb
 review = FactoryBot.create(:review)
```

という記述を

```ruby:reviews_spec.rb
  review = create(:review)
```

という省略系にすることができました。

今回はcreateメソッドでしたが、buildメソッドで省略系を書きたい時も同様です。
Bokehグラフと表の組み合わせ_html出力

from bokeh.plotting import figure, output_file, show
from bokeh.models import DatetimeTickFormatter
from bokeh.models import ColumnDataSource, HoverTool, CrosshairTool, NumeralTickFormatter
from bokeh.models.widgets import Button, Select, RadioGroup, TextInput, TableColumn, DataTable
from bokeh.models.widgets import DateFormatter

from bokeh.layouts import Column, Row
from bokeh.plotting import curdoc
import pandas as pd
import datetime 

# 出力HTMLファイルパスを指定
df = pd.read_csv("stockchart_20201115.csv")
#output_file("graph1.html", mode="inline")

# 描画レイアウト
#source = ColumnDataSource(df)
output_file("graph1.html", mode="inline")
df['日付']=pd.to_datetime(df['日付'])

data = {'x' : df["日付"],
        'y' : df["始値"],
        'y_end': df["終値"],
        'y_start' : df["始値"]
       }

source = ColumnDataSource(data= data)

p = figure(
   title="simple line example",
   plot_width=1000,
   plot_height=500,
   x_axis_type="datetime",
   y_axis_label ="日経平均株価",
   x_axis_label ="日時"
)


# プロットに判例と線の暑さを指定したrenderer(今回は折れ線グラフ)を追加
p.line('x', 'y', source = source)     

# 吹き出し
hover = HoverTool(
   tooltips=[
        ("Date", "$x{%F}"),
       ("始値", "$y{0,0}"),
       ("終値", "@y_end{0,0}")       
   ],
   formatters={"$x": "datetime"},
   mode="vline",
   show_arrow=False,  # 矢印を消します
)

columns = [ 
    TableColumn(field="x", title="One", formatter=DateFormatter()), 
    TableColumn(field="y", title=" Two")
] 

#表を表示
data_table = DataTable(source=source, columns=columns,selectable = True,
                       sortable = True, width=600, height=500, fit_columns=False)

![bokeh.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520203/adfcc1b3-b5b7-3ac1-d2f3-ebb6fc173794.png)
layout = Row(p,data_table)

# 結果を描画
show(layout)
リファクタリングをいつやるか？

普段は Rails を書いていますが、リファクタリングっていつやるのがいいのかと言うのを考えていました。

`リファクタリング:Rubyエディション` を読んでいていろいろと気づきがあったのでそのまとめです。

# リファクタリングとは
ありきたりですが、忘れるので書いておきます。

> プログラムの外部から見た動作を変えずにソースコードの内部構造を整理することである。

[wiki:リファクタリング 2020/11/15](https://ja.wikipedia.org/wiki/%E3%83%AA%E3%83%95%E3%82%A1%E3%82%AF%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0))

# いつリファクタリングするのか？
リファクタリングは常にやりつつ開発をしていくというのがよく言われてますが、具体的にいつやっていくのか？がよく分かっていませんでした。

まずは既存のコードを改修、機能追加することを例に考えます。

上記実装を行うとき、`実装→テストコード→リファクタリング` といった感じでリファクタリングをすると考えていました。

実際に機能を追加する場合、既存コードの理解から入ります。

リファクタリングはコードを読みやすくすると言うことも含んでいるため、最初の既存コードの理解のときにリファクタリングするのも正しい選択かなと。

なので、 `既存コードの理解→リファクタリング→実装→テストコード→リファクタリング` という流れで実装していくといいと考えています。

この方法をやると、最初のリファクタリングでわかりやすいコードになって理解が進み、この時点で Pull Request を出しておくと他の開発者も理解が進みます。 

テストコードがある場合は最初のリファクタリングも上手くいくと思うし、テストがなければコード理解も含めてその時に書いてしまえばいい気がします。

# まとめ
リファクタリングをやるときは以下のタイミングでやるのが良さそう。

`既存コードの理解→リファクタリング→実装→テストコード→リファクタリング`
Intel Macでmatplotlib+cartopyの環境構築

# はじめに

気象データを Python を使って地図とともに可視化するためには、matplotlib と cartopy を使うことが一般的です。そのための環境を Anaconda (Miniconda) で構築する手順について述べます。手元のOSのバージョンは macOS Catalina 10.15.7 (Intel)です。

M1 Macでの環境構築については、[「M1 Macでmatplotlib+cartopyの環境構築」](https://qiita.com/wm-ytakano/items/f1597dfd4fc93961382a)をご覧下さい。

# Anaconda (Miniconda) のインストール

[Anaconda](https://www.anaconda.com/) はパッケージ管理や仮想環境の作成ができるPythonのディストリビューションです。pyenv と pip を使って同等のことが出来ますが、依存するプログラムを同時にインストールできて便利なのでこちらを使う事にします。

[Miniconda](https://docs.conda.io/en/latest/miniconda.html) は Anaconda の最小構成版です。初期にインストールされるパッケージが少なく、ディスク容量をとらないメリットがあるのでこれを導入することにします。

```shell
# インストーラーのダウンロード
wget https://repo.anaconda.com/miniconda/Miniconda3-latest-MacOSX-x86_64.sh

# 対話形式でインストール
bash Miniconda3-latest-MacOSX-x86_64.sh
```

使い方は適宜他の記事を参照してもらえばよいですが、`conda`コマンドを使って仮想環境ごとにパッケージ管理を行うことができます。プロンプトに`(base) $`などと表示されている場合、`base`というanacondaの仮想環境にいることを意味します。`base`環境でパッケージを導入してもよいですが、ここでは新たに`cartopy-env`という環境を作成してみることにします。

```shell
conda create -n cartopy-env python=3.9
```

仮想環境を`conda create`で作成しただけでは`python`が含まれないので、Pythonをバージョン指定してインストールするようにします。ここでは執筆時の最新版のバージョン3.9を指定しました。

仮想環境を切り替えるには`conda activate`を叩きます。

```shell
conda activate cartopy-env
```

プロンプトに`(cartopy-env) $`のように表示されればOKです。

# パッケージのインストール

次に必要なPythonのパッケージをインストールしていきます。例えば科学技術計算を行うための`numpy`をインストールするには次のコマンドを使います。

```shell
conda install -c conda-forge <パッケージ名>
```
condaでは同じパッケージが複数のリポジトリから提供されるため、どのリポジトリからインストールするかを`-c`オプションで指定しています（ここでは`conda-forge`）。どのようなパッケージがあるかは https://anaconda.org/ で検索することができます。基本的には`conda-forge`リポジトリを選べばよいです。

それでは他に必要なものをインストールしていきます。パッケージ名はスペース区切りで複数指定できます。

```shell
conda install -c conda-forge numpy scipy xarray netcdf4 matplotlib cartopy
```

インストールされたパッケージのバージョンは`conda list`で確認できます。手元の環境でインストールされた主要なパッケージのバージョンとざっくりとした説明を書いておきます。

- `numpy (1.20.1)`：科学技術計算用のライブラリ
- `scipy (1.6.0)`：科学技術計算用のライブラリで、`numpy`にない機能も含んでいる
- `xarray (0.16.2)`：netCDF形式などのファイルの読み書きを行うのに必要
- `netcdf4 (1.5.5.1)`：netCDF形式などのファイルの読み書きに使っていたが、今は`xarray`を推奨。`ncdump`コマンドが同時にインストールされる。
- `matplotlib (3.3.2)`：図の描画に必要
- `cartopy (0.18.0)`：`matplotlib`で地図を描画するのに必要

説明は以上です。
circleciのjob結果をslack通知する方法(slack-orb v4版)

# はじめに

circleciから[slack-orb](https://github.com/CircleCI-Public/slack-orb)のversion4以降を使ったslack通知方法の記事が見つからず、公式もわかりにくかったので備忘録かねて記載。


# 設定方法

基本的に公式のwikiを見て設定すればOK
https://github.com/CircleCI-Public/slack-orb/wiki/Setup

## slackアプリを作成する

ここが従来の設定方法と異なるところ。
今まではwebhookURLをcircleciのProject SettingのEnvironment Variableに設定すればよかったがslackでアプリを作りOAuth tokenを設定して欲しいとのこと。

### 補足(というか余談)
webhookURLからtokenに設定方法が変わった理由については不明。
以前まで[slackが出してるcircleciのアプリ](https://slack.com/apps/A0F7VRE7N-circleci)にwebhookURL設定追加して使ってたけど
アプリのDeveloperがslackだったからアプリの責任範囲を各自にしたかったのかもですね。

## 環境変数の設定 

記事によると以下をcircleciのProject SettingのEnvironment Variableで指定すれば良い。


SLACK_ACCESS_TOKEN: slackアプリのアクセストークン
SLACK_DEFAULT_CHANNEL: slack通知のデフォルトチャネル


### 補足
現在のcircleciのProject Setting > Slack Integrationの設定画面では
1. webhookURLを設定しましょ
2. orbs連携しましょ
と記載がある。

![スクリーンショット 2020-11-16 0.45.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48316/c07b53fd-dfea-9f11-e54e-adaa5e5063ab.png)

が、これはorbsのver3までの話であり
orbs4ではwebhookURLは使われてないので1.は無視して良い。


## config.ymlの設定

基本的に(これ位しか資料が見つからなかったので）orbsのexample記事を見ながら設定する。
https://circleci.com/developer/orbs/orb/circleci/slack?version=4.1.1

### orbs連携の記載


```
orbs:
  slack: circleci/slack@4.1.1
```

必須設定。これはorbs3でも同じ。

### stepsに通知メッセージを記載

```
      - slack/notify: #slack通知のステップ名。orbs3は設定方法が全く異なるので注意。
          custom: |
            {
              "blocks": [
                {
                  "type": "section",
                  "fields": [
                    {
                      "type": "plain_text",
                      "text": "*This is a text notification* :smile:", #メッセージ内容
                      "emoji": true #絵文字(:xxx:)を使いたい場合の指定
                    }
                  ]
                }
              ]
            }
          event: always #circleの結果指定。failの場合は失敗時、passは成功時。alwaysは結果問わず。
          channel: ABCXYZ #slackチャネル指定。記載がなければSLACK_DEFAULT_CHANNELに届く
```


#### 補足

公式exampleのjobs配下にある以下記載について

```
context:
     - slack-secrets
```

wikiの環境変数の設定方法は
Organization Settingでこの名前のcontextを設定する場合を記載しており
本記事のようにProject Settingで設定した場合は記載不要。
contextについての公式説明は[こちら](https://circleci.com/docs/ja/2.0/contexts/)


## おわりに

slack-orbだけ新しくなってたけど
circleciのUIはついてきてないし
slack公式のwebhook用circleciアプリは残ってるしで
これから整備されてく(されて欲しい)のかなー。
という感じでした。
git commit -m --amendを覚えたのでメモ

作業を終えてcommitする際に、commitメッセージを間違えたり、変更したファイルをaddし忘れたりした時に、

`git commit -m 'Aの実装'`

`git commit -m 'Aの実装: コミット漏れの追加'`

みたいなことをするとダサい気がしたし、色々と他人に迷惑がかかる気がしたので、修正方法を調べると `--amend`というものを発見したので、メモしておく。

## git commit --amendでできること
* commitメッセージの修正
* commitの内容を後から追加

## git commit --amendでできないこと
* pushする前のcommitにしか利用することができない
* commitに含まれた修正を取り消すことはできない -> resetというものを使わないといけないらしい
* 2つ以上前のcommitを修正する-> rebaseというものを使わないといけないらしい


### addしてなかったファイルを追加したい

以下のようにする。

```
$ git add A
$ git commit -m 'Aを追加'
$ git add B
$ git commit -m --amend 'AとBを追加
```
`--amend`に`--no-edit`オプションを付けると、元々のcommitメッセージをそのまま利用することができる。

### commitメッセージを変えたい

以下のようにする。

```
$ git add A
$ git commit -m 'Aを追加'
$ git commit -m --amend '実はBを追加'
```

## まとめ
GIt力を高めたい
文字のだるま落とし(ruby編)

#[Ruby編]文字のだるま落とし
#問題
だるま落としは 5 段の木片からなり、その木片には 1 つにつき 1 つの英字小文字が書いてあります。
木片を飛ばす前の文字列と、飛ばしたのが何段目の木片であったかが与えられるので、木片を飛ばした後の文字列を求めるプログラムを作成してください。
#入力される値
入力は以下のフォーマットで与えられます。

S
N
・1 行目には、木片を落とす前の文字列を表す S が与えられます。
・2 行目には、何段目の木片を落とすかを表す整数 N が与えられます。
・入力は全部で 2 行となり、最後に改行が一つ入ります。
#期待する出力
木片を落下させた後にできる文字列を出力してください。

末尾に改行を入れ、余計な文字、空行を含んではいけません。
#入力例1
apple
2
#出力例1
aple
#入力例2
water
5
#出力例2
wate
#私の答え
```java:
a = gets.chomp
b = gets.to_i
str = a.slice!(b - 1)
print a
```
#今回のポイント
###1行目で文字列の呼び出し
###2行目で数値の呼び出し
###3行目でsliceメソッドを用いて b - 1で文字列を指定して呼び出している
###4行目でstrにすると　a という文字列のみ出力されるので print a　でsliceした文字列を除外した文字列を出力した
#以上！
AWS Lambdaでpythonプログラムの定期実行

#はじめに
AWSのlambdaを使用して、スケジュール実行のプログラムを設置しました。
lambdaの基本的なことで意外とつまったので残しておきます。
AWSのアカウントは作成しているものとしています。

MAC OS X
python 3.6

# 対象
・lambdaを触ったことのない方
・とりあえず何か動かして見たい方

#lambdaとは
スクリプトを実行することが出来るサーバーレスのサービスです。
サーバレスと言ってもスクリプトの実行時にのみサーバを起動するイメージです。

呼び出しはAWSの空いているサーバから行われるため、実行するサーバーは都度違います。
（固定IPを割り当てたサブネットにlambdaを設置して実行することでIPを固定にすることは出来ます）

無料使用枠が月ごとに100万件の無料リクエストと1秒あたり40万GBのコンピューティング時間あるので、たいてい無料枠で動かせます。WebやIOTのバックエンドのAPIとしても使えるのでめちゃくちゃ便利なサービスですね。

#簡易的なスクリプト作成
pythonでLambdaのスクリプトを作成する場合、 **lambda_function.py** という名前で作成しなければいけません。
その中の **lambda_handler** という関数が呼ばれるようになっているので、lambda_handler関数も用意します。



```lambda_function.py
# -*- coding:utf-8 -*-

# lambda実行時に呼ばれる関数。引数はevent,contextがデフォルトっぽいです。
# 引数なくてもいいっぽいですが、書いておきます。
def lambda_handler(event, context):
    print('テスト実行')

```

このスクリプトをzip形式に圧縮します。

```shell:bash
$ zip function.zip lambda_function.py
```

MACの場合はエクスプローラー上で圧縮すると.DS_Storeファイルが入ってlambda_function.pyを読み込めないのでコマンドで圧縮します。

#Lambda関数の作成
AWSのコンソール画面から「Lambda」→「関数の作成」を選択。
関数名を入れて、ランタイムは今回はPython 3.6にします。

![スクリーンショット 2020-11-15 23.18.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381859/25cb3653-188d-55d3-bc6b-27a963a550ad.png)

入力できたら、「関数の作成」ボタンをクリックします。
これで関数ができたので、先ほどのスクリプトをアップロードします。
右下の「アクション」ボタンから「.zipファイルをアップロード」で先ほどのzipファイルをアップロードします。

![スクリーンショット 2020-11-15 23.22.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381859/9da3b024-7d3a-30f3-8bba-bc1752a86e81.png)

![スクリーンショット 2020-11-16 0.26.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381859/02ab62e5-595c-dafb-cd46-bc721c1c6e95.png)

#テストを実行
右上のテストをクリックして、イベント名を入力します。
下の配列は関数に渡すイベント引数ですが、今回は使用していないので、変更せずにそのまま作成します。

![スクリーンショット 2020-11-16 0.30.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381859/54ae086b-152b-5462-7de3-8aca2b8788ad.png)

作成したテストを選択された状態でテストボタンをクリックしてください。

![スクリーンショット 2020-11-16 0.33.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381859/7bd1e1db-925e-73fc-7e6e-18df060145b9.png)

関数コードの下に実行結果が出てきてるので成功です。

![スクリーンショット 2020-11-16 0.34.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381859/f77280c9-d2cb-bb6f-bbd5-09254390ae42.png)

#定期実行のイベント作成

デザインナーの「トリガーを追加」ボタンをクリック。

トリガー：EventBridge(CloudWatch Events)
ルール：新規ルール
ルールタイプ：スケジュール式
スケジュール式：cron(30 1 * * ? *)
※このスケジュール式は午前10時30分に実行されます。
　式の時間はUTC時間なので、設定したい時間から9時間マイナスした時間で設定します。
　cron(分 時 日 月 曜日 コマンド)

![スクリーンショット 2020-11-16 0.46.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/381859/13a3cebd-dd9b-4ec0-a3c2-e0c86cc16697.png)

「追加」ボタンをクリックして、これで設定完了です。
【読書記録】Kotlinイン・アクション -第5章-

書籍「Kotlinイン・アクション」を読んで個人的に疑問に思った点や調べたことについて記載する読書記録です。
書籍の内容については記載しません。

## 第5章の内容

第5章　ラムダを使ったプログラミング
https://book.mynavi.jp/ec/products/detail/id=78137

## ラムダが使えると何が嬉しいのか？

- インターフェースをわざわざ作らなくて済む
  - ClickListenerのようなインターフェース

- 無名クラスのインスタンスを作成する必要がなくなる
  - 特に唯一のメソッドを持つクラスのインスタンスをメソッドの引数に渡したい時に使う(SAM = Single Abstract Method = 単一の抽象メソッド と関係)
  - タイプ数を減らせる
  - 読みやすくなる
 
## ラムダ式が用いられるシーン

- コレクション操作
- Java API
    - setOnClickListener()などラムダを引数にとるメソッド

## シーケンス

- 要素数が多いコレクションを扱う時に使う
- メソッドチェイン時に処理途中のコレクションを作成しないため、メモリを節約できる
RailsにおけるModelの関連付け

#概要
モデル間の関連付けは、アプリケーションを作る上で基本中の基本になると思うので、復習の意味を込めてまとめてみます。

#関連付けとは
モデル間の関連付けとは、データベースのテーブル間を外部キーを使用し関連付けることです。
これを行うことで、必要なデータを簡単な記述で呼び出したり、データを削除する際、関連したデータを同時に削除できたり非常に便利です。

#一対多の関連付け
関連付けの中で代表的なのは、一対多の関連付けだと思われます。
一対多の関連付けとは、あるテーブルの一つのレコードが別のテーブルの複数のレコードと関連付くことです。
例:UserモデルとPostモデルを関連付ける

```ruby:app/models/user.rb
class User < ApplocationRecord
  has_many :posts
end
```

```ruby:app/models/user.rb
class User < ApplocationRecord
  belongs_to :user
end
```

has_manyメソッドを使用すると「〜をたくさん持っている」、belongs_toメソッドを使うと「〜に属している」という意味になり、二つのモデルが関連付けます。
上記の場合、「UserはPostをたくさん持っている」のような意味合いになります。

これらのメソッドには命名規約があり、has_manyメソッドではモデル名は複数形とし、belongs_toメソッドではモデル名は単数形を使います。
また外部キーのカラム名は参照先モデル名（単数形）＋\_idと指定します。（例:user\_id）外部キーを指定する場合は、オプションでforeign_keyを指定します

```ruby:app/models/user.rb
class User < ApplocationRecord
  has_many posts, foreign_key: "client_id"
end
```

メソッド名を変える場合はclass_nameオプションを指定します。has_manyの後ろは新たなメソッド名に変更し、class_nameに本来のモデル名を指定します。

```ruby:app/models/user.rb
class User < ApplocationRecord
  has_many tweets, class_name: "Post"
end
```

has_manyにdependentオプションを指定し:destroyと指定すると、参照先レコードが削除された際、参照元のレコードも自動で削除します。

```ruby:app/models/user.rb
class User < ApplocationRecord
  has_many posts, dependent: :destroy
```

#関連付けによってできること
モデルが関連付くと以下の記述で参照元のデータを取り出せます。

```ruby:example
@posts = @user.posts
```

has_manyにて使えるようになったメソッドは集計メソッドやクエリーメソッドを使うことができます。

```ruby:example
@posts = @user.posts.count
@posts = @user.posts.order("")
```

参照先へ関連付けるデータを設定する場合、buildメソッドを使用して関連づけることができます。また、引数にモデルの属性を指定できます。

```ruby:example
@user.posts.build(name: "taro")
```

<<と記載すると、レコードの保存まで行うことができます。

```ruby:example
@user.posts << @post
```

#まとめ
モデル間の関連付けに関して復習の意味も込めて、再確認できました。
まだまだ基本的な部分であり、一対一だったり、多対多の関連付けなどもあるので、別の機会にまとめていきたいです。
deviseでログアウト時に確認ページに遷移させる

# はじめに
railsでdeviseをしようしたログインログアウト機能を実装していて、
ログアウトした際に確認ページに遷移するように実装していたところ
つまずいたので記事にしようと思います。
さらに良い方法とかがあればコメント欄か編集リクエストに記載願います。:bow_tone2:

# バージョン情報
- ruby 2.6.5
- rails 6.0.3.3

# 前提条件
- hamlでの記載(gem 'haml-rails')
- deviseが導入済みでログインができている

# コントローラーの変更
sessions_controllerの**respond_to_on_destroy**がデフォルトで記述されていて
root_pathに遷移されるようになっていました。
なのでここのコードを削除します。
そこに**render '遷移先URL'**を記述することでURL先のページに遷移することができます。

~~~ruby
# controllers/users/sessions_controller.rb

def destroy
  signed_out = (Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
  set_flash_message! :notice, :signed_out if signed_out
  yield if block_given?
  respond_to_on_destroy #デフォルトの記述 ← コード削除
  render '遷移先URL'　＃renderで遷移先のURLを記述 ← コード記入
end
~~~

# Viewの作成
私は`users/destoroy`にdestroy.html.hamlファイルを作成しました。

```ruby:
%h1 ログアウトしました。
= link_to "マイページに戻る", "/"
```
![destroy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684702/11d5cb90-246c-1a0f-18ff-9bb21de7b4fd.png)

# コントローラーのカスタマイズ
**sesstions: "users/sessions"**を追記して、sessionsをカスタマイズしました！！

```ruby:
  devise_for :users, controllers: {
    registrations: "users/registrations",
    sessions: "users/sessions" #カスタマイズ
  }
```
# ルーティングのカスタマイズ
ルーティングもカスタマイズします！
HTTPメソッド**:delete**, URL, コントローラー名＃アクション名


```ruby
  devise_scope :user do
    get 'profiles', to: 'users/registrations#new_profile'
    post 'profiles', to: 'users/registrations#create_profile'
    get 'addresses', to: 'users/registrations#new_address'
    post 'addresses', to: 'users/registrations#create_address'
    delete 'users/destroy', to: 'devise/sessions#destroy' #追記
  end
```

二つをあわせて
`routes.rb`

```ruby

  devise_for :users, controllers: {
    registrations: "users/registrations",
    sessions: "users/sessions" #カスタマイズ
  }
  devise_scope :user do
    get 'profiles', to: 'users/registrations#new_profile'
    post 'profiles', to: 'users/registrations#create_profile'
    get 'addresses', to: 'users/registrations#new_address'
    post 'addresses', to: 'users/registrations#create_address'
    delete 'users/destroy', to: 'devise/sessions#destroy' #追記
  end
```

# まとめ
まだまだMVCの理解がないと感じました。
冷静になって考えたらすぐに解決できた問題でした。
そして、マークダウン の書き方にも苦戦してます。
記事書くのにすごい時間かかってしまっているので早くなれなければ…
もっとアウトプットしていきます。

<font color="Orange">しょうま</font>
【CSS】ナビゲーションバー作成のポイント【自分用】

<ol><li>なんでもclassで括らない。
tool barなどのbar系の中で要素を並べたい時は
クラス名＋ul,
クラス名＋ul＋li
で表現する。</li>
<li>navigation barnの固定の仕方
最初にnavigation barの幅、高さをdivのCSSで固定
→＜li＞で作成した各要素は、margin:0、padding:0を指定する</li>
<li>h1は１ページに１つ</li>
<li>ページの各セクションは以下のように固定。
（position:relative=現在の表示位置から相対的に要素の位置を動かしたいときに使用）</li>

```css
.section{
   float: left (or right);
   position: relative;
   bottom: ?;
   right: ?;
   left: ?;
   top: ?;
}
```
<li>
Excel VBAのSplit関数の使い方メモ

#セルの値の状態
以下のように全角スペースで、姓と名前が区切られている場合に
姓と名前を別々で変数に格納していきます。
変数に格納した後、B1セルに姓、C1セルに名前を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536529/8d44e331-3fbc-f216-38bd-c23946556ff6.png)

#コード

```vb
Option Explicit

Private Sub splitExample()
    Dim lastName As String, firstName As String
    Dim var As Variant

    var = split(Range("A1").Value, "　")
    lastName = var(0)
    firstName = var(1)

    Range("B1").Value = lastName
    Range("C1").Value = firstName
    
End Sub
```

#マクロ実行結果
B1セルに姓、C1セルに名前が入力されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536529/fe0203c3-8cee-07df-2e8f-6c13fdd86794.png)

#半角スペースと全角スペースの両方に対応させる
条件分岐で半角のときと全角のときで、区切り記号を変えるようにしました。
区切り記号がない場合は、何も出力しません。

```vb
Option Explicit

Sub splitExample()
    Dim lastName As String, firstName As String
    Dim var As Variant

    If InStr(Range("A1").Value, " ") > 0 Then
        var = split(Range("A1").Value, " ")
        lastName = var(0)
        firstName = var(1)
    ElseIf InStr(Range("A1").Value, "　") > 0 Then
        var = split(Range("A1").Value, "　")
        lastName = var(0)
        firstName = var(1)
    Else
    End If
        Range("B1").Value = lastName
        Range("C1").Value = firstName
End Sub
```

#マクロ実行結果
全角スペースの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536529/a0a9a1d9-0d2e-1462-eab7-37fa5ce26b3f.png)
半角スペースの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536529/8b812e47-83e6-91ab-c5c0-cb839be8c2e5.png)
区切り文字なしの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536529/5b5e32c2-1320-a41c-5f7d-a28b1ece51bf.png)
実際にVPCを構築してみる(VPCとサブネット)

## 勉強前イメージ

前に実際書いた構成図で書いたやつやってみる。
普通に考えて行けそうな気がする？多分。

## VPCとsubnet

![subnet下書き一覧 - Qiita - Google Chrome 2020-11-14 13.39.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/56b80362-33f0-8e58-452f-c70b17ca2a82.png)


### VPCの構築

- VPCを作成

![VPC無題 - ペイント 2020-11-14 13.42.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/eee5e0e9-41e7-89e1-6730-ecd0c4b6c091.png)


- VPCの設定

名前タグ : qiita-test
IPv4 CIDR : 10.0.0.0/16 ※/8では作れず、/16にしました。

![VPC Management Console - Google Chrome 2020-11-14 .png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/7b3397a9-60f1-80fc-ec58-f905935a0259.png)


- 作成しました。

![無題 - ペイント 2020-11-14 13.46.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/98133138-3d78-af3a-fd6b-c3521c549cd5.png)



### subnetの構築

- サブネットの作成

続きましてサブネット作ります。

![無題 - ペイント 2020-11-14 13.48.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/11ae7e5c-4960-3030-bd27-2a62af0a6cc6.png)


- サブネット1つ目作成

1つ目です。
名前タグ : qiita-test-1
VPC : ↑で作ったVPC
IPv4 CIDR ブロック : 10.0.1.0/24 ※さっき↑で/8で作れなかったので変更しました。

![無題 - ペイント 2020-11-14 13.50.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/c8e62664-aec0-2001-8cde-b07a7e35725d.png)


- サブネット2つ目作成

2つ目です。
名前タグ : qiita-test-2
VPC : ↑で作ったVPC
IPv4 CIDR ブロック : 10.0.2.0/24 ※さっき↑で/8で作れなかったので変更しました。

![無題 - ペイント 2020-11-14 13.52.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/7f1d6052-bf9a-2c8e-31d7-4ba81b120728.png)

- 出来た

![無題 - ペイント 2020-11-14 14.06.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/11c10bd4-3ef1-eecd-d50b-0e251f77cf1a.png)


- 作ってみてからの構成

実際には/8では作れなかったですね。AWSの仕様？
実際にはできそうでも、やってみないとわからないですね。

![VPCsubnetUntitled Diagram.drawio - diagrams.net - Google Ch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/5454528a-8bfb-b877-e06b-9fd7d8c917ac.png)


## 勉強後イメージ

やっぱり引っかかった。
AWSの仕様かな、知らなかった。
作ってみないと分からない。。。。
AtCoder Beginner Contest 183

##[A - ReLU](https://atcoder.jp/contests/abc183/tasks/abc183_a)
この問題は数学の表記を知っているか知らないかの問題です。
ReLUは（x）の関数である。
つまり、xに関連する式だという表記です。
条件式が２つあるのでそれをプログラミングします。

```C++:C++
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<utility>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cctype>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll =long long;
using P = pair<int,int>;
 
int main(int argc, const char * argv[]) {
    
    int x;
    cin >> x;
    
    if(x>=0) cout << x << endl;
    else cout << 0 << endl;
    return 0;
}
```

##[B - Billiards](https://atcoder.jp/contests/abc183/tasks/abc183_b)
この問題は数学の傾きの方程式を知っているか、一次方程式を解けるかの問題です。

-1*(y1-0)/(x1-x)=(y2-0)/(x2-x)

4つの変数が入力で与えられるので一次方程式になり、
x=(y1*x2+x1*y2)/(y1+y2)
となります。

```C++:C++
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<utility>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cctype>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll =long long;
using P = pair<int,int>;
 
int main(int argc, const char * argv[]) {
    
    double sx, sy, gx, gy;
    cin >> sx >> sy >> gx >> gy;
    
    cout << fixed << setprecision(10) << (sy*gx+sx*gy)/(sy+gy) << endl;
    return 0;
}
```

##[C - Travel](https://atcoder.jp/contests/abc183/tasks/abc183_c)
入力値が無向グラフ、計測する時間は順列全探索で処理を行います。
問題文とサンプル入力でこの２つが思い浮かぶ必要があります。

```C++:C++
#include<iostream>
#include<vector>
#include<algorithm>
#include<iomanip>
#include<utility>
#include<iomanip>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cctype>
 
#define rep(i,n) for(int i=0; i<(n); ++i)
#define pai 3.1415926535897932384
#define NUM_MAX 2e18
#define NUM_MIN -1e9
 
using namespace std;
using ll =long long;
using P = pair<int,int>;
 
int main(int argc, const char * argv[]) {
    
    int n, k;
    cin >> n >> k;
    
    int filed[8][8]={0};
    vector<int> vec(n);
    rep(i, n){
        vec[i] = i;
        rep(j, n){
            cin >> filed[i][j];
        }
    }
    
    int ans=0;
    do{
        if(vec[0]>0) continue;
        int sum=0;
        for(int i=1; i<n; i++){
            int y = vec[i];
            int x = vec[i-1];
            sum += filed[x][y];
            if(i==n-1) sum += filed[y][0];
        }
        if(sum==k) ans++;
    }while(next_permutation(vec.begin(), vec.end()));
    
    cout << ans << endl;
    return 0;
}
```

茶色パフォーマンス５５0〜が出ました。
jqueryメモ　オブジェクトにプロパティを追加・削除する方法　

###オブジェクトにプロパティを追加する方法

```jquery:jquery.js
let data = {} //空のオブジェクトを定義
data['name'] = taro ;  //これでdataは{name:'taro'}になった
```

###オブジェクトのプロパティを削除する方法

```jquery:jquery.js
let data = {name:'太郎',age : 20}
delete data['age']; //data中のageを削除
```
【Python】初心者でスクレイピングする時に冒頭脳死して書けるコード

スクレイピングをするときに毎回毎回

```python:test.py
from bs4 import BeautifulSoup
```
とこのように記述するのが面倒くさいので、とりあえずこれ使っとけば間違いなしのテンプレートを作成します。

```python:test.py
!apt-get update
!apt install chromium-chromedriver
!cp /usr/lib/chromium-browser/chromedriver /usr/bin
!pip install selenium
!pip install requests-html
```

まずはライブラリ関係。
私は普段clbを使っているので、とりあえずこれ入れとく。

```python:test.py
import pandas as pd
import datetime
from tqdm.notebook import tqdm
import requests
from bs4 import BeautifulSoup
import time
import re
from urllib.request import urlopen
import urllib.request, urllib.error
from requests_html import HTMLSession
from selenium import webdriver
from selenium.webdriver.chrome.options import Options

# htmlを取得するところまで
options = webdriver.ChromeOptions()
options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
driver = webdriver.Chrome('chromedriver',options=options)
driver.implicitly_wait(10)
url="https://www.XXX.com"
driver.get(url)
html = driver.page_source.encode('utf-8')
soup = BeautifulSoup(html, "html.parser")
```

はい、ここまで脳死でコピペでOKです。
あとは

```python:test.py
soup
```

これで、とりあえずhtmlを出力するところまではものの数秒で到達できます。

厳密に言えば、tqdmとか使ってないライブラリもあるんですけど、個人的にスクレイピングするときにほぼ毎回セットで使用しているライブラリをインポートするコードも全部詰め込んでます。

私自身、これでコピペして使いまくってます。
Julia便利記法・機能備忘録(関数編)

## この記事の目的
自分用にjuliaの便利な記法や機能をまとめておきたかったので記事にして公開することにしました。
juliaはpython並みの書きやすさをうたっているのでかなり簡潔にコードを書くことができます。せっかくならできるだけすっきりしたコードを書けるようになりたいですよね。


- - - 

ここからは全部REPL上で行います。前に出てきた変数は再定義しない限りそのまま使います。

## 簡単な関数定義

```julia
julia> function f(x)
           2x + 3x^2
       end
f (generic function with 1 method)

julia> f(x) = 2x + 3x^2
f (generic function with 1 method)
#上二つは等価で、頭にfunctionなんて書かなくてもよいです。
#実際の数式に近い記法で定義できます。
#また、数字×文字の場合は*を省略できます。

julia> f = x -> (2x + 3x^2)
#49 (generic function with 1 method)
#このように書いても等価です。
```

## 無名関数

```julia
julia> x -> x^2
#3 (generic function with 1 method)

#mapとか使うときに簡単な関数をこう書くとよさそうです。
```

## 関数のベクトル化

```julia
julia> xs = [1 2 3 4]
1×4 Array{Int64,2}:
 1  2  3  4

julia> f(xs)
ERROR: DimensionMismatch("matrix A has dimensions (1,4), matrix B has dimensions (1,4)")

julia> f.(xs)
1×4 Array{Int64,2}:
 5  16  33  56
#.を入れることで自作の関数も配列に対して計算してくれます。

julia> map(f, xs)
1×4 Array{Int64,2}:
 5  16  33  56
#一応mapでも同じことができますが、上記のほうが簡潔です。

julia> y =  @. sin(cos(xs))
1×4 Array{Float64,2}:
 0.514395  -0.404239  -0.836022  -0.608083
#マクロ@.を使うとその行すべての関数を.があるものとして扱えます。
```

## 関数合成

```julia
julia> g(x) = -x
g (generic function with 1 method)

julia> 2 |> g |> f
8
#f(g(2))をこのように書けます。括弧がいっぱいあると嫌なのでこの方がきれいですね。
#パイプライン演算子とかいうらしいです。

julia> (f∘g)(2)
8
#この表記でもいいです。∘は\circ + tabで出せます。
#g|>fと f∘gは等価ではありません。
#前者は最初の引数から順番に評価している(必ずgの引数を書く必要がある)だけに対し、
#後者は先に関数の合成をしてから引数を受け取ります。
#合成関数を１つのオブジェクトとして扱いたい場合は∘を利用します。

julia> xs .|> g .|> f
1×4 Array{Int64,2}:
 1  8  21  40
#この表記の時も.でベクトル化できます。
```


## 畳み込み

```julia
julia> foldl( *, [1,2,3,4], init=1)
24

julia> foldl((x,y)->x+2y, 1:4)
19
julia> foldl((x,y)->x+2y, 1:4, init=0)
20

#juliaは多重ディスパッチが使えるので初期値を利用したい場合はinit=と書けば別の関数を勝手に呼び出してくれます。
#書かない場合は第一要素が初期値として使われます。
```

- - - 


## 微分
http://www.juliadiff.org/ForwardDiff.jl/stable/

```julia
#f(x) = 2x + 3x^2
#g(x) = -x
julia> using ForwardDiff
julia> df(x)=ForwardDiff.derivative(f,x)
df (generic function with 1 method)

julia> df(2)
14
#一変数関数の微分
#省略しますが、gradientやhesse行列も計算できます。
#pythonのsympyと違って普通の関数表記で利用できるのがいいですね。


julia> d_dx(f) = x -> ForwardDiff.derivative(f,x)
d_dx (generic function with 2 methods)

julia> d_dx(f)(2)
14
#関数d_dxを微分演算子のように思えるのでこの方がいいかもしれません。

julia>  d_dx(f ∘g)(1)
4
#(f ∘g)(x) = 3x^2-2x
#(f ∘g)'(x) = 6x-2
#このように合成関数の微分を簡単に実現できます。
```

便利な記法・面白い機能を見つけ次第追記していきます。
juliaは本当に数学に近い表記ができるので使いやすいですね。
【oracle備忘録】UNION ALL を使ってテーブルを結合

※この備忘録は初学者の私が学習した内容を忘れないために書き起こしたものとなります。

##今回の目的
下記の「県テーブル」、「色テーブル」から、各県の人口に応じて、カラーコードを取得したい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520051/091de01a-6d56-b471-b502-a8a246af70fb.png)
＜条件＞
◇下記人口に応じて、必要なカラーコードを取得
・人口100万人未満…青色
・人口100万人以上200万人未満…緑色
・人口200万人以上300万人未満…黄色
・人口300万人以上…赤色 
##作成したコード

~~~C#
    SELECT 県.県ID 
         , 県.県名 
         , 県.人口 
         , 色.カラーコード 
      FROM 県, 色 
     WHERE 県.人口 < 1000000 
       AND 色.色ID = 1 
 
    UNION ALL 
 
    SELECT 県.県ID 
         , 県.県名 
         , 県.人口 
         , 色.カラーコード 
      FROM 県, 色 
     WHERE 県.人口 <  2000000 
       AND 県.人口 >= 1000000 
       AND 色.色ID = 2 
 
    UNION ALL 
 
    SELECT 県.県ID 
         , 県.県名 
         , 県.人口 
         , 色.カラーコード 
      FROM 県, 色 
     WHERE 県.人口 <  3000000 
       AND 県.人口 >= 2000000 
       AND 色.色ID = 3 
    
    UNION ALL 
 
    SELECT 県.県ID 
         , 県.県名 
         , 県.人口 
         , 色.カラーコード 
      FROM 県, 色 
     WHERE 県.人口 >= 3000000 
       AND 色.色ID = 4 
 
    ORDER BY 県ID
~~~
 
## 取得結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520051/e85b1099-022f-26f9-6b9d-d466b205c060.png)

## 感想
2つのテーブルを使用して何らかのデータを取得したいとき、
私は真っ先ににjoinを考えてしまうが、今回のように2つのテーブルがjoinで結合するのが困難な時(2つのテーブルで共通するカラムの無いとき)は、UNION ALLを扱えるようにしたい
【アウトプット】eachについて

eachについて
何をするものか
配列の中身などを繰り返しやってくれる働きをもつ
例）
<% @posts.each do |post| %>
postsは変数名　postはとりあえず配列の中身を入れるやつ
<　div class = "posts-index-item">

<　% = post.content %>
ここはpostだけでも良い状況がある。
今回はターミナルでPost.allで配列を取っている（contentというカラム名にデータがある為）
<　/div>
<% end %>

例をあげたら余計にややこしくなったが繰り返しの処理を書くときにeachを書いたら
短く書けるということ。
Googleスプレッドシートでチェックボックスを追加する

#チェックボックスの追加
```
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName('シート1');

sheet.getRange('A1').insertCheckboxes();
```

#チェックボックスを追加し、チェックをつける
```
sheet.getRange('A1').insertCheckboxes().check();
```

#TRUE or FALSEの代わりにYES or NOの値でチェックボックスを追加する
```
sheet.getRange('A1').insertCheckboxes('YES', 'NO');
```

その他チェックボックスを削除する.removeCheckboxes()や、チェックを外す.uncheck()があります。
AWSを使ってデプロイ

#はじめに
　AWSを初めて使ってみたが、難しすぎる…
　完全に自分用メモ

##EC2のサーバーにログイン

```
ssh ~ user@ ~ #ユーザー名とElastic IP アドレスの入ったコード
```

<font color=red>以下、ログイン状態で実行</font>

##デプロイ方法

```
# 開発中のアプリケーションに移動
cd /var/www/アプリケーション名
```

```
# GitHubの内容をEC2に反映させる
git pull origin master
```

##Unicornの再起動方法
1. プロセスを確認

```
ps aux | grep unicorn
```
2. プロセスをkill

```
kill プロセス番号
```
3. unicorn_railsコマンドを実行

```
RAILS_SERVE_STATIC_FILES=1 unicorn_rails -c config/unicorn.rb -E production -D
```

##エラーログの確認

```
sudo less /var/log/nginx/error.log
```
PC-98のC言語(TurboC++)で湯婆婆を実装してみた

#始めに
先週辺りに、「◎◎で湯婆婆を～」というのが流行ってました。今となっては遅いですが、「入力文字列からランダムに一文字選んで表示する」と捉え、練習のつもりで作ってみました。
#環境
PC-9821Cx + TurboC++1.01 + vz1.6 + ms-dos6.2
ちなみにODP(DX66MHz相当)を積んでます。今回は関係ないですけど。
#コード
```c:yubaba.c
/***********************************
 yubaba.c
 
 > tcc yubaba
 
 ***********************************/
#include <stdio.h>
#include <stdlib.h>
#include <dos.h>
#include <string.h>

#define MES1 "湯婆婆：契約書だよ。そこに名前を書きな。\n\r"
#define MES2 "湯婆婆：フン、%s というのかい。贅沢な名だねえ。\n\r"
#define MES3 "湯婆婆：今からおまえの名は %s だ。いいかい、%s だよ。\n\r"
#define MES4 "湯婆婆：分かったら返事をするんだ、%s ！！\n\r"

int main()
{
	char name[256],new_name[3];
	int len;
	float r;
	struct time t;
	
	gettime(&t);
	srand(t.ti_hour*100+t.ti_min*10+t.ti_sec);
		
	printf(MES1);
	printf("　　　　名前を全角で> ");
	gets(name);
	len = (int)strlen(name)/2;
	r = 1+rand()%len;
	
	if (r >= len) r-=2;
	new_name[0]=name[2*r];
	new_name[1]=name[2*r+1];
	new_name[2]=NULL;
	printf(MES2,name);
	printf(MES3,new_name,new_name);
	printf(MES4,new_name);
	
	return len;
}
```
#実行例
```
B:\SRC\C\TEXT>yubaba
湯婆婆：契約書だよ。そこに名前を書きな。
　　　　名前を全角で> アブドーラ・ザ・ブッチャー
湯婆婆：フン、アブドーラ・ザ・ブッチャー というのかい。贅沢な名だねえ。
湯婆婆：今からおまえの名は ャ だ。いいかい、ャ だよ。
湯婆婆：分かったら返事をするんだ、ャ ！！

B:\SRC\C\TEXT>yubaba
湯婆婆：契約書だよ。そこに名前を書きな。
　　　　名前を全角で> ジャイアント馬場
湯婆婆：フン、ジャイアント馬場 というのかい。贅沢な名だねえ。
湯婆婆：今からおまえの名は ト だ。いいかい、ト だよ。
湯婆婆：分かったら返事をするんだ、ト ！！

B:\SRC\C\TEXT>yubaba
湯婆婆：契約書だよ。そこに名前を書きな。
　　　　名前を全角で> キン肉マン
湯婆婆：フン、キン肉マン というのかい。贅沢な名だねえ。
湯婆婆：今からおまえの名は 肉 だ。いいかい、肉 だよ。
湯婆婆：分かったら返事をするんだ、肉 ！！

B:\SRC\C\TEXT>yubaba
湯婆婆：契約書だよ。そこに名前を書きな。
　　　　名前を全角で> テリーマン
湯婆婆：フン、テリーマン というのかい。贅沢な名だねえ。
湯婆婆：今からおまえの名は マ だ。いいかい、マ だよ。
湯婆婆：分かったら返事をするんだ、マ ！！
```
#考えたこと

+ 「入力文字列の○文字目だけを選んで表示する」のは簡単にできた。
+ 漢字は２バイトで１文字を表す。乱数で適当に文字（実際は○バイト目）を選んだ場合、偶数バイトが最初に来ると、漢字コードが正しく選ばれない状態になり、まったく違う漢字になってしまった。ので、乱数で発生させた数値は必ず奇数バイト目になるようにした。
+ srand()のランダムシードの作り方、もっと効率いい方法ないですか？私はプログラムの基本を全く知らない・・・。
+ もっといい方法があるかもしれません。includeファイルは、これでいいんでしょうか？検証する気がないです。
Firebase storageのセキュリティルールを理解したい

# 0. 前書き
　本記事は、拙作[Firestoreセキュリティルールを読み解く](https://qiita.com/hiroki-harada/items/99d13efe432eb89e9391)のFirebase storage版みたいな位置づけです。
調べた事をつらつら書いていきます。どなたかの参考になれば幸いです。


# 1. Firebase storageとは
　例によって、Firebase storage(以下、storage)公式ドキュメントを参照します
> Cloud Storage は、写真や動画など、ユーザーが作成したコンテンツを保管、提供する必要のあるアプリ デベロッパー向けに構築されています。
> 
> Cloud Storage for Firebase は、Google 規模で構築された、強力かつシンプルでコスト効果の高いオブジェクト ストレージ サービスです。Cloud Storage 用の Firebase SDK では、ネットワーク品質にかかわらず、Firebase アプリでのファイルのアップロードとダウンロードに Google のセキュリティが適用されます。この SDK は、画像、音声、動画、またはその他のユーザーが生成したコンテンツを格納する場合に使用できます。サーバーでは、Google Cloud Storage を使用して同じファイルにアクセスできます。
https://firebase.google.com/docs/storage

写真は保存できそうだと思っていましたが、動画もいけるんですね。。。凄い。。。

# 2. デフォルトルールの確認
　続いてstorageを見てみます(左の数字は行番号です)。
firestoreとは違い、storageのルールは認証済みユーザしか受け付けないようになっています。[^21]

```shell
1 rules_version = '2';
2 service firebase.storage {
3   match /b/{bucket}/o {
4     match /{allPaths=**} {
5       allow read, write: if request.auth != null;
6     }
7   }
8 }
```

　1, 2行目は特に疑問はないでしょう。
3行目ですが、firestoreのルールの対応しそうな箇所(下記)と比較すると`b`は`bucket`、`o`は`obuject`と類推できます。

```shell
match /databases/{database}/documents {
```
`{bucket}`の部分ですが、バケットが一つの場合は`(default)`が設定されているのでしょう。
また、firestoreだとデータベースが1プロジェクト1つですが、storageの場合は有料プランなら複数バケットを持てるため、場合によっては具体的なバケット名を指定する事に意味がありそうです。

```shell
4     match /{allPaths=**} {
5       allow read, write: if request.auth != null;
6     }
```
4行目が、バケットの全オブジェクトに対してルールを適用するよう記載しています。
バケットにフォルダを作成して、そのフォルダ配下にあるオブジェクトにルールを課す書き方もできます。ただし、storageのルールは制約が緩い方が適用されるため、全オブジェクトに対するルールを設定する場合は注意が必要です(参考2)。

# 3. 具体的なルールを設定してみる
ここまでを踏まえて、具体的にルール設定してみます。
要件は、
①ルート直下のファイルは認証無しで閲覧可
②ルート直下のファイルの編集は認証が必要
③ルート配下のユーザ毎のフォルダ配下の全ファイルはそのユーザでないと閲覧、編集できない

って感じにしてみましょう。
すると、設定すべきルールは以下のようになります。
②のルールを設定する際に、条件を関数化することもできます(参考3)。

```shell
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {

    function isAuthenticated() {
      return request.auth.uid != null;
    }

    match / {
      allow read: if true;
      allow write: if isAuthenticated();
    }

    match /{userId}/{allPaths=**} {
      allow read, write: if request.auth.uid == userId;
    }
  }
}
```
　
また、storageの構成は以下のようになっています。
ユーザIDをフォルダ名にして作成します(上記の`{userId}`の部分に対応)
![Inkedimage_2020_11_22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314204/ccd35f71-8640-ba8c-04a5-4b55d76ace47.jpeg)
　
ファイル名に指定したユーザIDはこちらで確認。
![Inkedimage_2020_11_22_2_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/314204/11590239-09f6-6d3d-79e3-0891d39b92f1.jpeg)


# 参考
１．[【公式ドキュメント】Cloud Storage](https://firebase.google.com/docs/storage)
２．[Firebase storageのセキュリティルールについて](https://qiita.com/okkuyama/items/d3877cc7e3b0ed7c83d0)
３．[【Firebase】Cloud Storage セキュリティルール条件の書き方](https://mintaku-blog.net/storage-securityrule/)

[^qt]: 
[^21]: リクエスト期限(storageを使用可能にしてから1ヶ月など)も設定されていないのも気になります。なにかあるのでしょうか。。。？
EC-CUBE4 プラグインのテンプレートを上書きする方法

EC-CUBE4のバージョン**4.0.5**にアップデートによって、プラグインのテンプレートを直接編集することなく*app/template*フォルダ内で編集することが可能になりました。

# 実装方法
このようなプラグインのファイル配置のとき、

```
[app/Plugin/Sample]
│ 
├── Controller
│   └── Admin
│       └── Controller.php
├── Resource
│   └── template
│       └── admin
│           └── config.twig
```

*app/template/plugin/Sample/admin/config.twig*に配置することで、こちらを優先して読み込まれます。

```
[app/template]
│
├── admin
├── default
├── plugin
│   └── Sample
│       └── admin
│           └── config.twig
└── user_data
```

#サンプル
商品レビュープラグインのテンプレートを編集してみようと思います。
※ちなみに、こちらです。https://www.ec-cube.net/products/detail.php?product_id=1756

対象ファイルは*app/Plugin/ProductReview4/Resource/template/default/review.twig*です。

```twig:review.twig
<div id="reviewContent">
      ...
            {% else %}
                <p>{{ 'product_review.front.product_detail.no_review'|trans }}</p>
            {% endif %}
        </div>
```

*app/template/plugin/ProductReview4/default/に編集したreview.twigを配置。

```twig:review.twig
<div id="reviewContent">
      ...
            {% else %}
                <p>{{ 'product_review.front.product_detail.no_review'|trans }}</p>wwwwwwww
            {% endif %}
        </div>
```

編集後はキャッシュを削除しましょう。

```
php bin/console cache:clear --no-warmup
```
![スクリーンショット 2020-11-15 22.37.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649661/e7c3f6ef-c263-cd61-c3ea-6b1a41e9f436.png)
↓編集後↓
![スクリーンショット 2020-11-15 22.42.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/649661/80ad2734-21ec-c6d4-339c-c71bb16a9a6b.png)