OmniAICreator/Qiita-1.07M huggingface dataset:
Db2 on CloudのINSERT性能を向上させる

# 目的

IBM CloudのDb2 on Cloudは、オンプレミスに比べてINSERT性能が非常に悪いと感じる場合があります。原因としては、Db2 on Cloudはクラウドのネットワーク越しに存在するため、ネットワーク遅延の影響を受けることが1つ。もう1つですが、Db2 on CloudはHADR構成がとられており、かつ、スタンバイ機の1台はSYNCモードになっています。つまり、1回のコミットに対して、プライマリとスタンバイ2つのデータベースに更新が反映されてはじめて応答が返ってくる仕組みになっているためです。

今回は少しでも性能を上げるための方策を検証してみます。

# 計測

## 計測方法

テスト用のCSVをIMPORTコマンドで投入する際の時間を測ります。IMPORTコマンドは内部的にはINSERT文として処理されます。

計測用DDLです。

```perftest.ddl
CREATE TABLE PERFTEST (
  C1 INT NOT NULL GENERATED ALWAYS AS IDENTITY,
  C2 DECIMAL(10,0),
  C3 DECIMAL(10,0),
  C4 DECIMAL(10,0),
  C5 DECIMAL(10,0),
  C6 DECIMAL(10,0),
  C7 DECIMAL(10,0),
  C8 DECIMAL(10,0),
  C9 DECIMAL(10,0),
  C10 DECIMAL(10,0),
  PRIMARY KEY(C1)
);
```

インポート用テストデータを生成します。10万行用意します。

```gen.pl
#!/usr/bin/perl

$max = 100000;

for ($i = 0; $i < $max; $i++) {
  printf("%d,%d,%d,%d,%d,%d,%d,%d,%d\n", $i, $i,$i,$i,$i,$i,$i,$i,$i);
}
```


# 計測

## チューニング前

1万行ごとにコミットしてデータをインポートします。インポートは内部的には1行ごとにINSERTする処理に変換されます。

```
$ time db2 "import from 100000.csv of del commitcount 10000 insert into perftest (c2,c3,c4,c5,c6,c7,c8,c9,c10)"
```

<br>|Db2 on Cloud|Db2（ローカル）
---|---|---
所要時間|6m57s|0m29s
スループット|241行/秒|3421行/秒

圧倒的な差が出ていることがわかります。

## 複数行を一括してインサート

Db2のIMPORTコマンドではmodified by compondを指定することで、複数のINSERTを一括して実行することができます。JDBCではStatement.addBatch()とexecuteBatch()に相当します。compoundの最大値である100行を指定して実行します。

```
$ time db2 "import from 100000.csv of del modified by compound=100 commitcount 10000 insert into perftest (c2,c3,c4,c5,c6,c7,c8,c9,c10)"
```

<br>|Db2 on Cloud|Db2（ローカル）
---|---|---
所要時間|1m53s|0m22s
スループット|885行/秒|4545行/秒

ローカルでは1.3倍、Db2 on Cloudでは3.6倍ほどの性能向上が見られました。それでもローカルとは1桁違います。

引き続き、他にいい策はないか検討してみます。

# 注意

本検証の結果ですが、実行時間の絶対値に意味はありません。modified by compound以外で処理性能を上げる方法はいくつかあります。例えば自動生成列のキャッシュサイズを大きくする、テーブルにAPPEND ONを付与する等です。本検証はあくまでmodified by compoundの効果を見ているだけということは注意ください。
cakePHP4 find('list')で取得したデータをForm->controlで上手く表示できない

Every Qiita #21
のんびり独学初学者投稿 21日目
今回は・・・
cakephp 連想配列の成形とformヘルパーの使用についての備忘録です。

###formヘルパーでformを作ってみる
投稿の絞り込みで登録済みのカテゴリーを選択できるようにしたい.
articles belongsTo categories の関係で、articles/index.phpで実装していると仮定してます。

*categoriesTableのカラムは検証のため以下で設定*

|  categoriesTable | column |
| --- | --- |
| primary_key | id |
|  カテゴリー名  | content (通常はtitle または name)|

```php:ArticlesController.php
$articles = $this->categories->find('list');
$this->set(compact('articles'));
```
上記でカテゴリーのデータを連想配列で取得できる。
FormHelperでフォームを作ってみる。

```php:articles/index.php
$this->Form->control('article_id');
```
ブラウザで確認すると・・・
![スクリーンショット 2021-07-26 17.39.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813099/eed4d6e9-173e-fd05-70a5-e2740db9e110.png)
上手く表示されません。

###find('list')は"name"または"title"がデフォルトで選択される
今回はcategoriesTableに"content"としていたため、上手くデータを取得できていなかったみたいです。
再度コントローラを修正します。

```php:ArticlesController.php
$articles = $this->categories->find('list',[
  'valueField'=>'content'
]);
$this->set(compact('articles'));
```
`'valueField'=>'content'`でidに対応する値を設定できます。
keyも選択したい場合は,`keyField`で指定できます。
Reactで<input type="file" webkitdirectory />が動かない時の対処法

`<input type="file" webkitdirectory />`は、Chromium系ブラウザでディレクトリごとファイルを選択するタグですが、Reactで使うのに一工夫必要だったのでメモします。

## 普通にそのまま書いた場合

```jsx
<input type="file" webkitdirectory />
```

```
Type '{ type: string; webkitdirectory: true; }' is not assignable to type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'.
  Property 'webkitdirectory' does not exist on type 'DetailedHTMLProps<InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>'.
```

`does not exist`って怒られてしまいます。

## 解決策

```jsx
<input
  type="file"
  directory=""
  webkitdirectory=""
/>
```

`directory="" webkitdirectory=""`と書くと動くようになります。

## TypeScriptを使っている場合

```tsx
<input
  type="file"
  /* @ts-expect-error */
  directory=""
  webkitdirectory=""
/>
```

`/* @ts-expect-error */`で強制的に黙らせます。
コピペでYouTubeの動画をダウンロードする(Python)

# コード
```python:jupyter_lab.ipynb
!pip install youtube-dl
import youtube_dl
ydl_opts = {
   'outtmpl':'保存先のパス/ファイル名.mp3'
}
with youtube_dl.YoutubeDL(ydl_opts) as ydl:
    ydl.download(['URL'])
```
これで完成！！！
Salesforceプロセスビルダーでアクションを自動化

<h2>プロセスビルダーとは</h2>
プロセスビルダー（Lightningプロセスビルダー）とは、次世代のワークフロー作成ツールです。
フローチャートのような状態なので前後の関係が分かり易く、一目で流れを把握できます。

<h2>プロセスビルダーで自動化できるアクション</h2>
プロセスビルダーでは以下のアクションを自動化できます。



|機能              |アクション              |
|:------------------|:------------------|
|Apex              |Apexコードをコール|
|Catterに投稿        |ユーザやグループ|、レコードのフィードにメッセージを投稿|
|クイックアクション|クイックアクションを使ったレコードの更新・作成、活動の記録|
|カスタム通知を送信|重要なイベントが発生したときに、カスタム通知を送信|
|フロー|VisualWorkflowを起動|
|メールアラート|メールアラートを送信|
|レコードを更新|プロセスを開始したレコードもしくは関連するレコードを更新|
|レコードを作成|関連するレコードの値を利用してレコードを作成|
|手順|有効な別のプロセスを呼び出す|
|Quip|文書、チャットルーム、フォルダを作成|
|承認申請|承認申請を更新|

<h2>プロセスを実際に作ってみよう</h2>
ここでは、「商談が成立したらChatterへ自動的に投稿する」というプロセスを作成します。

まず、プロセスビルダーにアクセスします。
【設定】＞【プロセスの自動化】＞【プロセスビルダー】

<h3>1.オブジェクトを選択する</h3>
①：オブジェクトを選択をクリック
②：オブジェクトを選択（商談）
③：レコードを作成または編集したときを選択
④：保存をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520342/704e234e-210e-44c2-c96f-d9097bdefb80.png)

<h3>2.条件を追加する</h3>
①：条件を追加をクリック
②：条件名を入力（商談成立）
③：条件を満たしているを選択
④：条件を設定
⑤：すべての条件に一致を選択
⑥：保存をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520342/59688d84-9fc7-dd5a-7c29-ec1328b2cdfb.png)

<h3>3.アクションを追加する</h3>
①：アクションを追加をクリック
②：Chatterに投稿を選択
③：アクション名を入力
④：投稿先を設定（ここでは営業グループ）
⑤：投稿したい内容を入力
⑥：保存をクリック
⑦：有効化をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520342/42c5ac40-ae26-6681-816b-308ef5da0f42.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520342/4e2aa245-502a-c793-d606-7009f857efdd.png)


これでプロセスの自動化が完了しました。

試しに新規商談を作成すると、、
↓のように自動的にChatterへ投稿されていることを確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520342/92cd0104-d030-64e5-deb8-c51aab58214f.png)
【Rails6】カスタムフォントの導入方法


開発中のRailsアプリでストップウォッチのフォントが普通すぎてダサいな〜と思ったのでカスタムフォントを導入しました。
知識定着のためにアウトプットします。

##環境
Rails 6.0.4
Ruby 2.6.5

## 好きなフォントをインストールして配置します。

私は「[DSEG](https://www.keshikan.net/fonts.html)」というデジタル時計をイメージしたカスタムフォントをインストールしました。

▼こんな感じです
![test](https://gyazo.com/306d9154e4ca78b9d6e8125d03d3b647/raw)

ファイルインストール後に、```app/assets```にfontsというフォルダを作成します。
その後、fontsフォルダにインストールしたファイルを配置します。

![test](https://gyazo.com/f35e9f3c2ca144f6e40a3e10cd700be7/raw)

## application.scssにインストールしたファイル名などを記述してCSSで参照できるようにします。

```ruby
/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS and SCSS file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */

// ↓下記追加↓

 @font-face {
  font-family: "DSEG"; //名前を命名（何でも良い）
  src: asset_url('DSEG7Classic-Bold.ttf');  //ファイル名を指定
 }

```

【注意】
```application.css```になっている場合は、```application.scss```にしましょう！
```.css```だとうまく読み込めないみたいです、、、。

## CSSに記載する

HTMLは以下のようになってます。

```show.html.erb
<h1>ストップウォッチ</h1>
 <div id="container">
  <div id="stopwatch">
   <div id="display">0.000</div>
  </div>
 </div>
```

CSSにさっきの命名した名前を書きます。

```show.css
#display {
  font-family: "DSEG";
}
```

## 完成！
これが、、、
![test](https://gyazo.com/ee72c395a39bf0850977ea8b6c177288/raw)

↓

こうじゃ~~
![test](https://gyazo.com/c392499edb594d41faf9e299278dc8b6/raw)
フォントが適用されましたね。
なんだかストップウォッチくんも嬉しそうですね。
（あとで他の装飾もしてあげます。笑）


## まとめ
かんたんにできましたね〜〜
フォント変えるだけで、結構雰囲気変わるので意外とフォントって重要なんですね〜。

##参考記事

https://qiita.com/kamataku/items/69df48ee04878c773d73
JavaScriptを基本からまとめてみた【6】【変数宣言】

##はじめに

####学習するに至った経緯

2020年より、未経験からエンジニアへの転職を目指し、某プログラミングスクールへ通う。
入学後、『Ruby』を未経験から学ぶ人が多いのと『Ruby』の求人が思っていた以上に少ないので、
卒業後、フロントエンドのエンジニアを目指す事に。
Javascriptの学習した事を言語化し、認識の深化による備忘録として記載。

##const, let等の変数宣言
####var
- JavaScript時代ともにバージョンが更新されて、「ES6（ECMAScript6）」が現時点での最新版。
以前までは変数宣言に『var』のみを使用していたが、ES6の環境から『let』と『const』が新たに追加された。『var』はスコープの範囲を広げる自由度の高い変数のため、意図していないエラーが起こり得ることから、使用頻度は低い。

####let
- 『let』と『var』においては初期値の設定は必須ではない。
- 『let』と『var』の違いは2つで、① 『var』は再宣言可、『let』は再宣言不可と② 『var』は関数スコープ、『let』はブロックスコープである。

####const
- 『const』で定義した変数に値を代入することはできない。
- 『let』と『const』の違いは、『再代入ができないこと』である。
つまり、『const』は、再宣言も再代入もできないため、値を一度決めたら途中で変更ができない。
- 『const』で定義したオブジェクトはプロパティの変更が可能。

####let, const, varの特徴
|　  | l e t |const | v a r  |
|---|---|---|---|
|再代入|⚪︎ |×  |⚪︎  |
|再宣言  |×  |×  |⚪︎  |
|ブロックスコープ  |⚪︎  |⚪︎  |×  |
|関数スコープ|⚪︎  |⚪︎  |⚪︎  |

#####変数の宣言<br>文字列や数字、配列などを格納すること。
#####再代入<br>文字列や数字、配列などを格納すること。
#####再宣言<br>一度宣言した変数を、同じ変数名を使って再び宣言をし直すこと。
#####スコープ<br>変数や関数の有効範囲のこと。
#####ブロックスコープ<br>ブロックごとに囲まれた範囲のこと。
#####関数スコープ<br>関数のブロックごとに作られる範囲のこと。




##参考サイト
[モダンJavaSciptの基礎から始める挫折しないためのReact入門]
(https://www.udemy.com/course/modern_javascipt_react_beginner/learn/lecture/21899196#overview)
[【JavaScriptの基本】letとconstどうやって使い分ける？スコープとの関係性も意識しよう]
(https://tcd-theme.com/2021/04/javascript-let-const.html)
[JavaScriptのletとは？知っておくべき特徴と使い方について]
(https://www.sejuku.net/blog/58429)
AmplifyでReact-Native導入

#まずAWS公式を参考に

https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/module-one/?e=gs2020&p=build-a-react-app-intro

#React
公式サイトを見ると、Reactは「A JavaScript library for building user interfaces」と称されています。UIのためのライブラリと理解して良いでしょう。

●Reactの主な仕事はデータを画面に表示する

さらに「Reactに与えるデータを変えると表示されるデータも変わる」という機能も備えています。データを変更してReactに与えれば、変更部分を半自動的に検出し、反応的（reactive）に表示を変えます。

この反応的変化がReactの価値を大きく高めています。webでは非常に多数の変数と状態管理が必要になります。JavaScriptだけでこれを解決しようとすると、複雑に絡んだいわゆるスパゲティコードになりがちです。そういった場合にReactを使えば、この変更を感知し、自動的に画面に反映させることができます。

また、Reactは表示要素のコンポーネント化（部品化）についても長けています。いくつかの表示要素と機能をまとめ、コンポーネントとして利用可能にします。ウェブにもWeb Componentsというコンポーネント化の標準規格がありますが、まだまだ実用的ではないということもあり、Reactが採用される場面が多く存在します。

```
npm install react react-dom
```
React および ReactDOM は CDN を介して利用することもができます。

```
<script crossorigin src="https://unpkg.com/react@17/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
```
上記のバージョンは開発のためだけのものであり、本番環境には適していません。圧縮・最適化された本番バージョンの React は下記のリンクから利用できます。

```
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
```

# Expo CLI と React Native CLI

## Expo CLI
Expo はすぐにネイティブアプリを作成できます。
アプリの機能は Expo のエコシステム内に限られます。

## React Native CLI
Xcode か Android Studio の設定が必要です。
大規模なアプリ開発向けです。

いったんExpo CLIを利用します。

```
npm install -g expo-cli
```

```
expo init react_native_amplify_30
```
npm start


## GitHubにコミットする
GitHub レポジトリを作成してコードをレポジトリにコミット
https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/module-one/

コマンドラインインターフェイスで以下のコマンドを実行する新しい GitHub レポジトリにアプリケーションをプッシュします。

```
git init
git remote add origin git@github.com:username/reponame.git
git add .
git commit -m “initial commit”
git push origin master
```
## デプロイ時のCannot find file './src/aws-exports'
amplify init
npm init

初期化する
Railsで架空のCafeのHPを作ってみよう!【12日目】『特定のデータの取得(active:hashの属性値)』編

#概要
基本Railsの記法に則り書いていきます！
１から全ての説明ではなく
その中であれ？どうやるの？と
疑問に思った点や実装に困った箇所を
ピックアップして紹介していきます♩

#設定と準備
・Rails
・HTML
・CSS
・Javascript(jQuery)

↑上記の言語とフレームワークを使い
架空(自分で考えたテキトーなもの)のCafeの
HPを作っていこうと思います！

#12日目の作業内容:round_pushpin:
・ビューの作成(トップページに特定の情報を表示)

#12日目の気になった箇所:zap:
特定のデータの取得でカラムごとの取得はできたが
属性まで指定できるのだろうか。

#仮説:pushpin:
カラム別に取得する場合は
(testテーブルのoptionカラムだけ取得したい場合とする)

```samples_controller.rb
@test_option = Test.select('option')
```
このような形で取得することができる。
(取得の仕方は複数存在します)

似たような形で属性まで指定できないか試してみる。

Testテーブルのoption_idカラムのname属性だけを
取得したい場合とする。今回はname属性の属性値2を取得したい。
(_idはactive:hashの使用時の記法です)

```samples_controller.rb
@test_option = Test.select('option.name.2')
```
このように記述してみたがうまくいかなかった。

#結論:star:
複数やり方があると思いますが今回は私がうまくいった方法を紹介します。

上記と同じ条件で
Testテーブルのoption_idカラムのname属性だけを
取得したい場合とします。今回はname属性の属性値2を取得するとします。

```samples_controller.rb
@test_option = Test.where(:option_id name='2')
```

私の場合このような記述の仕方でうまくいきました。

簡単に説明すると
取得したいテーブル(モデル)に対してwhereメソッドを使います。

```samples_controller.rb
@test_option = Test.where
```
whereメソッドは条件に一致したレコードを配列で取得してくれます。
そして、
whereに取得したい条件を入れていきます。
まずはカラム名です。

```samples_controller.rb
@test_option = Test.where(:option_id)
```
この状態だとoption_idカラムの全てを取得する条件になります。

なので、さらに属性まで絞りたいので、

```samples_controller.rb
@test_option = Test.where(:option_id name)
```
このように続けて記述することでその属性まで条件まで絞ることができます。

同じように続けて、

```samples_controller.rb
@test_option = Test.where(:option_id name='2')
```

と、することで、属性の属性値まで条件を絞ることができました。
[SwiftUI] Picker 内の ForEach で id: \.self した時のバグ

``selection`` が index の値になってしまいます。

![スクリーンショット 2021-07-26 午後4.21.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178570/620e9dd0-a3ab-790f-de1d-b6c8c8103a50.png)

```swift
struct MyView: View {
    @State var selection = 10
    let items = [10,20,30]
    
    var body: some View {
        VStack {
            Text("selection: \(selection)")
            Picker(selection: $selection, label: Text("")) {
                ForEach(0..<items.count, id: \.self) { index in
                    Text("\(items[index])")
                        .tag(items[index])
                }
            }
        }
    }
}
```

下の様に、``Identifiable``なものを``ForEach``すれば直りました。

![スクリーンショット 2021-07-26 午後4.28.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/178570/01b6c6f6-3838-c8db-8b7d-7e703d25ff3b.png)



```swift
struct MyView: View {
    @State var selection = 10
    
    struct Item: Identifiable {
        var id = UUID()
        var num:Int
        init(_ num: Int) { self.num = num }
    }
    let items = [Item(10), Item(20), Item(30)]
    
    var body: some View {
        VStack {
            Text("selection: \(selection)")
            Picker(selection: $selection, label: Text("")) {
                ForEach(items) { item in
                    Text("\(item.num)")
                        .tag(item.num)
                }
            }
        }
    }
}
```

---

**バージョン**
Swift 5.4
SQLcl独自の機能を試す（３）

# TAB 補完
SQL文の途中でタブを入力することにより、構文を補完することができます。候補が複数ある場合には選択肢が表示されます。矢印キーで候補を選択することでSQL文を完成させることができます。下記の例では「SELECT * FROM S」を入力した時点でタブキーを押すとSで始まるスキーマ名やテーブル名が候補として出力されています。残念ながら、「スキーマ名.」入力後のタブ補完はできないようです。

```
SQL> SELECT * FROM S
SCOTT.       SCOTT04.     SCOTT3.      SYS.         SYSDG.       SYSRAC.
SCOTT01.     SCOTT2.      SYS$UMF.     SYSBACKUP.   SYSKM.       SYSTEM.

SQL> SELECT * FROM SCOTT.{TAB}
```

# HISTORY
SQL*Plusにも過去に実行したSQL文を再実行する機能がありますが、SQLclのヒストリー機能はキーボードの矢印キーで履歴が呼び出せる点が異なります。この機能により矢印キーとエンターキーだけで過去に実行したＳＱＬ文を再実行できます。
セミコロンより前の部分でエンターキーを入力すると、再実行ではなく編集モードに移行します。

SQL*Plusのヒストリー機能はデフォルトでは無効ですが、SQLclのヒストリー機能はデフォルトで有効になっています。
設定はSET HISTORY文で実行します。

```
SQL> SHOW HISTORY
HISTORY
        enabled
        filter: show, history, connect, clear, dbccred, dbcc
        Do not show failed statements
SQL>
SQL> HELP SET HISTORY
SET HISTORY
-----------

set history [FAILS [LIMIT [ n | DEFAULT ] ] | NOFAILS
           |FILTER [DEFAULT <command list>?|<command list>? | NONE]
           |LIMIT [n|DEFAULT]]

        FAILS sets history command to show failed statements.
       use limit to limit number of failues
        NOFAILS sets history command to not show failed statements
FILTER sets a list of sqlcl commands that can be excluded from the history
        LIMIT sets a new max size for the history

 NB. History will not save failed commands at end of session.
```

設定には以下の項目を指定できます。

|設定|説明|デフォルト|
|:---|:---|:---|
|FAILS|失敗したSQLをヒストリーに含める、個数の上限（LIMIT）を指定可能|NOFAILS|
|FILTER|履歴から除外するSQL文のリスト|SHOW, HISTORY, CONNECT, CLEAR, DBCCRED, DBCC|
|LIMIT|保存する履歴の上限|DEFAULT|

# LOAD
CSVファイルをテーブルに対してロードする機能です。簡易SQL*Loaderのように使えます。CSVファイルのフォーマットはUNLOADコマンドと同じくSET LOADFORMATコマンドで変更します。

```
SQL> LOAD TABLE data1 /tmp/DATA1_DATA_TABLE.csv

format csv

column_names on
delimiter ,
enclosure_left "
enclosure_right "
encoding UTF8
row_limit off
row_terminator default
skip_rows 0
skip_after_names

--Number of rows processed: 1,000,000
--Number of rows in error: 0
--Last row processed in final committed batch: 1,000,000
0 - SUCCESS: Load processed without errors
```

# PWD/CD
CDコマンドはLinuxシェルと同じようにカレントディレクトリを移動できます。残念ながら移動先ディレクトリ名には環境変数は使えません。
カレント・ディレクトリの確認にはPWDコマンドを実行します。

```
SQL> PWD
/tmp/
SQL> CD /home/oracle
SQL> PWD
/home/oracle
```
Azureにてサブスクリプションへの権限付与が適切に実施されているにも関わらずAzureポータルにて表示されない場合の対応方法

## 概要
Azureにてサブスクリプションへの権限付与が適切に実施されているにも関わらずAzureポータルにて表示されない場合の対応方法を共有します。

サポートリクエストを作成しようとした際に、`開発テスト...`で始まるサブスクリプションが表示されませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f0d3c3ad-7f30-de1c-7bd4-c2ec4dbdeeec.png)

## 対応方法
### 1. Azureポータルの右上にある`ディレクトリ + サブスクリプション`を選択後、`既定のサブスクリプション フィルター`の`すべて選択`を選択してすべてのフィルターを解除。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/f515a86f-e0bb-84ed-e29f-142f6d09191a.png)

### 2. ページをリロードして、`開発テスト...`で始まるサブスクリプションが表示されたことを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d5ef7608-1ca3-2fcf-f1db-fc1c7c36e2b2.png)
遠隔でJetsonデバイスのGPU/CPUパフォーマンスの監視について

#GPU/CPUのパフォーマンスについて
NVIDIA向けの掲示板でよく見られる質問の一つとしては
GPU/CPUのパフォーマンスになるます。
現場にあるデバイスは環境などでパフォーマンスが影響される可能性がございます。
この際に、遠隔でGPU/CPUのパフォーマンス監視ができるツールがあれば、
いつでもどこでもGPU/CPUが最大効力発揮しているかを監視できるようになります。

#GPU/CPUのパフォーマンス監視機能のアーリーアクセス
ご興味のある方は是非私のプロフにあるメールアドレスをご連絡頂ければ、
GPU/CPUのパフォーマンス監視のアーリーアクセスをお試して頂けます！
【Kubernetes】2つ以上のyamlファイルを１つのファイルにまとめる no.12

![名称未設定のデザイン (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/68adb3a8-f5cd-80d8-5b52-5226f9a50462.png)


KubernetesのdeploymentオブジェクトとServiceオブジェクトのファイルを2つのファイルに分けて書いたが、1つのファイルにまとめることもできる。

その時は、３つのダッシュ(---) で区切るだけ。

ベストプラクティスでは、

service.yamlを最初に書き、---で区切ってからdeployment.yamlを書く

![2021-07-26_16-12-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/ce9512af-3d1a-293c-24c6-d405ec9633d5.png)
Nuxt.js APIを呼び出すproxyの設定

Nuxt.jsでproxyが上手く動作せずにハマったので備忘録として投稿します。
### 実現したいこと
Nuxtで、usersのnewページから名前を投稿し、リダイレクトされ_id.vueページで送信した名前を表示しようとしています。Dockerを使用しfront、backに分けてfrontにNuxtをRailsをAPIでProxyで呼び出す設定をしています。

### 発生している問題
投稿フォームから送信するとリダイレクトはされるが、名前が表示されない。
URLにはlocalhost:8000/users/undefinedとなっている。
Networkを確認すると、APIのlocalhost:3000が読み込まれていない様子。。
データの送信はconsole.logで確認。

### 該当のソースコード

```nuxt.config.js
 modules: [
    '@nuxtjs/proxy',
    '@nuxtjs/axios'
  ],
  proxy: {
    '/api/': {
      target: 'http://localhost:3000',
      pathRewrite: {
        '^/api/': '/'
      }
    }
  },
  axios: {
    prefix: '/api/',
  },
```
```plugins/axios.js
export default function({ $axios, redirect }) {
  $axios.setToken('access_token')

  $axios.onResponse(config => {
      $axios.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
  })
}
```

```users/_id.vue
<template>
  <h1>Hello, {{ name }}</h1>
</template>

<script>
export default {
  asyncData({ $axios, params }) {
    return $axios.get(`/api/users/${params.id}`)
      .then((res) => {
        return { name: res.data.name }
      })
  }
}
</script>
```
```users/new.vue
<template>
  <section>
    <div>
      <h1>New user</h1>
      <form @submit.prevent="post">
        <label for="name">Name: </label>
        <input id="name" v-model="name" type="text" name="name" />
        <button type="submit">submit</button>
      </form>
    </div>
  </section>
</template>

<script>
export default {
  data() {
    return {
      name: ''
    }
  },
  methods: {
    post() {
      this.$axios.post('/api/users', { name: this.name })
        .then((res) => {
          this.$router.push(`${res.data.id}`)
      })
    }
  }
}
</script>
```

# 解決策
_id.vueページの```return $axios.get(/api/users/${params.id})を```
```return $axios.get(users/${params.id})```に変更すると、
リダイレクトされ投稿した名前を表示することができました。

```nuxt.config.js
 modules: [
 // '@nuxtjs/proxy',
    '@nuxtjs/axios'
  ],
  // proxy: {
  //   '/api/': {
  //     target: 'http://localhost:3000',
  //     pathRewrite: {
  //       '^/api/': '/'
  //     }
  //   }
  // },
  // axios: {
  //   prefix: '/api/',
  // },
```
をコメントアウトしても処理ができていたことから、proxyが動作せずに実行できてしまったようです。。しかし、なぜそうなるのか理論の裏付けができていないので根本的な解決に至らず、今後の課題として記録します。

#参考記事
https://www.blog.umentu.work/nuxt-cors-axios-proxy/
https://riptutorial.com/webpack/example/30415/using-proxy
https://qiita.com/mouse_484/items/71f77aef3dfe5216a71b#2-proxy-%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E3%81%99%E3%82%8B

#終わりに

初投稿です。至らない点もあるかと思いますがこれから日々の学習の記録、気づきなどを投稿し少しでも誰かの役に立つことができれば幸いです。
ipython 自作モジュールのパスを通して起動するTips

# 作成中のモジュールをちょっとテストしたい
ということが多々あります。
ある程度開発が進んできたらちゃんとテストツールを使って試験データを作って、、、とすればいいのですけれど、まだそこまで仕様が固まってないとか、そもそもテストデータ作るほどの規模でもないしなーと言うくらいのときのTIPS。

# どうするか？
こうすればいいだけ。

``` cmd
> env PYTHONPATH="./" ipython
```

./ならパス通す必要ないのでは？
まぁ無いんですけど、ipythonの中に入ってからcdして目当てのスクリプトの入っているディレクトリに引っ越したり、あるいは同一ディレクトリ以外に配置したモジュール使ったりというのは往々にしてあるわけで、そういうときに起動前にワンライナーでPYTHONPATH与えておけばOKです。

そんだけ。
npx gulp watchでError: Node Sass does not yet support your current environment: OS X 64-bit with Unsupported runtime (93)

`npx gulp watch`を実行すると

```terminal
$ npx gulp watch
Error: Node Sass does not yet support your current environment: OS X 64-bit with Unsupported runtime (93)
For more information on which environments are supported please see:
https://github.com/sass/node-sass/releases/tag/v4.14.1
以下略
```
エラー文の通り、`https://github.com/sass/node-sass/releases/tag/v4.14.1`にアクセスして確認すると、下の表の通り。

### Supported Environments
|OS|Architecture|Node|
|---|---|---|
|Windows|x86 & x64|0.10, 0.12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14|
|OSX|x64|0.10, 0.12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14|
|Linux|x86 & x64|0.10, 0.12, 1, 2, 3, 4, 5, 6, 7, 8**, 9**, 10**^, 11**^, 12**^, 13**^, 14**^|
|Alpine Linux|x64|6, 8, 10, 11, 12, 13, 14|
|FreeBSD|i386 amd64|10, 12, 13|

サポートはNodeのバージョン14までになっている。

### バージョン確認
```terminal
$ node --version
v16.4.2
```
手元の環境はバージョン16になっていました。

### Nodeアンインストール
```terminal
brew uninstall node
Error: Refusing to uninstall /usr/local/Cellar/node/16.4.0
because it is required by yarn, which is currently installed.
You can override this and force removal with:
  brew uninstall --ignore-dependencies node
$ brew uninstall --ignore-dependencies node
Uninstalling /usr/local/Cellar/node/16.4.0... (2,459 files, 48.1MB)

```
エラーが出ましたが指示に従いつつアンインストール成功

### Nodeのインストール
```terminal
nvm install --lts --latest-npm
Installing latest LTS version.
Downloading and installing node v14.17.3...
Downloading https://nodejs.org/dist/v14.17.3/node-v14.17.3-darwin-x64.tar.xz...
######################################################################### 100.0%
Computing checksum with sha256sum
Checksums matched!
Now using node v14.17.3 (npm v6.14.13)
以下略
```
サポートされている最新のNodeをインストールできました。

### rebuildしてgulp watch
```terminal
$npm rebuild node-sass
rebuilt dependencies successfully
$ npx gulp watch
[15:25:21] Using gulpfile ~/hoge/gulpfile.js
[15:25:21] Starting 'watch'...
```
関数と文字列まとめ

:::note info
こんにちは、にんじゃわんこさん
:::


#JavaScript#

```JavaScript:JavaScript
const name = "にんじゃわんこ";
console.log(`こんにちは、${name}さん`);
```

```JavaScript:JavaScript
const name = "にんじゃわんこ";
console.log("こんにちは、" + name + "さん");
```

#Ruby#

```Ruby:Ruby
name = "にんじゃわんこ"
puts "こんにちは、#{name}さん"
```

```Ruby:Ruby
name = "にんじゃわんこ"
puts "こんにちは、" + name + "さん"
```

:::note alert
連結は文字列同士でしかできないため、基本的に変数展開を使うのが無難
:::
[Ruby]文字列（String）のtrue、falseをBoolean（TrueClass、FalseClass）へ変換

rubyでture、falseの入力を文字列（Stirng）として受け付けたとき、Boolean型のtrue、falseとして扱うために変換するコードを紹介します。

## 前提
Rubyでは**nillかfalse以外をtrue**として扱います。
そのため、文字列のfalseを条件文に利用すると、論理値としてはtrueになってしまいます。

``` false.rb
bool = gets
p bool.class

if bool
  p "Trueです！"
else
  p "Falseです！"
end

＝＝＝＝＝入力・出力結果＝＝＝＝＝
false
String
"Trueです！"
```

## String→Booleanの変換コード、動作の紹介
文字列のtrue、falseをBooleanに変換する方法を早速紹介します。

``` string→boolean変換.rb
class String
  def to_bool
    # 関数の呼び出し元文字列がtureだったらBoolean型のtrueを返す
    if self =~ /(true|True|TRUE)/
      return true
    # 関数の呼び出し元文字列がfalseだったらBoolean型のfalseを返す
    elsif self =~ /(false|False|FALSE)/
      return false
    # 関数の呼び出し元文字列がtrue、false以外だったら元の文字列を返す
    else
      return self
    end
  end
end
```

コードの要点をひとつだけ補足すると、class String部分は**オープンクラスというRubyの概念を利用して、元々存在していないメソッドを追加**しています。

オープンクラスについてはページ下部で紹介しますので、一旦置いておいて、動作確認のコードも合わせて紹介します。

```動作確認.rb
class String
  def to_bool
    # 関数の呼び出し元文字列がtureだったらBoolean型のtrueを返す
    if self =~ /(true|True|TRUE)/
      return true
    # 関数の呼び出し元文字列がfalseだったらBoolean型のfalseを返す
    elsif self =~ /(false|False|FALSE)/
      return false
    # 関数の呼び出し元文字列がtrue、false以外だったら元の文字列を返す
    else
      return self
    end
  end
end

str = gets.to_bool

if str.class == String
  p 'Stringです!'
else
  if str
    p 'Trueです!'
  else
    p 'Falseです!'
  end
end

＝＝＝＝＝入力・出力結果＝＝＝＝＝
例①
false
"Falseです!"

例②
true
"Trueです!"

例③
a
”Stringです！”
```


## オープンクラスの補足
**オープンクラスはざっくりいうと、クラスの再定義、メソッドの上書き、メソッドの追加**を可能にしてくれる概念です。
メソッドの上書きかどうかはメソッド名で判別されるので、名前被りが発生していないかの確認はとても大切になります。

名前が被っていないかの確認は以下二つが簡単かと思います。

1. コードを書いて検証（No methodがエラーが出るかどうかを確認）
1. リファレンスを見る（[Stringクラス](https://docs.ruby-lang.org/ja/latest/class/String.html)はこちら）

## Boolean→Stringの補足
String→Booleanは自らメソッドを追加しなければなりませんが、逆のBoolean（TrueClass、FalseClass）→Stringは用意されています。

```Boolean→String.rb
bool = false
str = bool.to_s

p bool.class 
p str.class

＝＝＝＝＝出力結果＝＝＝＝＝
FalseClass
String
```
【UiPath】OrchestratorのAPIを使ってみる①～APIマニュアル～

# はじめに

UiPath Orchestratorには、いろいろなAPIが用意されています。
今回はこのAPIを使ってみようと思います。

# どんなAPIがある？

マニュアルを見てみましょう、
以下にアクセスします。

```
https://[OrchestratorのURL]/swagger/index.html
```

このような画面が表示され、Orchestratorで用意されているAPIが出てきます。

アセットの追加や取得、トリガーの作成、フォルダーやマシン・ロボットの管理など、Orchestratorの画面からできることはだいたい揃っています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517338/b77a25f2-66ec-78e7-d6bd-a6a3445a0f63.png)

# APIを実行してみる

簡単なAPIを叩いてみます。
[UiPath Orchestrator システムの基盤設計・運用ガイド](https://www.uipath.com/ja/resources/knowledge-base/uipath-orchestrator-design-operation-guide)にも記載がありますが、Orchestratorのヘルスチェック用APIを見てみましょう。

## マニュアルを見てみる
マニュアルの Status > /api/Status/Get を参照します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517338/e7708e06-be6f-2f8f-a4fc-70cf42b16ac6.png)

パラメーターは特に必要なく、レスポンスは正常であればHTTPステータス200を返すことがわかります。

## 実際に叩いてみる

GETメソッドなのでブラウザから直接叩いても良いですが、HTTPをいろいろ叩けるツールを使います。
私は、[Talend API Tester](https://chrome.google.com/webstore/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm?hl=ja)を使っていますので、ご参考までに。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517338/de3d2e4e-1699-b3b8-9266-d83374352989.png)

200が返ってきていますね！

# ログインとか必要なんじゃない？

上記のヘルスチェックはパラメーターも不要のAPIでしたが、Orchestratorではユーザー毎の権限があるため、ログインが必要です。
APIを利用するときも、あらかじめユーザー認証をする必要があります。

## 認証API

`Account > ​/api​/Account​/Authenticate` を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517338/0e4ebb27-623e-d4ad-9f8c-a513d4493b7e.png)

`Deprecated（非推奨）`となっていますが、問題ありません。
というのも、そもそもOrchestratorでログインするときもこのAPIを使っているようです。
また、Orchestratorの管理画面も、マニュアルに記載されているAPIを叩いているだけのようです。
（Chromeの開発者ツール等でリクエスト覗いてみるとわかります。）

# 次回

一旦ここで区切ります。
次回、ユーザー認証から他のAPI叩くところまで説明します。
Reflection オーバーロードされているメソッドの呼び出し　--メモ--

Reflectionでメソッドを呼び出したい。

###StringクラスのRemoveメソッド呼び出し
引数に(int,int)タイプのものを使う。

```csharp

string str = "HelloWorld";
Type type = str.GetType();

MethodInfo mi1 = type.GetMethod("Remove",new Type[] { typeof(int), typeof(int) });
Console.WriteLine(mi1.Invoke(str, new object[] { 0, 5 }));

```

###GetMethodsのリストから該当するメソッドを選択

GetMethodsでStringクラスのメソッドをすべて呼び出す。
そのうちRemoveメソッドを名前で選択。さらに引数が2つのものを選択

```csharp
            string str = "HelloWorld";
            Type type = str.GetType();

            MethodInfo[] methodInfos = type.GetMethods();
            foreach (var mi in methodInfos)
                if (mi.Name == "Remove")
                {
                    ParameterInfo[] pi = mi.GetParameters();
                    if (pi.Length == 2)
                    {
                        Console.WriteLine(mi.Invoke(str, new object[] { 0, 5 }));
                    }
                };
```

###参考
[文字列で指定したメソッドを呼び出すサンプル・プログラム](https://www.atmarkit.co.jp/ait/articles/0512/16/news110.html)
[C#のリフレクションについて、思いつくままにコードを書く](https://s-kita.hatenablog.com/entry/20081228/1230455271)
Railsでサイトを作成する下準備までの大まかな手順

# 　記事の目的
　Cloud9にてECサイトを作るにあたって「何から始めればいいんだっけ？」と思いQiitaを含めて何回か参照していましたが、流れがまとまらなかったので自分用の備忘録として記載します。参考までに。
　本当に大まかにまとめたので、詳細箇所については別途追記するかもしれません。

#  ECサイト作成前に準備すること。
　個人製作の場合は必ず必要というわけではないですが、作成する前に作っておくと後々サイトを作りやすいです。
Cacooというサイトであれば両方作成できるので、おすすめです。
####・ER図
####・ワイヤーフレーム
####・GitHubの連携
####・ImageMagickのインストール


# ファイル・モデル・コントローラーの作成
####①ファイルの作成
※Cloud9にて諸々の初期設定が終わっていること。これに関しては個人の設定に左右される。
ターミナルを開いて、下記を入力しファイルを作成する。
(例)として、ファイル名を「Illusters」というアプリを作るものとします。

```
【ターミナル】
    ~$ rails new ファイル名
(例)~$ rails new Illusters
※ファイル名は"頭文字:大文字"
```

####②モデルの作成
作りたいモデルを作成する。
モデルの中にカラムとデータ型を一緒に作成すれば後々マイグレーションファイルがごちゃごちゃしないのでオススメ。
user_idといったモデルに直結するidは記載不要。

```
【ターミナル】
    ~$ rails g model モデル名 カラム1:データ型1 カラム2:データ型2 ...
(例)~$ rails g model user name:string profile_image:string introduction:text
※モデル名は"頭文字:小文字,単数形"
```
必要なモデルを作成した後に必ず下記の文を実行しマイグレーションすること！

```
【ターミナル】
~$ rails db:migrate
```
↑を行わないとrailsの実行時にエラーが発生する。

#####モデルを削除したい場合...「モデルを間違えて作ってしまった」「後々いらなくなってしまった」など

```
【ターミナル】
　  ~$ rails d model モデル名
(例)~$ rails d model user
```
を実行すれば削除される。
もちろん、削除した後でも```~$ rails db:migrate```を行って、マイグレーションファイルを更新する必要がある。

#####【補足】・・・よく使うデータ型

|データ型  |入力される値  |使用例  |
|---|---|---|
|integer  |整数  |id, 単価, 個数 など  |
|string  |文字列(256文字以内)  |名前, 住所, 画像, 電話番号(0から始まる) など |
|text|文字列(制限なし)|自己紹介, キャプション など |
|boolean|true / false|男女設定, はい/いいえの質問, 表示/非表示 など|
|float|小数点以下を含んだ数値|数量, パーセンテージ, |
|datatime|日時|現在時刻, 登録日時 など|

####③コントローラの作成
②で作成したモデルに付随するアクションコントローラーを作成する。

```
【ターミナル】
    ~$ rails g controller コントローラ(モデルの複数形) アクション1 アクション2 ...
(例)~$ rails g controller users new show edit
※コントローラ・・・頭文字:小文字,複数形"
```
アクション名はターミナルで記載すると、下記が自動で行われるため、時短できる。
また、任意で作成したアクションも記載することはできる。
・Cloud9内で自動で「△△-controller.html.erb」内にアクション名が追加される
・Cloud9内にフォルダが追加されその中に「△△.html.erb」が作成される

#####コントローラを削除したい場合...
モデル同様、コントローラも削除できる。

```
【ターミナル】
　  ~$ rails d controller モデル名
(例)~$ rails d controller users
```
を実行すれば削除される。


### route.rbファイルにアクション名を追加
route.rb内のファイルにコントローラを記載する。
RESTfulなアクションと任意のアクションで対応が異なるのでそれぞれ説明する。

####【A. RESTfulなアクションのみ使用する場合】
```
【routes.rbファイル内】
     resources :コントローラ名
(例) resources :users 
```
RESTfulなアクションはよく使うため、「resources :△△」の一文のみで下記7つのアクションができる。

反対に、RESTfulなアクションを限定的に使用したい場合、onlyを使用することで、RESTfulを定義しながら他のアクションは稼働しないようにできる。
例えば、
「新規作成と閲覧はできるが、編集・削除ができない」設定の場合、
必要なアクションは「new,create,show」でそれ以外は使用しない。

```
【routes.rbファイル内】
     resources :users, only: [:new, :create :show]
```
####【補足】・・・RESTfulなアクション一覧
|アクション名|使用用途|メソッド|
|---|---|---|
|new|新規作成画面|GET|
|create|新規作成|POST|
|index|一覧表示|GET|
|show|詳細画面の表示|GET|
|edit|編集画面の表示|GET|
|update|編集|POST/PATCH|
|destroy|削除|DELTE|
なお、メソッドについて端的に言うと
　・GET : 画面に表示されるもの
　・POST,PATCH : 専用の画面はなくコントローラ内のみで使用される
　・DELETE : POST,PATCH同様専用画面はない。削除するメソッド


####【B. 任意のアクションを設定する場合】
RESTfulのものとは一致しないアクションを作成したいときはroutes.rbファイル内に任意のアクション名を追加する。

```
【routes.rbファイル内】
    メソッド 'アクション名' => '保存するファイルの場所'
(例)get 'download' => 'item_images#download'
(例)post 'download' => 'item_images#download'
※'保存するファイルの場所'に指定がなければ "=> '~~~~'"以降は不要
```

# 以上！下準備はこれで完了です。
下準備はこれで終わりです、ここから先はコードをご自由に書いてみてください。
Python3: JSON 形式の Post で受け取ったデータを redis に入れる

こちらのプログラムを改造しました。
[Python3: JSON 形式の Post を処理する方法](https://qiita.com/ekzemplaro/items/66f846cc9fcd640a9b8c)

サーバープログラム　(CGI)

```py:redis_post.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#   redis_post.py
#
#                                               Jul/26/2021
#
# ---------------------------------------------------------------------
import	os
import  sys
import  json
import	cgi
import  datetime
import  redis
#
# ---------------------------------------------------------------------
def redis_insert_proc(key,json_str):
	rr = redis.Redis(host='localhost', port=6379, db=0)
	rr.set(key, json_str)
# ---------------------------------------------------------------------
if os.environ['REQUEST_METHOD'] == 'POST':
	length, _ = cgi.parse_header(os.environ['CONTENT_LENGTH'])
	data = sys.stdin.buffer.read(int(length))
#
	json_str = data.decode("utf-8")
#
	dt = datetime.datetime.now()
	key = "%02d%02d%02d" % (dt.hour,dt.minute,dt.second)
	redis_insert_proc(key,json_str)
#
	data_aa = {}
	data_aa['key'] = key
	data_aa['value'] = json_str
	str_aa = json.dumps(data_aa)
#
	print('Content-Type: text/json; charset=utf-8')
	print("Access-Control-Allow-Origin: *\r\n")
	print(str_aa)
# ---------------------------------------------------------------------
```

テストスクリプト

```bash
URL="http://localhost/redis_post/redis_post.py"
#
curl -X POST -H "Content-Type: application/json" \
	 -d '{"aa":"32","bb":"56"}' $URL
```

reis-cli で確認

```text
$ redis-cli
127.0.0.1:6379> keys *
1) "145859"
127.0.0.1:6379> get 145859
"{\"aa\":\"32\",\"bb\":\"56\"}"
127.0.0.1:6379> exit
```
WebSpeechAPIを使ってブラウザにQiita記事をしゃべらす

誰もが一度はQiita記事をラジオのように音で聞けたらなと思ったことがあると思う（ない）

先日、TwitterでWebSpeachAPIというJavaScriptのライブラリを使って簡単にブラウザを喋らせることができると話題になっていた。（ずいぶんと前からあったっぽいが）
とても面白そうなんだけど、なにをしゃべらせばいいのか思いつかなかったからQiita記事をしゃべらせてみた

##つくったもの

```app.py
from flask import Flask
from flask import render_template, request
from bs4 import BeautifulSoup
import requests

app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')

@app.route('/', methods=['POST'])
def url_post():
    qiita_url = request.form.get('qiita_url')

    # スクレイピングするURLを指定しHTMLを取得  
    res = requests.get(str(qiita_url))

    # BeautifulSoupオブジェクトをつくる
    soup = BeautifulSoup(res.text, 'html.parser')

    # クラス名を指定して要素を取得
    speech_title = soup.find("h1",class_='css-cgzq40').get_text()
    speech_text = soup.find("section",class_='it-MdContent').get_text()

    context = {
        'title': speech_title,
        'text': speech_text
    }
    return render_template('index.html', context=context)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port='5000')
```

```template/index.html
<html>
    <body>
        <h2>ブラウザにQiita記事をしゃべらす</h2>
        <form action="/" method="POST" enctype="multipart/form-data">
            <input type="url" name="qiita_url">
            <input type="submit" value="決定">
        </form>
        {% if context %}
        <div>
            <h4>{{context.title}}</h4>
            <button id="speech-btn">再生</button>
            <button id="cancel-btn">停止</button>
            <button id="pause-btn">一時停止</button>
            <button id="resume-btn">再開</button>
            <p id="text">{{context.text}}</p>
        </div>
        {% endif %}
    </body>

    {% if context %}
    <script>
        const text      = document.getElementById("text").textContent
        const speechBtn = document.querySelector('#speech-btn')
        const cancelBtn = document.querySelector('#cancel-btn')
        const pauseBtn  = document.querySelector('#pause-btn')
        const resumeBtn = document.querySelector('#resume-btn')

        // 再生
        speechBtn.addEventListener('click', function() {
        const uttr = new SpeechSynthesisUtterance(text)
        speechSynthesis.speak(uttr)        
        })

        // 停止
        cancelBtn.addEventListener('click', function() {
            speechSynthesis.cancel()
        })

        // 一時停止
        pauseBtn.addEventListener('click', function() {
            speechSynthesis.pause()
        })

        // 再開
        resumeBtn.addEventListener('click', function() {
            speechSynthesis.resume()
        })

    </script>
    {% endif %}
</html>
```

全体はFlaskを使ってて、その中でBeautifulSoupを使って指定のQiita記事をスクレイピングして、喋らせたい要素をWebSpeechAPIに渡してる感じ

ただChromeだとうまく動作しなかった、なんか声の種類が関係しているっぽい

動作確認済の環境
Win : Edge 
iOS : safari

##まとめ
しゃべらせるものを間違えてる感が半端なくて個人的にはとても好き

思ったよりちゃんと喋っててて驚き

https://github.com/SourCreamX/WebSpeechAPI-Qiita/tree/main


<br>
（初投稿頑張った）
GitLab 14.1.0 へのアップグレード

なんでもかんでも自粛、というわけでもないのですが、GitLabのアップグレードを忘れていたら
いつものようにアップグレードを実施すると

> It is required to upgrade to the latest 14.0.x version first before proceeding.

と言われてしまました。

13の最終版と14.0の最終版を経由して最新版の14.1までアップグレードした記録です。
いつものようにやってみたら、こうなった

```
[ ~]$ sudo yum install gitlab-ce
--> トランザクションの確認を実行しています。
---> パッケージ gitlab-ce.x86_64 0:13.11.1-ce.0.el7 を 更新
---> パッケージ gitlab-ce.x86_64 0:14.1.0-ce.0.el7 を アップデート
Is this ok [y/d/N]: y

gitlab preinstall: It seems you are upgrading from major version 13 to major version 14.
gitlab preinstall: It is required to upgrade to the latest 14.0.x version first before proceeding.
gitlab preinstall: Please follow the upgrade documentation at https://docs.gitlab.com/ee/update/index.html#upgrade-paths
```

上記のリンク先に
>Two intermediate versions are required: 13.12 and 14.0, then 14.1. 
と書いてあったので、どのバージョンを経由すればいいか確認

```
[ ~]$ yum list --showduplicates gitlab-ce|less
13.12.8-ce.0.el7
14.0.6-ce.0.el7
```
まずは13.12.8へ

```
[ ~]$ sudo yum install gitlab-ce-13.12.8-ce.0.el7
更新:
  gitlab-ce.x86_64 0:13.12.8-ce.0.el7                                                               

完了しました!
```

次に14.0へ

```
[ ~]$ sudo yum install gitlab-ce-14.0.6-ce.0.el7
  検証中                  : gitlab-ce-14.0.6-ce.0.el7.x86_64                                    1/2 
  検証中                  : gitlab-ce-13.12.8-ce.0.el7.x86_64                                   2/2 

更新:
  gitlab-ce.x86_64 0:14.0.6-ce.0.el7                                                                

完了しました!
```
そして、いつもの手順で最新版へ

```
[ ~]$ sudo yum install gitlab-ce
Backup task is done.
gitlab preinstall: Automatically backing up /etc/gitlab
Running configuration backup
Creating configuration backup archive: gitlab_config_1627276567_2021_07_26.tar
  検証中                  : gitlab-ce-14.1.0-ce.0.el7.x86_64                                    1/2 
  検証中                  : gitlab-ce-14.0.6-ce.0.el7.x86_64                                    2/2 

更新:
  gitlab-ce.x86_64 0:14.1.0-ce.0.el7                                                                

完了しました!
```

今回は下記のreconfigureは不要だった
$ sudo gitlab-ctl reconfigure
ShinyのサイドバーパネルsidebarPanelの表示・非表示を切り替えるボタン

# つくったもの
Shinyのnavbar上にsidebarLayoutのsidebarPanelの表示/非表示切り替えボタンを作った。
![sidebar2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100646/65d54055-301c-6c5b-b009-6e7a91bdf2c9.gif)

# 動機など
2021年7月現在、Shinyアプリのフレームワークは
・navbarPage & sidebarLayout
・shinydashboard
の２つに大別されると思いますが、shinydashboardにあって、sidebarLayoutに無いもの、
それは「サイドバーパネルを隠すボタン」です。

sinydashboardの、サイドバーを隠すボタンの例
https://shiny.rstudio.com/gallery/hospital-data-antimicrobial.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100646/70d0a8bf-34af-a849-a24e-6f5f23ab7520.png)

これがnavbarPageにもあればなー。
ということで作りました。

# コード
コードはこちらです。
表示非表示リンククリック時のobserveEventの中に、
shinyjsの関数toggleを入れて、サイドパネルの表示を切り替えます。
同時に、runjsによりメインパネルの幅を100%にする/空にする　という動作もしています。

```R
library(shiny)
library(shinyjs)

ui <- fluidPage(
  useShinyjs(),
  navbarPage(title = tagList("title",actionLink("sidebar_button","",icon = icon("bars"))),
             tabPanel("tab1",
                      sidebarLayout(
                      sidebarPanel("sidebar1",width=3),
                      mainPanel("MainPanel1",width=9,style="background-color:gray"
                                ,tableOutput("table"))
                      )
             ),
             tabPanel("tab2",
                      sidebarLayout(
                        sidebarPanel("sidebar2",width=5)
                        ,mainPanel("MainPanel2",width=7,style="background-color:gray"
                                   ,tableOutput("table2"))
                      )
             )
  )
)

server <-function(input, output, session) {
  output$table <- renderTable(
    cbind(iris,iris)
  )
  output$table2 <- renderTable(
    cbind(iris,iris)
  )
  
  observeEvent(input$sidebar_button,{
    shinyjs::toggle(selector = ".tab-pane.active div:has(> [role='complementary'])")
    js_maintab <- paste0('$(".tab-pane.active div[role=',"'main'",']")')
    runjs(paste0('
          width_percent = parseFloat(',js_maintab,'.css("width")) / parseFloat(',js_maintab,'.parent().css("width"));
          if (width_percent == 1){
            ',js_maintab,'.css("width","");
          } else {
            ',js_maintab,'.css("width","100%");
          }
          '))
  })
}

shinyApp(ui, server)

```

以上、もっと良い方法などありましたらお知らせいただけますと助かります。
【React】Unterminated regular expressionの対処法 【Javascript】

<h2>症状</h2>
reactでSPAアプリ開発中に以下のエラーが発生しました。
翻訳すると、「終了していない正規表現」でした。

```terminal:error
 Unterminated regular expression 
```

```react:
import {homeURL,userCreateURL,signInURL} from "../urls/index";
import {useHistory} from "react-router-dom";

export const Hoge = () => {
  const history = useHistory();

  function signUpHandle() {
    history.push(userCreateURL)
  }

  function signInHandle() {
    history.push(signInURL)
  }

  return(
    <Button color="inherit" onClick={() => signUpHandle()} btnLabel={新規登録}></Button>
    <Button color="inherit" onClick={() => signInHandle()} btnLabel={サインイン>サインイン</Button>
)
}
```

<h2>解決方法</h2>
サインインのbtrLabelの{}の閉じかっこを追加したら、解決されました。
このエラーは、「文字列リテラルは単一引用符 (') または二重引用符 (") で囲む必要」があり、btnLabelの{}が閉じられていなかったため、後半のサインインまでもbtnlabelとして認識されていたようです。(なお、2重でサインインを書く必要はそもそもないです)

```react:
import {homeURL,userCreateURL,signInURL} from "../urls/index";
import {useHistory} from "react-router-dom";

export const Hoge = () => {
  const history = useHistory();

  function signUpHandle() {
    history.push(userCreateURL)
  }

  function signInHandle() {
    history.push(signInURL)
  }

  return(
    <Button color="inherit" onClick={() => signUpHandle()} btnLabel={新規登録}></Button>
    <Button color="inherit" onClick={() => signInHandle()} btnLabel={サインイン}>サインイン</Button>
)
}
```

<h2>症状</h2>
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Errors/Unterminated_string_literal
ディレクトリ構造をMappingとして読み取れるやつ作った

ユニットテストを書くとき、ストレージへの書き出し状況が意図通りであるという点を見たい場合があります。
それを簡単にするために、ディレクトリツリーの現在の状況をMappingとして読み出せるクラスを作りました。ライブラリにしてPyPIに出すほどではない規模なのでここにコード書いちゃいますね。ご自由にお使いください。

これで、 `assert PathMapping(tmp_dir) == {'xx': b'yyyyyy'}` なんていう簡単な式でストレージ書き出しを検証できるようになります。パラメータ化テストならこの右辺をパラメータ化できるので複雑な書き出しがあるモジュールのテストでもパラメータ化していろんな動作条件での出力を簡潔な記述で網羅できるようになりますね。

```python
class PathMapping(Mapping):
    """
    ディレクトリパスを再帰的なマッピングとして扱う
    （文字列をキーに、ディレクトリはマッピング、ファイルはbytes）
    例:
    my_home
    ├ foo
    │ └ bar.txt （内容は "some content"）
    └ baz.txt （内容は "another content"）
    というディレクトリ構造のとき、以下の等式が成立
    PathMapping(Path('my_home')) == {
        'foo': {
            'bar.txt: b'some content\n'
        },
        'baz.txt': b'another content\n' 
    }
    """
    def __init__(self, path: Path):
        self._path = path

    def __getitem__(self, k: str):
        child = (self._path / k)
        if child.is_dir():
            return PathMapping(child)
        elif child.is_file():
            return child.read_bytes()
        else:
            raise KeyError

    def __len__(self) -> int:
        return len(list(self._path.iterdir()))

    def __iter__(self) -> Iterator[str]:
        for child in self._path.iterdir():
            yield child.name
```

このクラスのオブジェクトが吐き出すkey-valueデータはオブジェクト生成時点のものではなく、今現在のディレクトリツリー状況です。
そのことがどう生きてくるかというと、pytestのこんなfixtureを作る場合です。

```python
@fixture
def mock_なんかストレージに書き出すモジュール(monkeypatch):
    """
    このfixtureオブジェクトそのものをMappingとしてアクセスすると書き出し結果がみられます
    """
    with TemporaryDirectory as tmp_dir:
        ... # 「なんかストレージに書き出すモジュール」 が tmp_dir に書き出すように
        ... # monkeypatchでいろいろ乗っ取っている

        yield PathMapping(Path(tmp_dir))
```

こうしておくと、ユニットテスト本文側では

```python
def test_XXX(mock_なんかストレージに書き出すモジュール):
    ... # ターゲットを呼び出している
    ... # ターゲットは「なんかストレージに書き出すモジュール」を叩いている

    # 検証：想定通り書き出されていること
    assert mock_なんかストレージに書き出すモジュール == {'xx': b'yyyyyy'}
```

と書けます。PathMappingオブジェクトを作った時点ではなく、assertのところまで来た時点でのディレクトリツリー状況が読み出せていますので、こういうことができます。
物理サーバのAWS移行注意点(CloudEndureを使ったP2V)

#P2V実施の経緯
老朽化している物理サーバが1台残っているのですが、復旧できない故障が発生した場合に備えてP2V(P2C)を検討しました。CloudEndureにて簡単にP2Vできるとの記事を見て実行したのですが、以外にハマりましたので、その内容を記載したいと思います。

#P2Vの流れ
■CloudEndureのアカウント作成
　　　　　　↓
■CloudEndure用のIAM作成
　　　　　　↓
■CloudEndure管理コンソールでプロジェクトの作成
　　　　　　↓
■CloudEndure管理コンソールで移行マシンの設定　←　ここがつまづいた原因
　　　　　　↓
■オンプレサーバへのエージェントインストール
　　　　　　↓
■P2Vしたサーバにリモート接続して動作テスト
　※スケジューラにタスクを登録している場合はタスクを無効にしておくこと
　　(そのまま動く可能性があります)

全体的な流れを解説しているサイトがありましたので、リンクを掲載させていただきます。

https://dev.classmethod.jp/articles/cloudendure-no-charge/

#つまづいた点
##■オンプレサーバへのエージェントインストール
CloudEndure管理コンソールからインストールエージェントのダウンロードしました。
コンソール上に表示してくれているコマンドをサーバのコマンドプロンプトに貼り付けて実行。

↓↓コマンドの内容↓↓
```
installer_win.exe -t xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx-xxxx　← 16ケタのコード　
--no-prompt
```

が、うまくいきません。
移行対象のサーバがWindowsServer2008R2であった為、.NET Frameworkが古く、アップデートが必要でした。

##■.NET Framework4.5以上のインストール
オフライン用.NET Framework4.5インストーラーをダウンロード
https://bit.ly/35HWLWd
![2021-06-22_14h36_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/a02d6b23-1842-c50c-eca4-29472d3c6bdc.png)

再度インストール用のコマンドをサーバのコマンドプロンプトに貼り付けて実行したところ、エージェントインストールは完了しました。

##■CloudEndure管理コンソールでレプリケーション情報を確認
エージェントがインストールされるとレプリケーションは自動で進みます。
CloudEndure管理コンソールでレプリケーション先のマシン設定を編集します。
Machinesタブから編集するマシンをクリックします。
![2021-06-22_16h06_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/e3260be8-4c66-a38b-3dcd-3aa3d7ec88fc.png)

###BLUEPRINTタブ
BLUEPRINTタブでレプリケーション先マシンの設定を確認します。
SubnetとSecurity groupsの初期値がCreate newになっている為、私は既存のSubnetとSecurity groupsを使うように変更しました。
![2021-06-22_15h35_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/0d354202-e2f2-5752-fe1e-91aa550852f2.png)

Private IPは初期値がSOURCE MachineのIPとなっています。
オンプレのマシンはIP体系が違う為、今回はCreate newを選択しました。
![2021-06-22_15h45_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/9d6e09ba-e8fa-f306-f84c-275184cee723.png)

Diskですが、初期値はProvisionedSSD-io1になっています。
汎用ボリュームで良いので、SSD-gp3に変更しました。
![2021-06-22_15h45_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/2e61af24-834e-3e0f-d2b4-a471df1caf81.png)

###REPLICATION SETTINGSタブ
![2021-07-02_17h46_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359386/44044622-7921-122b-f969-d00529bd7451.png)
<span style="color: red; "> Choose the Replication Server instance typeは**Defaultを推奨**</span>

##■ここがつまづいた原因
最初、コストを節約したかったのでレプリケーション先サーバインスタンスを固定する為にMachineTypeをm5.largeに変更しました。後からわかりましたが、ここが問題だったようで、Defaultのままにしておいた方が良いようです。
理由として、1度目にm5.largeにしたことで起動できなかったのですが、2度目はDefaultでうまく立ち上がりました。その差として、**自動で生成されたスペックがc4.4xlargeでした。試しにc5.4xlargeにしても起動できなくなりましたので、恐らくCPUの世代が古くてc4しか対応していなかったのだろうと予想しています。**
Defaultであればこの差を自動で対応してくれる為、Defaultが良いと考えています。

ドキュメントに記載があるのかも知れませんが十分な調査を行っていなかった為、起動しない原因がわからず結構ハマりました。
どなたかのお役に立てれば幸いです。
【Kubernetes】VMのDockerのShellにアクセスする (自分用メモ) no.11

![名称未設定のデザイン (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/c65f76c5-caa2-371c-f896-67cea42d77eb.png)

#VM上にあるdocker-cliのシェルを使いたい時
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/e1ef3b8b-baf2-1edf-9c4f-f523d07d0bae.png)

```
minikube docker-env
```

とコマンドを打つと、minikubeのdocker のシェルを使うために必要なコマンドが表示される


![2021-07-26_14-09-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/d389594f-6ae4-f03b-7db9-811195bfdc71.png)

使うターミナルが違うとVMのdocker-cliのターミナルにアクセスするためのコマンドも違う


![2021-07-26_14-13-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/eb1b2da4-4f91-0117-3456-adc580f34e39.png)