OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS 6 でとりあえずcertbotを使えるようにする


# はじめに

本来はOSアップグレードすべきな CentOS 6 で必要に迫られて、certbotを動作させたときのメモ。

## certbot導入していた方法

もうこの方法は使えませんし、cartbot-auto自体も全てのシステムで非推奨。

```
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
./certbot-auto
```

## certbot-auto のエラー

```
sudo certbot-auto renew --dry-run
Bootstrapping dependencies for Legacy RedHat-based OSes that will use Python3... (you can skip this with --no-bootstrap)
yum is /usr/bin/yum
To use Certbot on this operating system, packages from the SCL repository need to be installed.
Enable the SCL repository and try running Certbot again.
```

Pythonのバージョンが3.6以上が必要らしい。

## yum

リポジトリをvaultを使うように変更

```
cd /etc/yum.repos.d/
sudo cp CentOS-Base.repo??CentOS-Base.repo.baksudo sed -i -e "s/^mirrorlist=http:\/\/mirrorlist.centos.org/#mirrorlist=http:////mirrorlist.centos.org/g" /etc/yum.repos.d/CentOS-Base.repo
sudo sed -i -e "s/^#baseurl=http:\/\/mirror.centos.org/baseurl=http:////vault.centos.org/g" /etc/yum.repos.d/CentOS-Base.repo
```

## python3.6

~~iusポジトリを使って、Python3.6をインストール~~
iuｓリポジトリがなくなっていたので、SCLを利用

### SCLリポジトリ導入とURL修正

```
sudo yum install centos-release-SCL
sudo vi /etc/yum.repos.d/CentOS-SCLo-scl-rh.repo 
....
[centos-sclo-rh]
name=CentOS-6 - SCLo rh
baseurl=http://vault.centos.org/centos/6/sclo/$basearch/rh/
#mirrorlist=http://mirrorlist.centos.org?arch=$basearch&release=6&repo=sclo-rh 
.....
```

### python3.6をインストール

```
sudo yum install -y rh-python36 rh-python36-pip
```

python3.6が /opt/rh/rh-python36/root/usr/bin/python3 にインストールされる。

### python3設定

```
cd /usr/bin
sudo unlinlk python3
sudo ln -s /opt/rh/rh-python36/root/usr/bin/python3 python3
```

## certbotのインストール

certbot用のvirtual envを作成し pipをアップデートしてからインストール

```
sudo python3 -m venv /opt/certbot/     # venv
sudo /opt/certbot/bin/pip install --upgrade pip
sudo /opt/certbot/bin/pip install certbot
```

/opt/certbot/bin/certbot にインストールされる。

## 動作確認

```
/opt/certbot/bin/certbot/certbot --version
certbot 1.13.0
```

あとは、certbot-autoコマンドの代わりにcertbotコマンドを使用するようにすれば、問題なくSSL証明書の更新や取得が利用可能になるはずです。

let’sencryptの設定(/etc/letsencrypt)の移動も必要ありません。

# 参考

* https://qiita.com/tetsu6/items/380d86fcae85a96ac443
【Laravel】Sortableを使用して簡単にソート機能を実装

## はじめに
データ一覧画面でソート機能を付けたいなぁ。
よし、JavaScriptを使ってごそごそして～...ってめちゃくちゃ面倒！！
ってことがあったので、ソート機能が簡単に実装できるパッケージを紹介します。
## 開発環境
OS Windows10
PHP 7.4.7
Laravel 8.45.1
## 事前準備
先ずはcomposerから、今回使用する「kyslik/column-sortable」のパッケージを追加します。
```$ composer require kyslik/column-sortable```
##開発
大まかなフローとして、
①ModelにSortableを宣言
②ControllerでDBからデータを取得
③Viewで表示
となります。

###①ModelにSortableを宣言
対象のModelにSortableをuse宣言します。

```php:Models/Post.php
<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Kyslik\ColumnSortable\Sortable; // 追加

class Post extends Model
{
    use Sortable;  // 追加
}
```
###②ControllerでDBからデータを取得
ControllerにSortableのクエリビルダを追加します。

```php:Controllers/PostsController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Post;

class PostsController extends Controller
{

    public function index()
    {
        $posts = Post::sortable()->get(); //sortable() を先に宣言
        return view('posts.index')->with('posts', $posts);
    }
    .
    .
    .
}
```
###③Viewで表示
テーブル構造のカラムに該当する部分にSrotable linkを付与します。
記法は下記になります。
```@sortablelink('*column_name*', '*カラム名称*')```

```html:posts/index.blade.php
<div>
    <table class="table table-bordered">
        <thead>
        <tr>
            <th scope="col">@sortablelink('id', 'ID')</th>
            <th scope="col">@sortablelink('title', 'タイトル')</th>
            <th scope="col">@sortablelink('text', '本文')</th>
            <th scope="col">@sortablelink('created_at', '作成日時')</th>
            <th scope="col">@sortablelink('updated_at', '更新日時')</th>
        </tr>
        </thead>
        <tbody>
        @foreach($posts as $post)
        <tr>
            <th scope="row">{{ $post->id }}</th>
            <td>{{ $post->title }}</td>
            <td>{{ $post->text }}</td>
            <td>{{ $post->created_at }}</td>
            <td>{{ $post->updated_at }}</td>
        </tr>
        @endforeach 
        </tbody>
    </table>
    </div>
</div>
```
## デモ
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/734b16c1-7f3f-cbb5-c5f6-a855aaa80205.gif)
## 終わりに
何か機能を追加したい！という場合は大体パッケージとして落ちているので、実装する前に探してみると良いと思います。
今回のソート機能はページネーションとも併せて使用できるので、お勧めです！
>[Github reference](https://github.com/Kyslik/column-sortable)
【Rails6】deviseの日本語化が、上手くいかない時の対処法

## はじめに

deiviseを使用していて、一部日本語化が出来ていない状況を解決したので、備忘録として残します。


## 開発環境
macOS Big Sur 11.3.1
Rails 6.1.2.1
devise
rails-i18n  6.0
devise-i18n


## 現状
![スクリーンショット 2021-05-09 15.50.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/8e6a6422-18fd-4e84-0f12-1a47c35256d8.png)

![スクリーンショット 2021-05-09 15.50.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/4800cea3-26b6-7bd3-cf8f-316aef70ba7e.png)

上記のように、一部日本語化がされていない状況です。


## 日本語化までの手順

`Gemfile`

```
# ログイン機能
gem 'devise'

# 日本語化(Rails 6の場合)
gem 'rails-i18n', '~> 6.0'
gem 'devise-i18n'
```
ターミナルで、`bundle install`をして、導入します。

```config/application.rb
(略)
module LikeApp
  class Application < Rails::Application
    config.load_defaults 6.0
    # 日本語化の設定
    config.i18n.default_locale = :ja
    # タイムゾーンの変更（例)created_at カラムを取り出したときに日本時間に変換されるようになる）
　　 config.time_zone = 'Asia/Tokyo'
(略)
```
`rails s`でサーバーを起動し、http://localhost:3000/users/sign_inへアクセス。この時点では、日本語化されていました。 

ビューファイルを生成するため、ターミナルで下記を実行
```
rails g devise:views
```
ビューファイルを編集後、一部日本語化されていない状況になりました。

## 原因＆対処法
ビューファイル実行の際に、

```
rails g devise:i18n:views
```
としなかったことが原因で、devise-i18nを無視した英語表記のビューファイルが作成されため。
`rails g devise:i18n:views`は `devise-i18n`を導入することで実行できる，多言語対応のビューファイルを作成するコマンドなので、ビューファイルを編集したい際は、`i18n`を入力し忘れないようにしましょう。

## おまけ
```
rails g devise:i18n:views　user
```
とした場合は、下記の記事「7. ログイン画面などの変更」を参考にすすめて下さい。（丁寧でわかりやすい記事ですよ！）

[Deviseでログイン機能を追加・日本語化・Bootstrap4適用まで](https://qiita.com/take18k_tech/items/a36d77316e32a6696205)

## まとめ
今回の場合は、エラー文が出ないので、原因がわかりづらかったです。ビューファイル作成のコマンドを間違えると日本語化に影響があるということが、わかり良かったです。
同じように、悩んでいる方の参考になると幸いです:relaxed:


## 参考記事
- [Deviseでログイン機能を追加・日本語化・Bootstrap4適用まで](https://qiita.com/take18k_tech/items/a36d77316e32a6696205)
【Rails6】deviseでログイン時、「Completed 401 Unauthorized」となり、ログインできない時の対処法（備忘録）

## はじめに
deiviseを使用していて、ログインできない現状に悩まされたので、備忘録として残します。

## 開発環境
macOS Big Sur 11.3.1
Rails 2.7.2
PostgreSQL 13.2


## 現状
アカウント登録し、ログアウト後にログインすると、「名前、Eメールまたはパスワードが違います。」と表示され、ログインできない。
ログを確認すると、`Completed 401 Unauthorized`認証に失敗していることが、原因とのこと。


## 今回の原因
```config/initializers/devise.rb
config.authentication_keys = [:name, :email]
```
「ログイン時に入力された name と email の両方が一致して，かつパスワードが正しくないとログインできない」という設定をしていたのが、原因でした。

## 対処法

```config/initializers/devise.rb
config.authentication_keys = [:email]
```
:nameを削除して、サーバーを立ち上げて確認すると、出来ました！

![スクリーンショット 2021-05-12 16.48.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923146/461b5852-063b-3f08-7f3d-16807d997fd8.png)

## 学び
今回、メンターさんに色々アドバイス頂きました！
・必ずログを確認すること（ここ重要！）

認証が失敗している場合は、
・原因が色々考えられるので、1つづ潰していく必要があること
・問題の切り分け方
　・新しくユーザーを作成して、ログイン情報が確実に間違っていないことを確認
　　出来た　　→　解決！
　　出来ない　→　view、もしくはapplication_contorollerに原因がありそう
　・application_contorolerに追記した部分を見直す
  　　解決 or 未解決
　・viewに追記した部分を確認
 　　解決 or 未解決

現役のエンジニアの方々は、このように問題を切り分けて考えていることがわかり、非常に勉強になりました。エラー続きですが、エラーがないとこのような気付きもないので、ラッキーと思うようにしています:relaxed:
同じようなエラーで躓いている方々へ、参考になると幸いです。
[WordPress][MySQL] クエリパフォーマンスが落ちてきたときに設定すると良いインデックス

WordPress でサイト運営しているとデータが溜まってきて、SQLクエリのパフォーマンスが落ちることがありますよね。

そういう時は、RDS の [Performance Insights](https://aws.amazon.com/jp/rds/performance-insights/) や、MySQL の [スロークエリログ](https://dev.mysql.com/doc/refman/8.0/ja/slow-query-log.html) を駆使して、ボトルネックになっているクエリを特定する必要があります。

## wp_postmeta.meta_value が検索条件に含まれる場合

例えば以下のようなクエリがボトルネックになっていると判明した場合

```sql
SELECT post_id, meta_value
 FROM wp_postmeta
 WHERE meta_key = '_wp_attached_file' AND meta_value = ?
```

これは [attachment_url_to_postid()](https://developer.wordpress.org/reference/functions/attachment_url_to_postid/) が発行しているクエリーです。
テーマやプラグインで、画像URLからポストIDを取得するために多発しているのかもしれません。


例えば以下のようなクエリがボトルネックになっていると判明した場合

```sql
SELECT wp_posts.ID
 FROM wp_posts
 INNER JOIN wp_postmeta ON ( wp_posts.ID = wp_postmeta.post_id )
 WHERE 1=1
 AND ( wp_postmeta.meta_key = ? AND wp_postmeta.meta_value = ? )
 AND wp_posts.post_type = 'post'
 AND wp_posts.post_status = 'publish'
 GROUP BY wp_posts.ID
 ORDER BY wp_posts.post_date DESC
 LIMIT 0,10
```

これは [Advanced Custom Fields](https://ja.wordpress.org/plugins/advanced-custom-fields/) プラグインなどを導入すると、発行されがちなクエリです。

これらのクエリは `wp_postmeta` テーブルにレコードが増えると実行に時間がかかるようになります。
`wp_postmeta` テーブルの `meta_value` にはインデックスが貼られていないため `WHERE` の中に `meta_value` が存在するとクエリのパフォーマンスが落ちてしまいがちです。
この場合は、思い切って `meta_value` にインデックスを貼ってしまうのも手です。

```sql
CREATE INDEX key_value
 ON wp_postmeta(meta_key,meta_value(255));
```

## wp_posts.guid が検索条件に含まれる場合

例えば、以下のようなクエリがボトルネックになっていると判明した場合

```sql
SELECT ID
 FROM wp_posts
 WHERE post_type = ?
 AND guid = ?
```

これは [S3 Uploads](https://github.com/humanmade/S3-Uploads) というプラグインが多く発行しているクエリーです。
`attachment_url_to_postid()` と同様にメディアファイルのURLからポストIDを取得するために使用されています。

`wp_posts` テーブルの `guid` にインデックスが貼られていないために、パフォーマンス劣化の原因になることが多いです。
この場合も、思い切って `guid` にインデックスを作成してしまいましょう。

```sql
CREATE INDEX type_guid
 ON wp_posts(post_type,guid);
```

このように、ボトルネックになっているクエリを特定して対処することで、あなたの WordPress の速度改善が簡単に行えます。
また、RDSのインスタンスタイプを一つ落としてもちゃんと動くようになるかもしれません。
【Kotlin】ExposedでPostgreSQLにバルクインサート

# batchInsertを使っているのに遅い気がする
　気がするというかかなり遅かった。
　たかだか10000件のInsertが10秒だって？

　**うわっ…私のDB、遅すぎ…？**

　というわけで少しこの問題を調べてみた。

# 確認：PostgreSQLのreWriteBatchedInsertsをTrueにしているか？
```kotlin
    Database.connect(PGSimpleDataSource().apply {
        setURL("jdbc:postgresql://localhost:5432/postgres")
        user = "pguser"
        password = "pgpass"
        reWriteBatchedInserts = true  // ← この野郎をTrueにしまくる
    })
```

# ドライバとExposedのバージョンを確認する
postgresqlのバージョンは**>=42.2.2**であれば```insert on conflict```の不具合が解消されているという事で、まあ最新ならよろし。

問題はexposedのバージョンで、下記のようにexposed-coreではなく、exposedの最新```implementation 'org.jetbrains.exposed:exposed:0.17.13'```を使っていた事に問題があった。よってこれを現在最新の以下のバージョンに書き換えた。

```gradle
dependencies {
    implementation 'org.postgresql:postgresql:42.2.23'

    implementation 'org.jetbrains.exposed:exposed-core:0.32.1'
    runtimeOnly 'org.jetbrains.exposed:exposed-jdbc:0.32.1'
}
```

# 結論をいうと10倍以上早くなった……が
**reWriteBatchedInsertsをfalseにしてもさほど結果が変わらない**という謎が実は残っている。**あれ？　結局バージョンを上げただけなの**って思うかも知れないが、そんだけの事で2時間ぐらいハマってしまった。

# ソース上の変更点
バージョンを上げるとbatchInsertが例外を吐くようになった。
プライマリキーのUUIDのデフォルトを```uuid_generate_v4()```としているが、デフォルトは使えなくなっている。全ての列に値を設定してやると良いようだ。

```kotlin
object HorseRaceResultTable: Table() { 
  val id = uuid("id")
  val raceName = text("レース名")
  val winner = text("勝ち馬")
  val reserve = text("reserve")
}

fun main() {
  Database.connect(PGSimpleDataSource().apply {
    setURL("jdbc:postgresql://localhost:5432/postgres")
    user = "pguser"
    password = "pgpass"
    reWriteBatchedInserts = true
  })

  val values = mutableListOf<Pair<String,String>>()
  
  values.add("宝塚記念" to "クロノジェネシス")
  values.add("安田記念" to "ダノンキングリー")
  values.add("東京優駿" to "シャフリヤール")
  
  measureTimeMillis {  // ← こいつは計測のため
    transaction {
      HorseRaceResultTable.batchInsert(values) { // ← batchInsertを使う
        this[HorseRaceResultTable.id]       = UUID.randomUUID() // ← UUIDも自分で設定
        this[HorseRaceResultTable.raceName] = it.first
        this[HorseRaceResultTable.winner]   = it.second
        this[HorseRaceResultTable.reserve]  = "" // ← 使わなくてもちゃんと設定
      }
    }
  }.let { println("insert time is $it ms") }
}
```

# MySQLだったら*rewriteBatchedStatements=true*でサクッと行くらしい
でもPostgreSQLはハマってる人結構たくさんいたんだよね。速くなったから使えてるんだと思うんだけど。

あと意外と重要なのが**ログレベルをDEBGUGにしてたらExposedがSQL全出力しちゃう**から大量データのInsertではここも気をつけましょうネ。
コミットをまとめる方法（git rebase -i）


# 問題です
現在、 `コミットID_1` の `develop` ブランチから別のブランチである `feature/hogehoge` ブランチを派生させて `コミットID_2` → `コミットID_3` → `コミットID_4` の順に修正をコミットし、`feature/hogehoge` ブランチをリモートブランチにプッシュしています。

この状態で `コミットID_2` 〜 `コミットID_4` のコミットをまとめたい場合どのようにすればよいでしょうか？

**つまり、これを**
`コミット1（develop ブランチ）` → `コミット2（feature/hogehoge ブランチ）` → `コミット3（feature/hogehoge ブランチ）` → `コミット4（feature/hogehoge ブランチ）`

**こうしたい**
`コミット1（develop ブランチ）` → `コミット2〜4（feature/hogehoge ブランチ）`


# 答え

1. 対象のブランチにチェクアウトして `git log --oneline` で rebase 元になるコミット ID を探す
1. `git rebase -i <コミット ID>` で rebase を実行する
1. Edit モードで rebase 指示書を修正する
1. `git push --force-with-lease origin HEAD` で強制プッシュする

## 1. `git log --oneline` で rebase 元になるコミット ID を探す

```bash
$ git checkout feature/hogehoge
$ git log --oneline

コミットID_4 (HEAD -> feature/hogehoge, origin/feature/hogehoge)コミットメッセージ_4
コミットID_3 コミットメッセージ_3
コミットID_2 コミットメッセージ_2
コミットID_1 (origin/develop, origin/HEAD, develop) コミットメッセージ_1
```

## 2. `git rebase -i <コミット ID>` で rebase を実行する

まとめるコミット ID の1つ前を指定して、`git rebase -i` を実行します。
今回の場合は `コミットID_2` 〜 `コミットID_4` をまとめるので `コミットID_1` を指定します。

```bash
$ git rebase -i コミットID_1
```

## 3. Edit モードで rebase 指示書を修正する

`git rebase -i` を実行すると Edit モードで以下のような表示が出現します。
ここで表示されるのは `コミットID_1` からみて時系列順でコミットが上から並んでいます（`git log --oneline`とは逆順のはず）。

```bash
pick コミットID_2 コミットメッセージ_2
pick コミットID_3 コミットメッセージ_3
pick コミットID_4 コミットメッセージ_4

# Rebase xxxxx..yyyyy onto zzzzzz
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
```

今回は `コミットID_2` に `コミットID_3` と `コミットID_4` をまとめる方法を選択します（`コミットID_4` にまとめる方法はないはずです。）。
省略形の `p` とか `r` とか `f` を指定することが多いはずです。

```bash:コミットメッセージ修正しない場合
p コミットID_2 コミットメッセージ_2
f コミットID_3 コミットメッセージ_3
f コミットID_4 コミットメッセージ_4
```

Edit モードを `:wq` でセーブして抜けて rebase がうまくいくと以下が出力されます。

```bash
Successfully rebased and updated refs/heads/feature/hogehoge.
```

これで rebase は完了です。

### コミットメッセージを修正する場合

多くの場合はコミットメッセージを修正するので、rebase 指示書を以下のようにします。（`r` がポイント）

```bash:コミットメッセージ修正する場合
r コミットID_2 コミットメッセージ_2
f コミットID_3 コミットメッセージ_3
f コミットID_4 コミットメッセージ_4
```

Edit モードを `:wq` でセーブして抜けるとコミットメッセージの修正が求められます。

それも`:wq` でセーブして抜けると、以下のような表示がされるので、`git rebase --continue` してrebase を進めてください。

```bash
Aborting commit due to empty commit message.
You can amend the commit now, with

  git commit --amend 

Once you are satisfied with your changes, run

  git rebase --continue
```

## 4. `git push --force-with-lease origin HEAD` で強制プッシュする

強制プッシュします。
このときに作業中のブランチが間違っていないかは確認したほうがいいです。

```bash
$ git push --force-with-lease origin HEAD
```



## （番外編） rebase 中に操作ミスした場合

以下を実行すると `git rebase -i` 実行前に戻るはずです。

```bash
$ git rebase --abort
```
Typescriptでnew演算子を使うobjectのTypeを定義したいとき

# tl;dr

`new ()` propertyで指定できます。

# サンプル

```test.ts
interface TestConstructor {
  new (a: string, b: number): Test;
}

// こんな事したい場合は参照ないことが多いので
declare const Test: TestConstructor;

const test = new Test('aaa', 100);
```
Rails6でDockerを用いてrails newするまで

# 本記事の目的
タイトルにある通り、Rails6でDockerを使用し環境構築を行う。
今までRails5をメインに使用してきたのでその忘備録も兼ねて執筆。
※Webpackerとは
https://railsguides.jp/webpacker.html

# 環境構築手順
どうやらRails6からWebpackerがデフォルトとなり、環境構築が一筋縄ではいかないらしい。
Dockerの公式マニュアルを読みながら、作業開始！
https://docs.docker.com/samples/rails/

##手順1.
まずはターミナルを開き

```
% mkdir <app名>
% cd <app名>
```

でアプリを作成するディレクトリの作成と作業ディレクトリへの移動。

##手順2.

```
% touch Dockerfile
% touch Gemfile
% touch Gemfile.lock
% touch entrypoint.sh
% touch docker-compose.yml
```
でDockerコンテナ作成のためのファイルを用意。

##手順3.
先程作成した5つのファイルに設定を記述していく。
実際はdockerの公式をコピペすればよい。
まずはDockerfileから
公式から引っ張ってこれば良いがこれに関しては追記が必要。

```ruby:Dockerfile
# syntax=docker/dockerfile:1
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
# 以下追記
RUN apt-get update && apt-get install -y curl apt-transport-https wget && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn
RUN curl -sL https://deb.nodesource.com/setup_7.x | bash - && \
apt-get install nodejs
#　ここまで

WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Configure the main process to run when running the image
CMD ["rails", "server", "-b", "0.0.0.0"]
```

以上の様に記入。
続いて、Gemfile

```ruby:Gemfile
source 'https://rubygems.org'
gem 'rails', '~>5'
```

Gemfile.lockには何も書かない。
次に、entrypoint.sh

```ruby:entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"
```

次に、docker-compose.yml

```ruby:docker-compose.yml
version: "3.9"
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db
```

##手順4.
設定の作成が終わったのでrails newをしていく
ターミナルにて、

```
% docker-compose run --no-deps web rails new . --force --database=postgresql
```

を実行。
次々とファイルが作成されていく。
終わったら次のステップへGo

##手順5.
ターミナルにて、

```
docker-compose build
```

でコンテナの作成。
続いて、databaseとの接続
rails newした時にできたconfig/database.ymlを

```ruby:config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  host: db
  username: postgres
  password: password
  pool: 5

development:
  <<: *default
  database: myapp_development


test:
  <<: *default
  database: myapp_test
```

に書き換える。

##手順6.
最後にターミナルで

```
% docker-compose up
```

を実行。
自分はこの段階でエラーが発生したので、
https://qiita.com/kurawo___D/items/a6c5d5f71f2b5ac83b58
を参考にさせていただき、解決。

dockerの起動が終わったら、localhost:3000にアクセスして
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1102785/94e51f84-49fb-e766-2d67-53daae861252.png)

が出れば成功！！
【非PDO】PHP+PostgreSQLで日付型をINSERT→UPDATEする（prepared&bind）

やたら苦戦してしまったのでメモに残します。
## やりたいこと
* 変数`$calc_date`には`""`もしくは日付`YYYY-MM-DD`を表す文字列が入る。
* この変数をdate型のカラムにアップサートしたい。（INSERTして重複する場合はUPDATEしたい。）
* SQL文はプリペアードしたものにバインドしたい。
* pg_prepare, pg_executeを使用する。（PDOを使用しない）
* 環境：PHP7、PostgreSQL12

## 実装

```PHP
// DB接続処理
$link = pg_connect("host=host_name port=XXXX dbname=db_name user=user_name password=XXXX");

// 日付もしくは""の配列
$date_list = ["", "2021-07-13", "", "2020-09-01"];

// テーブルINSERT（重複したらUPDATE）のSQL
$sql = 'INSERT INTO table_name (id, sample_date)
            VALUES ($1, $2)
        ON CONFLICT (id)
        DO UPDATE SET  sample_date = $3
        ';

// プリペアードステートメント作成（preparedする）
$res = pg_prepare(
            $link,
            'pr_table_name01', // ←これはプリペアードステートメントの名前
            $sql
        );

$cnt = 0;
foreach($date_list as $row){
    $cnt = $cnt + 1;
    // 日付もしくは""が入る
    $calc_date = $row;

    // ""だったらnull、それ以外は''（シングルクオート）で囲う
    $calc_date = $calc_date == "" ? null : '\''.$calc_date.'\'';

    // プリペアードステートメント実行（bindする）
    $res = pg_execute(
               $link,
               'pr_table_name01',
               [$cnt, $calc_date, $calc_date]
           );
}
//DB後処理
$close_flag = pg_close($link);

```

## キーポイント

- PostgreSQLのdate型には null か日付しか入らない。""（空文字）は不可。
- ON CONFLICT文はPostgreSQL独自の構文。MySQLではON DUPLICATE KEYを使う。
- 日付形式の文字列をバインドする時は''で囲う。（nullは囲んじゃダメ！）

### 参考：ループ内でプリペアードステートメントを作成
foreach内でpreparedしたい場合は、最初の1回のみ行うようにする。

```PHP
// DB接続処理
$link = pg_connect("host=host_name port=XXXX dbname=db_name user=user_name password=XXXX");

// 日付もしくは""の配列
$date_list = ["", "2021-07-13", "", "2020-09-01"];
$cnt = 0;
foreach($date_list as $row){
    $cnt = $cnt + 1;
    // 日付もしくは""が入る
    $calc_date = $row;

    // ""だったらnull、それ以外は''（シングルクオート）で囲う
    $calc_date = $calc_date == "" ? null : '\''.$calc_date.'\'';

    // テーブルINSERT（重複したらUPDATE）のSQL
    $sql = 'INSERT INTO table_name (id, sample_date)
                VALUES ($1, $2)
            ON CONFLICT (id)
            DO UPDATE SET  sample_date = $3
           ';

    // 1回目のみプリペアードステートメント作成（preparedする）
    if($cnt == 1) {
       $res = pg_prepare(
                  $link,
                  'pr_table_name01', // ←これはプリペアードステートメントの名前
                  $sql
              );
    }
    // プリペアードステートメント実行（bindする）
    $res = pg_execute(
               $link,
               'pr_table_name01',
               [$cnt, $calc_date, $calc_date]
           );
}
//DB後処理
$close_flag = pg_close($link);

```


今どきはPDOが主流なので（プロジェクトの方針で禁止されない限り）PDO形式が良いと思います。
railsでcssが反映されないエラーActionController::RoutingError (No route matches [GET] "/stylesheets"):style


app/assets/stylesheets/home.scss
上記のようにhome.scssファイルを作ってcssを書き

app/assets/views/home/index.html.erb
上記のようにhomeフォルダにindex.html.erbファイルを作ってhtmlを書いた。

「rails s」でサーバーを起動すると

```
ActionController::RoutingError (No route matches [GET] "/stylesheets")
```
のエラーが起きてしまった。

```routes.rb
Rails.application.routes.draw do
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
  get "index" =>"home#index"
  get "myactive" => "home#myactive"
  get "myhobby" => "home#myhobby"
  get "myskill" => "home#myskill"
end
```
ルーティングを確認したが特に問題はなさそう。

```home.controller.rb
class HomeController < ActionController::Base
    def index
    end

    def myactive
    end

    def myhobby
    end

    def myskill
    end
end
```

上の「ActionController::Base」を「ApplicationController」に変更すると上手くいった。

これで理解したこと
・home.controller.rbとはviews/homeフォルダをコントロールするもので
　routes.rbでは「home#index」のようにする。home.scssに書く。
　<font color="Red">home.controller.rbなど新しくファイルを作った場合は、親クラスをApplicationControllerにする。</font>

・わざわざhome.controller.rbなど新しくファイルを作らなくても、views/applicationフォルダを作り、
　既存のapplication.cssにコードを書くとcssを反映することができる。
JavaScript の即時関数さんてさ？

## 即時関数とは
即時関数について知らない方はググって知識を得てからいかに進んでくださいm(_ _)m

## 文が書けるとこでは即時関数の出番は減る
JavaScript には、「文(statement)」と「式(expression)」という概念があります。それを知らずにプログラミングするということは、冬に富士山頂上を目指すようなものですから（？）、ググって知識を得てからいかに進んでくださいm(_ _)m

さて、ここまで進んでこられた皆さんにすればどうということもない話であると思いますが、ブロック文を使えば、即時関数の出番は減ります。

```js

let c = 0;
{
  const a = 1;
  const b = 2;
  let c = a + b;
}
console.log(c); // 0

```

つまり、変数のスコープを狭めるだけの目的でわざわざ即時関数を使う種族は絶滅したはずである、ということです。

## 文が書けない場所
JavaScript には、「式」しか書けない場所というものがあります。
有名なところでは、React などの jsx 内の`{ここ}`や、テンプレートリテラル内の`${ ココ }`です。あと、「演算子」ですから当たり前かもしれませんが、三項演算子の中でも「式」しか使えませんよね。
[do 式](https://github.com/tc39/proposal-do-expressions)なるものが提案されていますが、まだ正式採用はされていませんので、「文」であるブロック文が使えない上記のような場所では、「式」である即時関数が大活躍することになります。

## 世界一美しい即時関数の書き方（※※※このような書き方は2025年現在は動作しません。おそらくブラウザ等が修正したのであると思います）

[【JS】世界一美しい即時関数の書き方 ~  JavaScriptに関するお知らせ ~](https://jsnotice.com/posts/2019-09-18/) では、次のような書き方が紹介されています。

```jsx

<div class="main"> {
  (_=>{
    // ここに
    // 処理を書く
  })``
} </div>

```

美しいですね。即時関数は普通に書くと`()`だらけでダサいんですよね。ちなみに最後の `` は、テンプレートリテラルのタグ関数というやつです。タグ関数知らない、という方はググって勉強しておいてくださいね。
However, 個人的には次の書き方が好みです。

```jsx

<div class="main"> {
  function immediately() {
    // ここに
    // 処理を書く
  }``
} </div>

```

外側の`()`がないだけでもかなり見やすい気がするのですが・・・
どうも、「式」しか書けない場所では、アロー関数形式ではなく`function()`形式を用いる限り、 外側の`()`はなくても許されるようです。
プロのエンジニアは、ひとつの言語だけず～っとやってるわけにはいきません。久しぶりにJavaScript に戻ってきて、過去のソースを見たときに、こちらの方が自分フレンドリーな気がするのですがどうでしょう。
美しさだけに頼って食べていけるわけではありません（泣）
`immediately` なくてもいいですが、書いておいた方が即時関数であることがパッと見から判別しやすいですし、英語圏のエンジニアに仕事を促す際に必須の単語ともいえる、`immediately` のスペリングにも強くなれます。

## 最後に
長々とすみませんでした。次の投稿で今回の知識が役立つことになりますので許してください。
Android StudioがiPhone実機を認識しなくなった場合の対処法

#現象
ケーブル抜き差ししても反応はあるものの、Android Studio上では認識しなくなったので実機ビルドができない。

#確認

`flutter doctor`を実行


```console
$ flutter doctor -v

　　...

[✓] Connected device (1 available)
    • Chrome (web) • chrome • web-javascript • Google Chrome 91.0.4472.114
    ! Error: Errors were encountered while preparing your device for development. Please check the Devices and Simulators Window.  (code -1)

• No issues found!
```

#手順

XCodeを開いて `Windows > Devices and Simulators`　を開く。 `Devices`を選択する。Android Studio上では認識しなくなった端末が、XCodeでは認識されていることを確認。エラー内容も表示されているので確認する。


端末を右クリックして`Unpair Device`を選択。その後ケーブルを抜き差しするとiPhoneで信頼できる端末がどうか聞かれるので信頼を押す。するとXCodeで表示されていたエラー内容が消え、Android Studioでも認識されるようになります。
Pythonでオーディオの分析を行う

# ライブラリのインポート
```
import sys
import scipy.io.wavfile
import numpy as np
import matplotlib.pyplot as plt
import librosa
import IPython.display as ipd
```

# オーディオを読み込んで再生ボタンを表示
'sample.wav'の部分で、使用したいオーディオファイルを指定してください。

```
audio_path = 'sample.wav'
librosa.load(audio_path, sr=44100)
ipd.Audio(audio_path)
```
# xにオーディオのデータを代入
```
audio_path = 'sample.wav'
x , sr = librosa.load(audio_path)
print(type(x), type(sr))
print(x.shape, sr)
```
# 波形を表示
```
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)
```

# スペクトル重心の定義式
```
def spectral_centroid(x, samplerate=44100):
    magnitudes=np.abs(np.fft.rfft(x)) # magnitudes of positive frequencies
    length=len(x)
    freqs=np.abs(np.fft.fftfreq(length, 1.0/samplerate)[:length//2+1]) # positive frequencies
    return np.sum(magnitudes*freqs)/np.sum(magnitudes) # return weighted mean
```

# スペクトル重心を計算
```
audio_path = 'sample.wav'
x , sr = librosa.load(audio_path)
spectral_centroid(x, samplerate=44100)
```

# スペクトル平坦度の定義式
```
def spectral_flatness(x): 
    X_f = fft(x) 
    N=len(X_f) 
    magnitude=abs(X_f[:N/2]) 
    sf=geom_mean(magnitude)/aritm_mean(magnitude) 
    return sf
```

# スペクトル平坦度を計算
```
audio_path = 'sample.wav'
x , sr = librosa.load(audio_path)
spectral_flatness(x)
```

# 
# 
# 
#
Vue.jsで環境変数を超簡単に切り替える

# 環境変数
本番環境、検証環境、開発環境の複数環境を作成したときにAPIの向き先を変えたりする必要がある。その都度ベタがきのコードを改修してfirebase,AWSにデプロイするなんていうのは嫌ですよね？
また、中にはビルド時に秘密にしたい秘密情報が必要な場合があります。そういったものをデプロイ・ローカルホストの起動時だけ利用できるように設定する簡単な方法がVue.jsには用意されています。


## 環境変数の切り替え
環境変数の切り替えをローカル上での起動とビルド時にできるようにするための７ステップを紹介します。

###1  .env.\*\*\* に変数を追加する

VUE_APP_\*\*\*をプレフィックスにして変数名を定義

例 : http://hogehoge を develop に登録する場合

```　.env.develop
VUE_APP_API_DOMAIN = http://hogehoge
```

###2 .env.\*\*\* に登録した環境変数を利用する

process.env.\*\*\* で利用したいところから呼び出す

記入例

```
const apiUrl = process.env.VUE_APP_API_DOMAIN
```

###3 ローカルホスト起動時に指定した環境変数を利用できるようにする

pachage.json に下記のように登録する
mode の右側の \*\*\* がついた.env.\*\*\*の環境変数を利用するようになる。

```
serve-**": "vue-cli-service serve --mode ***"
```

記入例

```
"scripts": {
    "serve": "vue-cli-service serve",
    "serve-dev": "vue-cli-service serve --mode development",
    "serve-stg": "vue-cli-service serve --mode staging",
    "serve-prod": "vue-cli-service serve --mode production",
  },
```

###4 ローカルホスト起動時に境変数を切り替える

下記のコマンドのように package.json で利用したい環境変数を指定してコマンドを入力する。

```
% yarn serve-**
```

記入例: .env.develop に定義した環境変数を利用する

```
 yarn serve-dev
```

###5 ビルド時に環境変数を切り分ける

ローカルホスト同様、pachage.json に下記のように登録する
mode の右側の \*\*\* がついた.env.\*\*\*の環境変数を利用するようになる。

```
build-**": "vue-cli-service build --mode ***"
```

記入例

```
  "scripts": {
    "serve-dev": "vue-cli-service serve --mode development",
    "serve-stg": "vue-cli-service serve --mode staging",
    "serve-prod": "vue-cli-service serve --mode production",
    "build-dev": "vue-cli-service build --mode development",
    "build-stg": "vue-cli-service build --mode staging",
    "build-prod": "vue-cli-service build --mode production",
```

###6 ビルド時に指定した環境変数を利用する

下記のコマンドのように package.json で利用したい環境変数を指定してコマンドを入力する。

```
% yarn build-**
```

記入例: .env.develop に定義した環境変数を利用する

```
％ yarn build-dev
```

### 7 .gitignoreに追加する
.gitignore に　github で保存したくないファイル名を追記することで秘密にしたい環境変数をgithubで公開しないで運用することができます。WEBで公開しているサービスのソースコードをポートフォリオとしてpublicにしたい人はこの方法が必要になります。

```
.env.development
.env.staging
.env.production
```

またファイルキャッシュされてしまっている場合があるのでgitignoreにファイル名を追加したにもかかわらず、gitのstagingに.envのファイル名が記載されている方は下記のコマンドでファイルのキャッシュを削除しましょう。

```
% git rm -r --cached . //ファイル全体キャッシュ削除
```

## 最後に
MENTAでVue/Nuxtについて教えているので興味ある方はご気軽にメッセージください！
https://menta.work/user/13200


## 参考

https://qiita.com/fuwamaki/items/3ed021163e50beab7154
async と await のまとめ（apiを後回しにするパターン例）

##async と await を使うとき、よくあるのが、apiを後回しにするパターンだと思う。

たとえば、下記のようなことがやりたいとする。

1.api以外の処理をする
2.画面を表示
3.apiで値をとってくる
4.とってきた値をいい感じに変更したりする
5.画面に反映

##もしこれを順番に書いてしまうと、こうなる。
apiが終わるまで画面が表示できない。。

```node.js
let tmp1 = sample()
console.log(tmp1)

let tmp2 = samAsync()
console.log(tmp2)

console.log("画面表示！！")



function sample(){//api以外の処理
    return "api以外の処理"
}

function samAsync(){//apiの値を操作する処理
    console.log(samAwait())
    return "apiの値を操作する処理（画面に反映）"
}

function samAwait(){//apiの処理
    return "apiの処理"
}

//実行結果

//api以外の処理
//apiの処理
//apiの値を操作する処理（画面に反映）
//画面表示！！

```


##async await を使うと。



そこで、async awaitを使って、順番をいい感じに変えることができる。
結果はこんな感じ。

```node.js
let tmp = sample()
console.log(tmp)

samAsync().then(value => {
    console.log(value)
})

console.log("画面表示！！")

function sample(){//api以外の処理
    return "api以外の処理"
}

async function samAsync(){//apiの値を操作する処理
    await samAwait().then(value => {
        console.log(value)
    })
    return "apiの値を操作する処理（画面に反映）"
}

async function samAwait(){//apiの処理
    return "apiの処理"
}



//実行結果

//api以外の処理
//画面表示！！
//apiの処理
//apiの値を操作する処理（画面に反映）


```
Hyper-V 仮想マシン内で Hyper-V の実行を可能にする設定

# やり方

- Hyper-V ホスト上で次のコマンドを実行します。

```
Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true
```

- 戻す場合は以下です。

```
Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $false
```

- 設定値の確認は以下です。

```
Get-VMProcessor -VMName * | ft VMName, ExposeVirtualizationExtensions
```

# 参考URL

https://docs.microsoft.com/ja-jp/virtualization/hyper-v-on-windows/user-guide/nested-virtualization
cakePHP データベース接続設定

Every Qiita #11
のんびり独学初学者の毎日投稿チャレンジ 11日目
今回は・・・
前回記事でご教示頂いたソートに関しての備忘録です。

###app.phpファイルで設定
 ```php:app.php
'Datasources' => [
        'default' => [
            'className' => 'Cake\Database\Connection',
            'driver' => 'Cake\Database\Driver\Mysql',
            'persistent' => false,
            'host' => 'localhost',
            'username' => env('DB_USERNAME',false),
            'password' => env('DB_PASSWORD',false),
            'database' => env('DB_DATABASE',false),
            'encoding' => 'utf8',
            'timezone' => 'UTC',
            'cacheMetadata' => true,
```
####ブラウザで確認してみます。
![スクリーンショット 2021-07-13 12.12.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813099/992fc0cc-2828-3f50-3b47-43f95ba6c641.png)

エラーが出ています・・・

###原因
app_local.phpにapp.phpと同じ記述があった場合、上書きされるみたいです。
環境変数の設定等で問題あるかと思っていたので、解決するまでに時間がかかりました・・・初歩的なミスでした:cry:


####app_local.phpに書き込み、サーバーを再起動して確認
![スクリーンショット 2021-07-13 12.11.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/813099/2a1a6ed9-450f-2c06-3285-a9370bbaefc9.png)

無事接続できました！
セッションハイジャックについて

# 目的
セッションハイジャックについて理解を深める。

# 目次

1. [はじめに](#はじめに)
1. [セッションハイジャック](#セッションハイジャック)
1. [セッションID](#セッションid)
1. [セッションIDの推測](#セッションidの推測)
1. [セッションIDの盗み出し](#セッションidの盗み出し)
1. [SSL](#ssl)
1. [セッションIDの固定](#セッションidの固定)

# はじめに

今回は、XSSを用いた個人情報を盗み出すセキュリティ攻撃とその対策について理解を深めていきます！

# セッションハイジャック

`セッションハイジャック`とは、セッションが保存されているクッキーを狙った攻撃のことを指します。
具体的には、XSSなどを用いて、正規利用者ではない者が正規利用者のセッションを取得する攻撃手法です。
クッキーはセッションをセッションIDという識別番号を用いて保存しますが、このセッションIDを盗み出されると、セッションハイジャックが成立してしまいます。

# セッションID

`セッションID`とは、通信中の正規利用者へ付与される、固有の識別情報のことです。
セッションハイジャックが行われた場合、アプリケーション内で正規利用者ができることはほとんど実行可能となってしまい、送金や物品購入、なりすましメールの送信やSNSへの犯罪予告など、正規利用者への被害は大きくなります。

具体的な攻撃手法としては以下の3つが挙げられます。

- セッションIDの推測
- セッションIDの盗み出し
- セッションIDの固定

# セッションIDの推測

Webアプリケーションに用いられるセッションIDは、以下のように生成規則に問題があると第三者にセッションIDが予測され、悪用されてしまう可能性があります。

- ユーザーIDやメールアドレス
- リモートIPアドレス
- 日時

対策としては`独自でセッションIDの生成を行わない`ことです。

推測可能なセッションIDを生成しないためには、独自での生成機構は作らず、フレームワークなどのWebアプリケーション開発ツールを利用することが安全とされています。

# セッションIDの盗み出し

XSSを用いたセッションハイジャックがこれにあたります。
JavaScriptでは、`<script>document.cookie</script>`というスクリプトでクッキーの情報が表示できます。
このスクリプトへ更に細工をして、攻撃者側のサーバーに正規利用者のクッキーの情報を送付するようにすると、セッションハイジャックが成立します。
仕込まれたスクリプトが発火した時点で、攻撃者に正規利用者のクッキーが行き渡ります。
また、インターネット環境のセキュリティ対策が不十分であると、正規利用者とサーバーの通信の際にセッションIDが傍受されることがあります。

対策としては`XSSを防ぐ`ことと、`安全なインターネット環境を用いる`ことが重要です。

安全なインターネット環境を用いるために、インターネット上の通信を暗号化する仕組みを`SSL`と言います。

# SSL

SSLとは、インターネット上の通信を暗号化してくれる技術です。これにより、第三者からの情報の盗聴や改ざんを防ぐことができます。
クッキーのような重要な情報をやりとりする際はSSLを使うと安全性を保つことができます。

# セッションIDの固定

セッションIDの固定化は以下の手順で行われます。

1. ①攻撃者は普通の利用者としてセッションID(abc123)を取得
2. ②正規利用者に対して①で取得したセッションIDを強制
3. ③正規利用者は標的アプリケーションにログイン
4. ④攻撃者は、正規利用者に強制したセッションID(abc123)を使って標的アプリケーションにアクセスする  
正規利用者は攻撃者が強制したセッションで認証が完了しているため、そのセッションを用いてアクセスした攻撃者はすでに認証済みのページにアクセスできる

対策としては`ログイン後にセッションIDを変更する`ことが挙げられます。

セッションIDを固定する方法は多種多様であるため、固定化されないように常に変更し続けることが有効です。具体的には、ログインが完了した時点でセッションIDを変更するという方法があります。
そうすることにより、認証前にセッションIDが固定されたとしても、認証後にセッションIDが変わるため、固定されたセッションIDでアクセスしようと試みる攻撃者は認証されず、攻撃は成功しません。
vscodeでコードフォーマットせずに保存するんだ！（自動フォーマットはONだけど）

どうも、最近Vueメインのしゅーいっちです。

タイトルは釣りです。「そうしろ」というわけではなくその方法です。最初は「vscodeでフォーマットせずに保存する方法」というタイトルだったんですが、勢いをつける過程で最後の部分を変えたら今のタイトルになりました。

遠く離れた異国のチーム内に違うコードフォーマット様式の人がいる場合があります。設定ファイルのおかげでvueファイルとかがずれることはほぼないのですが、素のjsやmdファイルとかずれてしまうこの頃です。

そういうファイルは必要なところだけ触ってそっと閉じておきたい。でも基本的には保存時に自動フォーマットをしたい。そういう状況です。

`cmd + k` そして `s`

（`s`を押す前に`cmd + k`は離します。）


以上になります。

参照: https://til.hashrocket.com/posts/xxh30emyqg-save-without-formatting-in-vscode

追記: あまりにも不親切な気がしたのでタイトルに注釈を追加。
【Swift 】列挙型（enum） 


##enumとは
特定の意味を持つ整定数の集合。一つの型として扱うことができるため、使い慣れると便利らしい。
正直なところstructなどの構造体との区別が曖昧なのでまとめながら整理していこうと思う。

##シンプルな列挙型
列挙型には値型や共用型など色々とありますが、ベースはこれです。
シンプルな列挙型は、特定の意味を持つ一つの集合を作成し一つの型として扱うことができます。
##定義方法
caseの後に任意の名前をつけます。

```swift:
enum 列挙型 {
    case ケース名1
    case ケース名2
    ...
}
```
##使用例
方角を一つのまとまりとして定義しました。

```Swift
enum Hand {
    case rock
    case scissors
    case paper
}
```
以下のような書き方もできます。

```Swift
enum Hand {
    case rock, scissors, paper
}
```
各ケースは以下のようにして変数や定数に代入可能です。変数cのように型が決まっていれば「.」から記述可能です。

```Swift
let a = Hand.rock
var b = Hand.sccciors

var c: Hand = .paper

a == c // false　比較も可能
```



## メソッドの定義
列挙型はケースを定義して値を当てはめるだけなく、メソッドを組み込み、型全体としての動作や機能を表すことができます。下記では、ジャンケンの列挙型を定義し、自分がじゃんけんに勝利するメソッドを作成してみました。

```Swift
enum Hand {
    case rock
    case scissors
    case paper

    func janken() -> Hand { 
        switch self {
        case .rock: return .scissors 
        case .scissors: return .paper
        case .paper: return .rock
        }
    }
}

let r = Hand.rock // rock
r.janken() // scissors

let s = Hand.scissors // scissors
s.janken() // paper

let p = Hand.paper // paper
p.janken() // rock
```
##  値型の列挙型
列挙型には、上記で扱ったものに加え、全てのケースが同じデータ型の何かしらの値を持つようになっている「値型」、各ケースが異なる型や値を持ち、インスタンスごとに値を変えることが可能な「共用型」があります。

## 定義方法
値の型をその列挙型の実体型（raw type）といい、各ケースに割り当てられた値を実体値（raw value） と言います。

```swift:
enum 列挙型名: ローバリューの型 {
    case ケース名1 = ローバリュー1
    case ケース名2 = ローバリュー2
    ...
}
```
##使用例
上記で記述した列挙型Directionに値（raw value）割り振りました。ローバリューが定義されている列挙型では、ローバリューと列挙型の相互変換を行うための失敗可能イニシャライザinit?(rawValue:)とプロパティrawValueが用意されます。

```swift:
enum Direction: String {
    case up = "上"
    case down = "下"
    case right = "右"
    case left = "左"
}

let a = Direction.up.rawValue // "上"  ケースのローバリューを返す
let b = Direction.init(rawValue: "上") // up  ローバリューが一致するケースがあればそのケースをインスタンス化
let c = Direction.init(rawValue: "斜め右") // nil  一致しなければnilを返す
```
##ローバリューのデフォルト値
ローバリューに対して値を設定しない場合、ローバリューの方に合わせてデフォルト値が出力されます。Int型の場合は0から1ずつプラスされた値が割り振られます。String型の場合はケース名がそのまま文字列として割り振られます。

```swift:
// 型がStringの場合
enum Direction1: Int {
    case up 
    case down
    case right 
    case left
}
// 型がIntの場合
enum Direction2: String {
    case up 
    case down
    case right 
    case left
}

let a = Direction1.up // 0
let b = Direction1.down // 1
...

let c = Direction2.up // "UP"
let d = Direction2.down // "DOWN"
...
```
##CaseIterableプロトコル
列挙型を一つの配列として取得したい場合はCaseIterableプロトコルに準拠させることで簡単に実装することができます。配列にすることで使える幅が増えそうですね。ただ、このプロトコルはシンプルな列挙型、値型の列挙型で使用可能ですが、共用型の列挙型では使用することができません。

```swift:
enum Hand :CaseIterable {
    case rock
    case scissors
    case paper
}

Hand.allCases // [rock, scissors, paper]

// ランダムでジャンケン
let fight = Hand.allcases.randomElement()
```


##まとめ

次回は共用型の列挙型についてまとめてみようと思います
Pythonで複数のDataFrameをExcelにシート別にfor文を使って出力してみる

### DataFrameが複数存在した場合にエクセルにシート別で出力できるのかなという疑問から

 - VBAしか触ったことがなかったのですが、多岐に自動化できるようになってみたい思いからpythonプログラミングの独学を始めてみて3か月ちょっとの者です。
 - コロナ関連の各自治体が出している報告pdfをtabulaで取得してdfに格納していくことに楽しさを感じたので　ついでにExcelにシートごとに出力する方法を調べてみたいなと思いながらも調べ方が悪く適当な方法を見つけられずにいましたがもう一度資料参考をしながら作成してみたところうまく出力されたので自分の覚書も兼ねて投稿します。



##### 環境
 - windows10 pro 64
 - python 3.9
 - tabula-py 2.2.0
 - pandas 1.3.0
 - jupyter-lab 3.0.13
 - Excel2019 
 
### コード

```python

import pandas as pd

#あとでファイル管理がしやすいように変数日付４桁を作成
datestr = input('四桁で日付を入力')

##以下すでにdfがいくつか存在していることが前提のコードです

#closeを忘れても良いようにwithブロックで pd.ExcelWriter を呼び出しf文字列で入力した日付をファイル名に結合
with pd.ExcelWriter(f'dataframes{datestr}.xlsx', engine='xlsxwriter') as writer:

    #for文 range内でlen関数でdfのデータ数を取得
    for n in range(0,len(df)):
        #dfの数ごとにExcelに出力しシートの名前もデータ番号を付与させる(f文字列でnを反映させる)
        df[n].to_excel(writer, sheet_name=f'df{n}', index=False)

```

### 参考記事など

[【Python】with open構文の使い方について](https://neko-py.com/python-with-open)
[Pythonのfor文によるループ処理（range, enumerate, zipなど）](https://note.nkmk.me/python-for-usage/)

### 補足

- 事前処理としてselenium 処理からheliumでブラウザ操作に変えたり　事後処理としてファイル操作プログラムとかも書いてみたりしていますがそこらへんは割愛して主題部分だけ載せました。
- 実際はtabulaやcamelotなどでpdfを読ませましたが一部の『新規陽性者数』などがなぜか欠損値として出力されたので無料のRPAツール(UiPath community)で画像認識させて欠損値の補完入力をさせてみたりなどしておりすべて自動的に行うというレベルまでにはまだまだ到達できていないなぁ…というのが現状です。
Open algorithm(OPAL)の概要

スマートシティを扱う講座の中で出てきた、Open Algorithmという手法が、ビッグデータと個人情報の共存を求める、今の社会にとても有効だと思ったのでご紹介します。

https://www.opalproject.org/about-opal

スマートシティを実現する上で、人の流れをデータ化することはとても重要です。なぜなら「どんな人が」「何の目的で」「どこに」「何時間いたか」というような情報が、街の移動手段を最適化に必要になるからです。
そしてこのような情報はCDRsと呼ばれる、携帯電話の利用と基地局との関係性から、地理情報を取得します。
ここで問題になるのが、プライバシーです。もちろん、人の流れの分析において、個人情報は不要ですが、ある場所に一定時間滞在していることが分かれば、それは家や仕事場である可能性が高くなり、個人が特定されるリスクが出てきてしまします。

そこで開発されたのが「Open Algorithm」という手法です。
その手順を簡単に説明すると、以下のようになります。

1. 人の流れと属性などを分析するアルゴリズムを開発
2. 権威ある団体がアルゴリズムをチェックし、正当性を保証
3. センシティブなデータを所持している企業（携帯通信会社など）が、社内の堅牢なセキュリティ環境内でアルゴリズムを使用して、結果を出力
4. 結果をアルゴリズム作成元に返す

手順によると、個人情報につながるようなデータは、元々の企業の手を離れずに、分析者はモデルや結果を得ることができるという仕組みです。

データの利活用が進む中で、今後日本でもこのようなサービスが展開されてく画が見えますね。
Backlogの課題にScrapboxでメモするためのブックマークレット

# 概要

各チケットの雑多なメモをScrapboxで書いている。
タイトルや引用を毎回書くのは大変なので、ブックマークレット化したものを使い続けている。

# 手順

1. 下記をブックマーク登録のURL欄に貼り、`proj-name`をScrapbox側に合わせて変更
1. 課題のページにてブックマークを実行

```js:Backlog&#x20;=&gt;&#x20;Scrapbox
javascript:(function(){
    var PROJ_NAME = 'proj-name';
    var getElement = function(className) {
    var element = document.getElementsByClassName(className)[0];
        return element ? element.textContent : null;
    };
    var keyNumber = getElement("ticket__key-number");
    var titleText = getElement("title-group__title-text");
    if (!keyNumber || !titleText) return;
    var markdownBody = document.getElementsByClassName("markdown-body")[0];
    markdownBody = markdownBody ? markdownBody.innerHTML.replace(/<li>/g, "・").replace(/<\/t(h|d)>\n\s*<t(h|d)>/g, " | ").replace(/<("[^"]*"|'[^']*'|[^'">])*>/g, '').replace(/\n+(\s*\n+)*/g,'\n> ') : "";
    var title = "\u{1F3AB}" + keyNumber + " " + titleText;
    var body = "#Backlog #\u{1F3AB} \n[" + keyNumber + " " + window.location.href + "]\n> " + markdownBody + "\nMEMO:";
    window.open('https://scrapbox.io/' + PROJ_NAME + '/' + encodeURIComponent(title.trim())+'?body='+encodeURIComponent(body.trim()));
 })();
```

title, bodyの内容はお好みで。「#🎫」のタグ付けは便利。
App Store Connect、TestFlightの外部テスターの有効期限切れ、外部テスターの削除の際の挙動

App Store ConnectでTestFlightの外部テスターの有効期限切れ、外部テスターの削除の際にどのような挙動になるかの確認です。

# 前提条件

Testflightにて外部テスターにてインストール

## 有効期限切れの場合

"アプリ名"ベータの使用期限が切れました

とダイアログが表示され使用不可になります。

## 手動での削除

### App Store Connectからユーザーを手動で削除した場合

App Store Connectからユーザーを手動で削除する。

 ![スクリーンショット 2021-07-13 11.02.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64331/f19cbb41-da21-4af8-cefd-ff77f1175849.png)

グループから削除をしてみる
![スクリーンショット 2021-07-13 11.03.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64331/07db98c2-1e3c-e8ba-7a91-3431d0684e59.png)


結果：消しても普通にアプリが起動できる。

### 外部テストグループごと削除してみた場合

今度は外部テストグループごと削除してみる

![スクリーンショット 2021-07-13 11.06.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64331/1845ca6b-ea3e-0476-1458-4965905f22cf.png)

グループとテスターをTestFlightから削除を選択
![スクリーンショット 2021-07-13 11.06.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64331/9732f038-5ffa-eaa4-3310-f86647ef737e.png)
普通に起動ができる。

もちろんTestflightアプリからアプリのインストールはできない

### TestFlightアプリからテストを停止ボタンを押してみた場合

別の端末からテストを停止ボタンを他のアプリでどうなるか？

結果：普通に起動できる。

### 手動でアプリのバージョンの有効期限切れにさせる

ちょっと待つと期限切れになる


![スクリーンショット 2021-07-13 11.17.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64331/535c7779-91bc-7983-4a12-af943a7107be.png)



アプリは起動できる。
一応再起動して再度確認　→ 起動できる
30分後に再度確認　→ 起動できる

自然と有効期限切れの場合は使用ができないので手動でも使えなくして欲しい。。
【Google Cloud Day'21】「仮想デスクトップ利用で Chromebook が優位な理由を教えちゃいます」を視聴して

仮想デスクトップ利用で Chromebook が優位な理由を教えちゃいます
https://cloudonair.withgoogle.com/events/google-cloud-day-digital-21/watch?talk=d2-sl-30
仮想デスクトップ専業ベンダーであるアセンテックがなぜ Chromebook が仮想デスクトップ利用に優位なのかを Chrome Enterprise の具体的な設定方法を通して教えちゃいます。

<table>
	<tr>
		<th>切り口</th>
		<th>内容</th>
	</tr>
	<tr>
		<th>アセンテックについて</th>
		<td>仮想化デスクトップ専業会社</td>
	</tr>
	<tr>
		<th>ChomeEnterpriseについて</th>
		<td></td>
	</tr>
	<tr>
		<th>デモ</th>
		<td>デバイスの登録のデモを実施</td>
	</tr>
	<tr>
		<th>セキュリティ</th>
		<td>ReadOnlyのほうで不正な動きをチェックしている.最新状態を常に保てる。</td>
	</tr>
	<tr>
		<th>CitrixCloudについて</th>
		<td></td>
	</tr>
	<tr>
		<th>全体の構成図</th>
		<td></td>
	</tr>
	<tr>
		<th>なぜChromeBookがテレワーク環境に最適か</th>
		<td>デバイスを登録しておけば、細かいセキュリティ設定が可能（ローカルデータの削除など）。PCを紛失したときに端末の停止も可能。</td>
	</tr>
</table>

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/d6321e8b-5985-615f-da16-91d28ff0a70b.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/90039afc-e80f-8554-028d-c534bbd29189.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/98a04eb6-985d-2a16-e1b8-3890da421a10.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/a0ec9531-145b-a289-a0ee-fb916ef114fa.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/2221cb7d-ce42-a0b4-6408-f25515eff226.png)
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/6511e8c0-ece2-b3f4-202b-dc76b68efea6.png)
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/83126ebb-5513-7e82-dfd3-c9799c0daedc.png)
GitHubのprivateなリポジトリをpip installする方法

弊社ではGoogle Colaboratryをよく使っています。その中で必要な処理をモジュール化し、GitHub上に登録、各コードからpip installして使いたい、ということがあります。

しかしながら、GitHubのリポジトリはprivateにしたい。privateリポジトリでもpip installできる方法について記載します。

「github private repo pip install」と検索して見つかったのがこの記事でした。

https://stackoverflow.com/questions/48350226/methods-for-using-git-with-google-colab?utm_source=pocket_mylist

# 方法

こちらには2通りの方法が提示されています。

```bash:①ユーザー名とパスワードを指定する方法
!git clone https://username:password@github.com/username/repository.git
```

```bash:②Gitトークンを指定する方法
!git clone https://git_token@github.com/username/repository.git
```

## 注意事項

①については、ユーザー名はともかくパスワードに「@」などの記号が含まれていると、URLの一部として認識されてしまい、実行できないという事象が起こり得ます。これは先程の記事にコメントがある通り「@」を「%40」に置き換えれば回避できます。

②についても、生成されたトークンに同様の記号が含まれれば同じ事象は起きますが、そうなった場合は同様の回避方法にて対応できます。

## どちらを使うか

個人的には②がオススメです。

①で対応したい場合、個人のユーザー名とパスワードを記載するのはあまり好ましくないため、共通アカウントを発行して使うなどした方が良いでしょう。

②で対応したい場合、トークンが漏れてしまわない限りは問題ありません。もし漏洩が発覚した場合にはトークンを無効とするだけで済みますし必要な権限のみコントロールできますので、こちらの方がセキュリティ上は安全かと思います。

トークンの発行方法は以下の記事を参照ください。（このリンクも貼ってくれていました、なんて親切な回答なのでしょう）

https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token

## ②でpip install

上記ではgit cloneでの方法でしたが、以下のコマンドでpip installできます。
※ git_token、username、repositoryは置き換えてください。

```bash
!pip install git+https://git_token@github.com/username/repository.git
```

git cloneでもできます。

```bash
!git clone https://git_token@github.com/username/repository.git
!pip install -e /content/repository
```
【Google Cloud Day'21】「データ ドリブンで意思決定 ! クラウド移行から始めるデータ分析ストーリー」を視聴して

データ ドリブンで意思決定 ! クラウド移行から始めるデータ分析ストーリー
データ ドリブンな分析を継続的に行うには、データ統合環境の整備と、データ分析、活用の体制が必要です。ここでは「 1. オンプレミス環境のクラウド移行 」「 2. データ分析基盤の構築 」「 3. 機械学習を用いたデータ予測によるレコメンド ならびに Looker によるデータの見える化」をシームレスに行う解決策をご紹介します。
https://cloudonair.withgoogle.com/events/google-cloud-day-digital-21/watch?talk=d2-gl-26

<table>
	<tr>
		<th>切り口</th>
		<th>内容</th>
	</tr>
	<tr>
		<th>課題</th>
		<td></td>
	</tr>
	<tr>
		<th>lift shiftの機能</th>
		<td>既存でVMwareを使っていればGCVEがおすすめ。IPも変わらないので。</td>
	</tr>
	<tr>
		<th>デモ</th>
		<td>Migrate for GCEのデモが見れる</td>
	</tr>
	<tr>
		<th></th>
		<td></td>
	</tr>
	<tr>
		<th></th>
		<td></td>
	</tr>
	<tr>
		<th>Da-winを使ったデモ</th>
		<td>da-winの画面が見れる</td>
	</tr>
	<tr>
		<th>Lookerを利用する</th>
		<td></td>
	</tr>
	<tr>
		<th>Lookerを使ったデモ</th>
		<td></td>
	</tr>
</table>

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/29410fce-f1ea-62bb-6b1f-522669f40f95.png)
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/4c0eb36e-1bd7-6c93-7fa2-7d97ca166591.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/a7caf596-0897-cdcd-d88b-2f2b553b9ced.png)
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/767cf99c-9d48-033b-d93b-fcd1f0613d12.png)
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556084/5e8079ec-4ce2-989a-9015-31909371a90b.png)
GitとGitHubを基本からまとめてみた【GitHub上からプルリクエストを作成までの流れ】

## GitHub上からプルリクエストを作成までの流れ


(1)『ベースブランチ』をクリックし、master(main)及びdevelopブランチを選択し、
　　変更履歴を確認する。

(2)『Pull requests』タブから『New pull request』をクリックする。

(3)『ベースブランチ』と『トピックブランチ』のブランチを選択する。
`例：『ベースブランチ』を master及びmain、『トピックブランチ』をdevelopを選択`
  **注意：変更履歴の差分とどのブランチに対して、プルリクエストするかを確認すること**

(4)『Create pull request』をクリックし、プルリクエストを作成する。

(5)タイトルにプルリクエストのタイトルを入力し、概要に変更内容や関連するイシューや資料への
　リンクなど、レビュー担当者(プルリクエストを確認する人)へ伝えておきたいことを記入する。

(6)『Create pull request』をクリックする。

(7)自身のGitHubのURLをレビュー担当者へ教える。



 






## 参考サイト
[初心者向けGithubへのPullRequest方法](https://qiita.com/samurai_runner/items/7442521bce2d6ac9330b)
[GitHubのレビューとプルリクエストについて、およびその作成方法](https://tonari-it.com/github-pull-request/)
[GitHubを使うなら最低限知っておきたい、プルリクエストの送り方とレビュー、マージの基本](https://www.atmarkit.co.jp/ait/articles/1702/27/news022.html)
dockerコマンド

```docker
# Dockerイメージ一覧
docker images

# Dockerコンテナ一覧
docker ps -a

# イメージのダウンロード
docker pull hello-world

# Dockerfileからイメージ作成
docker build .

# イメージからコンテナ起動
docker run -d --name hello-world -p 80:80 hello-world

# コンテナを停止
docker stop hello-world

# コンテナの削除
docker rm hello-world

# イメージの削除
docker rmi hello-world

# オプション

-d
コンテナをバックグラウンド実行

–name
コンテナ名を指定します

-p
ホストとコンテナ間のポートフォワード設定。
基本的には、「-p <ホスト側のポート>:<コンテナ側のポート>」で書きます。
（ホスト側を省略すると自動で設定されます。）
コンテナは、Dockerにより作成されるネットワークに属するため、
このオプションを使わないと、ホストのIPアドレスを用いて、d
コンテナで使用しているポートにはアクセスができません。

--rm
起動が終わればコンテナ削除

```
.NET Cosmos DB LINQ to SQLのクエリの性能分析

自分用備忘録

以下のMicrosoft公式のドキュメントを参考に、Cosmos DBのクエリの分析結果を閲覧できるようにする。

SQL クエリの実行メトリックを取得し、.NET SDK を使用してクエリのパフォーマンスを分析する
https://docs.microsoft.com/ja-jp/azure/cosmos-db/profile-sql-api-query

あとは、実際に実行したクエリ、処理時間、参照した行やデータ量、インデックスの使用割合、RU、などを分析して性能改善を試みる。

以上

----
2021/7/16: @junerさんの指摘を経て、URLをおおもとのGitHubでなくMicrosoftのURLに修正。 @junerさんありがとうございます。
↓もとのURL
https://github.com/MicrosoftDocs/azure-docs.ja-jp/blob/master/articles/cosmos-db/profile-sql-api-query.md