OmniAICreator/Qiita-1.07M huggingface dataset:
ChromebookのランチャーからJupyter Notebookを起動できるようにする方法

# はじめに
　ChromebookでLinuxモードを有効にした場合、Linux内の /usr/share/applications/ にデスクトップエントリファイル（.desktop）を保存すれば、ホスト側（ChromeOS）のランチャーにLinuxアプリを表示できるように [Garcon daemon](https://chromium.googlesource.com/chromiumos/platform2/+/HEAD/vm_tools/garcon/) が動作しています。
　ところが、Anaconda3 の jupyter-notebook のデスクトップエントリ（notebook.desktop）を登録して、ランチャーから実行するとシェルフに表示されたアイコンが永遠とローディング状態となり一度本体をシャットダウンしないと２回目の起動ができないという問題が発生しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23691/a88d3941-fc0d-5ed6-052b-fcd37f065e3d.png)

# 実行環境
|  |  |
|:--|:--|
| 機種 | Chromebook 3100 2-in-1 |
| CPU | Intel(R) Celeron(R) N4020 CPU @ 1.1 GHz x 2 |
| MemTotal | 3,897,296 kB |
| ChromeOS | Google Chrome OS ver.93.0.4577.107（64 bit） |
| LinuxOS | Debian GNU/Linux 10.11 |
| Anaconda3 | ver. 2021.05-Linux-x86_64 |

# 対処方法
　今回は **xfce4-terminal を経由することで問題を回避**しました。Anaconda3 を /opt 以下にインストールした場合の notebook.desktop の修正例を下に示します。これをデスクトップエントリとして登録すると、ランチャーから xfce4-terminal を立ち上げると同時に jupyter-notebook を起動します。Notebook を終了すれば xfce4-terminal も自動的に終了し、逆に xfce4-terminal から Notebook を終了することも可能です。どちらにしても正常に起動・終了するようになりました。
　なお、**xfce4-terminal のデスクトップエントリが存在すると正常に動作しない**ため、 /usr/local/share/applications/xfce4-terminal.desktop を削除するか末尾に `hidden=true` を追記して更新する必要があります。

```diff_system_d:/usr/share/applications/notebook.desktop
[Desktop Entry]
Version=1.0
Name=Jupyter Notebook
Comment=The Jupyter HTML Notebook.
- Exec=/opt/anaconda3/bin/jupyter-notebook
+ Exec=xfce4-terminal -e "/opt/anaconda3/bin/jupyter-notebook"
Icon=/usr/share/icons/hicolor/256x256/apps/notebook.png
Terminal=false
Type=Application
```

:::note warn
ちなみに、Linuxモードの標準ターミナルから新規ターミナルを立ち上げると同時に jupyter-notebook を起動するという方法でもローディングが永遠と続くため、標準ターミナルとは別の xfce4-terminal のようなGUIターミナルは必要と考えられます。
:::

# おまけ
　Anaconda3のインストールから jupyter-notebook のデスクトップエントリの登録までをスクリプトにしてみたので参考にして下さい。

```shell:setupAnaconda.sh
#更新・インストール
sudo apt update -y
sudo apt upgrade -y
sudo apt install -y wget xfce4-terminal
#
#install Anaconda3
ANACONDA_URL="https://repo.anaconda.com/archive/Anaconda3-2021.05-Linux-x86_64.sh"
wget ${ANACONDA_URL} -O Anaconda.sh
sh Anaconda.sh -b -p /opt/anaconda3
rm Anaconda.sh
#
#PATHを通す
echo '
# set PATH of Anaconda3
if [ -d "/opt/anaconda3/bin" ] ; then
    export "PATH=${PATH}:/opt/anaconda3/bin"
fi' >> .profile
#
#JupyterNotebookのデスクトップエントリの登録
NOTEBOOK_ICONURL="https://icon-icons.com/downloadimage.php?id=161280&root=2667/PNG/256/&file=jupyter_app_icon_161280.png"
sudo wget ${NOTEBOOK_ICONURL} -O /usr/share/icons/hicolor/256x256/apps/notebook.png
echo "\
[Desktop Entry]
Version=1.0
Name=Jupyter Notebook
Comment=The Jupyter HTML Notebook.
Exec=xfce4-terminal -e \"/opt/anaconda3/bin/jupyter-notebook\"
Icon=/usr/share/icons/hicolor/256x256/apps/notebook.png
Terminal=false
Type=Application" | \
sudo tee /usr/share/applications/notebook.desktop
#
#xfce4-terminalのデスクトップエントリの無効化
echo "Hidden=true" | sudo tee -a /usr/share/applications/xfce4-terminal.desktop
#
#デスクトップエントリの更新
sudo update-desktop-database
#
#終了
echo "
=-------------=
| F I N I S H |
=-------------="
rm setupAnaconda.sh
```
Rails部分テンプレート（パーシャル）まとめ

## 使い方１
```erb:before
xxx.html.erb

<%= @user.name %>
<%= @user.email %>
<%= @user.age %>
```


```erb:after
xxx.html.erb
<%= render partial: 'hoge', locals: {user: @user} %>

_hoge.html.erb
<%= user.name %>
<%= user.email %>
<%= user.age %>
```
※ 書き方：`<%= render partial: 'ファイル名', locals: { '部分テンプレート内で使う変数': '変数に入れる値' } %>`

※ ファイル名は、render記載のファイルと同じディレクトリにある`_hoge`なら`hoge`。

※ localsオプションを使った場合はpartialは省略できない。

※ partialを省略したいならlocalsオプションも省略しないといけない

（例：`<%= render 'hoge', user: @user %>`）

※ メリット：コードがスッキリする。部分テンプレートを使いまわせるから便利＆コードの保守性が上がる。

<br/>

## 使い方２

```erb:before
xxx.html.erb

<% @users.each do |user| %>
  <%= user.name %>
  <%= user.email %>
  <%= user.age %>
<% end %>
```
```erb:after
xxx.html.erb

<% @users.each do |user| %>
  <%= render partial: 'user', user: user %>　#使い方１と同じ
<% end %>
```
```erb
_user.html.erb
  <%= user.name %>
  <%= user.email %>
  <%= user.age %>
```
※ @usersの要素の個数分、部分テンプレートが呼び出されて表示される。

<br/>
collectionオプションを使うと、下記のように__each文を省略__できる。

```erb
xxx.html.erb
<%= render partial: 'user', collection: @users %>
```
```erb
_user.html.erb
  <%= user.name %>
  <%= user.email %>
  <%= user.age %>
```

※ 書き方：`<%= render partial: 'hoge', collection: 繰り返し表示する要素が入っているインスタンス %>`

※ collectionオプションの部分にeachで回したかった変数を入れる

※ collectionに指定した変数の要素の分だけ部分テンプレートが繰り返し表示される

※ collectionオプションを使用した場合、__partialで指定したファイルの名前がそのまま部分テンプレート内で使用する変数名になる__。

<br/>
もし別の名前として変数を使いたい場合は`as`に変数名を指定する

```erb
<%= render partial: 'user', collection: @users, as: "hoge" %>
```
```erb
_user.html.erb
  <%= hoge.name %>
  <%= hoge.email %>
  <%= hoge.age %>
```
※ @usersに入っている要素が一つずつ取り出され、部分テンプレート`_user.html.erb`内の変数`hoge`に代入される。

<br/>
※ 上のコード(asは除く)は以下の条件を全て満たしている時、省略できる。

・ viewsフォルダ内にある`users`フォルダに部分テンプレート`_user.html.erb`が存在する

・部分テンプレート内で使う変数が`user`である

まとめると、`views/hoges/_hoge.html.erb`内で変数`hoge`を使っていることが省略の条件

なので、

```erb
<%= render @users %>
```
と書けば、上述した`each文`と`collection`記法と意味は同じ

```erb
#3つとも意味は同じ
xxx.html.erb

<%= render @users %>

<% @users.each do |user| %>
  <%= render partial: 'user', user: user %>
<% end %>

<%= render partial: 'user', collection: @users %>
```
```erb
users/_user.html.erb
  <%= user.name %>
  <%= user.email %>
  <%= user.age %>
```
※ ３つとも意味は同じだがパフォーマンス（実行速度）が変わってくるので注意

<br/>

## each文の中にrender入れる　VS　collectionオプションを使う

eachで表示すると`@users`などに入っている要素の個数回分部分テンプレートが呼び出されるが、collectionオプションを使用して記述すると部分テンプレートが呼び出されるのは1回のみ。

なので、__eachで表示するよりもcollectionオプションを使う方がパフォーマンスが良くなる__。

部分テンプレートを繰り返し呼び出す時はなるべくeach文ではなくcollectionオプションを使うようにする。
Macのショートカットのまとめ

<h2>最初に
<p> 業務や開発なのでマックを使う機会が増えてきたので、ここにショートカットのコマンドをメモしておきます。
</p>
 
<h2>Chromeコマンド一覧（自分が使ったもの）

|  Command  |  Chorme  |
| ---- | ---- || ---- | ---- |
|  Command  +  N  |新しいウィンドウを作成|
|  Command + Shift + N  |新しいシークレットを作成| 
|  Command  +  T |新しいタブを作成|
|  Command + Shift + T | 直前のタブを複製させる| 
|  Command  + option + ⇨   |右タブに移動|
|  Command + option + ⇦  | 左タブに移動|
|  Command  +  W |現在のタブを閉じる|
|  Command + M  | 最小化| 
|  Command  +  Q  |アプリを閉じる|
|  Command + Shift + M  | 複数のユーザーを切り替える| 
|  Command  +  L  |　URL検索|
|  Command + R  | ページをリロードする| 
|  Command  +  C  |クリップボードにコピー|
|  Command  + D  | ブックマークに登録する| 

<h5>
こちらも参考にし、実際に使ったコマンドを書き写しました。

https://qiita.com/fantm21/items/430a1486132c8938ae1e
WordPress REST APIでカテゴリーを指定する

WordPress REST APIでカテゴリーを指定したURLの書き方。

ページ指定や投稿ID指定、取得件数指定はよく解説記事があるが、カテゴリー指定の記事は殆どなかった。

## 1つのカテゴリーを指定

>https://example.com/wp-json/wp/v2/posts?categories=1

``categories=``の後にカテゴリーIDの数字を入力する

## 複数のカテゴリーを指定

>https://example.com/wp-json/wp/v2/posts?categories=1+3+5

``categories=``の後に+を挟んでカテゴリーIDの数字を好きなだけ入力する

## 参考

その他のWordPress REST APIの細かいカスタマイズ方法については以下の記事が参考になります。

https://designsupply-web.com/media/programming/6307/

## WordPressのお役立ち情報

https://wagtechblog.com/programing/wordpress-school

https://wagtechblog.com/programing/php-school
ABC222 C - Swiss-System Tournament から学んだ

https://atcoder.jp/contests/abc222/tasks/abc222_c

![abc221_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/df577a1b-5859-6bff-0900-115c1cd44ec2.png)
![abc221_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/18cc47c7-094b-666b-e366-a423304850c1.png)
![abc221_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/db570551-dcb7-690a-4e43-30fd5b63c758.png)
![abc221_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/db4adacb-351a-1aab-8253-8a36faaf2059.png)

わからん。回答を見た。

https://atcoder.jp/contests/abc222/editorial/2740

これは思いつかない。勉強になった。

```SwissSystemTournament.py
N,M = map(int,input().split())
S = [input() for _ in range(2*N)]
rank = [[0,Y] for Y in range(2*N)]
#rank[i] = [X,Y] ->i 位なのは X 勝の 人Y
#[順位,人] を 1 セルとした配列を作るメリット
###順位が入れ替わった後、配列内の順位を sort により整理できるため、
###for 文を使って簡潔に順位順に処理が出来る
#####※辞書で実現できないか検討したが、結局、ソートを使うので記述が複雑化し、訳が分からなくなる(今の自分では)

# 勝ち:0 , 負け:1, 引き分け:-1
def judge(a,b):
    if a==b:return -1
    if a=="G" and b=="P":return 1
    if a=="C" and b=="G":return 1
    if a=="P" and b=="C":return 1
    return 0

for j in range(M):
    for i in range(N):
        player1 = rank[2*i][1]
        player2 = rank[2*i+1][1]
        result  = judge(S[player1][j],S[player2][j])
        #↓↓補足
        #a が勝者(return 0)の場合、a の rank[2*i + 0] 勝数を -1.
        #b が勝者(return 1)の場合、b の rank[2*i + 1] 勝数を -1.
        #2人ずつ勝負して、小数をメモ
        if result != -1: rank[2*i+result][0] -=1
    #sort して 勝数が小さい順に並べることで、勝者をグループ化できる
    rank.sort()

for _,i in rank:print(i+1)
```

正直、思いつかないし、読んでスグにはピンとこなかった。
中々自分には難しかった。
WordPress REST APIを読み込めない時の対処法

WordPress REST APIの読み込みができない時の原因と対処法。

## 原因1. URLが間違えている

WordPress REST APIのURLはパラメーターが複雑なので、間違える可能性が高いです。

パラメーターで取得内容をカスタマイズしたい方は以下の記事が参考になります。

https://www.sofplant.com/blog/tech/wp-rest-api-tips/

https://designsupply-web.com/media/programming/6307/

## 原因2. レンタルサーバー側で制限がかかってる

レンタルサーバーでWordPressを管理している人は自動のセキュリティ設定で、アクセス制限が行われている可能性があります。

エックスサーバーのサーバーパネル画面だとこんな感じ。

![スクリーンショット 2021-10-11 0.00.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/522445/9a9d50a8-4213-493d-2974-ae14b821cf4e.png)


エックスサーバーの初期設定では国外IPアドレスからのアクセスができないようになっています。

画像のように「REST API アクセス制限」をOFFにすれば海外からでもアクセスできるようになります。

もし日本のみでの使用を想定していたとしても、例えばWordPress REST APIを用いた機能を搭載したiOSアプリをAppleStoreで公開する場合、アプリの審査は海外で行われるため、リジェクトを受けるので注意が必要です。

## WordPressのお役立ち情報

https://wagtechblog.com/programing/wordpress-school
RSpec 導入法

# RSpecとは
***RSpecとはRailsでwebアプリを開発する時に、想定通りの動きをするかどうかを検証する
テストフレームワーク***です。
```実務では```、スクールみたいなコードを確認してアプリが動くのかどうかを確認するのではなく、
```RSpecを使って、アプリの挙動を確認します。```
この記事ではRSpecの導入をお伝えします。

# Gemfileに追記
まず初めに```rspec-rails```をインストールします。

```Gemfile

group :development, :test do
  # 省略
  gem 'rspec-rails', '~> 5.0.0'
end
```
その後、```bundle install```します。

●補足
上は2021年10/10現在のものです。
バージョンは変わっていくので
***rspec-railsで検索して公式ドキュメントはチェックしてください。***
https://github.com/rspec/rspec-rails

実際はドキュメントに手順は載っています。


# rspec-railsの設定
次に以下のコマンドを実行します。

```
$ rails g rspec:install
```
すると、

```
=>create  .rspec
  create  spec
  create  spec/spec_helper.rb
  create  spec/rails_helper.rb

```
上の4つのファイルができます。

# .rspecの修正
先ほど生成された、```.rspec```に追記して行きます。

```
--require spec_helper
--format documentation
-- color
```
***--format documentationはテストを見やすくする***ためのものみたいです。
specの部分をrailsにすると、railsでrspecを動かしていくことになるみたいです。

# RSpecを動かす。
ある程度設定が終わったら、テストを動かして見ましょう。

まず、テスト用のモデルを作成します。

```
$ bundle exec rails g rspec:model user　　　　#userはmodel名

```
でテスト用のmodelを作成します。

```
$ bundle exec rspec

```
これがテストを動かすコマンドです。

```
No examples found.


Finished in 0.00031 seconds (files took 0.19956 seconds to load)
0 examples, 0 failures

```
このうな表示が出たら、テストは動くので、
specファイルのなかのuser_spec.rbにテストを書いていけばテストを実装できます。

# 補足
RSpec以外にもテストの方法はあるみたいです。
よく使われる順です。

1 RSpec
2 Minitest
3 test-unit

***RSpecが主流***みたいです。test-unitを使う方はあまりいらっしゃらないみたいです。

# 最後に
上で紹介した以外にも、FakerやFactoryBotの導入やgeneratorの修正などもありますが、
今回はRSpecが使えるまでの導入とさせていただきます。
ご了承ください。
公式ドキュメントなども見ながら実装してみてください。

https://rspec.info/documentation/

# 有益な資料

以下の書籍や記事も参考にしてください‼︎

- ***書籍***

https://leanpub.com/everydayrailsrspec-jp?utm_campaign=everydayrailsrspec-jp&utm_medium=embed&utm_source=blog.jnito.com

- ***有益な記事***

https://qiita.com/jnchito/items/42193d066bd61c740612

https://qiita.com/jnchito/items/2e79a1abe7cd8214caa5

https://qiita.com/jnchito/items/640f17e124ab263a54dd

https://qiita.com/jnchito/items/607f956263c38a5fec24





# 参考資料

https://qiita.com/ralugoro/items/60684f3be8ea07b001b1

https://techtechmedia.com/rspec-test-rails/
令和3年度データベーススペシャリスト 自己解答 (午前2）

# 午前2 (22/25)

問1:エ、問2:エ、問3:ウ、問4:イ、問5:ウ
問6:ア(★正解:エ)、問7:ア、問8:ア、問9:エ、問10:ウ
問11:ウ、問12:ウ(★正解:イ)、問13:エ、問14:イ、問15:エ
問16:ウ、問17:ウ、問18:ウ(★正解:イ)、問19:エ、問20:エ
問21:イ、問22:エ、問23:ア、問24:ア、問25:エ

# 感想

ほとんど勉強しなかったが無事クリアすることができた。
問1〜5、問7〜10は過去問で解いた問題そのままだった。
長文の答えを暗記していると時間の節約になった。
【Moq】Moq.VerifySet()を用いたExcel描画のテスト方法

# Moqとは
型さえあれば未実装であってもMock(=ダミーの実装)を作ってくれる。
実装の出来不出来に関係なくテストを書ける。

# Excelに描画するテスト
今のデータをExcelに描画する機能をClosedXMLを用いて実装しているのですが、ちゃんと描画されたか否か確認するのが少し大変です。
例えばサーバー側にExcelがあることを前提としている場合はClosedXMLの正式な実装を使ったときにLinuxサーバーなどのExcelがない環境では正しく実行されない。
そのため、なるべく環境に依存しないコードを書きたい。

そこで今回はMoqでClosedXMLのダミーを作り、そのダミーを使って自ら書いたプログラムが正しい挙動か確認します。
[Mocking library for .NET](https://github.com/moq/moq(4))

# 描画された文字が正しいか判定すテスト

テストの流れは
1. テストしたいクラスの初期化
2. moqでClosedXMLのIF、実体クラスを生成
3. 生成したクラス・メンバーに値を入れた時の返り値を設定（ダミー実装）
4. 値を入れられることを確認（テスト）

とします。

```csharp
//確認したいメソッド
//Renderの中では指定したsheetのrow,colに値を代入するだけとする
class Renderer()
{
	public void Render(sheet, row, col)
	{
		//例
		sheet.Cell(row, col).Value = "糖質過多";
	}
}

//テスト
public class Test()
{
	public void RenderTest()
	{
		//1. テストしたいクラスの初期化
		var renderer = new Renderer();

		//2. moqでClosedXMLのIF、実体クラスを生成
		//MoqでClosedXMLのラッパークラスを作る
		var mockSheet = new Mock<IXLSheet>();
		var mockeCell = new Mock<IXLCell>();
		//Mock<T>.Objectで型引数の実態クラスを生成する
		var mockSheetObject = mockSheet.Object;

		//3. 生成したクラス・メンバーに値を入れた時の返り値を設定
		//mockCell.Valueプロパティのsetterにstring型なら何でも代入できるようにする
		//Verifiable()でVerify()できるようにする
		mockCell.SetupSet(o => o.Value = It.IsAny<string>()).Verifiable();
		//Setup()で引数とそれに対する返り値を設定する
		mockSheetObject.Setup(o => o.Cell(1, 30)).Returns(() => mockCell.Object);

		//4. 値を入れられることを確認(テスト)
		//mockSheetObectに上で指定した引数を渡す
		renderer.Render(mockSheetObject, 1, 30);
		//mockCell.Valueプロパティに"糖質過多"が代入できることを確認する	
		mockCell.VerifySet(o => o.Value = "糖質過多");
	}
}
```
これでテストは完了です。
使用したMoqの関数を一つずつ見ていきましょう

# Moqで使用した関数

### Mock<T>.Object
モックオブジェクトを取得する。指定した型の実装クラスを作ってくれます。

[Mock.InitializeInstance()](https://github.com/moq/moq4/blob/7848788b5968eb29056599db91f9e9b9d16f9ba9/src/Moq/Mock%601.cs#L303)

### Mock<T>.Setup()
Setup()は「実装する関数を準備する」関数です。
### Mock<T>.SetupSet()
返り値が`VoidSetupPhrase<T> : SetupPhrase`となりこのSetupPhraseクラス内に引数の値(今回であれば`IXLCell Cell(row, col)`の返り値)を保持します。

[WherePhrase.SetupSet()](https://github.com/moq/moq4/blob/b7b07279c45c29a201399a7fa93764892422e687/src/Moq/Language/Flow/WhenPhrase.cs#L48)
### Mock<T>.SetupSet().Returns()
SetupSet()ではSetupPhraseクラスに値を保持させましたが、Returns()ではその値を保持していた場合にどんな値を返すか設定します。
今回は引数(row: 1, col:30)が入力されたときの返り値は`mockCell.Object`であると定義しています。
mockCellは`IXLCell`IFのダミー実装ですね。

[SetupPhrase.Verifiable()](https://github.com/moq/moq4/blob/0103409b909442e741e3fdee694dfdf03a58d54d/src/Moq/Language/Flow/SetupPhrase.cs#L275)

### It.IsAny<T>()
T型のダミーな値を返します。用法としては指定した型を受け入れるようになります。
今回はstring型の値であればどんな値でも代入できるようにしました。
### It.IsAny<T>().Verifiable()
`Verifiable()`はSetupクラス内のプライベートなフラグをVerifyにします。
これによりテストでVerify()が使えるようになるようです。

フラグには他に`Overridder`と`Matched`があるようですがこれらの使われ方は追いきれませんでした。。ご存じでしたら教えて下さい。
[enum Flags](https://github.com/moq/moq4/blob/b7b07279c45c29a201399a7fa93764892422e687/src/Moq/Setup.cs#L211)

[Setup.MarkAsVerifiable()](https://github.com/moq/moq4/blob/b7b07279c45c29a201399a7fa93764892422e687/src/Moq/Setup.cs#L108)
### Mock<T>.VerifySet()
ここまででSetterに値が代入されたかを判定する。代入されていなければ例外が投げられテストが通らない。
今回は実装クラス(Moqではない方)で”糖質過多”を代入しているのでテストパスとなる。



# まとめ
Verify～の関数を使えばvoidの関数をテストできるので便利ですね。
【Nextcloud(Docker)】初心者が自宅ファイルサーバを建てるためにやったこと

# はじめに
ファイルサーバを建てるにあたって、割と簡単に実現できそうで、かなり便利そうなNextcloudを採用することにしました。
ただし、手動インストール作業で手間取ったり、次回建てるときに手順書通りに進まなかったりするのが嫌なので、Docker環境にこだわりました。
ネット上に確認できる情報では不満・不十分な部分があったので、自分なりに改良しています。

なお、試しに使ってみたかっただけなので、最低限の設定にしてあります。

# 手順

1. Docker環境でNextcloudを建てる
1. GUIで各種設定をする
1. ポート開放をする
1. クライアントソフトを導入する。

## 1. Docker環境でNextcloudを建てる

以下の2ファイルを同一ディレクトリに用意します。

```yml:docker-compose
version: "3"

services:
  db:
    image: mariadb:10.5
    restart: unless-stopped
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    volumes:
      - type: volume
        source: db
        target: /var/lib/mysql
    env_file:
      - ./db.env

  app:
    image: nextcloud:22.2.0-apache
    restart: unless-stopped
    ports:
      - 8080:80
    volumes:
      - type: volume
        source: app
        target: /var/www/html
    environment:
      - MYSQL_HOST=db
    env_file:
      - ./db.env
    depends_on:
      - db

volumes:
  db:
    name: nextcloud_db
  app:
    name: nextcloud_app
```

ボリューム名指定が重要です。
未指定だと、親ディレクトリ名が含まれたボリュームが作成されます。
そのため、親ディレクトリ名を変えるだけで過去のデータが引き継げなくなってしまうため、指定しておくとよいでしょう。

また、個人的にはバインドマウントを利用したかったのですが、少なくともWindows環境においてレスポンスが著しく悪化したためボリュームマウントとしました。

```ini:db.env
MYSQL_ROOT_PASSWORD=password
MYSQL_USER=nextcloud
MYSQL_PASSWORD=password
MYSQL_DATABASE=nextcloud
PHP_UPLOAD_LIMIT=2048M
NEXTCLOUD_TRUSTED_DOMAINS=「ポート開放する場合はサーバアドレスを入力」
```

デフォルトでは、1ファイルあたりの最大アップロードサイズが512MBです。
`PHP_UPLOAD_LIMIT` を指定することで、これを2048MBまで拡張します。
作成されたコンテナの `/usr/local/etc/php/conf.d/nextcloud.ini` を見てみると、 `PHP_UPLOAD_LIMIT` という環境変数を参照していたことが確認できたため、このようにしました。
公式ドキュメントや他サイトで確認したわけではないので、他にいい方法があるのかもしれませんが、これで正常に動作はしています。

## 2. GUIで各種設定をする。

しばらく待つと、 `http://localhost:8080` にて次のような画面が表示されます。
適当なユーザ名とパスワードで管理者アカウントを作成します。

![2021-10-09_05h35_21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/936879/8f4fb77d-61ab-96a0-354f-f03cd2390129.jpeg)

あとはユーザアカウントを作成するなど、その他自由に設定していきます。

## 3. ポート開放をする

最も厄介だった作業です。

我が家は集合住宅向けのプロバイダ契約であって、グローバルなIPv4アドレスが割り当てられていませんでした。
また、我が家の契約ではIPv6 over IPv4でVPNが利用できないようで、VPNも断念しました。
仕方がないので、IPv6のポート開放で妥協しました。
幸いにも、自分の周りのネットワークはすべてIPv6に対応しているので、問題なくファイル共有できそうですが、しかし気軽に他人とリンクによるファイル共有などはしにくい欠点は残ります。

ポート開放手順はおま環なので省略します。
ネットワークの知識が全く無くて困っているのなら、設定するのが難しい上に危ない自体になりかねないので、一旦ローカルで遊ぶに留めるのが吉だろうと思います。

## 4. クライアントソフトを導入する

NextcloudにはPCやモバイル向けのクライアントソフトウェアがあり、これらを導入することで、OneDriveなどのクラウドストレージなどと変わらない利便性を享受できます。

# さいごに

サーバ・ネットワーク周りに関してはズブの素人でしたが、今回の作業を通していろいろと勉強になりました。

直近の目標は、RAIDを組んで冗長化するなど、ファイルサーバとしての信頼性を高めていきたいと思います。

# 参考文献

「Nextcloud Docker-Compose」などと検索して出てくる記事たくさん
OS(operating system)について



OS(オーエス）って何か、製品によって範囲がいろいろで、分かりにくいかもしれません。

www.jisc.go.jp
で無償でJIS(日本工業規格)が閲覧できるので参考に記録します。


# JIS X 0001　情報処理用語（基本用語）

01.01.09　ファームウェア

命令の順序付けられた集合及び関連データであって、主記憶装置とは機能的に無関係な方法で記憶されるもの。通常,ROMに記憶される。


01.04.02　システムソフトウェア

応用ソフトウェアの実行を支援するが応用には依存しないソフトウェア

例：オペレーティングシステム


01.04.08　オペレーティングシステム, OS

プログラムの実行を制御するソフトウェアであって、資源割振り、スケジューリング、入出力生後、データ管理などのサービスを提供するもの。

備考　オペレーティングシステムは、ソフトウェアが主体であるが、部分的にハードウェア化することも可能である。


# OSは、システムソフトウェアの一種であることが分かります。

1　関係者
1.1 OS機種共通部分設計者

1.2 OS 機種依存部分設計者

1.3 応用ソフト設計者

1.4 システム利用者

2  OSの必要なこと
2.1 システム利用者
　ハードウェアによるシステムの違いを感じずに済むこと。
　場合によってはOSの機能が不十分な場合は、応用ソフトウェアで違いを感じないようにする。

2.2 応用ソフト設計者
　ハードウェアによって、応用ソフトを変更しなくても済む事。

2.3 機種依存部分設計者
　ハードウェア依存部分の追加、変更がなるべく少なくて済む事。

2.4 共通部分設計者
　共通部分の追加、変更が、新しいハードウェアの追加対応でも少なくて済む事。

図1 OS(CPU1）
![os1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/1ad50c54-0446-6ab3-0d0b-8663df906dbc.png)


図2 OS(CPU2)
![os2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/63375736-0970-9dc7-3007-4481c26be3ce.png)


3. 経過。
3.1 最初の利用事例図には、「利用者」がなかった。
OSはプログラマが使うものという仮定を考えていた。
実際には、利用者が同じ操作、使用感があることが大事だということに、図を書いてから気が付いた。
3.2 
仕様に、当事者としての利用者を追加した。


https://researchmap.jp/blogs/blog_entries/view/80826/12aecbc251b97114ca65eef9f16a6be5?frame_id=441424
CCNA　VLAN　コマンド集

● スイッチポートにVLANを割り当てるコマンド

(config-if)# switchport access vlan <vlan-id>

基本的にVLANを作成した後でスイッチポートにVLANを割り当てるのが一般的ですが、作成していなくても存在していませんとメッセージが表示され、自動的に作成されます。

● VLANの作成

(config)# vlan <vlan-id>
(config-if)# exit

上記のようにvlanを作成した後で、コンフィギュレーションモードから出たら作成が
完了します。

● SVI（管理インターフェイス)の作成

(config)# interface vlan <vlan-id>

● スイッチポートのアクセス・トランクの切り替え

(config-if)# switchport mode access

● トランクプロトコルの設定

(config-if)# switchport trunk encapsulation {isl|dot1q|negotiate}
これでトランクプロトコルを決定した後に

● トランクポートの設定

(config-if)# switchport mode trunk
これでトランクポートを設定します。

● スイッチにある全てのVLAN情報の開示

show vlan

● 特定のスイッチポートのVLAN情報の開示

show interfaces interface-id switchport
show interfaces interface-id trunk

● 現在、動作中の設定を確認する。

show running-config

● 指定したインターフェイスの情報を開示する。

show interfaces status

● インターフェイスの要約情報を開示

show ip interface brief

● 指定したVLANの管理インターフェイスの表示

show interfaces vlan

● トランクポートで許可する範囲を指定する。

switchport trunk allowed vlan <vlan-id>

追加だと最後にadd vlan-id
除去だと remove vlan-id

● ネイティブVLANの変更コマンド

switchport trunk native vlan vlan-id

● 全てのVLANにタグを付加するコマンド

vlan dot1q tag native

● DTPを無効にするコマンド

switchport nonegotiate

● VTPの詳細の表示

show vtp status

● 音声VLANの設定

switchport voice vlan

アクセスポートに音声VLANコマンドを入力すると設定ができます。
これにより、IP PhoneとPCを接続できます。
wsl2でssh-addするやつ

wslとwsl2どっちも同じだと思いますが、よくわかんなくなったのでメモ代わりです
何も入ってない状態から入れることを想定しています

# OpenSSH Serverを入れる
[ここ](https://docs.microsoft.com/ja-jp/windows-server/administration/openssh/openssh_install_firstuse "ドキュメント")の通りいれます
管理者権限でPowerShellを開き

```
# Install the OpenSSH Client
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0

# Install the OpenSSH Server
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
```
起動後、PCをシャットダウンして起動してもOpenSShは停止したままだと思うので、PCの起動時にOpenSSHも起動する設定にしておくと楽です。

# Scoopを入れる
[これ](https://github.com/lukesampson/scoop)を入れます
これもPowerShellで

```
iwr -useb get.scoop.sh | iex
```

ExecutionPolicyで怒られたら

```
Set-ExecutionPolicy RemoteSigned
```
と入力しましょう(警告でも同じようなこと出ますが)

# ssh-agent-wslを入れる

[これ](https://github.com/rupor-github/ssh-agent-wsl)を入れます
まだPowerShellのまま

```
scoop bucket add extras
scoop install ssh-agent-wsl
```

を入力します

# .bashrcに設定追加
今回入れたssh-agentはだいたい`C:/Users/(ユーザー名)/scoop/ssh-agent-wsl/current/ssh-agent-wsl`に入っています
なので、wslから見ると`/mnt/c/Users/(ユーザー名)/scoop/ssh-agent-wsl/current/ssh-agent-wsl`です

wslを開いて、`~/.bashrc`に以下を追記しましょう

```
eval $(/mnt/c/Users/(ユーザー名)/scoop/ssh-agent-wsl/current/ssh-agent-wsl -r)
```

最後に、シェルを再起動するか`source ~/.bashrc`をして、`ssh-add -l` がエラー無く出てたらOKです
【備忘録】イベントログのアーカイブ作成とセキュリティ設定

イベントログのローテーションタイプで「上書きしないでログをアーカイブする」を選択すれば、イベントログの出力先と同じフォルダにアーカイブファイルが作成され、古いログが退避される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651121/9f5aacf2-5bcc-ec9a-bf77-668e713a3c22.png)

ログ管理の都合上、イベントログの出力先を変更する場合は、出力フォルダのセキュリティ設定に注意する必要がある。

イベントログは「Windows Event Log」サービスによって管理されているが、実行アカウントが`ローカルサービス`であるためUsers権限で動いている。従って、ログ出力先フォルダにて「Users」に書き込み権が無い場合はアーカイブファイルを作成することができない。
（初心者）CloudFormationでデザイナーを利用する人へざっくり説明

#目的
・すでに作成されたスタックをデザイナーズを利用して更新する

#対象
・デザイナーでテンプレートを編集している人
・テンプレートの操作ボタンがいまいち理解できない人

#用語
・CloudFormation・・・AWSリソースの環境構築を、設定ファイル (テンプレート) を元に自動化できるサービス
・スタック・・・テンプレートで記述したAWSリソースの集合

#デザイナーズを表示させるまでの手順
①自分のスタックを選択
②「更新」をクリック
③「デザイナーでテンプレートを編集する」をクリック
④表示された「デザイナーでテンプレートを編集する」画面の「デザイナーで表示をクリック」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/4bb6b173-5b0f-e4f6-c058-cce94015a14b.png)

#本題
##大まかな構造

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/e4bdf40a-3719-843b-d54c-3d1e2e9a840e.png)

①テンプレートの記述のリソースの関係を図に表している。リソースをクリックすると、そのリソースの記述が書いてある箇所へ移動できる。

②実際のテンプレートの記述。JSON形式とYAML形式の選択ができる。

##ボタンの説明

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/db9ac239-94f7-0741-c04e-feedf16d9754.png)

①「ファイル」・・・「新規」「開く」「保存」「サンプルテンプレート」がある
「新規」・・・現在記述テンプレートをリセットしまっさらになる
「開く」・・・S３バケットかローカルに保存しているテンプレートを開く
「保存」・・・S３バケットかローカルに保存
「サンプルテンプレート」・・・すでに用意されているいくつかのサンプルテンプレートを開くことができる。こちらは既に記述された内容も消えてしますし、レパートリーも少ないので使うことは少なそうです

②「スタックの作成」・・・テンプレートの記述が更新され、スタックの編集画面が閉じられる。
注意点が二点ほどあります
※１：そのあと次へを押していき「スタックの更新」をクリックしないと変更が反映されない
※２：③「テンプレートの検証」をクリックすることを推奨する

③「テンプレートの検証」・・・テンプレートの記述に矛盾している点や構造がおかしくないか確かめる

##テンプレートの記述に関して補足

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/969819/af5bc67c-ed12-aff8-29ed-0eac03e15281.png)

①テンプレートを記述したとき
→　デザイナー画面の図が変更される。しかし手動で行う必要があるため、右上の更新ボタンをクリックすることで変更が反映された図が表示される

②「テンプレートの検証」をクリック時のエラーパターン
→　例えば今回は「ParameterType」に存在しない記述をすると「Unrecognized parameter type（そんなパラメータータイプしらないぞ）」って言われています
Widows Server 2016 にDocker入れようとしたらいきなりつまずいた

#はじめに
Dockerを使うのに、普段はメインPC(Windows10 -> 11に最近アップしました)に入れているのですが、タイトルにある通り、Windows Server 2016に入れようとふと思い立ちました。

#いきなりつまづいた
ということでPowerShellから以下のコマンドを実行しました

```
Install-Module DockerMsftProvider -Force
```
ところが、いきなりエラー
画面のキャプチャーしてなかったので、細かいところは忘れてしまいましたが、とにかく「インターネット接続を確認しろ」というような感じのメッセージでした。
「いや、ネットつながってるし・・・」と思いながら、いろいろと調べてみると、どうやら通信がうまくいっていないらしい。

#とりあえず解決した方法
きちんと理解しているわけではないので、同じようにつまづいた方の参考になればと思うのと、自分の備忘録として記録しておきます。
PowerShellで最初に以下を実行

```
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
```

要するに、通信で使用するSSLのバージョンを1.2にしましょうということですが、これでうまくいきました。
EBSのマウントとアタッチの違いについて

### EBSのマウントとアタッチの違いについて

まずはEBSを作成してEC2にマウントするまでの流れを見ていく。(コマンドは気にしないでくれ)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1355275/a783ba9f-e2d6-f208-5221-ed87a5a5106c.png)

背景が青のところがアタッチ。黄色のところがマウントである。
これを見たあなたは思うだろう。アタッチはストーカーでマウントはカップルなんじゃないかと。
そのとおりである。
アタッチはEBSから一方的にEC2へ思いを寄せている。
マウントは、EBSとEC2の両思いなんじゃないかと。その感覚でよい。

## 詳細
### IT用語としてのアタッチとマウント
アタッチ
>クラウドサービスにおけるアタッチ／デタッチとは、
仮想マシンのボリューム（データディスク）を追加（割り当て）／削除する際に使用されます。

らしい

https://www.idcf.jp/words/attach-detach.html

マウント
>コンピュータ本体に接続した周辺機器をオペレーティングシステム（OS）などのソフトウェアに認識させ、
操作・利用可能な状態にすることをマウントという

らしい


[アマゾンec2のebsのアタッチとマウントの違いは何ですか](https://cloud6.net/so/amazon-ec2/1516110)によると

>ボリュームをアタッチすると、単にボリュームがブロックデバイスとしてインスタンスにアタッチされます。
このアクションは、デバイスがオペレーティングシステム内でのみ表示されるようにします。

>それを使用するには、フォーマットし、ファイルシステムにマウントする必要があります。
マウントは、WindowsよりもLinuxで頻繁に使用される用語です。 
Linuxでは、実際にmountコマンドを使用して、デバイスをファイルシステム内のポイントに割り当てています。
 Windowsでは、ディスク管理を介してボリュームにドライブ文字を割り当てます。

ここで重要なのがファイルシステムだ。
普段私たちが何気なく使っているhtmlファイルやexelファイルなどは、
ファイルシステムというOS機能によって保存・整理されている。[参考：ファイルシステムとは？](https://hnavi.co.jp/knowledge/blog/filesystem/)
ということは、ファイルシステムにマウントしないとリソース(htmlファイルやexelファイル、バックエンド系のファイル)はストレージに格納できないということである。

### まとめ

* アタッチは片想い
* マウントは両思い

このイメージで良い。
C#　リストのシャッフル

##0.0 はじめに
リスト(List)内の要素をシャッフルする方法を調べてみました。

##1.0 スクリプトでシャッフル
下記のスクリプトでシャッフル可能です。

```C#:Shuffle.cs
// リストlistをシャッフルする (for降順ランダム取り)
for (int i = list.Count - 1; i > 0; i--){
    var j = Random.Range(0, i+1); // ランダムで要素番号を１つ選ぶ（ランダム要素）
    var temp = list[i]; // 一番最後の要素を仮確保（temp）にいれる
    list[i] = list[j]; // ランダム要素を一番最後にいれる
    list[j] = temp; // 仮確保を元ランダム要素に上書き
}
```

##2.0 定型文を利用したシャッフル方法
OrderByを使うためにusing System.Linq、Guidを使うためにusing Systemを追加します。

```C#:Shuffle.cs
// リストをランダムに並べ替える
list = list.OrderBy(a => Guid.NewGuid()).ToList();
```
配列の場合は下記でOKです。
array = array.OrderBy(a => Guid.NewGuid()).ToArray();
Unity C# 自作Randamクラス

##0.0 はじめに
using Systemを追加したらRandamクラスはUnityEngineの明示が必要となります。
ほかにも方法がありますが、対策しないとエラーになります。
Systemとぶつからない様にするためのいろいろと検討しましたが、自作Randamクラス（Randクラス）を使うのが簡単でした。


##1.0 スクリプト
以下はint, floatでランダムな数字を入手するための関数を入れています。

```C#:Rand.cs
using UnityEngine;

// using Systemを使ったときにぶつからない様にするための疑似Randamクラス
public static class Rand{

    /// <summary>
    /// minとmaxの間のランダムなintを返す。min含む、max含まない。
    /// </summary>
    public static int Range(int min, int max) {
        return Random.Range(min, max);
    }

    /// <summary>
    /// minとmaxの間のランダムなfloatを返す。min含む、max含む。
    /// </summary>
    public static float Range(float min, float max) {
        return Random.Range(min, max);
    }

}
```
varでできてletでできないこと

# 遭遇した背景
「Node.js超入門第3版」という本を借りていた。p.104を写経し、実行すると、

```
... let content = ejs.render(other_page,{
...
$ SyntaxError: Identifier 'content' has already been declared
```
というエラーが現れた。
読んでそのまま「contentはすでに定義されている」ということだろう。
しかし、プログラムは全く同じだった。

ある一部を除いて。
# 解決編１
どこぞのYouTuberがvarよりもletが使われているとか言っていたので、
調子に乗って私もletを使っていた。

試しに問題の変数の定義をletからvarに変えると、
__完全に解決したッ！__

# 解説
私はurlパースを使ってswitch-case文でルーティングをしていました。

```javascript:app.js
let url_parts = url.parse(request.url);
    switch(url_parts.pathname){
        case '/':
            let content = ejs.render(index_page,{
            ...
            });
            ...
            break;

        case '/other':
            let content = ejs.render(other_page,{
            ...
            })
            ...
            break;
        ...
```
ここで、問題なのは2つの

```javascript
let content
```
です。
## letとvarの違い
とりあえず、上のままの単語で検索し、[TechAcademyの記事](https://techacademy.jp/magazine/14872)にアクセスしました。
まとめると、次の表のようになります。

||let|var|
|:-:|:--:|:--:|
|再代入|○|○|
|再宣言|☓|○|
|スコープ|ブロック|関数内|

letを使ってエラーが出て、varを使ってエラーが出ないのは
**varが再宣言可能だから。**
というだけでした。
### これだけでもいいけれど。
動くのでいいのだが、
再宣言は普通に気持ち悪い。

解決してしまおう。

## letのスコープ範囲をよく見る。
ここで、一度`let`のスコープ範囲について確認しましょう。
[MDNの解説](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/let)では`let`は
>`let`文はブロックスコープのローカル変数を宣言します。任意で値を代入して初期化できます。

とされています。
他のサイトも漁ったところ、
ブロックスコープとは変数が
**`{...}`の範囲だけで定義される**
と分かりました。

### おや？するとどうでしょう。
今、この__app.js__、caseで区切られてはいますが、`{...}`では区切られていないですね？
試しにcase文を`{...}`で囲ってみましょうか。

# 解決編２
それでは、`case '...': ~~ break;`までを`{ }`で囲っていきます。

```javascript:app.js
let url_parts = url.parse(request.url);
    switch(url_parts.pathname){
        case '/':{
            let content = ejs.render(index_page,{
            ...
            });
            ...
            break;
            }
        case '/other':{
            let content = ejs.render(other_page,{
            ...
            })
            ...
            break;
            }
        ...
```
はい、実行してみましょう。

```
$ node app.js
Server Start!
```

**OK!**

# あとがき
なんかさ...こんなところ(case内)で宣言せず、関数内で定義しとけば丸く収まらない？

お読み頂きありがとうございました。
階層構造を維持したままcurlコマンドでアップロードする方法 解説

[前回](https://qiita.com/fy406/items/40ac3340dd2e95a60e7d)の続きとなります。
以下のスクリプトを紹介しましたが、それの解説となります。

```
#!/bin/sh

if [ $# != 1 ]; then
 echo "引数を1つ指定してください"
 exit 1
fi

DIRCNT=`pwd | wc -m`
let DIRCNT++
ALLFILES=`pwd`'/'$1'/'*
FINDFILE=`find $ALLFILES -type f`

for NOWFILE in $FINDFILE;
do
 NOWDIR=`echo $NOWFILE | cut -c $DIRCNT-`
 echo "curl -T "$NOWFILE" http://<サーバーのFQDN or IP>/"$NOWDIR
done

exit 0
```

#解説
まず最初のIF分で、このスクリプトを実行する時に引数を指定しなかった場合に処理を終了させます。

続いて変数の定義となりますが、`DIRCNT`にてカレントディレクトリの文字数を代入しています。
詳細は[こちら](https://qiita.com/fy406/items/c058436fc789644708ba#%E8%A7%A3%E8%AA%AC)で説明しています。
なお、`let DIRCNT++`では上記`DIRCNT`の値に1を足していますが、後ほど登場するカレントディレクトリを削るコマンドで、カレントディレクトリの後ろの`/`までを削るために1を足しています。
変数`ALLFILES`にはカレントディレクトリの中にあるアップロード対象ディレクトリ内に存在するファイルやディレクトリのパスが格納されます。
変数`FINDFILE`には上記変数を参照し、全ファイルのパスが格納されます。

for分についての解説です。
ループの条件は、作業対象ディレクトリ内に存在する全てのファイルに対する処理が完了するまで回し続けます。
このとき参照しているパスを変数`NOWFILE`に格納します。
変数`NOWDIR`には、現在参照しているファイルパスが格納された変数`NOWFILE`を、`cut`コマンドで指定された文字数分削った文字列が格納されます。
この`cut`変数で削る文字数というのが、先程定義した`DIRCNT`までとなっています。cut変数で指定した数値分文字を削除する際の書式は`cut -c <開始位置>-<終了位置>`となりますが、終了位置を指定しない場合は一番うしろまでが対象となります。（逆に開始位置を指定しない場合は先頭からとなります）
例えば`/home/user/dir/file`というパスに対して、`cut -c 11-`というコマンドを実行した場合、`dir/file`というパスが返ってきます。
これらを組み合わせることによって、`NOWDIR`変数にはカレントディレクトリ直下の作業対象ディレクトリから格納対象ファイルまでのパスが代入されるようになります。
このファイルパスを整形するテクニック自体は[こちら](https://qiita.com/fy406/items/c058436fc789644708ba#%E8%A7%A3%E8%AA%AC)で紹介しています。

最後にechoコマンド内のcurlコマンドですが、アップロード対象ファイルは`NOWFILE`変数で指定し、格納先のURLにはアップロード対象のディレクトリからアップロード対象ファイルまでのパスを追加するようにしています。
Artifactory等、curlコマンドでファイルのアップロードができるサービスで格納先のディレクトリまで指定できる場合にはこのように`NOWDIR`変数の中身を追加することでアップロード時にディレクトリ構成を維持してアップロードすることができます。
ちなみにこのスクリプトをこのまま実行するとcurlコマンドが表示されるだけですが、`echo`とダブルクォートを外せばそのままcurlコマンドが実行されます。
アップロード対象の全ファイル容量次第ではサーバーやネットワークに負荷がかかってしまうので、ループの中に`sleep`コマンドを挟んだほうが良いと思います。

以上です。
Ruby on Rails のwhereメソッドの条件を文字列だけで構成するとはSQLインジェクションの危険がある。

Railsのwhereメソッドの条件を文字列だけで構成することは危険なようです。

Webサービス作成する中で「あるカラムに値が設定されているレコードを取得する」為、下記のようにコーディングしていました。

値が設定されていないだったらRailsのwhereメソッドに「selling_day:nil」みたいな感じで取得してあげれば良いかと思いますが

```ruby:stocks_controller.rb
@stock = Goal.where('selling_day like ?','%')
```
ただ、文字列だけで条件を指定するとSQLインジェクションのリスクがあるようです。
具体的には

```ruby:stocks_controller.rb
@stock = Goal.where("selling_day = '#{params[:day]}'")
```
みたいに書くとparams[:day]に悪意のある文字列を設定され、認証をすり抜けるリスクがあります。
下記のように条件をハッシュ値で指定するか、配列で指定するようにするとリスク回避できるようです。

```ruby:stocks_controller.rb
@stock = Stock.where(sold:true)
```


下記サイトを参考にしました。
https://railsguides.jp/active_record_querying.html
https://railsguides.jp/security.html#sql%E3%82%A4%E3%83%B3%E3%82%B8%E3%82%A7%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3
mac初心者がやりがちな痛恨のミス

<h2>初心者じゃなくても失敗はあるよね</h2>
<p>mac歴はそこそこ長いはずなんですが、久しぶりに痛恨のミスをしたので自戒を込めて。<br>
mac初心者がよくやってしまうミスについて説明します。</p>
<p>事の発端は、VScodeの壁紙設定をしようとしたら、どうしても設定できないことからでした。<br>
read-onlyになって上書き設定ができない。<br>
/private/var/folders/xj/tbr93j3d66xxxxxxxxxxx/T/AppTranslocation/d/Visual Studio Code.app/Contents/Resources/app/out/bootstrap-window.js'<br><br>

など、調べても不明なエラーで設定ができない。<br>
答えは、ものすごくシンプルなことでした。<br><br>

インストールしたのが、ダウンロードフォルダのままだっただけ。<br><br>
でも、これmacではよくやっちゃうミスです。windowsの感覚のままインストールすると、<br>
フォルダがアプリケーションフォルダに移動できていない事がよくあります。<br>
解決方法はすごく簡単で、ダウンロードフォルダからアプリケーションフォルダにドラッグ＆ドロップしなおせば良いのです。<br><br></p>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1954516/6074d1c6-3bc0-a52b-cfcc-71271cda0d04.gif">


<p>macでよくわからない不明エラーが出た時は、エラーコードをちゃんと読むのも大事ですが、アプリケーションのインストール場所も確認しておくと良いですよ。

</p>
Power Automate: Yammer 用のカスタムコネクターの作成 #2

# はじめに
今回は、メンバー一覧取得を生成

URL 貼り付けて自動生成からは出来ないので、Swagger Editor から、Yaml定義をします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/caebaab5-b1c5-13cc-aa83-2a58d33f8968.png)
以下の続き

https://qiita.com/baku2san/items/818887dc899c1891bf16

以下のAPIが検索すると見つかってきますけど古いものなので無視しましょう

# 今回使用する Rest API についての補足

```url:旧_GetGroups
https://www.yammer.com/api/v1/groups
```

```url:GetGroups
https://www.yammer.com/api/v1/users/in_group/:Group_Id.json
```

https://developer.yammer.com/docs/usersin_groupidjson

上記を確認すると、以下のように URL Parameter が Limit しかないように思えるが、実際は num_per_page が使えます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e491d9de-fd7a-485c-1c65-22f9c8e38059.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ddd270b0-d023-1a41-dd1b-e5c83b857b56.png)




# メンバー一覧 Action の追加定義
## New Action から新しい Action を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/43f484bb-7a83-e944-e798-1260e9e18d8c.png)
## Swagger Editor で定義追加して、更新
メンバー一覧の追加の定義を追加して、更新するだけ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ba7693d7-97cd-4ee8-ff3c-4a1a122f6936.png)

```yaml:メンバー一覧部分
  /api/v1/users/in_group/{groupID}.json:
    get:
      responses:
        default:
          description: default
          schema: {}
      summary: GetMembers
      operationId: GetMembers
      description: メンバー一覧を取得
      parameters:
      - {name: groupID, in: path, description: group ID, required: true, type: integer}
      x-ms-visibility: important
```

# 利用例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/f3c49cfd-425f-2cdb-9177-a9d3b62e450f.png)
※アイコン変えるとそれっぽくなりますよね 😁

# 参考資料
## GroupID を指定した、メンバー一覧の取得 API

https://developer.yammer.com/docs/usersin_groupidjson

## Open API 

https://cloud.google.com/endpoints/docs/openapi/openapi-overview?hl=ja

# あとがき
こんな感じで、Yammer Rest API を全部定義して、社内で使えるようにしたいものだ・・

ただ、Power Automateではなく、Logic Appsで定義したほうがもしかして共有はしやすい？？（未調査）

# Keyword

How to create custom connector to get a group members
【Rails6】cocoonによる動的フォーム作成時に注意すべき点。「"accepts_nested_attributes_for"」、「"can't be blank"」

cocoonを用いて、動的に変化するフォームを作成した際にハマったことを記します。
cocoonの導入は以下の記事を参考にしました。
・[【Rails】cocoonを用いて親子孫関係のテーブルに複数のデータを同時保存する方法 - Qiita](https://qiita.com/hitochan/items/5a45a95e644492d66160)
・[【Rails6】cocoonを使った動的フォーム入力画面の作り方 - Qiita](https://qiita.com/shooo777/items/4691a08357ee15233d4a)


#問題概要
　以下のような3つのモデルを作成し、関連づけたと仮定します。

|関係  |モデル名  |
|---|---|
|親  |Parent  |
|子  |Child |
|孫  |Grandchild |

上記記事を参考にしながらフォームを作成し、できたフォームよりデータを送信したら、以下のようなバリデーションに引っかかりました。

:::note alert
Child Grandchild child can't be blank
Child Parent can't be blank
:::

#原因
各モデルのvalidationの記述に問題がありました。

```parent.rb
has_many :children, dependent: :destroy
accepts_nested_attributes_for :children
```

```child.rb
belongs_to :parent
has_many :grandchildren, dependent: :destroy
accepts_nested_attributes_for :grandchildren
validates :parent_id, presence: true
```

```grandchild.rb
belongs_to :child
validates :child_id, presence: true
```


`accepts_nested_attributes_for`によって、親作成時にその子供のデータも**同時**に作成できるようになります。
このとき、childの`parent_id`やgrandchildの`child_id`は各データの保存と**同時**に、そのデータのidが格納されます。
従って、データを保存し終わるまでは各フォームから、

```_children_fields.html.erb
<%= hidden_field_tag :parent_id, @parent.id %>
```

```_grandchildren_fields.html.erb
<%= hidden_field_tag :child_id, @child.id %>
```

のようにインスタンス変数から直接値を代入するよう試みても、各データは保存される前でありidを持たないため、バリデーションのpresenceに引っかかってしまいます。

#解決策
方法は非常にシンプルで、`validates :child_id, presence: true`と`validates :parent_id, presence: true`を削除します。

#おわりに
`accepts_nested_attributes_for`のような1行で大きな効果を有するコードは、その動作を理解できていないと、予想外のエラーの原因になります。便利なものほどその本質の理解を心がけようと思いました。
[06] declarative pipeline の使用例 -- 例外を握り潰す（分散ビルド）


## 概要

goto 文のようなことをするために例外を投げて且つ握り潰す.
waitUntil (== true の間ループする) で使うことがあったので、書き残しておく.

なお、使用した Jenkins バージョンは Jenkins 2.314 である.

```groovy
略
        stage('A') {
            echo " in stage."
            parallel ( // 本記事では並列処理は気にしなくて良い
                "task1": {
                     // 何か処理をしているものとする．本記事では重要ではないので省略する
                },
                "task2": {
                    waitUntil { // true の間は継続する
                        try {
                            RC = sh (
                                     [
                                         script: "python3 /var/lib/jenkins/bin/is_finished.py", 
                                         returnStatus:true
                                     ]
                                 )
                            if (RC != 0) {
                                // 意図的に例外を生じさせて catch に進める
                                error message: "Continue"
                            }
                            echo "Finished"
                            false // false を定義することで waitUntil を脱出できる
                        } catch(error) {
                            true // 処理継続
                        }
                    }
                }
            )
        }
    }    
略
```

# 参考記事

・https://qiita.com/i47_rozary/items/b05b52b3c16041f91196

　

以上
ABC222 チャレンジ結果

ABC222結果 : ABC3完
相変わらずD問題で詰まってしまう...
以下ソースコード

A : Four Digits
パッと構文が分からないときのとりあえずfor文で回す.

```python
N = input()
k = 4 - len(N)
for i in range(k):
    print(0, end="")

print(N)
```


B : Failing Grade
問題文そのまま. 解説見たら内包表記使えば行数少なくできることに気づかされる.

```python
N, P = list(map(int, input().split(" ")))
list_N = list(map(int, input().split(" ")))

num = 0
for i in range(N):
    if list_N[i] < P:
        num += 1

print(num)
```

C : Swiss-System Tournament
勝数とindexでソートするために, 勝った場合は減算することに.
途中でindexもいると気づいてコードいじったため, リストが[勝数, じゃんけんの情報, index]の順になり見栄え悪し.

```python
import operator

def janken(p, q, i):
    if (hito_list[p][1][i] == "G" and hito_list[q][1][i] == "C") \
       or (hito_list[p][1][i] == "C" and hito_list[q][1][i] == "P") \
       or (hito_list[p][1][i] == "P" and hito_list[q][1][i] == "G"):
        hito_list[p][0] -= 1
    elif (hito_list[p][1][i] == "C" and hito_list[q][1][i] == "G") \
          or (hito_list[p][1][i] == "P" and hito_list[q][1][i] == "C") \
          or (hito_list[p][1][i] == "G" and hito_list[q][1][i] == "P"):
        hito_list[q][0] -= 1

N, M = list(map(int, input().split(" ")))
hito_list = []

for i in range(2 * N):
    GCP_list = input()
    hito_list.append([0, GCP_list, i+1])

for i in range(M):
    for j in range(N):
        janken(2 * j , 2 * j + 1, i)

    hito_list = sorted(hito_list, key=operator.itemgetter(0, 2))


for num in range(2 * N):
    print(hito_list[num][2])
```

D : Between Two Arrays
・間違いコード
自分なりに一通り組んでみたが, 提出すると後半実行時エラーのオンパレード.
再帰でうまくいくと思ったのにー
TLEはしょうがないが, REになるのは未だ分かっておらず泣

DP使う発想が全くなく使い方も分かってないので修行を重ねるしかあるまい...

```python
N = int(input())
a_list = list(map(int, input().split()))
b_list = list(map(int, input().split()))
num = 0
d = 0

def ktz_kosuu(list1, list2, N):
    global d, num

    d = max(list1[0], d)
    if N == 1:
        erabikata = list2[0] - d + 1
        num += erabikata
        
            
    else:
        e = d
        for j in range(e, list2[0]+1):
            d = j
            x = list1.pop(0)
            y = list2.pop(0)
            ktz_kosuu(list1, list2, N-1)
            list1.insert(0, x)
            list2.insert(0, y)

    return num % 998244353

kotae = ktz_kosuu(a_list, b_list, N) 
print(kotae)
```
SQLの重複行のまとめ方に関して

## はじめに

仕事で勉強になったクエリの書き方だったので、ここで記録しておきます。

まったく同じクエリは書けないので簡略化して書きます。

以下のような、テーブルがあるとします。

- 商品テーブル `services`
- 購入テーブル `payments`
- 顧客テーブル `customers`

Schema (MySQL v8.0)

```sql
CREATE TABLE services (
  id INT NOT NULL PRIMARY KEY auto_increment,
  name TEXT,
  category_id INT
);

INSERT INTO services VALUES
    (1, 'cookie', 1),
    (2, 'candy', 1),
    (3, 'ice', 2),
    (4, 'rice', 3),
    (5, 'ball', 4),
    (6, 'cake', 1);
    
CREATE TABLE customers (
  id INT NOT NULL PRIMARY KEY auto_increment,
  name TEXT
);

INSERT INTO customers VALUES
    (1, 'brown'),
    (2, 'rally'),
    (3, 'boggie'),
    (4, 'tashiro'),
    (5, 'yamada'),
    (6, 'takeda');
    
CREATE TABLE payments (
  id INT NOT NULL PRIMARY KEY auto_increment,
  customer_id INT,
  service_id INT
);

INSERT INTO payments VALUES
    (1, 1, 1),
    (2, 1, 2),
    (3, 2, 1),
    (5, 3, 4),
    (6, 3, 3),
    (8, 4, 1);
```

以下のような結果を得たいとしましょう（お題）。

## お題

「甘い食べ物（sweets `category_id: 1`）を購入した顧客は、一人当たり何個購入したか？」

この時、自分はクエリ1の発想しかありませんでした。

つまり、購入した甘い食べ物（sweets `category_id: 1`）のidをDISTINCTで重複を削除して、COUNTする方法。

> DISTINCTは一般にソートが発生する負荷の高い処理です。

https://thinkit.co.jp/free/marugoto/2/1/18/1.html

という主張もあるそうです。

実際は`EXPLAIN`して確かめたり、以下👇のような使い分けを考慮する必要がありそうです。

https://qiita.com/yamadayamada_jp/items/ef7ac4301f9c20491bae

いずれにせよ、`DISTINCT`以外の書き方も心得ておきます。

それがクエリ2（`GROUP BY`を用いた集計）です。

### クエリ1

```sql
SELECT
   payments.customer_id,
   COUNT(DISTINCT(services.id))
FROM payments
INNER JOIN services ON services.id = payments.service_id
   AND services.category_id = 1
GROUP BY 1
```

Results

| customer_id | COUNT(DISTINCT(services.id)) |
| ----------- | ---------------------------- |
| 1           | 2                            |
| 2           | 1                            |
| 4           | 1                            |

### クエリ2

```sql
WITH paid_sweets_ids AS (
	SELECT
          service_id,
          customer_id
	FROM payments
	INNER JOIN services ON services.id = payments.service_id
		AND services.category_id = 1
   GROUP BY 1, 2
)

SELECT
	customers.id AS customer_id,
	paid_sweets_counts.value AS paid_sweets_count
FROM customers
INNER JOIN (
	SELECT customer_id, count(*) AS value FROM paid_sweets_ids GROUP BY 1
) AS paid_sweets_counts ON paid_sweets_counts.customer_id = customers.id
```

Results

| customer_id | COUNT(DISTINCT(services.id)) |
| ----------- | ---------------------------- |
| 1           | 2                            |
| 2           | 1                            |
| 4           | 1                            |

どちらも結果は同じです。が、パフォーマンスを考慮する際は状況に応じて書き換えるスキルが必要です。

`DISTINCT`だけでなく、甘い食べ物（sweets `category_id: 1`）の商品idを`GROUP BY`して、それを購入した顧客idを`GROUP BY`する方法も検討できるようにしておきます。

本日は、以上です。

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
Python機械学習/pickleファイルを使ったオブジェクトの保存

# Introduction
Pythonで機械学習をする際のデータやモデルの保存にはpickleファイルを使用するのが非常に便利なので，その使い方についてメモを残しておく．

# データの準備
今回はScikit-learnのガンデータを使用．

```py
from sklearn.datasets import load_breast_cancer
import pandas as pd

cancer = load_breast_cancer()
data_feature = pd.DataFrame(cancer.data, columns=cancer.feature_names)
data_target = pd.DataFrame(cancer.target)
```

# csvファイルでデータ管理
まずは一般的なCSVファイルでのデータ読み書きについて記す．

csvファイルで保存

```py
data_feature.to_csv('data_feature.csv')
data_target.to_csv('data_target.csv')
```

csvファイルの読込

```py
feature_csv = pd.read_csv('data_feature.csv', index_col=0)
target_csv = pd.read_csv('data_target.csv', index_col=0)
```

# pickleファイルでデータ管理
では本題のpickleファイルでのデータ読み書きについて記す．

pickleファイルで保存

```py
data_feature.to_pickle('data_feature.pkl')
data_target.to_pickle('data_target.pkl')
```

pickleファイルの読込

```py
feature_pkl = pd.read_pickle('data_feature.pkl')
target_pkl = pd.read_pickle('data_target.pkl')
```

pickleファイルで保存することで，ヘッダーやインデックスの有無など気にすることなく，保存時のデータをそのまま読み込めるので非常に便利．

# 機械学習モデルをpickleファイルで管理
生成した機械学習モデルもpickleで保存できるので，その方法について記す．

とりあえずロジスティック回帰でモデル生成．

```py
from sklearn.linear_model import LogisticRegression

model = LogisticRegression()
model.fit(feature_pkl, target_pkl)

print(model.score(feature_pkl, target_pkl))
```

```
Out:
0.945518453427065
```

モデルの保存

```py
import pickle
pickle.dump(model, open('model.pkl', 'wb'))
```

モデルの読込

```py
model_pkl = pickle.load(open('model.pkl', 'rb'))
```

```py
print(model_pkl.score(feature_pkl, target_pkl))
```

```
Out:
0.945518453427065
```

# Conclusion
今回使用した関数．
- ```DF.to_pickle()```：データフレームをpickleファイルで保存
- ```DF.read_pickle()```：pickleファイルで保存されたデータフレームの読込
- ```pickle.dump()```：機械学習モデルをpickleファイルで保存
- ```pickle.load()```：pickleファイルで保存された機械学習モデルの読込

pythonによる機械学習が捗ると思うので，pickleファイルを活用されたし．

# Code
```py
# データの準備
from sklearn.datasets import load_breast_cancer
import pandas as pd

cancer = load_breast_cancer()
data_feature = pd.DataFrame(cancer.data, columns=cancer.feature_names)
data_target = pd.DataFrame(cancer.target)


# csvファイルでデータ管理
## データの保存
data_feature.to_csv('data_feature.csv')
data_target.to_csv('data_target.csv')
## データの読込
feature_csv = pd.read_csv('data_feature.csv', index_col=0)
target_csv = pd.read_csv('data_target.csv', index_col=0)


# pickleファイルでデータ管理
## データの保存
data_feature.to_pickle('data_feature.pkl')
data_target.to_pickle('data_target.pkl')
## データの読込
feature_pkl = pd.read_pickle('data_feature.pkl')
target_pkl = pd.read_pickle('data_target.pkl')


# 機械学習モデルをpickleファイルで管理
## モデル生成
from sklearn.linear_model import LogisticRegression

model = LogisticRegression()
model.fit(feature_pkl, target_pkl)

print(model.score(feature_pkl, target_pkl))
## データ保存
import pickle
pickle.dump(model, open('model.pkl', 'wb'))
## データの読込
model_pkl = pickle.load(open('model.pkl', 'rb'))

print(model_pkl.score(feature_pkl, target_pkl))
```
プログラミングの入り口として自動テストは有効だ

[プログラミングの入り口として自動テストは有効か - マンガ・ロジスティクス・エフ](https://tsuemura.hatenablog.com/entry/2021/08/26/063628)

を読んでの記事です。

前提として、すえむらさんの元記事を否定したいポイント等はなく、自分の視点からも書きたくなったのが２割。最近Qiita書いてないなー何かネタはないかなーと思っていたところでPocketを漁っていて思い出したというのが8割です :smiley: 

## 普段プログラミングをやらないテストエンジニアやテスターにとっての入り口として有効

本記事タイトルに若干付け加えています。「誰にとっても」自動テストが有効だとは言えないですが、普段のお仕事の中でプログラミングをしていないテストエンジニアやテスターにとって、プログラミングの入り口としての自動テストは有効である、というのが私の考えです。

「根拠は、そういったバックグラウンドのエンジニアにプログラミングを教えた実感からである」なのですが、それではただの感想文なので、もうちょっと思いを書いてみようと思います。

### Hello!Worldでは感動しないし「計算機」に計算させても面白くない

tsuemuraさんの記事にあるように、モチベーションが重要であるという点は完全同意です。

が、プログラミング学習のモチベーション、あるいは「これをやりたい」という強い動機を持つことは**とてつもなく難しい**と思っています。

分厚い入門書を買ってきて、Hello!Worldと画面に表示したり、BMIの計算をさせてみたり。こういったプログラムを書いて「おお！」と感動出来る人はおそらく少数です。実際には「はぁそうですか」で終わってしまう人が大半のはず。

そういった人に、変数とは、関数とは、クラスとは、を教えて「はいダイクストラ法を実装してみましょう」と言っても、挫折するに決まっています。数字を並び替えても、最短経路を求めさせても、それは人間がやればひと目でわかるものを回りくどく機械にやらせているだけ、と思われてしまいます。ここで学習を止めてしまう可能性が非常に高く、ここを越えるのに「自動（システム）テストである点って有効だよね」という話がこの先です。

### 「画面が動く」は、非常にわかりやすいインタラクティブな体験

Seleniumなどのライブラリを使ってシナリオテストやE2Eテストを自動化する場合、プログラミングによって画面を操作することが多いです。これが、普段テストを行っているプログラミング初学者にとって、計算処理の実装などに比べてわかりやすい。

特に「どの手順までうまくいっていて、どの手順で失敗したのか」がわかりやすい。「OKボタンのクリックに失敗しているみたいだから、40行目まではうまくいっているみたいだ」がわかるのが大きい。

最近の小学生もプログラミング学習などやっていますが、いきなりコンソールに向き合ったりしていません。Scratchでブロック組み合わせてキャラクターを動かすところからやっています。

自分がなにか手を加えると動きが変わる、というインタラクティブな体験をGUIを対象に経験することには意味がある、ということだと捉えています。

かつ、その先に待っているのは「自分が普段やっていることを機械に任せられるかもしれない」という気づきです。ダイクストラ法やユークリッド互除法よりも、自分が楽になる可能性が高い。

### 手順化されているというハードルの低さ

システムテストを自動化しようという場合（是非はおいておいて）自動化したい操作・オペレーションはわかっているか、自力で作れるはずです。

ここが一般のプログラミングと違う点です。

一般のプログラミングは「手続きを考える」ところから必要で、ここで不慣れな人は詰まります。

GUI操作の自動化をする場合、手続きは（全てではないが）Excelのテスト仕様書に沿って行えばいい。（是非は置いておいて。2度め）

つまり、自分で考えなければいけない部分が少ない。この点も、自動テストがプログラミングの入り口として有効だと考える根拠です。

ここまでかんたんにまとめると、つまり「初学者が投げ出したり、行き詰まったりするポイントが、自動テストのためのプログラミングだったら少なく済むよね。だから有効だと思うよ。」という話しです。

## 手段の目的化でいいじゃない
「これをやりたい、だからプログラミング」が理想で、このモードに入れた人が爆発的に成長したりすることは確かにあります。し、ストーリーとして非常に魅力的です。ネットを見るとこの手の話がいくつも出てきます。

一方で、魅力的なストーリーの主人公を皆が歩むわけではありません。

自分の経験上、明確な「コレ」がないけれど、機会が与えられてとりあえずテスト自動化（の前提となるプログラミング）を学んでみたところ、「なるほど、これができるということは普段のあれも自動化できそうだぞ」という気づきを得て実践するパターンも少なくありませんでした。

つまり、道具を手にする前はそもそも何がしたいといった発想が出てこない。道具を得て初めて、適用先が思いつくこともあるのです。

ということで、「これがやりたいからプログラミングを学ぼう」ができれば最高ですが、それが特に無い場合でも、テストエンジニアやテスターやQAなどというお仕事をしている方でプログラミングやったこと無いぜって方は、とにかく自動テスト向けにプログラミングを学ぶ、をやってみましょう。

というポジショントークでした。