OmniAICreator/Qiita-1.07M huggingface dataset:
「新・明解Pythonで学ぶアルゴリズムとデータ構造」で勉強日記#3

[前回の続きです](https://qiita.com/kato_squalldeka/items/1ef9e8f1de43b019bf73)
【出典】[「新・明解Pythonで学ぶアルゴリズムとデータ構造」](https://www.amazon.co.jp/%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E6%9F%B4%E7%94%B0%E6%9C%9B%E6%B4%8B/dp/4815603197/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1BG3JS7CKMZA0&keywords=Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0&qid=1644336329&sprefix=python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0%2Caps%2C212&sr=8-2)



すごい中途半端なスタート・・・。

#繰り返しの過程における条件判定（その3）
for文の続きですね。前回までは改行をしないプログラムでしたが、ここでは改行を指定します。
次の文は*をn個w回改行します


```python:list1-14
#n個の記号文字*をw個ごとに改行しながら表示（その１）

print('記号文字*を表示します。')
n = int(input('全部で何個：'))
w = int(input('何個ごとに改行：'))

for i in range(n):
    print('*', end='')
    if i % w == w-1:
        print()      #改行

if n % w:
    print()         #改行

```
そして例のごとくその１はif文が処理回数を増やすので効率的でないということですね。
変更したのが↓で

```python:list1-15
#n個の記号文字*をw個ごとに改行しながら表示（その２）

print('記号文字*を表示します。')
n = int(input('全部で何個：'))
w = int(input('何個ごとに改行：'))

for _ in range(n // w):
    print('*' * w)
    
rest = n % w
if rest:
    print('*' * rest)
```
また_出てきましたね。変数を置くまでもない時に使えばいいのでしょうか？
そしてまた商と余りを使った書き方ですね。
商の回数for文を回して（改行）w個並べ、余りの文は最後の行に余りの数だけ*を並べるというようなイメージでしょうか？

#正の値の読み込み
ここでは、負の数を消す処理をしていますね。
初回のlist1-8では負の数を代入すると処理できなかったので修正版として↓

```python:list1-16
#1からnまでの総和を求める（nに正の整数値を読み込む）

print('1からnまでの総和を求めます。')

while True:
    n = int(input('nの値:'))
    if n > 0:
        break
        
sum = 0
i = 1

for i in range(1, n + 1):
    sum += i
    i += 1
print(f'1から{n}までの総和は{sum}です。')
```

'pythonでは後判定繰返しのための繰返し文が提供されないため、前判定繰り返し文とbreak文を組み合わせる必要がある'


**コラム1-11：for文終了時のカウンタ用変数の値**
コラムでちょこちょこ注意点を書いてくれていてありがたいです。

while i <= n:  繰返し終了時のiの値はn + 1
for i in range(開始値, n + 1):繰り返し終了時のiの値はn

#辺と面積が整数値である長方形
```python:list1-17
#縦横が整数で面積がareaの長方形の辺の長さを列挙

area = int(input('面積は：'))

for i in range(1, area + 1):
    if i * i > area: break
    if area % i : continue
    print(f'{i}x{area // i}')
```

'continue文が実行されると、ループ本体内の後続部の実行がスキップされて、プログラムの流れが判定に戻る。'

コンテニューと聞くと続きそうなイメージが先行されちゃうんですが、後続部が飛ばされて処理すんですねー。混乱しそう。

```python:list1-18
#10 ～99の乱数をn個生成(13が生成されたら中断)

import random

n = int(input('乱数は何個：'))

for _ in range(n):
    r = random.randint(10, 99)
    print(r, end=' ')
    if r == 13:
        print('\n事情により中断します。')
        break
else:
    print('\n乱数生成終了')
```

'else節はbreakが実行されなかったときのみ実行される。'
今までifの中で使うものと認識してた・・・。

本日は以上です。ありがとうございました。
ケース作成フォームをコミュニティに追加する！

# ケース作成フォームで挫折する
コミュニティに「ケース作成フォーム」コンポーネントを追加してもたら、真っ赤な文字でエラーが出て唸ったのでその対処法。

1. グローバルアクションを作る！
2. パブリッシャーレイアウトに追加する！
3. ゲストユーザのプロファイルいじる！
4. Force.comで設定いじる
5. 「ケース作成フォーム」のプロパティ設定する！

でなんとか出ました。
ちょっと気になる点もあるので併せて記載します。

## グローバルアクションを作る！
ケース作成フォームはグローバルアクションを通じてレイアウトなども表示しています。
なので、
グローバルアクションをつくるかあるものを利用します。
私の場合は**GuestCommunityCase**を利用したかったのでそのまま利用しました。
運悪くない場合は一から作ってくださいませ。

## パブリッシャーレイアウトに追加する！
グローバルアクションを作ったら次はパブリッシャーレイアウトに追加しないと利用できません。
設定からパブリッシャーレイアウトを検索して**グローバルパブリッシャーレイアウト**を編集して、
**Salesforce Classic パブリッシャーのクイックアクション**セクションに追加してくださいませ。これで利用できます。

## ゲストユーザのプロファイルいじる！
ゲストの問い合わせフォームを作ってたのでゲストプロファイルの設定を行います。
コミュユーザの場合は必要なプロファイルに設定してください。
ゲストユーザプロファイルはコミュニティのビルダーにある設定＞全般からしか行きます。
「ゲストユーザプロファイル」項目に表示されてるリンクからゲストプロファイルにいって、

1. ケースオブジェクトに作成、参照権限を与えます。
2. ケースオブジェクトの項目アクセス権は必要に応じてチェックで。編集権ないと作成できませんからね。

## Force.comで設定いじる
サイト設定にいきます。コミュニティの管理＞ページ＞Force.com に移動です。
編集すると**サポート API へのゲストアクセス**って項目がありますのでチェックを入れるとグローバルアクションが選択できます。
１でつくって２で追加したグローバルアクションを選択してやりましょう。

## 「ケース作成フォーム」のプロパティ設定する！
最後にコミュニティのビルダーで好きなページに**「ケース作成フォーム」コンポーネン**トを追加してやればいいのです！
が、注意が一つ。
プロパティに**パブリッシャーのアクション**って項目があるのでそこに1で作って2で公開したグローバルアクション名を記載しないとだめっす。
今回だとGuestCommunityCaseって記載します。

これでめでたくケースがゲストから作成できます。よかったよかった。
Javaのオーバーロードについて学習をしてみた

今回はJavaのオーバーロードについて学習をしたのでまとめてみようと思います。

#オーバーロードとは

オーバーロードというのは、同じ関数名で様々な値を扱いたい時に役に立ちます。
処理は同じだけど、渡す引数の値が違うときにそれぞれの関数を作成していくことは間違いではありません。
しかし、どうせ処理が同じなら同じ関数名で使えるようにしたほうがいちいち違う関数について覚える必要がない上に、設計書にそういったことを書かなくていいので便利です。
今回はそんな便利なオーバーロードの使い方について紹介したいと思います。


# 書き方

```main.java
  public static void main(String args[]){

    int a = culclate(11, 2);
    System.out.println(a);
    
    String b = culclate("算数", "数学");
    System.out.println(b);
  }
  
  private static Integer culclate(Integer culc1, Integer culc2){
    return culc1 * culc2;
  }
  
  private static String culclate(String elementary, String middle){
    return elementary + "は小学校までで中学校からは" + middle;
  }
```

というように、同じ関数名の引数に対してそれぞれ違う値を入れて違う処理をさせることができるわけです。
今回は少々強引ですが計算に関するものを同じ関数として扱いたいのでこういった形にしました。
こうすることで同じメソッド名に違う型で違う値の引数を渡して実行させることができました。
実際これを見れば様々な役割の関数を一つの関数名でつくることがかのうになっていることを見ることができると思います。

ちなみになのですが、コンストラクタをオーバーロードさせて動かくこともできます(これ知った時へぇ~って驚いた)。

コンストラクタというのは、かんたんに説明すると特別な関数みたいなものです(詳しくはググってくれ)。
やり方としては、

```computer.java
class computer{
	public static void main(String[] args) {
    new cmpParts("Windows10", 16384);
    new cmpParts(1024);
  }
}

class cmpParts{
  cmpParts(String os, Integer memory){
    System.out.println("OSは" + os + "でメモリは" + "GBです。");
  }

  cmpParts(Integer ram){
    System.out.println("1GBにつき" + ram + "MBです。");
  }
}
```
このように、コンストラクタに対してもオーバーロードをしてそれぞれ違う引数の値と型の値をcmpPartsというコンストラクタに与えることができています。

これは非常に便利です。
例えば、引数として渡って来る値が場合によって違う場合(ユーザーが入力をしてきた項目の数)などにこれを使えばそれぞれ違う引数の値で違う処理を実装することができます。
ユーザーがどのくらいの項目を入力してきたのかによって返す値を変えたいときなどにこれを使えば非常に便利だと思います。
# 余談
コンストラクタは胸中処理を書いていくためのものですが、そのコンストラクタに対しても共通処理を作成することができます。
初期化子というものです。
構文は

```
{
　　　　実装内容
}
```
とかくだけです。
これはコンストラクタが実行されるたびに実行されるので、試しにコンストラクタの処理をまとめて書いてあるクラスのcmpPartsに対して書いて出力をさせると

```
パソコンのOSについて表示します。
OSはWindows10でメモリはGBです。
パソコンのOSについて表示します。
1GBにつき1024MBです。
```
と表示されます。
このように、コンストラクタが実行されるたびに初期化子の処理が動いています。

```Java
class cmpParts{
	{
		System.out.println("パソコンのOSについて表示します。");
	}
	cmpParts(String os, Integer memory){
		System.out.println("OSは" + os + "でメモリは" + "GBです。");
	}

	cmpParts(Integer ram){
		System.out.println("1GBにつき" + ram + "MBです。");
	}
```

ちなみにコードは上記のようになります。

以上になります。

# 参考サイト
https://kanda-it-school-kensyu.com/java-basic-contents/jb_ch05/jb_0501/
https://www.javadrive.jp/start/method/index8.html
node.js v16 で nexeのコンパイルがこけてしまった時の対処法

# nexeとは

> 引用： Nexeは、Node.jsアプリケーションを単一の実行可能ファイルにコンパイルするコマンドラインユーティリティです。

https://github.com/nexe/nexe

# 使用環境
* macOS `11.5.1` (Intel)
* node `v16.13.2`
* nexe `4.0.0-beta.19`

# 発生した事象
* `npx nexe {project.js}` してみる。
    * エラーが出て `using the --build flag` と表示される。
* `npx nexe {project.js}　--build　` してみる。
    * `Error: python ./configure.py --dest-cpu=x64 exited with code: 1`
    というエラーが出てコンパイルが失敗してしまう

# 解決策
下記のissue 参照。
https://github.com/nexe/nexe/issues/926

`npx nexe src/index.js --build --verbose --python python3`
とすることでコンパイルがが成功した。
（なお今回使用したプロジェクトの場合、初回コンパイルに数時間を要した）
（2回目以降は30秒程度でコンパイルできている）
openFrameworksでMac英数キー・かなキーの入力がスペースキーになってしまう問題

openFrameworksではなぜか**英数キー**を押すと**スペースキー**として処理されてしまう。

私の場合、基本的にはプログラムを書いているので、常に半角英数入力になるように、手癖で英数キーをポチポチ押してしまうのですが、
意図せずにスペースキーに実装した機能が走ってしまい非常にうざい。


```c++:ofApp.cpp
void ofApp::keyReleased(int key) {
  cout << key;
}
```

このようなプログラムを走らせると
Macの日本語キーボードの場合、
スペースキー・英数キー・かなキーが全部`32`になります。


## 回避策

```c++:ofApp.cpp
void ofApp::keyReleased(ofKeyEventArgs & key) {
  cout << key.key;
  cout << key.keycode;
  cout << key.scancode;
}
```

`ofKeyEventArgs` を使った実装であれば、それぞれのキーを個別に判定することが可能です。
`key.keycode`と`key.scancode`の中身が異なります。


### スペースキーの場合
```c++
  cout << key.key // 32;
  cout << key.keycode // 32;
  cout << key.scancode // 49;
```

### 英数キーの場合
```c++
  cout << key.key // 32;
  cout << key.keycode // -1;
  cout << key.scancode // 102;
```

### かなキーの場合
```c++
  cout << key.key // 32;
  cout << key.keycode // -1;
  cout << key.scancode // 104;
```
100日でSQLの達人になる@LeetCode! Day8 <WHER 変数 NOT IN (SELECT文)> 要リベンジ

## 176. Second Highest Salary （問題レベル: Medium）
今日の問題はこれ。
二番目に大きい数を表示するという問題。

まだ投稿していないEasyレベルの問題もあるのだが、一通り解いたので今日からMediumにチャレンジ。

この問題は、初見では、行数を取得するのかと思い調べて、
`RANK() OVER(ORDER BY 変数 DESC)`を使うのかと思いコードを記載。実際これで半分正解だった。
しかし、テーブルに１つしか値が入っていない場合は、二番目に大きい数が無いので`NULL`を返す必要があり、Acceptされなかった。
この方針で突き進むと、`ISNULL()`(注)を使ったり、`SELECT文`いくつも記載する必要があって断念。
実際Discussionには５つ以上の解法があるとのこと。
その中で一番シンプルでわかりやすい解答を今回は採用し一旦終了。
もう少し力を付けたら戻ってきて、別の解法も試してみたい。
とりあえず、`WITH句`とか学びが多い問題だった。

そこで今回のポイントは`WHERE　変数 NOT IN (SELECT文)`とした。
`NOT IN`以降にテーブルの最大値を取得する`SELECT文`を持ってきて、１番を除外した１番（つまり２番）を持ってくるという解法。
３番とか４番とかには使いにくいと思うが、なかなかスマートな解法だ。

注: MySQLでは`IFNULL()`を使用する。`COALSCE()`を覚えたほうが良いのかも。

* [LeetCode](https://leetcode.com/)の問題は、`MS SQL Server`で解いています。
256kbpsの信号をLANケーブルで5m通信してみた

##はじめに
今まで以下の記事で伝送がどうこうって色々やってたが、　元々256kbpsを5mの距離をシングルエンドのままLANで送れるかどうか知りたくて始めたので実際に試してみる。
あんまり中身の無い記事だが、誰かが同じことやりたいかも知れないので実績残しの為に書く

[ESP32で500円3chプログラマブルオシレータ「Si5351A」を使ってみた](https://qiita.com/DaigoNomura/items/fe10430e0b5192d691e4)
[シングルエンド伝送、差動伝送についてのメモ](https://qiita.com/DaigoNomura/items/6f08e962e223073ba88d)
[差動伝送で距離5mの信号を送ってみてシングルエンドと比較してみた](https://qiita.com/DaigoNomura/items/6f08e962e223073ba88d)

##どうやって試したか
GBA(ゲームボーイアドバンス)の通信ケーブルでの通信が256kbpsらしいのでとりあえず通信ケーブルぶった切ってLANケーブルに接続して正常に通信が出来るか（通信エラーが起きないか）確かめた
写真は版権の問題とかがありそうなので無しで…

通信ケーブルは分解してみたら真ん中のブロック(３，４人通信の時に使うやつ)の所で結線を変えていたので、
そこでぶった切るなら結線を以下のように変える

![キャプチaaaャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/867623/02aefcaf-40d7-a8f7-a5b9-9cdfb97f3397.png)

そこを避けて切るなら同じ色を繋げるだけで良いだろう。

##結果
GBAの通信ケーブルをLANで5m伸ばしてみた結果
対戦ゲームで試してみても特に通信エラーは起きず。
今までの実験結果より、遅延も20nsくらい(なハズ)なので当たり前だが、操作の遅延も体感できず。

以上
Golangでフロントエンドを作るならどうするかの検討メモ（簡単なWEB＝Golang×Gin）

# はじめに
もしGoでWEB画面作るなら、っていう過程で色々調べてみる記事。
結論はタイトルに書いてある。

# 1.ググる
[前回](https://qiita.com/nh321/items/e72de28852e5171857b0)と同様の過ちを繰り返す。人間とはそういうモノである。

「Golang Frontend」でググった。

http://golang.rdy.jp/govecty/#/

- 破壊的な変更も含まれる話だったので、本格利用には対象外・・・
- いつの話かわからんけど

https://www.slideshare.net/hico_horiuchi/goweb-58764875

- Feb. 26, 2016：ちょっと古いなー
- 内容はいいんだけど、やっぱり新しい情報が欲しい

https://liginc.co.jp/567735

- 2021.10.22：新しいジャーン
- と思ったけど、言語として触ってみたレベルの話だった。

https://blog.logrocket.com/getting-started-with-go-for-frontend-developers/

- 2021年5月13日：悪くない
- ちょっと煽ってる感があるからあんまり好きじゃない。
- まぁやっぱりデファクトスタンダードなフレームワークはないっぽい。
- だけど、選ぶだけの価値があるよー的な話をしてる

https://stackoverflow.com/questions/60129763/how-do-you-create-front-end-in-golang-and-other-questions

- 回答→2020年2月8日：古くはない
- React/Goを推奨されてたけど、質問内容は初心者っぽいので、あんまり参考にはできないかも。

https://blog.decipher.dev/golang-for-frontend-developers-a-beginner-guide-to-golang

- ちょっとしたチュートリアル記事なだけだった。そういうことじゃないんだよなー。

https://github.com/kyoto-framework/kyoto

- kyotoと呼ばれるGoのフロントエンドライブラリ。
- まだv0.2。プロダクトとして使用するにはまだ至らないかな・・・

# 2.公式ドキュメント

https://go.dev/doc/

https://go.dev/doc/articles/wiki/

ちょっとしたWEBサイトのチュートリアル的な感じだなぁ・・・
う〜ん・・・

# 結論
エンタープライズとして使うにはまだ早そう。
ただ、これから来そうな感じを出してる人もいる。（海外の記事では、そういう人はよく居るので、あんまり信用はしてない。）

Goじゃなさそうだなぁ・・・う〜ん。。。。

# 2022/02/11追記

https://twitter.com/hikarine3/status/1491653385321615361

Ginがかなり伸びてきてる様子。エンタープライズ向けではないのものの、簡単なWEBくらいだったらデファクトになりつつあるって感じかな・・・
選ぶとしたらこれかなぁ・・・
セキュリティことはじめ

セキュリティ勉強したいけど、何すればいいの！？という方向けの記事です。
サイトの脆弱性診断などについても書きます。

## 参考になるもの

### IPAのサイト

[安全なウェブサイトの作り方：IPA 独立行政法人 情報処理推進機構](https://www.ipa.go.jp/security/vuln/websecurity.html)
ここに載っているものはメジャーなものなので、それぞれの攻撃方法・対策方法を学習していくと良いと思います。

```
1 SQLインジェクション
2 OSコマンド・インジェクション
3 パス名パラメータの未チェック／ディレクトリ・トラバーサル
4 セッション管理の不備
5 クロスサイト・スクリプティング
6 CSRF（クロスサイト・リクエスト・フォージェリ）
7 HTTPヘッダ・インジェクション
8 メールヘッダ・インジェクション
9 クリックジャッキング
10 バッファオーバーフロー
11 アクセス制御や認可制御の欠落
```

### OWASP TOP 10

[OWASP Top 10:2021](https://owasp.org/Top10/ja/)
影響度や発生率などを考慮して気をつけるべき項目をランキング付されたものです。
2~3年毎ぐらいに発表されていて、現在の最新は2021版です。

```
1 アクセス制御の不備
2 暗号化の失敗
3 インジェクション
4 安全が確認されない不安な設計
5 セキュリティの設定ミス
6 脆弱で古くなったコンポーネント
7 識別と認証の失敗
8 ソフトウェアとデータの整合性の不具合
9 セキュリティログとモニタリングの失敗
10 サーバーサイド・リクエスト・フォージェリ
```

### セキュリティの本

[体系的に学ぶ 安全なWebアプリケーションの作り方 第2版 脆弱性が生まれる原理と対策の実践 | 徳丸 浩 | Amazon](https://www.amazon.co.jp/dp/4797393165)

通称・徳丸本は分厚いですがタイトルの通り体系立てられていてすごく勉強になるのでおすすめです。
著者の徳丸さんはセキュリティ界の第一人者で、[Twitter](https://twitter.com/ockeghem)もやってるのでフォローしておいて損はないと思います。


## 脆弱性診断

### 診断ツール

脆弱性診断ツールは有償・無償問わず多くあります。
ここでは例として[OWASP ZAP](https://www.zaproxy.org/)というOSSを紹介します。
インストールして動的スキャンを実行すると、アラートとして脆弱性のある箇所を教えてくれます。

![zap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/465d1285-710f-ed31-c423-cc6873394c91.png)


パラメータ等を設定すればログイン後の画面なども検証してくれます。
ただ、システムにゴミデータを残したりするので本番環境以外で実行することをお勧めします。

### IPAのチェックリスト

ツールは便利ですが完全ではないため、手動で検証していくことも大切です。
IPAのサイトの[ここ](https://www.ipa.go.jp/files/000044403.xlsx)(ダウンロードされます)に優秀なチェックリストがあるので、これに沿って検証していくと良いと思います。

![doga_20191026_01_00.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/140953/bb69512e-afdd-1b92-bf04-e91d764f4b9c.jpeg)

## おまけ

WAFなど低レイヤーの設定の見直しや、使用ライブラリやフレームワークのバージョンをLTS版にアップデートするだけでもセキュリティ強化になったりすると思います。

ついでにレスポンスヘッダーに追加するだけでセキュリティ強化できる種類の紹介です

```
・x-frame-options: sameorigin または deny → 外部サイトのiframe内部に表示できなくする
・x-content-type-options: nosniff  → MIMEタイプの解釈を厳密にさせる
・x-xss-protection: 1; mode=block → XSSフィルタの設定を強制する 
・content-security-policy: よしなに → スクリプトやメディアの読み込み元を限定する
・strict-transport-security: よしなに → HTTPS接続を強制する常時TLS
```

## おわりに
対策方法は調べればわかるんですが、システムごとに構成は違うため手段として具体的にどこにどのように設定するかというのは、仕組みを理解して考えないといけない少し難しいところかなと思います。
知識をつけるのは前提として、ぜひ実務に落とし込んでセキュリティ対策やっていきましょう！
記事に間違いなどありましたら遠慮なくご指摘ください。

おしまい！
FactoryBotにおけるassociationとは

##associationとは
関連するデータを一緒に作成してくれるメソッド。
例として``task``を作成する際に、``project``も作成必須の場合で``association``無しのコードを見てみると、

```rb
#associationを使わない方法
let(:project) { create(:project) }
let(:task) { create(:task,project: project) }
```
このように``task``と``project``の両方のテストコードを記述しなければならない。
本来なら、さらに関連するテーブルが増えていくので、後々しんどくなる。
これを解決するのが``association``メソッド。

##associationの記入法
``association``の記述の仕方は簡単で、　``Factory``にアソシエーションするものを記述するだけである。

```factories/tasks.rb
FactoryBot.define do
  factory :task do
    title { 'Task' }
    content { 'content' }
    association :project
  end
end
```


次に``spec``ファイルにて記入する。``association``の有無は以下の通り。

```rb
#associationを使わない方法
  let(:project) { create(:project) }
  let(:task) { create(:task,project: project) }

#associationを使った方法
  let(:project) { create(:project) }
  let(:task) { create(:task) }
```
アソシエーションしているので、**`` let(:task) { create(:task) } ``**と記載することで、``task``データ作成と同時に``project``データも作成され、``project``の``project_id``も自動で``id``が入るようになる。

-**``association``で作成するデータが被る場合**-
例えば``like``データを作成する時、以下のようにすると``task``データが2つ作られてしまう。

```likes.rb
FactoryBot.define do
  factory :like do
    # taskには「association :project」が宣言されているため
    # projectのデータが2つ作られることになる。
    association :project
    association :task
  end
end
```

``task``で作成された``project``を使えば解決する。

```likes.rb
FactoryBot.define do
  factory :like do
    association :project
    user { project.task }
  end
end
```

##associationをした事による引数に注意
例えば下記のようなテストコードがあったとする。この記述は``association``を使用していない記述である。

```rb
RSpec.describe 'Task', type: :system do
  let(:project) { create(:project) }
  let(:task) { create(:task,project: project) }
  describe 'Task詳細' do
    context '正常系' do
      it 'Taskが表示されること' do
        visit project_task_path(project, task)
        expect(page).to have_content(task.title)
        expect(page).to have_content(task.status)
        expect(page).to have_content(task.deadline.strftime('%Y-%m-%d %H:%M'))
        expect(current_path).to eq project_task_path(task.project, task)
      end
    end
  end
end
```

このコードを``association``を使って記述するとき、``let``の部分は``let(:task) { create(:task)}``と書けば済むが、

**``visit project_task_path(project, task)``**の引数をこのままでは、
``第１引数にtaskと結びついていないproject_idを呼び出す事になってしまう``。

第２引数の``task``に紐づくよう、第1引数は``task.project``にしなければならない。

```rb
# 上記のコードをassociationで記述した場合
RSpec.describe 'Task', type: :system do
  let(:project) { create(:project) }
  let(:task) { create(:task) } #ここと
  describe 'Task詳細' do
    context '正常系' do
      it 'Taskが表示されること' do
        visit project_task_path(task.project, task) #ここ
        expect(page).to have_content(task.title)
        expect(page).to have_content(task.status)
        expect(page).to have_content(task.deadline.strftime('%Y-%m-%d %H:%M'))
        expect(current_path).to eq project_task_path(task.project, task)
      end
    end
  end
end
```


##参考記事
[【FactoryBot】associationの使い方](https://qiita.com/Ryoga_aoym/items/741c57e266a9d811a2d4)
MS FluentUI DetailsList Tips

# FluentUI DetailsList Tips
FluentUIのDetailsListに役立ちそうなコードを載せていきます。

### 1.クリックでアイテムを選択した際に、すでに選択したアイテムが解除されないようにする

Detailsリストのセルをクリックすることで選択することができるのですが、チェックボタン以外の部分をクリックしてしまうとすでに選択したアイテムが解除されてしまいます。
#### 解決方法
selectionオブジェクトを作成し、setModal関数にtrueをセットしてDetailsListに渡すと、セルのどの部分をクリックしても選択したアイテムが解除されないようになります。

```js
const selection = new Selection()
selection.setModal(true);

const MyGrid = () => {

    return(
        <DetailsList items={items} columns={columns} selectionMode={2} selection={selection}/>
    );
}

```
### 2.上下キーで移動した際に選択したアイテムが変更されないようにする


#### 解決方法
ISelectionZoneProps型のオブジェクトを作成し、isSelectedOnFocusにfalseを、selectionにDetailsListに渡したものと同じselectionを渡します。
これをDetailsListのselectionZonePropsにセットします。
これで上下キーでフォーカスを移動してもアイテムの選択状況は変更されないようになります。

```js
const selection = new Selection()
selection.setModal(true);

const MyGrid = () => {

    return(
        <DetailsList items={items} columns={columns} selectionMode={2} selection={selection} 
        selectionZoneProps={{isSelectedOnFocus:false, selection:selection}}/>
    );
}
```
Vivado v2021.2にDigilent製のボードファイルを追加する方法

皆様、ごきげんよう。ちゃまおです。
Qiitaに記事を書くのはとても久しぶりになります。

最近、FPGAに手を出して、日々勉強していますが・・・FPGA難しいですね。
FPGAを購入した当初は、[参考書](https://www.shuwasystem.co.jp/book/9784798063263.html)に従って、Vivado v2020.1を使用していたのですが、何となく最新のVivadoを使いたくなって、v2021.2をインストールしました。

Vivadoはサードパーティ製のFPGAボードを使う際に、ボードファイルと言うものを自分で入れる必要があるのですが、少し手間取ったので、手順をここに載せておきます。

#開発環境など
- PC: Ubuntu 18.04.3 LTS
- FPGA: Zybo Z7-10
- FPGA開発ツール: Vivado v2021.2
- Vivadoのインストール先: `/tools/Xilinx/`

#やってみたこと

[FPGAの部屋](https://marsee101.blog.fc2.com/blog-entry-5276.html)や、[ひがし研究所](https://phys-higashi.com/73/)の記事によると、Vivado v2021.1では、新規プロジェクトを作成して、ボードを選ぶ下図の状況で、画面左下にある"Refresh"ボタンを押すことで、Zyboなどのボードをインストール出来るようになると書かれていました。

![Vivado-board-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/930492/e271d925-99be-d119-d6fa-76230321c989.png)

しかしながら、私の環境では、下図のように、Refreshボタンを押すと真っ白な画面となってしまいました。

![Vivado-board-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/930492/05d576d4-039d-8583-36ca-a47019f973fb.png)

さてどうしたものかと思いながら色々調べていたところ、[解決策となりそうな公式サポートページ](https://support.xilinx.com/s/question/0D52E00006qcrEYSAY/hi-i-am-trying-to-install-the-board-files-for-my-digilent-arty-s750-into-vivado-20212?language=ja)を見つけました。これによると、tclファイルにボードファイルの情報を書いてVivado起動時に読み込ませれば良いとの事でした。

上記のサポートページと、[こちらのサポートページ](https://support.xilinx.com/s/article/72033?language=ja)を参考にしながら、作業していきます。

[こちらのGitHubページ](https://github.com/Xilinx/XilinxBoardStore/tree/2021.2)の内容をZIPファイルでダウンロードします。ZIPファイルの解凍先は、Vivadoをインストールした場所にします。私の環境では、`/tools/Xilinx/XilinxBoardStore-2021.2/`となりました。

次に行うことは、tclファイルの作成です。作成場所は`~/.Xilinx/Vivado/2021.2/`です。ここに、`Vivado_init.tcl`と言うファイルを作成します。このtclファイルの中に、Digilent製のボードファイル情報を書きます。ただし、今回はZybo Z7-10だけ使いたかったので、ピンポイントで記述しています。他のボードでもボードファイルのディレクトリを指定すれば良いと思います。

```Vivado_init.tcl
set_param board.repoPaths {/tools/Xilinx/XilinxBoardStore-2021.2/boards/Digilent/zybo-z7-10/A.0}
```

その後、vivadoを起動すると、下図のように無事ボードが選択できるようになりました。

![Vivado-board-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/930492/4a5965f9-38cc-b48b-4832-a873e5f46491.png)
sshで公開鍵認証設定時にハマったこと(From Linux to Synology NAS)

# はじめに
Linuxサーバをクライアントにして、Synology NASへ定期的にデータをバックアップする
機会がありましたので、sshで公開鍵認証の設定を試みました。
しかし、いくつかうまく行かずハマってしまったポイントがありましたのでまとめてみます。

# ハマったポイント
 1．クライアントのサーバ(From)からNAS(To)に作成した公開鍵を保存できない
 2．クライアントサーバ(From)で作成した公開鍵をNAS(To)にコマンド1つでコピーできた！
 3．秘密鍵(From)、公開鍵(To)を設定後にssh接続した後にもパスワードを聞かれる

# 解決方法
## 1．クライアントのサーバ(From)からNAS(To)に作成した公開鍵を保存できなかった

確認ポイント1:Synologyの[コントロール パネル] > [端末と SNMP] > [端末] 画面に設定しているポートとクライアントサーバ側で設定しているSSHのポート番号が一致していること

確認ポイント2:SSH接続させるユーザはAdministratorグループに所属するユーザであること

下記、ポート番号の設定時に注意事項が載っていたので、
![NAS_Terminal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/770141/a42ba27f-4c0d-ac48-40c7-8579cd443bef.png)

公開鍵を持たせるユーザーにはadministrators groupを追加します。

![NAS_Admin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/770141/cbaf3f8d-9e19-fa69-0f0b-e9c5e79343fd.png)

次にssh-keygenコマンドを使って秘密鍵、公開鍵を作ります。

## 2．クライアントサーバ(From)で作成した公開鍵をNAS(To)にコマンド1つでコピーできた！
公開鍵を作成した後、手動でコピーする手間を省き、コマンドで簡単にできる方法をご紹介します。

クライアントサーバ(From)上で、以下のコマンドから鍵を作ります。

```
ssh-keygen -t rsa
```

次に、クライアントサーバ(From)上から、以下のコマンドで公開鍵をNAS(To)をコピーします。

```
ssh-copy-id [USERNAME]@[IP ADDRESS]
```

さらに、クライアントサーバ(From)上から、コピーが完了したらssh接続を試します。

```
ssh [USERNAME]@[IP ADDRESS]
```

Note: 初めて接続する場合には以下のようなメッセージが表示されるのでYesにします。
```
Are you sure you want to continue connecting (yes/no)? yes
```

ここでログアウトせず次のポイントを確認してください。
この続きをしておかないと、次にssh接続する際にもパスワードを聞かれるようになってしまいます。

## 3．秘密鍵(From)、公開鍵(To)を設定後にssh接続した後にもパスワードを聞かれる
コピーした公開鍵は、所有者のみがアクセスできるように設定する必要があります。
しかし、すべての設定が終わってからやればよいかなと思って、一旦置いてしまったためにハマりました

NAS(To)側にコピーされた公開鍵は
```
~/.ssh/authorized_keys
```

に保存されたことを確認するだけではいけません。
以下、ファイルとディレクトリのパーミッションを変更しておくことが必要です。


```
chmod 600 ~/.ssh/authorized_keys
chmod 711 ~/.ssh
chmod 711 ~
```

こうすると、一度ログアウトして、再度ssh接続する際にはパスワードは聞かれなくなります。

# さいごに
LinuxサーバからSynology NASにSSH接続するために、
ssh公開鍵認証設定の様々なページを探しながら進めていく中で、
細かい部分ではありますが引っかかった部分がありましたので、
Qiitaに書かせていただきました。
同じところで引っかかった方の参考となりますように。
【Ruby】dynamic constant assignmentというエラー

#状況
ページタイトルをhelperを使って動的に表示するために、以下のコードを書いた。

```ruby:application_helper.rb
def full_title(page_title)
  BASE_TITLE = "HOGE".freeze
  if page_title.blank?
    BASE_TITLE
  else
    page_title + " - " + BASE_TITLE
  end
end
```
ここで、BASE_TITLEは定数であるため、UPPER_SNAKE_CASEで定義している。
またrubyにおける定数は再定義ができるソフトな（破壊的変更が可能な）代物なので、再定義ができないようにfreezeメソッドを使って凍結しておいた。

実行した結果、
syntax errorとして以下のエラーが表示された

```
dynamic constant assignment
BASE_TITLE = "title"
^~~~~~~~~~
```
#対処法
メソッドの外で定数を定義する。

```ruby:application_helper.rb
BASE_TITLE = "HOGE".freeze
def full_title(page_title)
  if page_title.blank?
    BASE_TITLE
  else
    page_title + " - " + BASE_TITLE
  end
end
```

どうやらrubyでは、メソッドの中で定数を定義できない仕様になっているらしい。
シェルを同時並列実行する方法

複数のシェルをバックグラウンドで同時並走させるときは以下のように
コマンドを&(アンパサンド)で繋ぐといいらしいです。
&はリスト演算子に含まれるようです。

```
$ sh shell_1.sh & sh shell_2.sh & sh shell_3.sh & sh shell_x.sh
```

もちもん上記のコマンドをshファイルの中に記述して実行することも可能です。

下記ファイルで検証してみました

```shell_1.sh
#!/usr/bin/bash

DATETIME=`date +%Y%m%d_%H%M%S_%s`
echo "shell_1.sh start $DATETIME"

DATETIME=`date +%Y%m%d_%H%M%S_%s`
echo "shell_1.sh end $DATETIME"

```

```shell_2.sh

#!/usr/bin/bash

DATETIME=`date +%Y%m%d_%H%M%S_%s`
echo "shell_2.sh start $DATETIME"

DATETIME=`date +%Y%m%d_%H%M%S_%s`
echo "shell_2.sh end $DATETIME"

```

```shell_3.sh

#!/usr/bin/bash

DATETIME=`date +%Y%m%d_%H%M%S_%s`
echo "shell_3.sh start $DATETIME"

DATETIME=`date +%Y%m%d_%H%M%S_%s`
echo "shell_3.sh end $DATETIME"


```

```douji.sh

#!/usr/bin/bash

sh shell_1.sh & sh shell_2.sh & sh shell_3.sh
```

```
$ sh douji.sh
```

出力結果

```
$ sh douji.sh
shell_2.sh start 20220209_232155_1644416515
shell_1.sh start 20220209_232155_1644416515
shell_3.sh start 20220209_232155_1644416515
shell_1.sh end 20220209_232155_1644416515
shell_2.sh end 20220209_232155_1644416515
shell_3.sh end 20220209_232155_1644416515

```
VirtualBox上のUbuntu20.04、画面が見切れてしまう問題の解決方法

VirtualBox上でUbuntuを導入した際、画面が見切れてしまう問題で相当苦戦したので忘備録として投稿。

1.そもそも最初から画面が見切れていてインストールができなかったのでここで１つ目の詰まり。
→→→"Alt+F7"で、画面を掴むマークが出現！
2.なんとかインストールはできたが画面が小さくて見辛い...。
→→→Ubuntu内の'設定'から'ディスプレイ'、ここで自分が使用しているディスプレイの解像度に設定してあげることで解決！！
VirtualBox側で設定してあげてもできそうなのですが、自分はこの方法で解決しました。
まだまだ初心者なので勉強します...!
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2518736/1ceca474-67da-04b6-63ce-b0ca1c3582d3.png)
Raspberry Pi OSをDocker上で動かす

[RaspbianをDockerイメージに変換する](https://qiita.com/yuyakato/items/5dd06fb179922206044d)の[コメント](https://qiita.com/yuyakato/items/5dd06fb179922206044d#comment-885516a16b64e5e442a0)をみて感動したので、同じことをやってみました。

* ホストの環境

Raspberr Pi 4(8GB)
Ubuntu 20.04(64bit)

# 手順

* root.tar.xzを入手

```console
https://downloads.raspberrypi.org/raspios_lite_arm64/root.tar.xz
```

* Dockerイメージとしてインポート

`docker pull`しかやったことなかったですが、イメージをインポートすることができるんですね。

```console
docker image import ./root.tar.xz raspios_lite_arm64:2022-01-28
```

以上です。

コンテナを起動するときは、entrypointの指定が必要です。

```console
docker run -it --rm --entrypoint /bin/bash raspios_lite_arm64:2022-01-28
```

# armhf版もいけました

ちなみに、64bit版OS上で32bit版(armhf)も起動できました。

```console
wget https://downloads.raspberrypi.org/raspios_lite_armhf/root.tar.xz
docker image import ./root.tar.xz raspios_lite_armhf:2022-01-28
docker run -it --rm --entrypoint /bin/bash raspios_lite_armhf:2022-01-28
```

[こちら](https://devlights.hatenablog.com/entry/2020/11/10/151736)の情報を参考に、32bitかどうか確かめてみました。

```console
root@f15b0214d185:/# file -e elf /bin/apt
/bin/apt: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV)
root@f15b0214d185:/#
```

32-bitと表示されました。

Kubernetes上でRaspberry Pi OSが動きますね！夢が広がります🤣
シェルって結局なに？

## 勉強前イメージ

コマンドの集まり的な？
bashとshを調べるに当たってまずシェルのを調べないと

## 調査

### シェル とは

OSをこうするソフトウェアの一つで、ユーザからの操作を受け付ける窓口になります。
ユーザからのコマンド入力で、シェルはカーネルとやり取りをしてプログラムを呼び出し立ち上げます。
シェルはユーザとカーネルの間に入ってコマンドを解釈してカーネルに伝えたり、プログラムの結果をシャルが解釈してユーザに表示させます。

### シェルの種類

大きく以下の5つがあります。

- sh

古くからあるシェルで、Steven Bourne氏によって開発されたのでその名ちなんで `Bシェル` と呼ばれています。
古くから今でも標準シェルとして使用されています。

- bash

Bシェルを拡張して作られたのがbashです。
Bourne Again Shellが正式名称です。
Bシェルと互換性を持つため、書き換えることが可能です。

- csh

C言語に似た構文から `Cシェル` と呼ばれています。
Bシェルに比べて対話をする場面では便利な機能があリますが、文法がBシェルとは違います。
Cシェルの後続としてTCシェルが存在します。

- tcsh

CシェルにTenexの機能(ファイル名などの補完機能があるシステム)を組み込んだのが `TCシェル` です。
Cシェルとは違い、対話をする場面で便利な機能があります。

- zsh

bashやTCシェルのいいとこ取り+拡張をしたのが `Zシェル` になります。
多機能な故使いこなすには時間がかかりますが、効率よく作業を行うことができます。

### 今使える(使ってる)シェルの確認方法

- 現在使用しているシェルの確認方法

`echo $SHELL` のコマンドで確認できます。
実行結果は以下になります。

```
[root@localhost ~]# echo $SHELL
/bin/bash
```

ユーザのデフォルトシェルは `/etc/passwd` に記載されているので、こちらを変更するとシェルの変更ができます。

```
[root@localhost ~]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
```

- 使用できるシェルの確認方法

今使用できるのは、 `cat /etc/shells` で確認できます。

```
[root@localhost ~]# chsh --list-shells
/bin/sh
/bin/bash
/usr/bin/sh
/usr/bin/bash
```

- シェルの変更

`chsh -s [シェル] [ユーザ名]` で変更ができます。

## 勉強後イメージ

カーネルとのやり取りをする間に立ってくれてるのがシェルなのか。。。
んで、シェルスクリプトはシェルの処理をまとめて実行するやつって感じかな？

そのシェルの種類としてbashとかshがあるのね。
ちょっと気になったのは、↑の `/bin/sh` と `/usr/bin/sh` ってどっちもBシェルでは？って思ったけど何が違うんやろ。。。
そもそもshとbashの違いを知りたかったので、それは次書く！

## 参考

- [Linuxで使用しているシェルを確認したり変更するコマンドまとめ](https://miningoo.com/855/)
- [【10分でわかるかもしれない】シェル（shell）とは？](https://recruit.cct-inc.co.jp/tecblog/os/shell/)
GitでAddしたファイルをまとめて削除する

## やりたかったこと

git checkout . などしても、Untracked fileは消えないのでまとめて消すコマンドを調べた。

```bash
$ git status
Untracked files:
  (use "git add <file>..." to include in what will be committed)
      "hoge.txt"
      "moge.txt"
```

## 答え
```
$ git clean -f
ディレクトリも含む場合は
$ git clean -df
```

おわり
S3で指定バケット配下のファイル一覧を取得する

# はじめに
こんにちは、株式会社ジールの[@Suguru-Terouchi](https://qiita.com/Suguru-Terouchi)です。
今回はS3バケット配下のファイル一覧を取得する方法について記載したいと思います。

はじめに断っておきますと、執筆（2022/02/09）時点で
AWS-CLIを使って簡単（ここ重要）にファイル一覧を取得する方法は実はありません。

Google先生に聞いてみても、なかなか良い方法が見つかりませんでした。
Pythonが得意な方はちゃちゃっとプログラムも書いて実装されている方もいましたが、
そこまでのモチベーション（）がない方向けにTipsとして残しておきます。

# ファイル一覧を取得する方法
前置きが長くなりましたが、早速、本題の方法について記載していきたいと思います。

    aws s3 ls s3://任意のバケット名/ --recursive

以上です。
この`--recursive`というオプションを追加することで
指定バケット配下のフォルダ含めて全てのファイル一覧を出力することが出来ます。

ただし、この方法には一つ問題があります。
それはS3の仕様上、フォルダも一つのオブジェクトとして出力されてしまうことです。

それだと困るよ！という方は出力結果の二つ目の数字が
オブジェクトのデータサイズを表しているので「0」のものをエクセルなどで除外すればファイル一覧が完成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1963640/2aba4501-8376-ca25-20bc-c9bb17f1d100.png)

# 参考URL
https://docs.aws.amazon.com/cli/latest/reference/s3/ls.html
https://dev.classmethod.jp/articles/amazon-s3-folders/
https://techblog.recochoku.jp/1894

# まとめ
いかがでしたでしょうか。
ふとした時に質問されて、あれ？どうだったっけ？と思ったので、備忘録として残しておきます。

ご参考になれば幸いです。

# データ活用をサクッと始めるなら！
株式会社ジールでは、「ITリテラシーがない」「初期費用がかけられない」「親切・丁寧な支援がほしい」「ノーコード・ローコードがよい」「運用・保守の手間をかけられない」などのお客様の声を受けて、オールインワン型データ活用プラットフォーム「ZEUSCloud」を月額利用料にてご提供しております。
ご興味がある方は是非下記のリンクをご覧ください：
 
https://www.zdh.co.jp/products-services/cloud-data/zeuscloud/?utm_source=qiita&utm_medium=referral&utm_campaign=qiita_zeuscloud_content-area
【AWS】AmazonConnectのContactLensで結果が反映されなかった話


# 1.概要
どうも、ARIの名古屋支社に勤務している愛知県民です♪
(/・ω・)/

**AmazonConnectでContactLensを使う時にWebの記事通りに設定したつもりが、
結果が反映されずに沼ったので、解決した方法をまとめてみました。**
（一番最初の設定の時に参考にしたWebの記事は[こちら](https://tech.systems-inc.com/col-aws-cn2/)となります。）

自分と同じくContactLensの結果が見られない人の助けになれば幸いです。

最後に、この記事が面白いと思った方はLGTM、ストックしていただけると励みになります♪
(*^^)v

# 2.NGパターンその1
## 2.1.コンタクトフロー・セキュリティプロファイルの設定
まず初めに、ダメだった時の設定情報を示します。
コンタクトフローの設定および「記録と分析の動作を設定」ブロックの設定を以下に示します。
また、「プロンプトの再生」ブロックでは「コンタクトレンズのテスト」というテキストを読み上げています。

|![インバウンドフロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/ee2f7606-c19d-af77-f7d1-656441db69b2.png)|
|:--|

|![記録と分析の動作を設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/f78f5bd0-ba8d-a5c7-1f0f-0daaad964420.png)|
|:--|

セキュリティプロファイルの設定を以下に示します。

|![セキュリティプロファイル_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/7e461a61-abdc-aa62-b16b-f371f64f54c1.png)|
|:--|

## 2.2.結果
問い合わせの検索ができませんでした・・・
(´;ω;｀)

|![コンタクトの検索_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/02b4c021-a582-301b-c09b-21e44562bf48.png)|
|:--|

# 3.NGパターンその2
## 3.1.修正点
**前節では「連絡先のアクセスを制限」にチェックをしており、
自分自身がエージェント階層に属していなかったため検索ができませんでした。**
そこで「連絡先のアクセスを制限」のチェックを外しました。

|![セキュリティプロファイル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/e777b229-2409-2657-f5c1-372fab77d8a7.png)|
|:--|

## 3.2.結果
問い合わせの検索はできましたが、感情分析の結果やトランスクリプトが出ませんでした・・・
(´;ω;｀)

|![コンタクトの検索_詳細_before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/b359f43b-0d53-84ed-d49c-f3ff6433f0c8.png)|
|:--|

# 4.OKパターン
## 4.1.修正点
**前節のセキュリティプロファイルの修正に加え、
インバウンドフローに顧客キューフローの設定を追加し、顧客キューフローを新規作成しました。**
顧客キューフローの「記録と分析の動作を設定」はインバウンドフローと同じです。

|![インバウンドフロー_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/e1aafc44-ac56-6cfd-e4d2-230667782d5f.png)|
|:--|

|![顧客キュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/09ebc9f3-102f-3b69-f46b-67aa16a6039f.png)|
|:--|

## 4.2.結果
感情分析の結果およびトランスクリプトが表示されるようになりました！

|![コンタクトの検索_詳細_after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/cfb6c8eb-c986-679d-53ca-b6bd0fce1578.png)|
|:--|

# 5.おわりに
インバウンドフローだけに「記録と通話の動作を設定」ブロックを設定した場合は、なぜかContactLensの結果が反映されませんでした。
調べはしたのですが原因は不明のため、ご存じの方がいればコメントなどで教えていただけると助かります。
(:3_ヽ)_
Excelで日付を和暦に変換する

日付のほとんどの扱いは西暦なのだが、Excelで和暦を扱う必要が出てきたので、関数だけで実装してみた。和暦の年号も明治=1、大正=2、…、令和=5と変換が必要だったので実装した。

A1セルに日付が数値で入っているとして、それぞれ以下の式で変換できる。

年号: `LOOKUP(TEXT(A1,"g"),{"H","M","R","S","T"},{4,1,5,3,2})`
年月日: `TEXT(A1,"eemmdd")+0`

## 解説

* 【年号】表示形式 `g` でアルファベット1文字の元号になる。
  LOOKUP関数の変換元は昇順に並んでる必要がある。
  それぞれH (平成) = 4、M (明治) = 1、…、T (大正) = 2と変換される。
* 【年月日】表示形式 `ee` で和暦の年に変換される。
  `+0` で強制的に数値に変換する。
herokuの多要素認証 (MFA) を今すぐGoogle Authenticatorから生体認証に変えるべき理由



:::note warn
Heroku Enterpriseじゃないと生体認証が使えないようです
:::


理由
-
はやい！！そして圧倒的に楽！！！
これに勝る理由はないかなと思います。
プログラマの三大美徳は「怠惰」「短気」「傲慢」といいますが、ガンガン効率化してを送りましょう。

自分はもともとGoogle AuthenticatorでMFAを行っていたんですが、手元にスマホがなかったり、ちょうどバッテリーきれてたりして時間ロスすることが結構あったんですよね。仮にスムーズにいっても10-20秒くらいはかかりますよね。

それと対称的に、生体認証であれば手持ちのMACに組み込まれているtouch IDで一瞬でできちゃうんですね。(Windowsの場合はWindows Hello)


対応機種
-
- MAC
  - MacBook Pro (2016以降)
  - MacBook Air (2018以降)
  - iMac (M1, 2021)
     - Touch ID付きMagic Keyboardによる
     
https://ja.wikipedia.org/wiki/Touch_ID

- Windows
    - Windows10 + 対応機種

設定方法
-

- herokuにアクセス
    - https://jp.heroku.com
- ログイン後右上のアイコンをクリックしメニューから「Account Settings」を選択
- ページ中段の「Manage Multi-Factor Authentication」ボタンをクリック
- 「組み込み認証アプリケーション」の右の「追加」ボタンをクリック
- 「組み込み認証アプリケーションの登録」画面にて、「登録」ボタンをクリックしTouchID認証を行いましょう。
- 無事認証されたら「完了」ボタンを押して下さい。

次回ログイン時にID、パスワード入力後に以下の画面が表示されるので、「検証」をクリックしてください。その後、生体認証を求められるのでMACならTouchID用のキーに指を触れればOKです。
<img width="400" alt="screenshot" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425910/212e6765-dec2-8a84-ec1c-b2247be9d2e6.png">


補足
-
ある日、上記の画面のところで、「お使いのブラウザでは組み込み認証は対応していません」的なメッセージがでて生体認証ができなくなった時があるんですが、chromeをアップデートしたらまた使えるようになりました。

参考資料
-
https://devcenter.heroku.com/ja/articles/multi-factor-authentication
C# - staticなフィールドは記述順序に気を付けよう - 順次実行されるが後出でも未定義エラーにならず初期値で代用される

# 問題となるソースコード

```c#

using System;

class SampleCode
{
    static readonly int Y = X;
    static readonly int X = 10;

    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine(Y);
    }
}
```

このコードをcsc.exeでコンパイルして実行するとどうなるでしょう？

(a). `X`が未定義としてコンパイルエラーになる
(b). 10が出力される
(c). (a)でも(b)でもない

<br>
<br>
<br>
<br>
<br>










# 実行結果

```text

0
```

タイトル通りの挙動になっています。
ちなみに`readonly`かどうかは影響はないです。（ユースシーン的に`readonly`[^1]を使うときにうっかりしそうなので書いた次第。）

[^1]:`static readonly` の代わりに `const` を推奨するものではありません。

# 言語仕様

https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/classes-and-structs/static-constructors

> <b>静的フィールドを初期化するための静的コンストラクターを指定しないと、すべての静的フィールドは、「C# 型の既定値」で示されている既定値に初期化されます。</b>

> 静的コンストラクターは自動的に呼び出されます。 これにより、最初のインスタンスが作成される前、またはそのクラス (基底クラスではない) で宣言された静的メンバーが参照される前に、クラスが初期化されます。 静的コンストラクターは、インスタンス コンストラクターの前に実行されます。 (中略)。 <b>静的フィールド変数初期化子が静的コンストラクターのクラスに存在する場合、それらは、クラス宣言に出現するテキストの順序で実行されます。</b> 初期化子は、静的コンストラクターの実行直前に実行されます。


# ildasmによる逆アセンブル結果

参考まで。
名称からして「静的コンストラクター」だと思われますが、言語仕様の章で抜粋した記載中の用語「静的フィールド変数初期化子」を内包しているっぽい。

```txt:static宣言部分の初期化処理の中身

.method private hidebysig specialname rtspecialname static 
        void  .cctor() cil managed
{
  // コード サイズ       18 (0x12)
  .maxstack  8
  IL_0000:  ldsfld     int32 SampleCode::X
  IL_0005:  stsfld     int32 SampleCode::Y
  IL_000a:  ldc.i4.s   10
  IL_000c:  stsfld     int32 SampleCode::X
  IL_0011:  ret
} // end of method SampleCode::.cctor

```

# 実行環境

コンパイル環境：
Microsoft (R) Visual C# Compiler version 4.8.4084.0
for C# 5
Formの質問と回答をメール送付する

## 事前準備

事前準備として下記2点が必要です。

1. トリガー設定でフォーム送信時にsubmitFormを実行させる設定
認証作業
2. の認証作業を行うのに下記関数を実行してください。
一度実行したらこの関数は消して問題ないです。

```js
function test() {
  FormApp.getActiveForm();
  GmailApp.getAliases();
}
```

メール送付が不要でしたらGmailAppの認証は通さなくて大丈夫です。


## メールアドレスを取得する場合

下記コードの
`e.response.getRespondentEmail()`でメールアドレスを取得していますが、
取得するためにはフォームの設定で`メールアドレスを取得する`にチェックする必要があります。


![c180d01c-0c4c-4fcf-b871-492a34a7e5d7-1920x937r.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/fd7d485f-cce3-1239-6ba4-62b7b370a949.png)


## コード

全ての項目名と回答をセットで送る設定になっているので、
不要な項目がある場合はコードを修正する必要があります。

```js

function submitForm(e){//フォームが送信されたら呼び出される，重複処理を避ける

  var lock = LockService.getScriptLock();//ロックサービスのオブジェクトを生成
  try{
    lock.waitLock(30000);//複数のフォーム送信がほぼ同時にあった時，遅い方に最大30秒待ってもらう
    Logger.log("コピー作業開始");
    main(e);
  }catch(err){
    Logger.log("発生したエラー："+err);
  }finally{
    lock.releaseLock();//次の送信のためにロック解除
    Logger.log("コピー作業終了");
  } 

}


function main(e){
  
  // 回答一覧の取得
  const itemResponses = e.response.getItemResponses();

  // 質問一覧の取得
  const items = FormApp.getActiveForm().getItems();
  
  // メールアドレスの取得
  let text = e.response.getRespondentEmail();

  for(let i=0; i<items.length; i++){
    text += `\n\n${items[i].getTitle()}\n`; // 質問を順にテキストに追加
    text += itemResponses[i].getResponse(); // 回答を順にテキストに追加 
  }

  const recipient = '';
  GmailApp.sendEmail(recipient, '', text);

}
Git mergeとrebaseの違い

## 〜宣伝〜

:::note info
個人開発でエンジニア専門マッチングサービスを開発しましたので、是非未経験からエンジニア目指している人！現役エンジニアで教えたい人！使ってみてください！

β版リリース記念キャンペーン中です！

10名様限定、抽選でお好きな技術本1冊プレゼント！
🎉当選者にはメッセージ差し上げます(送付の際に住所はお聞きしません)
詳しくはこちらから↓

https://x.com/dokupro01/status/1796837336145436846
:::
https://dokupro.dev/

## 概要

- Gitのmergeとrebaseの違いが自分の中で曖昧だったのでまとめてみた。

## ことの発端

- 「プルリク出す前に分岐元ブランチの最新状態にrebaseしてください」とよく聞く。
- 「履歴がきれいになるから」とか「差分が見やすいから」とかよく言われているが、実際どんなことなんだろうと気になった。
- なんで「分岐元ブランチの最新状態を作業ブランチにmergeする」はだめなのかもよくわかっていない。

## 前提情報

- 今回の説明で使用する各ブランチの状況を図にまとめてみた。

    ![other__Online_Whiteboard_for_Visual_Collaboration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/74732085-d7e1-9972-928f-247456ac950a.png)

- 言葉で説明する。（ごちゃごちゃ記載しているので「?」となったら図だけ見ていただければOK）
    - mainブランチとworkブランチがある。
    - mainブランチは下記の順でコミットされている。
        1. first_commit
        1. コミット1
        1. コミット2
        1. コミット3
    - workブランチはmainブランチのコミット1の直後から分岐して下記の順でコミットされている。
        1. first_commit
        1. コミット1
        1. 開発コミット01
        1. 開発コミット02
    - mainとwork両ブランチの時系列順のコミット履歴は下記の様になる
        1. first_commit
        1. コミット1
        1. コミット2
        1. 開発コミット01
        1. 開発コミット02
        1. コミット3

## merge

1. ローカルリポジトリで下記コマンドを実行して最新のmainブランチをworkブランチにmergeしたとする。

    ```terminal
    $ git switch main
    $ git pull origin main
    $ git switch work
    $ git merge main
    ```

1. 下記のような結果になった。

    ![other__Online_Whiteboard_for_Visual_Collaboration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/d12339c7-f3b7-f5a7-3c46-8081f0cde81b.png)

1. mainブランチのコミットとworkブランチのコミットが時系列順にまとめられた。

## rebase

1. ローカルリポジトリで下記コマンドを実行して最新のmainブランチの状態にworkブランチをrebaseしたとする。

    ```terminal
    $ git switch main
    $ git pull origin main
    $ git switch work
    $ git rebase main
    ```

1. 下記のような結果になった。

    ![other__Online_Whiteboard_for_Visual_Collaboration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/90201248-cc01-e9cd-fe72-96e7201321bb.png)

1. mainブランチのコミット履歴の後にworkブランチのコミットが並んだ。

## まとめ

- 振る舞いとしては下記の様になった。
    - merge: 時系列順に両ブランチのコミットをまとめる。
    - rebase: 分岐元ブランチのコミット履歴 → 分岐先ブランチのコミット履歴の順に並ぶ。
- mergeとrebaseで大枠の「mainブランチの変更をworkブランチに取り込む」は達成できている。
- しかし、mergeだと「時系列」でみるとコミット履歴はきれいだが、「個々の開発」として見るといろいろなコミットが入り混じってて見にくい。
- 特にこだわりがない限り、プルリク作成前にはrebaseを用いたほうが良さそうだ。（ただし、コンフリクトしている場合はrebaseのほうが面倒な場合もあるのでケースバイケース。とりあえず、毎日こまめにrebaseしたほうがPR作成時に辛くないかも。）

## 2024/04/11 追記

ぱっとみrebaseのほうが整理されていていい気がする。実際その通りできれいに整理されている。
ただ、mergeやrebase時にコンフリクトが発生するとrebaseはかなり面倒である。コミット2やコミット3などのコミット毎にコンフリクトを修正する必要があるはずである。（間違えてたらすみません。）
絶対に「mergeは許さん」みたいなプロジェクトじゃない場合、コンフリクトしたらmergeで一回のコンフリクト修正で終わらせてしまう方が楽なのかも。
「mergeは許さん」なプロジェクトなら、こまめにrebaseを挟んだほうが楽だと思った。

## 付録

- 今回説明用に作った図を下記に添付する。

    ![other__Online_Whiteboard_for_Visual_Collaboration.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/effb0663-ceb8-d174-1971-2864d7155ebe.png)
Dockerをやってみた。(コマンド編)

## 目次
* 初めに
* 開発環境について
* 本記事の目標
* Dockerにおける基本コマンド
* 基本コマンドを基にコンテナやイメージを作成する。
* 最後に

## 初めに
この記事をクリックして下さり、ありがとうございます。<br>
本記事は復習及び、アウトプットを目標に作成しています。<br>
この記事は以下の動画、参考書を基に作成いたしました。
・ <a href="https://www.udemy.com/course/aidocker/" > 米国AI開発者がゼロから教えるDocker講座</a>&nbsp;(Udemy)
・<a href="https://www.amazon.co.jp/IT%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%AB%E3%81%AA%E3%82%8B-%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8Docker%E4%BB%AE%E6%83%B3%E5%8C%96%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89%E5%85%A5%E9%96%80-%E5%B0%8F%E5%B3%B6-%E4%B8%80%E4%B9%9F/dp/4798054526/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=3I2GN3D8UZT03&keywords=%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8+docker&qid=1643614449&sprefix=%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8+docke%2Caps%2C182&sr=8-1" > ITエンジニアになる! チャレンジDocker仮想化環境構築入門 </a>
※更新が必要になった際には更新をしたいと思っています。

## 本記事の目標
* 見返した際にDockerの基本コマンドが思い出せる。
* Dockerの基本コマンドを再度理解し、自分の中に落とし込めるようにする。

## 開発環境について
* Windows10
* Docker Desktop for Windows (version 20.10.8)

## Dockerの基本コマンド
#### Dockerにログイン <br>

 ```
 docker login 
 ```

※Docker Desktop for Windowsは起動させておかないと下記のようにDockerが動いてない為、
ログインできませんよと言われてしまう。

 ```
 Authenticating with existing credentials...
Login did not succeed, error: error during connect: This error may indicate that the docker daemon is not running.: 
(以下省略)
 ```
---
#### docker imageを取得<br>
&nbsp; &nbsp;Docker&nbsp;hubから指定したイメージを取得する。
&nbsp; &nbsp;※後述しているdocker runコマンド実行時にイメージを取得することもできるので、そんなに活躍しないかもしれない。

```
docker pull <image名>
```
---

####新しいコンテナを作成し、作成したコンテナを起動
image名と実行コマンドを指定してコンテナを起動させる。
このコマンドはDocker create&Docker startを両方同時に行う。
もし使用したいイメージが存在しない場合はDocker hubからイメージを取得して、実行してくれる。
<br>
よく使うoption一覧

   - -i&nbsp; コンテナの STDIN にアタッチする。<br>
    &emsp;→キーボード文字入力を可能にし、コンテナ内でコマンドを使えるようにする。
   - -t&nbsp; 疑似ターミナル (pseudo-TTY) を割り当てる。<br>
    &emsp;→,ターミナルやコマンドプロンプトのような表示に切り替わる。
   - --name&nbsp; 作成されるコンテナに特定の名前をつけることができる。
   - --rm&nbsp;作成したコンテナを止めた際に削除する
   - -v, --volume&nbsp; 共有ファイルを指定する際につけるoptionコマンド


```
docker run [option] <image名> "実行コマンド"
```

---
#### 新しいコンテナを作成<br>
&emsp;※基本的にはdocker runを使用することが多いらしい。

```
docker create <image名>
```

---
#### 作成したコンテナを起動させるコマンド<br>
&emsp;※基本的にはdocker runを使用することが多いらしい。

```
docker start <コンテナ名 or コンテナID>
```


## 基本コマンドを基にコンテナやイメージを作成する。
  
  * 流れ
    1. imageをdocker hubから取得する
    1. 取得したイメージを基にコンテナを起動するコマンドを打つ。

  &emsp;今回はubuntuのイメージを取得して、ubuntuを起動させる
  
  1. imageをdocker hubから取得する
  ```
  docker  pull ubuntu
  ```
  2. 取得したイメージを基にコンテナを起動するコマンドを打つ。
  ```
  docker run -it --name test-ubuntu bash
  ```

  1と2を実行するとLinuxのCUIでよく見る形が表示されるようになる。

  ```
 root#
  ````

## 最後に
最後まで読んでいただき、ありがとうございました。
私自身未熟なところも多くあるので、上記の記事でミス等があるかもしれません。
そのようなミスを発見して下さった際には、ぜひコメント教えていただけると幸いです。

今後はdockerfileの記事やdocker-composeの記事についてまとめて行けたらいいなと思っております。
良かったらフォローをしていただけると励みになります。

ありがとうございました。
PHP　SQLインジェクションを意識する 初学者向け

※PHP初学者向けコンテンツです。
内容に誤りがある場合はご指摘頂けますと大変ありがたいです。

PHP学習時に何か作成しながら勉強しようと思っている際に、
DB連携を行う時、サイトに書いてあるコードをコピペして動けるようになったと満足していたあの頃の自分へ向けて書きます。

<h1>PHPを用いてDB連携を行う僕へ

例えば僕はこんなプログラムを書いていた。

```index.php

画面上でユーザーが入力するためのフォーム画面（簡易版）です。
<form action="<?php $_SERVER['REQUEST_URI']; ?>" method="POST">
    <input type="text" name="category_id">
    <input type="submit" value="ボタン">
</form>

<?php

//入力情報がPOSTであった場合ifの中の処理を行うように定義
//issetとは簡単には、存在した場合処理trueとして処理するもの！
//!issetとは簡単には、存在しない場合処理trueとして処理するもの！
if(isset($_POST['category_id'])) {
    
    //form(UI)から入力された値を$shop_idに格納するよう定義
    $shop_id = $_POST['category_id'];
    
    //以下DB接続詳細項目記載
    $user = '接続するDBに対して権限あるユーザー名';
    $pass = '接続するDBに対して権限あるユーザーのPASSWORD';
    $host = 'localhost';
    $dbName = '接続するDB名';

    //上でDB情報を定義した関数を１つの関数にまとめて使いやすくする。
    $dsh = "mysql:host={$host};port=8080;dbname={$dbName};";
    $cone = new PDO($dsh, $user, $pass);
    $cone->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    $cone->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    
    //$coneで接続定義したDBへSQLを実行するためのSQLを記載
    $psq = $cone->exec("select * from DB名.テーブル名 where category_id = :c_id;");
    //データ取得後にどの関数へどのように格納するかを定義(id,'値',オプション);
    $psq->bindValue(':c_id',$category_id,PDO::PARAM_INT);
    //実際にSQLを実行
    $psq->execute();
    
    //上記で実行されたデータを取得して（ここではfetch())$resultに格納
    //resultの日本語訳 ＝ 結果
    $result = $psq->fetch();

    //取得データ格納されている$resultを用いて出力
        echo "アイス味は[{$result['type']}]です。";
}
?>
```


<h1>SQLインジェクションとは

簡単に、
「UI画面であったり、容易にDBデータをいじられる（いたずらできる）状態」のこと

<h1>最初のプログラムでダメだった点</h1>


```index.php

//この部分
$psq = $cone->exec("select * from DB名.テーブル名 where category_id = :c_id;");

//対策として、以下にする必要がある。
$psq = $cone->prepare("select * from DB名.テーブル名 where category_id = :c_id;");

補足：prepare
    //prepareが対応できないSQL構文を擬似的にprepareで対応するようにする定義
    $cone->setAttribute(PDO::ATTR_EMULATE_PREPARES,false);

```

<h2>今回のケースおさらい

<font color="DeepPink">文章となるが、以下読むべし！</font>

【prepare】
prepare⇒bindValue⇒execute
①ユーザーが入力した変動値(フォーム画面より)を取得すると、
　<font color="DeepPink">一旦すぐにSQL実行ではなく、DB上でSQL構文解析、書き換えが行われます。</font>
後は、「指定した変動値(:id)」と「実行命令」が来たらSQLが実行されるまでの状態の処理が行われています。

②　<font color="DeepPink">bindValueにて、データ型を指定したい場合はbindValueを使用します。</font>
　→デフォルト値はPARAM_STR(文字列型)でした。文字列型でもいいなら省略しても良いと思います。
※bindValueを省略しても処理は実行されます。

③やっとここで、SQL実行が行われます！
※bindValueが省略されている場合は、execute(変動値　=>フォーム画面から受け取ったデータ格納されている関数);とする必要があります。
　<font color="DeepPink">prepare(プリペアド)で構文チェック書き換えが行われたSQLの処理を実行します！</font>

補足：
prepareでは、①でSQL構文解析・書き換えが行われており、同じ構文が繰り返しよく使われる場合は、構文解析作業が繰り返されることを防止され、パフォーマンス向上というメリットもあります。

【query exec】
有無を言わずにSQL実行！！truncateでも何でも！
変動値のないSQL構文の場合で尚且つ単発処理の場合は、利用しても良いのかもしれません。

<h2>補足 PARAM_?

PARAM_ほにゃららには以下のような種類があります。
SQL文の対象部分をどのデータ型で表現するかを決めることができます。

PDO::PARAM_STR　・・・デフォルトで文字列型
PDO::PARAM_INT　・・・数値型
PDO::PARAM_BOOL　・・・BOOLERN型
PDO::PARAM_NULL　・・・NULL型
Excel VBAでグラフのプロットエリアの隅に凡例を配置する

#はじめに

Excelで作成したグラフの凡例の位置には、デフォルトで以下の選択肢があります。

 * グラフに重ねる／グラフに重ねない
 * 上／下／左／右／（右上）

自分は現在Excel2019を使用しているのですが、いつからか右上という選択肢が増えていました。
昔は無かったような気がします。

上下左右を選択する場合は、基本的にグラフに重ねず使用すると思います。
（グラフに重ねて上下左右を選択すると、見栄えが相当悪くなります。）
グラフに重ねる場合は、凡例をプロットエリア内の好きな位置に配置したい時でしょう。
そう、できればこんな感じに…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514045/17e7085a-19e5-6cb7-7d15-87e4b19a1f76.png)

しかし、なぜかExcelにはこのようにプロットエリアの隅に凡例を配置するボタンが有りません。
ドラッグ＆ドロップで配置するのはとても腕が疲れます。
では、マクロを使えばこのような配置が自動でできるようになるのでしょうか。

#凡例の位置を指定する

Excel VBAを使えば、凡例の位置を指定することができます。

```vb
Sub test()
    With ActiveChart
        .Legend.Top = 50
        .Legend.Left = 50
    End With
End Sub
```

例えばこんなプログラムをグラフを選択して実行すれば、凡例の位置はこのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514045/bf297cf2-758f-823c-f182-84727f2f9039.png)

つまり、プロットエリアの隅の座標さえ求まれば、なんとかなりそうな気がします。

#プロットエリアの隅の座標を求める

調べてみると、意外とすぐにそれらしいものが見つかりました。
こんな感じのプログラムです。

```vb
Sub test()
    With ActiveChart
        .Legend.Top = .PlotArea.Top
        .Legend.Left = .PlotArea.Left
    End With
End Sub
```

プロットエリアのTopとLeft…これでええやん！と思い実行すると…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514045/383eaf06-07c2-50dd-30ba-175052ea9c6b.png)

違う。これじゃない。
どうやらExcelでは、"PlotArea"は軸の数値まで含めた部分になるようです。
さらに調べていくと、それらしいものが見つかります。

```vb
Sub test()
    With ActiveChart
        .Legend.Top = .PlotArea.InsideTop
        .Legend.Left = .PlotArea.InsideLeft
    End With
End Sub
```

これを実行すると…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514045/90a211da-9fb5-96c2-589f-98566e818778.png)

やっとうまくいきました。
どうやら、グラフが描画される範囲は、”.PlotArea.Inside”となっているようです。
紛らわしいので、この部分をここではそのまま”プロットエリア内部”と呼びます。
これを応用すれば、いろんな位置に凡例を置けそうです。
例えば、左下に置きたい場合は、左上の位置からプロットエリア内部の幅だけ下げて、
凡例の幅だけ上げれば良さそうです。
（”.PlotArea.InsideDown”みたいなのも一応打ってみましたがだめでした。）

```vb
Sub test()
    With ActiveChart
        .Legend.Top = .PlotArea.InsideTop
        .Legend.Left = .PlotArea.InsideLeft + .PlotArea.InsideWidth - .Legend.Width
    End With
End Sub
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2514045/696d713c-a4fc-20d4-2054-5521e203e69d.png)

さらに、プロットエリア内部の右側に寄せたいときも同様にできます。
最後にまとめとして4パターン載せておきます。

```vb
Sub test()
    With ActiveChart
        'プロットエリア内左上側
        .Legend.Top = (.PlotArea.InsideTop)
        .Legend.Left = (.PlotArea.InsideLeft)
        'プロットエリア内右上側
        .Legend.Top = (.PlotArea.InsideTop)
        .Legend.Left = (.PlotArea.InsideLeft + .PlotArea.InsideWidth - .Legend.Width)
        'プロットエリア内左下側
        .Legend.Top = (.PlotArea.InsideTop + .PlotArea.InsideHeight - .Legend.Height)
        .Legend.Left = (.PlotArea.InsideLeft)
        'プロットエリア内右下側
        .Legend.Top = (.PlotArea.InsideTop + .PlotArea.InsideHeight - .Legend.Height)
        .Legend.Left = (.PlotArea.InsideLeft + .PlotArea.InsideWidth - .Legend.Width)
    End With
End Sub
```

#感想

これらがデフォルトで使用できるのはいつになるのでしょうか？
もう少しこういった機能を充実させてくれれば使いやすくなる気がします。
とはいえ、やろうと思えばだいたいできてしまうのものです。
これで、ボタン１つで凡例の位置を自由自在に…

※グラフの大きさを変えたときは位置がずれてしまうので、
　早くデフォルトの設定にプロットエリア内部の隅を追加してください。早く。
Cloud9 Railsバージョンを変更



####Cloud9　

Railsの現在のバージョン6.0.4.4

```cmd
$ rails -v
Rails 6.0.4.4
```
Railsバージョン6.0.3をインストール

```cmd
$ gem install rails -v 6.0.3
```

※最新のバージョンを追加でインストールしも、古いバージョンは上書きされない。

Railsバージョン6.0.4.4をアンインストール

```cmd
$ gem uninstall rails -v 6.0.4.4
Successfully uninstalled rails-6.0.4.4

$ gem list rails
rails (6.0.3, 5.0.0)
```

削除されたが、アンインストールしたバージョンが残る。

```cmd
$ rails -v
Rails 6.0.4.4
```
railtieをアンインストールする必要ある。

```cmd
$ gem uninstall railties -v 6.0.4.4
Successfully uninstalled railties-6.0.4.4

$ rails -v
Rails 6.0.3
```

# 参考
https://qiita.com/pyon_kiti_jp/items/37860333b1467f0cf573
https://yuruli.info/railsverup-rails-in-gem-on-aws-cloud9/
https://qiita.com/Hassan/items/eef26c870eb26a0c68e0
VSCodeでSSH接続して直接ファイル編集する手順まとめ(Windows10)

VSCodeでSSH接続して直接ファイル編集するための手順です。

#### OpenSSHのインストール
- windowsはsshが使えないので、OpenSSHをインストールする
    - コマンドプロンプトとかでもsshコマンド使えるようになる
- 参考
    - https://www.kkaneko.jp/tools/win/openssh.html


#### VSCode Pluginのインストール
- Remote Development
    - SSH接続した際、接続先の環境に~/.vscode-serverというものがインストールされる
    - このときproxyの問題で.vscode-serverのインストールがうまく行かない可能性があるので、その場合は.wgetrcにproxy設定など追加する。

#### sshのconfig設定
- .ssh/configファイルの設定が必要
    - 接続先のIPとPort
    - User
    - SSH鍵があるなら指定
        - なければなしでOK
            - その場合プレインパスワードログインになる（接続のたびに毎回聞かれる）

     
```sh:.ssh\config
Host 任意の名前
    HostName 192.168.x.x
    User user1
    Port 20
    IdentityFile "C:\Users\user1\id_rsa.pem"
```

#### 注意点
- 秘密鍵の拡張子がpemの場合、Windows用にppkに変換する必要がある
    - PuTTYGemで変換する
- WindowsのVSCodeの場合、秘密鍵の格納場所がProglamFilesとかになっていると権限の問題で怒られる
    - UNPROTECTED PRIVATE KEY FILE!!
    - Userディレクトリ直下に置くことで解消できる