OmniAICreator/Qiita-1.07M huggingface dataset:
LAMP+CakePHP3開発環境をVSCodeRemote+Dockerで構築② -VSCodeRemote編-

[LAMP+CakePHP3開発環境をVSCodeRemote+Dockerで構築① -Docker編-](https://qiita.com/goodkei/items/24143d5fa129890d2a7f)からの続きです。

VSCodeでPHPの開発をするにあたり、XDebugやPHP Intellisenseなどの拡張を入れようとするとVSCodeのインストールされている自PCにもPHPをインストールする必要がありますが、VSCode Remote Developmentを利用するとDockerのコンテナ内で全て完結できました。

導入の際に問題が起きてかなりはまってしまったので、その際の対応を記載しています。

完成した環境は[GitHub](https://github.com/goodkei/cakephp3.8_with_vscode)にアップロードしてあります。

## VSCode Remote Developmentの導入

Docker関連のファイルは前回作成したものをそのまま使用しています。
以下の記事を参考にして導入してみます。
[Visual Studio CodeのRemote DevelopmentとDockerで快適な開発環境をゲット](https://tech-lab.sios.jp/archives/18677)

すると、コンテナの起動とVSCodeからコンテナへの接続は上手くいきます。

が、ブラウザからhttp://localhost:8093/ へアクセスすると「ERR_EMPTY_RESPONSE」と表示され接続できません。

### VSCodeRemoteをコンテナに接続するとコンテナ内のサーバーへアクセスできなくなる問題


#### 調査


```terminal:ターミナル
curl http://localhost:8093

エラー
curl: (52) Empty reply from server
```


コンテナ内で以下のコマンドを実行すると

```terminal:ターミナル
curl http://localhost:80

エラー
curl: (7) Failed to connect to ::1: Cannot assign requested address
```


となりこちらもエラーが出ます。
localhostを127.0.0.1に置き換えても同様です。

以下の記事達を参考にし、どうもコンテナは起動しているがサーバーが起動していない状態にありそうだという事がわかりますが、解決しません。

[Dockerコンテナで起動したサーバにアクセスできないときの確認と対処方法](https://web.plus-idea.net/on/docker-web-server-access-denied/)

[docker上のアプリにlocalhostでアクセスしたらERR_EMPTY_RESPONSEが出る](https://qiita.com/amuyikam/items/01a8c16e3ddbcc734a46)

VSCodeRemoteで接続した際にのみアクセスできなくなるので、そちらに原因がありそうだと当たりをつけて公式ドキュメントを読んでみます。

[Visual Studio Code | Developing inside a Container](https://code.visualstudio.com/docs/remote/containers)

### 公式ドキュメントを読んでみて大事そうなところ

・VSCodeRemoteでコンテナに接続した場合、コンテナを開いたrootディレクトリに対してworkspaceという名前のvolumeが作られる。
・rootディレクトリは設定で変更可能

・rootディレクトリ直下にdevcontainerフォルダが作られる。

フォルダ構成は以下の様な形

```text:rootディレクトリ
devcontainer
 - devcontainer.json
 - docker-compose.yml（VSCodeによって生成された、設定上書き用ファイル）
...
他のファイルやフォルダ達
docker-compose.yml(コンテナ生成の元になっている自分で用意したファイル)
```

・ このうちdevcontainer.jsonには以下の設定項目があり、上から指定されている順にdocker-compose.ymlが読み込まれ、上書きされていく。

```json:devcontainer.json
	"dockerComposeFile": [
		"../docker-compose.yml",
		"docker-compose.yml"
	],
```

### 以上を踏まえて問題となっていた箇所

自動生成されたdocker-compose.ymlには、以下の設定がされています。
これは、コンテナがすぐに終了してしまわないようにするため設定されている様です。

```yml:docker-compose.yml(VSCodeによって生成された、設定上書き用ファイル)

    # Overrides default command so things don't shut down after the process ends.
    command: /bin/sh -c "while sleep 1000; do :; done"
```

また、用意してあるDockerFileでは、サーバーを自動起動するために以下のコマンドを実行しています。

```text:docker/app/DockerFile
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]
```
Docker側の仕様として、docker-compose.ymlにcommandが記載してあるとDockerFileで記載したCMDを上書きするらしく、このCMDが実行されていないためサーバーが立ち上がらずに問題が起きていたようです。

以下の様に修正したところ、問題なくコンテナのサーバーにアクセスできました。

```yml:docker-compose.yml(VSCodeによって生成された、設定上書き用ファイル)

    # Overrides default command so things don't shut down after the process ends.
    command: /bin/sh -c "/usr/sbin/httpd -DFOREGROUND; while sleep 1000; do :; done"
```
【AWS　SAA】VPC内のEC2インスタンスがインターネットに接続できない原因の備忘録

#はじめに
AWS SAAの模擬試験問題で「VPC 内のEC2 インスタンスがインターネットに接続できない原因」が出てきた。その問題解決方法について備忘録として今回載せたい。

#主な原因
下記の設定ミスが、主な原因とのこと。
①セキュリティグループ
②ネットワークアクセスコントロールリスト (ACL)
③ルートテーブル
④パブリックIPアドレス

#①セキュリティグループのチェック
セキュリティグループの設定で、インターネットアクセス許可が設定されていない可能性がある。
本稼働環境では、特定のIP アドレスや特定のアドレス範囲にのみインスタンスへのアクセスを許可。
テスト目的では、0.0.0.0/0のカスタムIPアドレスを指定し、すべてのIPアドレスにSSHまたは RDPを使用したインスタンスへのアクセスを許可。
イメージ画像①
<img width="932" alt="スクリーンショット 2020-07-06 17.24.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/1e29d2ef-be46-5167-2f70-611c94b5bdff.png">

#②ネットワークアクセスコントロールリスト (ACL)のチェック
ネットワークACLの設定でインターネットアクセス許可が設定されていない可能性がある。
以下の項目を確認。
・ポートを経由するトラフィックを許可されていることを確認
・インバウンドとアウトバウンドの両方のトラフィックが許可されていることを確認
・アウトバウンドACLで開いているのがエフェメラルポートのみであることを確認

イメージ図②
<img width="1192" alt="スクリーンショット 2020-07-06 17.33.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/a295671b-fd30-f1bb-80d8-ef94ef05f587.png">

#③ルートテーブルのチェック
インターネットゲートウェイがVPCにアタッチされていない。
1.VPCにアタッチしたインターネットゲートウェイのID(例、igw-xxxxxxxx)を書き留める。
2.VPCのルートテーブルでインターネットゲートウェイのルートを確認。Targetが、インターネットゲートウェイがVPCにアタッチしたID(例、igw-xxxxxxxx)に一致し、送信先が0.0.0.0/0 であるルートエントリを探す。
3.このルートがなければ、ターゲットがこのインターネットゲートウェイで、送信先が0.0.0.0/0 であるルートエントリを追加。

イメージ図③
<img width="960" alt="スクリーンショット 2020-07-06 17.51.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/5ecfd5f4-5250-2e10-26bb-28eb38d8cca6.png">


イメージ図④<img width="976" alt="スクリーンショット 2020-07-06 17.54.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/af04fb71-db40-2cf5-b66b-d3306ede2733.png">


#④パブリックIPアドレスのチェック
パブリックIPアドレスが付与されていない可能性がある。
パブリックIPアドレスがVPCインスタンスに割り当てられているか、または、ElasticIPアドレスがインスタンスのネットワークインターフェイスにアタッチされているかを確認。

イメージ図⑤
<img width="977" alt="スクリーンショット 2020-07-06 18.00.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449478/978eb196-fed3-0b0d-138f-dc064a806a07.png">

参考
https://aws.amazon.com/jp/premiumsupport/knowledge-center/vpc-connect-instance/
https://www.udemy.com/course/aws-associate/
【FolioLSP】Stripes CLI



##ガイド
https://github.com/folio-org/stripes-cli

- ユーザーガイド：https://github.com/folio-org/stripes-cli/blob/master/doc/user-guide.md
- コマンドリスト：https://github.com/folio-org/stripes-cli/blob/master/doc/commands.md
- 開発者ガイド：https://github.com/folio-org/stripes-cli/blob/master/doc/dev-guide.md
- バックエンドガイド：https://github.com/folio-org/stripes-cli/blob/master/doc/backend-guide.md
- トラブルシューティング：https://github.com/folio-org/stripes-cli/blob/master/doc/troubleshooting.md

##Stripes CLIとは
Stripes CLIはStripes UIモジュールの作成、開発、構築、テストを容易にするコマンドラインインターフェイスです。

##Stripes CLIの導入

npm-folioとnpm-foliociの両方のレジストリを利用できます。 どちらのレジストリを使用するかについては、folioレジストリの設定を参照してください。以下は、npm-folioからグローバルにCLIをインストールする方法です。

① `yarn config set @folio:registry https://repository.folio.org/repository/npm-folio/`

```
vagrant@vagrant:~$ yarn config set @folio:registry https://repository.folio.org/repository/npm-folio/
yarn config v1.22.4
success Set "@folio:registry" to "https://repository.folio.org/repository/npm-folio/".
Done in 0.11s.
```

② `yarn global add @folio/stripes-cli`


```
vagrant@vagrant:~$ yarn global add @folio/stripes-cli
yarn global v1.22.4
[1/4] Resolving packages...
[2/4] Fetching packages...
[3/4] Linking dependencies...
[4/4] Building fresh packages...
success Installed "@folio/stripes-cli@1.17.0" with binaries:
      - stripes
Done in 189.46s.

```

以下のエラーが出たら

```
-bash: stripes: command not found
```

このあたりを参考にする。
https://stackoverflow.com/questions/40317578/yarn-global-command-not-working

例：以下を~/.bash_profileに追記する。
`PATH="$PATH:$HOME/.config/yarn/global/node_modules/.bin"`
【FolioLSP】チュートリアル④ローカルでの開発

##フロントエンドの開発
Stripes CLIを活用する。
詳しくは以下を参照。
- https://github.com/folio-org/stripes-cli

##バックエンドの開発

ホストシステム上で稼働しているバックエンドモジュールサービスを、Vagrant VMで稼働しているOkapiシステムで利用できるようにすることができます。
※host-onlyのプライベートネットワークをVirtualBoxに設定し、VMのOkapiを再構成してX-Okapi-URLヘッダーとしてプライベートネットワークIPを利用できるようにする必要があります。

設定方法はこちら：「Running backend modules on your host system」（https://github.com/folio-org/folio-ansible/blob/master/doc/index.md#running-backend-modules-on-your-host-system）

##モジュール依存関係グラフ
特定のモジュールの依存関係を決定する方法です。

何もインストールされていない状態で新しいテナントを作成し、確認したいモジュールのインストールをシミュレートして、インストールが必要な他のモジュールを表示します。

```
#!/usr/bin/env bash

# install a fresh tenant and show dependency graph

MODULE=${1:-"mod-inventory"}

TENANT="depgraph"

OKAPIURL="http://localhost:9130"
CMD_CURL="curl"
CURL="$CMD_CURL -w\n -D - "
PATH_TMP="/tmp/folio-depgraph"

H_TENANT="-HX-Okapi-Tenant:$TENANT"
H_JSON="-HContent-type:application/json"

echo "Pulling updated ModuleDescriptors from registry ..."
$CURL $H_JSON -X POST \
  -d '{ "urls": [ "http://folio-registry.aws.indexdata.com" ] }' \
  $OKAPIURL/_/proxy/pull/modules

echo
echo "Initialise the tenant '$TENANT' ..."
cat >$PATH_TMP-tenant.json << END
{
  "id" : "$TENANT",
  "name" : "Dependency grapher"
}
END
${CMD_CURL} -s -S $H_JSON -X POST \
  -d @$PATH_TMP-tenant.json \
  $OKAPIURL/_/proxy/tenants

echo
echo "Enable Okapi internal module for tenant '$TENANT' ..."
${CMD_CURL} -s -S $H_JSON -X POST \
  -d '{"id":"okapi"}' \
  $OKAPIURL/_/proxy/tenants/$TENANT/modules

echo
echo "Get dependency graph for '$MODULE' ..."
cat >$PATH_TMP-enable.json << END
[{"id":"$MODULE","action":"enable"}]
END
${CMD_CURL} -s -S $H_JSON -X POST \
  -d @$PATH_TMP-enable.json \
  "$OKAPIURL/_/proxy/tenants/$TENANT/install?simulate=true"
echo

```

##参考

https://dev.folio.org/tutorials/folio-vm/04-local-development/
yoast seo をカスタマイズするちょっとした方法

wordpressサイトの構築において、SEO系のプラグインを使用する場合、
代表的なものとして、「Yoast SEO」「All in One SEO Pack」があげられるのではないでしょうか。

Yoast SEOを使用した場合に、「個別ページ」「投稿ページ」「アーカイブページ」など、meta設定やrobotsの設定を一括で指定するができます。
また、それそれの編集ページで個別に調整することもできます。

しかし、個別に調整したい投稿が、全投稿のうち10件あったとした場合（10件の調整内容は同じとする）、10件それぞれに管理画面から編集していてはめんどくさい。
調べたら、フィルターをかましたら、諸々PHPで上書きできるようでした。管理的にもこちらのほうがよさそうなのかも〜。
メモがてらに、いくつか書き留めておきます。

# メタタグ
### title
```php
add_filter( 'wpseo_title', 'custom_title' );
function custom_title($title) {
  //条件分岐
  if ( is_page('about') ) {
    return '会社概要';
  }
  return $title;
}
```

### description
```php
add_filter( 'wpseo_metadesc', 'custom_metadesc' );
function custom_metadesc($metadesc) {
  //条件分岐
  if ( is_page('about') ) {
    return '会社概要をご紹介いたします。';
  }
  return $metadesc;
}
```

### robots
```php
add_filter( 'wpseo_robots', 'custom_robots' );
function custom_robots($robots) {
  //条件分岐
  if ( is_single('test') ) {
    return 'noindex,nofollow';
  }
  return $robots;
}
```

# OGタグ
### og_site_name
```php
add_filter( 'wpseo_opengraph_site_name', 'custom_og_site_name' );
function custom_og_site_name($site_name) {
  //条件分岐
  if ( is_page('about') ) {
    return '企業サイト';
  }
  return $site_name;
}
```

### og_site_title
```php
add_filter( 'wpseo_opengraph_title', 'custom_og_title' );
function custom_og_title($title) {
  //条件分岐
  if ( is_page('about') ) {
    return '会社概要';
  }
  return $title;
}
```

### og_site_desc
```php
add_filter( 'wpseo_opengraph_desc', 'custom_og_desc' );
function custom_og_desc($desc) {
  //条件分岐
  if ( is_page('about') ) {
    return '会社概要をご紹介いたします。';
  }
  return $desc;
}
```

## 参照サイト
https://liginc.co.jp/web/wp/plug-in/135609/
[Ruby] yieldがあるのにblock引数がない

# こういう関数

```enumerable.rb
module Enumerable
  #省略
  def all?(*several_variants)
    yield to_enum.next; __unknown
  end
end
```

all?はこんな感じで使う

```sample.rb
%w[ant bear cat].all? { |word| word.length >= 3 } #=> true
```

引数に`&block`があるわけでもないのに、なんで渡せるのか？
それは**メソッド中にyieldがあればブロック引数は省略できるから**です。

ただ、メソッドの中を見ないとブロックを渡せるかわからなくなるので、省略するかは考える必要がありそうです。
CSVファイルにSQLできるツールが便利だった

この手のツールはいくつかあるようなのですが、今回「q」というのを使ってみました。

≫ [http://harelba.github.io/q/](http://harelba.github.io/q/)

内部的にSQLite3を使っているようで、サブクエリやJOINもできる本格的なSQLが使えます。
RDBのテーブルを適当にCSV出力したものを手元で加工するのに非常に便利でした。

何かと便利に使えそうなので、MacならHomebrewでサクッと入れておくと良いでしょう。

```
% brew install q
```

ですがbrewで入れただけだと、僕の環境では次のようなエラーが出てしまいました。

```
% q
Traceback (most recent call last):
  File "/usr/local/bin/q", line 49, in <module>
    from six.moves import configparser, range, filter
ImportError: No module named six.moves
```

Pythonのsixというモジュールが必要なようです。次のようにインストールしたら解消しました。

```
% pip install six
```

使ってみます。

オプションは`-H`で1行目がヘッダであることを明示。`-d','`でカンマ区切り(CSV)であることを明示します。

2つのCSVファイルをJOINして新しいCSVファイルに書き出すなんてこともできて便利！

```
% q -H -d',' "
SELECT l.created_at, u.full_name, l.url
FROM logs.csv l
INNER JOIN users.csv u ON u.id = l.user_id
ORDER BY l.created_at ASC
" > access_log.csv
```
RSpecでclassの参照をする(memo)


RSpecの勉強中
将来のためにドキュメントとして残しておく

間違いなどあればツッコミ入れてください！


ファイル階層

```
foo
      ├── foo.rb
      └── foo_spec.rb
```

fooのclass`User`を参照したい

```Ruby:foo.rb
class User
  def initialize(name:, age:)
    @name = name
    @age = age
  end
  def greet
    if @age <= 12
      "ぼくは#{@name}だよ。"
    else
      "僕は#{@name}です。"
    end
  end
end
```

`spec`ファイルに`require_relative`を追加しファイル名`foo`を添える


```Ruby:foo_spec.rb
require 'rails_helper'
require_relative 'foo' #classの参照

RSpec.describe User do
  describe '#greet' do
    let(:user){User.new(params)}
    let(:params){{ name: 'たろう', age: age}}
    context '12歳以下の場合' do
      let(:age){12}
      it 'ひらがなで答えること' do
        expect(user.greet).to eq 'ぼくはたろうだよ。'
      end
    end
    context '13歳以下の場合' do
      let(:age){13}
    it '漢字で答えること' do
      expect(user.greet).to eq '僕はたろうです。'
    end
  end
  end
end

```

出力結果


```
User
  #greet
    13歳以下の場合
      漢字で答えること
    12歳以下の場合
      ひらがなで答えること

Finished in 0.00295 seconds (files took 1.39 seconds to load)
2 examples, 0 failures

Randomized with seed 43154
```
HerokuのDB（MySQL）をローカルで確認する方法


HerokuにMySQL(ClearDB)にてアプリをデプロイしました。アプリをデプロイしたのでDBをローカルで確認しようとしたところPostgreSQLでのやり方の説明は多くあったものの、MySQLの説明はつくなかったので紹介します。
おそらくMySQLのコマンドをよく理解してる人はすぐできると思うのですが、自分はあまり理解してなかったので結構時間をとられてしまいした。

# HerokuにデプロイしたMySQLをローカルで確認する方法

・heroku configでDBの情報を確認

```
% heroku config
=== db Config Vars
CLEARDB_DATABASE_URL:     ------
DATABASE_URL:             ------
DB_HOSTNAME:              us-cdbr-east-02.cleardb.com
DB_NAME:                  heroku_aaaa
DB_PASSWORD:              aaaaaaaa
DB_PORT:                  ----
DB_USERNAME:              aaaaaaaaaaaaa
・・・
```

herokuの情報を元にmyqslコマンドを実行します。
`-pDB_PASSWORD`は`-p`の後にスペースを開け内容にしてください。

```
％ mysql -u DB_USERNAME -h DB_HOSTNAME DB_NAME -pDB_PASSWORD
```


```
mysql> 
```

このように出てきたら成功です
【初心者向け】【PHP】FizzBuzz問題



今回はphpでFizzBuzz問題を書きました。と言っても前回とほとんどおんなじようなコードです。




# FizzBuzz問題とは？
1から100まで順に数えて出力して行き、3で割り切れる数は「Fizz」5で割り切れる数は「Buzz」両方で割り切れる数は「FizzBuzz」と出力する、ようにプログラムを書く問題です。

これが書けるか書けないかでプログラマー志願者を仕分けられるようになったようです。実際今でも使われていますから押さえておいて損はないと思います。[FizzBuzz詳細](https://ja.wikipedia.org/wiki/Fizz_Buzz)


# 私が書いたコード


```php:sample.php
<?php
$i  = 0;
for($i = 1; $i < 100; $i++) {
    if($i % 15 === 0) {
        print "FizzBuzz!<br />";
    } else if ($i % 5 === 0) {
        print "Buzz<br />";
    } else if ($i % 3 === 0) {
        print "Fizz<br />";
    } else {
        print $i."<br />";
    }
}
?>
```

## 書く順番

前回同様、ifは条件が厳しいものから順番に書いていった方が良いです。今回の問題だと"Fizz"や"Buzz"を表示させるifを先に書いてしまうと3と5の倍数の数字がif文を通過するとき、3の倍数をFizzに置き換えるところで条件を満たしてしまうのでその先の処理は行わないからです。
今更Basic認証の設定手順

- CentOS Linux release 7.8.2003 
- Server version: Apache/2.4.6 (CentOS)

## パスワードファイル作成

### .htpasswd 作成

```bash
htpasswd -c ./.htpasswd [ユーザー名]
```

### 実行例

```bash
$ htpasswd ./.htpasswd nozaki
New password:
Re-type new password:
Adding password for user nozaki
```

## .htaccess設定

```
AuthType Basic
AuthName "[認証名]"
AuthUserFile ".htpasswdのファイルパス"
require valid-user
```
Laravelのマイグレーションで「Application In Production!」が表示されたときの対処法

# はじめに
本番環境でマイグレーションを実行したら、以下のメッセージが表示されて、マイグレーションが実行されなかった。

```
**************************************
*     Application In Production!     *
**************************************
```

# 環境
```
$ php artisan -V
Laravel Framework 5.8.29
```

# メッセージが表示された理由
productionでマイグレーションを実行する場合、以下のメソッドで環境のチェックが行われ、productionの場合はメッセージが表示されます、


```/vendor/laravel/framework/src/Illuminate/Console/ConfirmableTrait.php
<?php

namespace Illuminate\Console;

use Closure;

trait ConfirmableTrait
{
    /**
     * Confirm before proceeding with the action.
     *
     * This method only asks for confirmation in production.
     *
     * @param  string  $warning
     * @param  \Closure|bool|null  $callback
     * @return bool
     */
    public function confirmToProceed($warning = 'Application In Production!', $callback = null)
    {
        $callback = is_null($callback) ? $this->getDefaultConfirmCallback() : $callback;

        $shouldConfirm = $callback instanceof Closure ? call_user_func($callback) : $callback;

        if ($shouldConfirm) {
            if ($this->hasOption('force') && $this->option('force')) {
                return true;
            }

            $this->alert($warning);

            $confirmed = $this->confirm('Do you really wish to run this command?');

            if (! $confirmed) {
                $this->comment('Command Cancelled!');

                return false;
            }
        }

        return true;
    }

    /**
     * Get the default confirmation callback.
     *
     * @return \Closure
     */
    protected function getDefaultConfirmCallback()
    {
        return function () {
            return $this->getLaravel()->environment() === 'production';
        };
    }
}
```

# 対処法
--forceオプションをつけて、マイグレーションを実行すればOK

```
$ php artisan migrate --force
```

# 余談
今回、事象が発生したのは、AWS Lambdaにてカスタムランタイム（brefを使用）上でLaravelを動かしている環境でした。
そのため、単に--forceをつけるだけだと、コマンドエラーとなり、以下のようにダブルコーテーションで囲むことで無事にマイグレーションが実行できました。

```
$  AWS_PROFILE=【profile name】 vendor/bin/bref cli --region ap-northeast-1 【function name】 "migrate --force"
```
[Javascript] 多次元ポケモンデータから取得するメソッドを作って”this”を理解した話[this]

#目的

- クラスのメソッド内で、メソッドを呼び出したい時にうまく呼び出せない事象を解決する

##結論

- 今後、"this"を使いたい時は、具体的に何を指しているか確認すること。

#今回やること

多次元データに対して、クラス内でメソッドを使います。

ポケモンが格納されているデータは、こんな感じ。（1匹分）
これが245匹分ある。

```
(() => {
  window.allPokemon = [{
    "Number": "001",
    "Name": "Bulbasaur",
    "Generation": "Generation I",
    "About": "Bulbasaur can be seen napping in bright sunlight. There is a seed on its back. By soaking up the sun's rays, the seed grows progressively larger.",
    "Types": [
      "Grass",
      "Poison"
    ],
    "Resistant": [
      "Water",
      "Electric",
      "Grass",
      "Fighting",
      "Fairy"
    ],
    "Weaknesses": [
      "Fire",
      "Ice",
      "Flying",
      "Psychic"
    ],
    "Fast Attack(s)": [{
      "Name": "Tackle",
      "Type": "Normal",
      "Damage": 12
    },
    {
      "Name": "Vine Whip",
      "Type": "Grass",
      "Damage": 7
    }
    ],
    "Special Attack(s)": [{
      "Name": "Power Whip",
      "Type": "Grass",
      "Damage": 70
    },
    {
      "Name": "Seed Bomb",
      "Type": "Grass",
      "Damage": 40
    },
    {
      "Name": "Sludge Bomb",
      "Type": "Poison",
      "Damage": 55
    }
    ],
    "Weight": {
      "Minimum": "6.04kg",
      "Maximum": "7.76kg"
    },
    "Height": {
      "Minimum": "0.61m",
      "Maximum": "0.79m"
    },
    "Buddy Distance": "3km (Medium)",
    "Base Stamina": "90 stamina points.",
    "Base Attack": "118 attack points.",
    "Base Defense": "118 defense points.",
    "Base Flee Rate": "10% chance to flee.",
    "Next Evolution Requirements": {
      "Amount": 25,
      "Name": "Bulbasaur candies"
    },
    "Next evolution(s)": [{
      "Number": 2,
      "Name": "Ivysaur"
    },
    {
      "Number": 3,
      "Name": "Venusaur"
    }
    ],
    "MaxCP": 951,
    "MaxHP": 1071
  },
```


##実装（うまくいっていない）


```
(() => {
  window.pokemonager = {

    findNames: (array = allPokemon) => {
      return array.map(pokemon => pokemon.Name)
    },

    findByResistance: (attack) => {
      return allPokemon.filter((pokemon) => {
        return pokemon.Resistant.includes(attack)
      })
    },

    findNamesByResistance: (attack) => {
      const a = this.findByResistance(attack)
      const b = this.findNames(a)
      return b;
    },
```

###だいたいこうなる

試行錯誤の結果だいたいこうなる。

```
is not defined
```
もしくは

```
is not function 
```

##学び

**thisの親は？　
->アロー関数である**

つまり、thisは findNamesByResistance自体を呼んでいる!!
完　全　理　解　！
（オブジェクトを呼んでいるつもりだった）

##実装
````

(() => {
  window.pokemonager = {

    findNames: (array = allPokemon) => {
      return array.map(pokemon => pokemon.Name)
    },

    findByResistance: (attack) => {
      return allPokemon.filter((pokemon) => {
        return pokemon.Resistant.includes(attack)
      })
    },

    findNamesByResistance: function (attack) {
      const a = this.findByResistance(attack)
      const b = this.findNames(a)
      return b;
    },

```
VimでWorld Wide Web

こんにちわ
ゴリラです

普段Vimを使ってコーディングしていると、「あれ、あの関数名なんだっけ？」とか「引数何を受け取るんだっけ？」とかで思い出せないことが多々あると思います。
そういう時、大抵の人はブラウザを使うと思いますが、アプリを切り替えないといけないので効率が悪いなとずっと思っていました。

そこで、この度[w3m](https://ja.wikipedia.org/wiki/W3m)を導入してみました。ちょっとQOL(Quality Of Life)上がった感があるので紹介してきます。

## `w3m`とは
簡単に言うとテキストベースブラウザです。一応`sixel`対応できるので画像表示もできます。（ただレイアウト崩れるので実用的ではなかった）
テキストベースゆえ、とても軽快で`cookie`や`openssl`も使えるので`Twitter`などのサービスにログインもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/1e017600-c9bf-d1d0-3e2c-63920ae527d3.png)

がっつり色々と調査するなら普通にブラウザを使ったほうが良いですが、
冒頭で言ったような用途であれば`w3m`で充分です。

## Vimで`w3m`を使う
Vimでは`terminal`機能があるので、それを使えばVim上で`w3m`を使用できます。例えば次のコマンドで`google.com`を開けます。

```vim
:term ++close w3m google.com
```

ただ、これだけだとちょっと不便です。大体は何かしら検索することが多いので、もう少し便利にするため`WWW`コマンドを用意します。

```vim
function! s:www(word) abort
  execute('term ++close ++shell w3m google.com/search\?q="' . a:word . '"')
endfunction

command! -nargs=1 WWW call s:www(<f-args>)
```

上記の設定を`vimrc`に追加すれば`:WWW ゴリラ vim`って実行するとGoogleの検索結果画面が表示されます。
とても良き。

検索以外に、ぼくは普段Goを書いたりするので`pkg.go.dev`を簡単に開く関数も用意しました。

```vim
function! s:gg(package) abort
  execute('term ++close ++shell w3m pkg.go.dev/' . a:package)
endfunction

command! -nargs=1 GG call s:gg(<f-args>)
```

上記設定をすると`:GG path/filepath`次のように`pkg.go.dev/path/filepath`が開きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/8c6be7cf-4440-3ac4-77ce-44967c49d793.png)

## Vimで`w3m`のメリット
ズバリ、翻訳できることです。ゴリラ製[翻訳プラグイン](https://github.com/skanehira/translate.vim)を使って、`godoc`の英語ドキュメントを翻訳しながら読めます。
英語苦手なので、こうやって翻訳しながらじゃないと読めないです（ツライ）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/7bd5f475-ed04-e8ad-fab3-0d6291d9acbf.png)

## `w3m`のキーマップ設定
デフォルトのキーマップでしっくり来ないところがあったので、`~/.w3m/keymap`に次の設定をしてなるべく使用感をVimに近づけています。

```
keymap C-u PREV_PAGE
keymap C-d NEXT_PAGE
keymap C-h BACK
keymap C-l NEXT
keymap ] NEXT_TAB
keymap [ PREV_TAB
keymap C-w CLOSE_TAB
keymap b PREV_WORD
keymap H HISTORY
keymap ? HELP
keymap C-n NEXT_LINK
keymap C-p PREV_LINK
keymap C-q EXIT
keymap C-k GOTO
```

## さいごに
導入したばっかりなので、しばらく使ってみています。
みなさんもぜひ使ってみてください。
[Rails]ユーザー退会機能の実装


こんにちは、tt_tsutsumiです。
今回はユーザー退会機能について実装を行いたいと思います。
こちらの記事が何方かのお役に立てると嬉しいです。

ユーザー新規登録、編集の記事は折を見て記載したいと思いますので、
今回はユーザー退会機能と退会済みユーザーがログインを行えない様に実装致します。

##1. 会員状況の定義
ユーザーの会員状況をenum(boolean型)で設定をする。
boolean型は真偽値を保存する型で、2つの状況しか登録する事が出来ません。
今回はユーザーが **有効会員か退会済み会員か** の2択なのでこの型を使用します。
また **is_active** が **true(有効会員)** の場合ログインが出来る設定を行います。

※ **is_active** が **false(退会済み会員)** の場合はログインが行えません。

```ruby:user.rb
    enum is_active: {Available: true, Invalid: false}
    #有効会員はtrue、退会済み会員はfalse

    def active_for_authentication?
        super && (self.is_active === "Available")
    end
    #is_activeが有効の場合は有効会員(ログイン可能)

```

##2. routeの記載

```ruby:routes.rb
    resources :users do
        member do
            get "check"
            #ユーザーの会員状況を取得
            patch "withdrawl"
            #ユーザーの会員状況を更新
        end
    end
```

##3. アクションの作成
次にコントローラーにアクションの作成を行います。
※　今回は退会確認を行うページの作成も行ったのでアクションが２つとなります。

```ruby:users_controller

def check
    @user = User.find(params[:id])
    #ユーザーの情報を見つける
end

def withdrawl
    @user = User.find(current_user.id)
    #現在ログインしているユーザーを@userに格納
    @user.update(is_active: "Invalid")
    #updateで登録情報をInvalidに変更
    reset_session
    #sessionIDのresetを行う
    redirect_to root_path
    #指定されたrootへのpath
end

private

def user_params
    params.require(:user).permit(:active)
end
```

##4. リンク先の作成
リンク先の作成を行いユーザーを退会させます。
methodは削除ではなく更新になるのでpatchの記載となります。

```ruby:withdrawl.html.erb

<div class="withdrawl">
    <%= link_to "Withdrawal", withdrawl_user_path(@user.id), method: :patch %>
</div>

```

これでユーザー退会機能と退会済みユーザーがログインを行えない様に実装が行えました。
ご覧いただきありがとうございました !!
vim cheat sheet

# Replace All
`:%s/foo/bar/g`
# Replace backward slash '\' with forward slash '/'
`:%s/\\/\//g`

#copy all lines
`gg"*yG`

#select all
`ggVG`

#cut paste
Shift + V => X => P

#copy paste
Shift + V => Y => P

#delete
`d`

# go to end of line
`$`

#open 2files
`vi -o /path/to/file1 /path/to/file2`

# go to end of the line
`$`

# go to end of the line and insert
`A`

# delete one word
`dw`

# delete line(s)below current line
`:+,$d`

# delete next 2 lines
`:+,+2d`

# Switch Windows
 `CTRL-W <down>` 

## Recover From .swp file
`vim -r .swp`

# Intent Code
`gg=G`

# Go to line 10
`:10`

## delete everything from a line after the cusor
`v$hd`
VB.NET 並列処理 コピペ用 サンプルコード チートシート

このまま動作します。
コピぺ、編集して利用するためのコードの断片です。
自由に使って頂いて構いません。
#パターン1 - インデックス0から9までの並列処理
```vb
Imports System
Imports System.Threading.Tasks

' インデックス0から9までの並列処理。
Parallel.For(0, 10,
    Sub(i)
        Console.WriteLine(i.ToString())
    End Sub
)
' 全ての並列処理が完了したら、処理がこの先へ進む。
```
#パターン2 - リストの内容で並列処理
```vb
Imports System
Imports System.Threading.Tasks

' リストの内容で並列処理。
Dim l = New List(Of String) From {"a", "b", "c"}
Parallel.ForEach(l,
    Sub(s)
        Console.WriteLine(s)
    End Sub
)
' 全ての並列処理が完了したら、処理がこの先へ進む。
```
#パターン3 - 繰り返しを使わない並列処理
```vb
Imports System
Imports System.Threading.Tasks

' 繰り返しを使わない並列処理。
' ここでは4つの処理を並列化しているが、処理数は自由。
Parallel.Invoke(
    Sub()
         Console.WriteLine("a")
    End Sub,
    Sub()
         Console.WriteLine("b")
    End Sub,
    Sub()
         Console.WriteLine("c")
    End Sub,
    Sub()
         Console.WriteLine("d")
    End Sub
)

'全ての並列処理が完了したら、処理がこの先へ進む。
```
#パターン4 - 並列処理を立ち上げる
```vb
Imports System
Imports System.Threading.Tasks

' 並列処理を立ち上げる。
Task.Run(
    Sub()
        Console.WriteLine("a")
    End Sub
)
' 処理の終了を待たずに、処理がこの先へ進む。
```
#パターン5 - 並列処理を立ち上げて、処理の終了を待ち合わせる
```vb
Imports System
Imports System.Threading.Tasks

' 並列処理を立ち上げる。
Dim t = Task.Run(
    Sub()
        Console.WriteLine("a")
    End Sub
)

Console.WriteLine("b")

' 処理の終了を待ち合わせる所でこうする。
t.Wait()
```
#注意事項 - 並列処理内の例外は呼び出し元でキャッチされない
```vb
Imports System
Imports System.Threading.Tasks

Task.Run(
    Sub()
        ' 並列処理内で送出された例外は呼び出し元でキャッチされない。
        ' このように、並列処理内で対処すると良い。
        Try
            Console.WriteLine("a")

        Catch ex As Exception
            Console.WriteLine(ex.ToString)
        End Try
    End Sub
)

```
Node.js でAWS Lambdaを量産する為のサンプルソースをgithubに公開してみた

# AWS LambdaをNode.jsで量産アレコレ
## 概要
AWS LambdaをNode.jsで書こうと思ったときに、良く思うのが、、、

- AWS SDKがPromise前提で入れ子が深くなりがち
- 継承使って汎用共通処理とオーバーライド使いたいなぁ～

である。

コールドスタート対策などで、javaでの実装は圧倒的に不利ってことで、java屋がNode.jsでLambdaを書こうと思うと、~~きっと同じ事を思うに違いない。~~(偏見)

という事で、上記が出来る汎用ソースをgithubに公開してみました。

（参考投稿）
[Lambdaのコールドスタートを改めて整理する](https://qiita.com/ny7760/items/700ae917da2c5b5e3f8a)

## index.js　の処理構造
![indexのイメージ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660954/37a78f07-3911-41ee-1e6e-3c8c76016bb6.jpeg)
として、業務処理を全て外だししてシンプルにする事で、汎用的なindex.jsにする。

## 業務処理の処理構造
![業務ロジック階層.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660954/0dbc502c-a9da-0535-6342-73d19b81f7f0.jpeg)

業務処理の継承ツリーは3階層でサンプルは書いてあります。
大体、3階層作ってあれば、~~大抵の業務は汎化できる。~~(これまた偏見)

## githubの公開場所
[サンプルソースの github 公開場所](https://github.com/SyoAwsBlog/ShoLambdaSample)

に置いてあります。

![githubからのダウンロード.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660954/b95cb103-aa9e-5a6a-731f-ac3b9680f96e.jpeg)

イメージ図は、別のサンプルですが、クリックする場所は一緒です。
ダウンロードしたZIPファイルを解凍すると、Lambda登録用のZipファイルが出てきますので、実行する場合は、それをLambdaとして登録してください。

## 設定可能な環境変数

| 変数名       |変数値 |
|:-----------------|:------------------|
| LogLevel             | ログの出力レベルを(0～4）までの間で設定する  |
| autoFunctionRetry            | 	省略したらエラー時再実行はしない。0より大きい値（数字）を設定すると、その回数、再実行を行う  |

## 他サンプルソース
具体的な、

- API Gateway + Lambda + DynamoDB のサンプルソース
- DynamoDB Stream + Lambda + SNS のサンプルソース

などは、[ブログ](https://awsblog.physalisgp02.com/2020/07/02/dynamodb-stream-lambda-snssimple-notification-service-%e3%81%ae%e3%82%b5%e3%83%b3%e3%83%97%e3%83%ab%e3%82%bd%e3%83%bc%e3%82%b9/)にて公開中です。
クラスメソッドとスタティックメソッドのいろいろ

#はじめに
この記事では「クラスメソッド」とは何かについて書いていきます。
前回までの記事
↓
↓
↓
[pythonのプロパティのあれこれ](https://qiita.com/heku_777/items/8a59d576d360b7568c3a)

#クラスメソッドとは
簡単に一言で言えば、「クラス変数のようにクラスから直接使用できるメソッド」のことです。
(メソッドとはクラス内の関数のことです)

```python
@classmethod
def メソッド名(cls, 引数１, 引数２, ...): 
```
これがクラスメソッドの形です。今まで見てきた関数とは違う部分がいくつかあるので、見分けがつきやすいと思います。
①インスタンス(実体)が存在しないので、自分自身を表す'self'は用意されません。
②'self'の代わりに'cls'という引数が用意され、クラスメソッドが保管されているクラスのオブジェクトが代入される。

クラスメソッドを呼び出す際は、クラスから直接呼び出すことが可能です。

```python
#クラスメソッドの呼び出し
クラス名.クラスメソッド名()

#通常のメソッドの場合
hello = クラス名   #インスタンス作成
hello.メソッド名    #メソッドの呼び出し
```
呼び出しの部分も違うので、使う際には注意してください。

#クラス変数
先ほどクラスメソッドのことを、「クラス変数のようにクラスから直接使用できるメソッド」と言いました。
しかしそもそもクラス変数が何かわからないと、何のことかさっぱりだと思います
クラス変数とは下のコードの「message」の部分です。

```python
class Lesson:
    message = 'OK'

    def print(self):
        print(Lesson.message)

le = Lesson()            #インスタンス作成
le.print()               #printメソッド呼び出し
Lesson.message = 'Welcome!'    #'message'変数の中身を'Welcome!'に変更
le.print()                     #再び'printメソッド'呼び出し
print(Lesson.message)          #クラス変数messsageも呼び出し
```
普通の変数とパッと見変わらないので、そんなに難しくないと思います。

一番最後をみてもらえればわかるように、インスタンスを作成しないでも、クラスから直接呼び出すことができます。
メソッド(defがついているもの)と違い、インスタンスではなくクラスそのものに値を保管しているからです。

そしてクラス変数とメソッドを合わせたものがクラスメソッドです。
クラスから直接呼び出せて、変更も簡単にできるというものです。

#クラスメソッドの活用例

```python
class MyObj:
  message = 'OK'
  
  @classmethod
  def print(cls):
    print(cls.message)
    
MyObj.print()   #OK
MyObj.message = 'Welcome!'
MyObj.print()   #Welcome!
print(MyObj.message)  #Welcome!

#通常のメソッドの場合
#mo = MyObj()
#mo.print()
```
インスタンスを作成せずに、クラスから直接呼び出せていることが確認できると思います。
値の変更も簡単にできるので通常のメソッドとは違うことがわかります。

#インスタンスを作成
では、通常のメソッドとクラスメソッドを用意し、インスタンスを作成したときにどのような動きをするのか確認していきましょう。

```python
class A():
  count = 0
  def __init__(self):
    A.count += 1      #インスタンスが作成されるたびに'count'が１足される
  def exclaim(self):
    print('I am an A!')
  @classmethod
  def kids(cls):
    print('A has', cls.count, 'title objects.')   #何回カウントされたかを表示
    
a = A()   #インスタンスを作成
b = A()   #インスタンスを作成
c = A()   #インスタンスを作成
A.kids()  #クラスメソッドの呼び出し  'A has 3 title objects.'
```
これはインスタンスが作成されるたびに'count'が１足されていくものです。

'a','b','c'で３回インスタンスを作成した後にクラスメソッドを呼び出して、何回カウントされたのかを表示しています。
3回インスタンスが作成されているので'count'が'３'足されているのが確認できます。
クラスメソッドを呼び出した時は、インスタンスが作成されないので足されていません。

#クラスメソッドとメソッドや関数との違いは？
ここでそれぞれの違いをまとめていきたいと思います。

```python
#クラスメソッド
＠classmethod
def メソッド名(cls, 引数１, 引数２, ...): 
```

```python
#メソッド
def メソッド名(self, 引数１, 引数２, ...): 
```

```python
#関数
def 関数名():
```
このように並べてみると違いがよくわかると思います。
①クラスメソッドとメソッドの違い
->メソッドはインスタンスを作成しないと呼び出せないですが、クラスメソッドはクラスから直接呼び出すことができます。

②クラスメソッドと関数の違い
-> 第一引数に'cls'というクラス自体を取得することができます。また、クラスの中にあるので、クラスをインポートすれば使えるという点も違います。


#スタティックメソッド
ここからはスタティックメソッドについて説明していきます。
スタティックメソッドとはクラスメソッドとにていますが、違いは引数を指定する必要がない点です
実際に見ていきましょう。

```python
@staticmethod
def メソッド名():
     print("これはスタティックメソッドです。")

#呼び出し
クラス名.メソッド名()
```
クラスメソッドの時は第一引数に'cls'というものがありましたが、スタティックメソッドにはありません。
メソッドとほとんど同じと思ってもらうとわかりやすいです。
あまり使われないですが、クラスメソッド同様クラスから直接呼び出し￥すことができるのが特徴です。

#終わりに
今回の記事では「クラスメソッド」と「スタティックメソッド」について書きました。
記事はこれからもアップデートしていく予定です。
前回までの記事
↓
↓
↓
[pythonのプロパティのあれこれ](https://qiita.com/heku_777/items/8a59d576d360b7568c3a)
情報共有のポイントとオープンデータについて

「情報共有」というのは見聞や知識、ノウハウを、仲間に伝達し共有することです。情報共有といえば、最初思いついたのは社内の情報共有でしょう。確かに、情報共有すれば、業務の効率化やトラブルの早期発見など組織としての成果に繋がります。

それでは、社内でうまく情報共有するには、何が必要なのでしょうか？ここでは３つのポイントを説明します。

#情報共有のポイント

##ポイント1：情報共有の目的を明確する

まずは情報共有の目的を明確する必要があります。何のためにその情報を共有なのか？というのを社内で統一しないと、何の意味もありません。


##ポイント2：情報共有ツールを活用する

情報共有を効率化するために、適当なツールを導入し、活用することがおすすめします。オンラインで共同作業といえば、多くの会社は　が「Googleドライブ」を利用しています。Googleドライブでは、テキストや表といったデータをクラウド上に保存し、共同で閲覧・編集できます。
もちろん、Slack、esaなどさまざまな強みや個性を備えたツールがたくさんリリースされています。より効率的に情報共有を行いたいという場合は、こういったツールを活用することも検討してみると良いでしょう。


##ポイント3：管理者と権限を設定する

共有ファイルはどんどん増えていた場合、定期的にチェックして、不要になったファイルや移動すべきファイルを整理する必要があります。ですから、ファイルの整理を担当する「管理者」を決めるのは重要です。
また、共有ファイルには誰でもアクセスできるため、うっかり上書きしてしまったり、削除してしまったりなどのトラブルがつきもの。トラブルを防ぐため、「アクセス権限」を設定するのも重要です。

以上は社内の情報共有のポイントです。

その一方、もし社外または世界中の情報を共有、集めるのはどうすればいいでしょうか？

#オープンデータ

実は日本政府では、公共データを営利目的、非営利目的を問わず「二次利用可能なルール」の下で、「無償」で公開する「[オープンデータ](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%BC%E3%83%97%E3%83%B3%E3%83%87%E3%83%BC%E3%82%BF)」の取組を推進しています。

オープンデータではよく、地図、ゲノム、コネクトーム、化合物、数学や自然科学の数式、医療のデータや実践、バイオサイエンスや生物多様性などのテキストでない素材に焦点が当てられます。

下記の記事では、政府機関、医療・健康、 金融・経済、ビジネス・企業、ジャーナリズム・メディア、不動産・観光、文化・教育などに関するオープンデータソースを70選まとめました。

[**2020年に知っておくべきオープンデータソース70選**](https://www.octoparse.jp/blog/70-amazing-free-data-sources-you-should-know/)


もし、Web上から情報やデータを取得したい場合、Pythonや[スクレイピングツール](https://www.octoparse.jp/blog/top-30-free-web-scraping-software/)などを利用して抽出する必要があります。[Octoparse](https://www.octoparse.jp/)は視覚的に分かりやすくデータを抽出できるWebスクレイピングツールです。Webページ自動認識の機能が備え、WebサイトのURLを入力すると、データを収集ことが可能です。

それに、データ抽出をよりやすくするために、OctoparseはAmazon、楽天市場、Twitterなど数多くのすぐに使える[Webスクレイピングテンプレート](https://service.octoparse.com/ja-jp/web-scraping-template)を提供しています。パラメータ（URL、検索キーワードなど）を入力するだけで、データが抽出されてきます。クラウド型プラットフォームも提供するので、スケジュール設定が可能で、リアルタイムデータを自動抽出し、Webサイトの更新情報をいつでも入手できます。

取得したデータはExcel、HTML、CSVのような構造化フォーマットで、またはご指定のデータベースに保存されます。


#まとめ
社内情報でもオーペンデータでも、どのように利用すれば一番効果が出るのかが大事です。情報やデータを活用してビジネス戦略を立てることや、新たなビジネス価値の創出などが求められています。
SQLの基本的な文法まとめ②


SQLの基本文法のおさらいをしたのでまとめました。

　<br/>

# データの検索

### テーブルの指定

```
FROM テーブル名
```

### カラムの指定

```
SELECT カラム名
```
### 使い方

```
ex)
SELECT * FROM users;
```

### ワイルドカード
```
*　のこと
上記では「すべてのカラム」を取得している
```

### 取得するレコードの制限
```
WHERE 条件

ex)
SELECT * FROM users WHERE name = "白石";
```

### 条件に使用できる論理演算子

- AND
- OR
- NOT

### 1つのカラム内での範囲検索
```
WHERE カラム名 BETWEEN 下限 AND 上限

ex)
SELECT * FROM users WHERE age BETWEEN 21 AND 24;
-- ageが20以上かつ25以下
```

### 1つのカラム内でのリスト検索
```
WHERE カラム名 IN (値1, 値2, ……)

ex)
SELECT * FROM users WHERE prefecture IN ("岐阜", "愛知");
```

# データの検索と形成

### データの結合
```
# CONCAT関数
CONCAT(文字列1, 文字列2, ……)

ex)
SELECT CONCAT(family_name, first_name) FROM users;
```

### 検索結果のカラム名の変更
```
# AS
SELECT 取得するデータ AS 別名

ex)
SELECT CONCAT(family_name, first_name) AS "名前" FROM users;
```

:memo: `AS`は省略ができる。

### 重複するデータを除外
```
SELECT DISTINCT カラム名

ex)
SELECT DISTINCT user_id FROM units WHERE date = "2020-07-06";
```

### レコードのグループ化
```
GROUP BY カラム名

ex)
SELECT user_id FROM units WHERE date = "2020-07-06" GROUP BY user_id;
```
:pencil: DISTINCT　と　GROUP BYの例文の取得データは同じ（見た結果）
`GROUP BYは集計した結果を取得する`ことができる。

### レコードの数を取得
```
SELECT COUNT(カラム名)

ex)
SELECT user_id, COUNT(*) "コマ数" FROM units WHERE date = "2015-07-01" GROUP BY user_id;
```

### 集計関数

- AVG　平均
- MAX　最大値
- MIN　最小値


### データの結合
```
FROM テーブル名1 JOIN テーブル名2 ON テーブル名1.カラム名1 = テーブル名2.カラム名2

ex)
SELECT user_id, COUNT(*) "コマ数", FROM units s JOIN users u ON s.user_id = u.id WHERE date = "2020-07-06" GROUP BY user_id;
```

### サブクエリ
SQLの中に入れ子になってSQLがはいっていること。

```
ex)
SELECT *
FROM users WHERE id NOT IN ( SELECT DISTINCT user_id FROM shifts WHERE date = "2015-07-01");
```

<br/>
どんどん文が複雑になっていきますね。。
でも読み解くことはできるので慣れかな〜と思っています♫

お読みいただき、ありがとうございました🌸
<br/>

[SQLの基本的な文法まとめ①](https://qiita.com/harurun_0025/items/56242fc40e210ea0b838)

<br/>
firebaseとfunctionsでstorageの画像ファイルを削除する

# 画像ファイルのフォルダ以下一括削除

1. usersコレクションのドキュメントの削除をトリガーに発火
2. storageの構成を`users/{ドキュメントID}/{画像ファイル名}`にしておく
3. 削除されたドキュメントID以下すべてが削除される

backetの`deleteFiles`を知りたければ下記を参考にする
https://googleapis.dev/nodejs/storage/latest/#deleteFiles

```ts

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
const tokyoRegion = 'asia-northeast1'

// 環境変数の取得
const firebaseConfig: string|any = process.env.FIREBASE_CONFIG
const firebaseConfigObj: object|any = JSON.parse(firebaseConfig)
const bucket = admin.storage().bucket(firebaseConfigObj.storageBucket)

module.exports = functions
  .region(tokyoRegion)
  .firestore.document('users/{userDocId}')
  .onDelete((snap, context) => {
    const { userDocId } = context.params

    return bucket.deleteFiles({
      prefix: `users/${userDocId}`
    })
  })

```

# 特定の画像ファイルを削除

こちらのコードは動作確認していません。
要点は
1. 削除したいimagePathを指定
2. bucketの設定（複数個バケットがある場合）
3. `bucket.file({filePath}).delete()`で削除

```ts

import * as functions from 'firebase-functions'
import * as admin from 'firebase-admin'
const tokyoRegion = 'asia-northeast1'

// 環境変数の取得
const firebaseConfig: string|any = process.env.FIREBASE_CONFIG
const firebaseConfigObj: object|any = JSON.parse(firebaseConfig)
const bucket = admin.storage().bucket(firebaseConfigObj.storageBucket)

module.exports = functions
  .region(tokyoRegion)
  .firestore.document('users/{userDocId}')
  .onDelete((snap, context) => {
    const { userDocId } = context.params
    const data = snap.after.data()

    // 何かしらで特定の削除する画像ファイルを指定
    const imagePath = data.imagePath

    return bucket.file(imagePath).delete()
  })

```
Deno: Starttls でメールの送信

こちらと同じことを Deno で行いました。
[Python3: Starttls でメールの送信](https://qiita.com/ekzemplaro/items/c248b52a6f36947af080)
hi-ho.ne.jp で試しました。

## プログラム

```ts:hi-ho.ts
// ---------------------------------------------------------------
//
//	hi-ho.ts
//
//					Jul/06/2020
//
// ---------------------------------------------------------------
import { SmtpClient } from "https://deno.land/x/smtp/mod.ts"
import { config } from "https://deno.land/x/dotenv/mod.ts"

console.error ("*** 開始 ***")

const config_env:any = config()


const client = new SmtpClient()

const config_mail = {
  hostname: config_env.SERVER,
  port: parseInt(config_env.PORT,10),
  username: config_env.USR,
  password: config_env.PASSWORD,
}

await client.connect(config_mail)

var str_out = "Mail Content<p />\n"
str_out += "<blockquote>\n"
str_out += "PM 16:07<p />\n"
str_out += "</blockquote>\n"
str_out += "こんにちは<p />\n"

await client.send({
  from: config_env.FROM,
  to: config_env.TO,
  subject: "Hello from Hi-ho Jul/06/2020 PM 16:07",
  content: str_out,
})

await client.close();

console.error ("*** 終了 ***")
// ---------------------------------------------------------------
```

```text:env
SERVER = 'hi-ho.mose-mail.jp'
PORT = 587
USR = '****@hi-ho.ne.jp'
PASSWORD = '****'
FROM = '****@hi-ho.ne.jp'
TO = 'sample@example.com'
```

## 実行結果

```text
$ deno run --allow-net --allow-read hi-ho.ts
*** 開始 ***
*** 終了 ***
```

## 確認したバージョン

```text
$ deno --version
deno 1.39.2 (release, x86_64-unknown-linux-gnu)
v8 12.0.267.8
typescript 5.3.3
```
おじさんの業務を自動化する②

# 自動化作業は続く
前回報告したおじさんが行っている「添付ファイルを保存する作業」の自動化ですが、社内の評判は上々でした。というのもおじさんがこの作業を担当していた時、作業をやり忘れてしまうことがよくあったんですね。人間は忘れる、ロボットは忘れずにかならずやる...、そりゃそうだよね、という結果になり、ロボット君は社内に無事に受け入れてもらうことができました。
そしてロボット君の担当する作業が増やすことになり、わたしに新しいロボットの作成のタスクが。

## 自動化する前の業務手順
以下の業務手順を自動化します。

- お客さんからメーリングリストあてに送られてきたメールを開く
- メールを別のメーリングリストに転送する

うーん、そもそもメールを送ってくる人に宛先を変更してください、とお願いすればいいのでは？という話ですが、そこは何か大人の事情があってできない相談になっているんだろうなと忖度して聞けず。

## JobAutoでやりたいこと
JobAutoでやりたいことは以下の3つ

### お客さんから送られてきたメールを探す
前回作成したロボットと同じ。送信元のメールアドレスをもらいました。

### お客さんから送られてきたメールを開く
前回作成したロボットと同じ。メールを開きます。

### 転送する
メールを別のメーリングリストへ転送します。

## いざ作成

### ブラウザかアプリか
前回作成したロボットはアプリでした。RPAはアプリ操作が安定しないという情報をネット界隈で見ていたので正直不安でしたが、思いのほか安定して運用できていました。なので、今回もアプリで。

### 前回作成したロボットをコピーする
今回作成するロボットの手順は、前回作成したロボットの手順とほぼ同じ。違うのは今回はメールを転送する、前回は添付ファイルを保存する、だけ。なので、前回作成したロボットをコピーし、添付ファイルを保存する手順を削除したところからロボットの作成を行います。

## 出来上がったもの
出来上がったものが以下。
前回のロボットを作成したときに考えた人間の手順をどうやったらロボットが行う手順に置き換えられるか、ということが今回作成したロボットで使えました。だからその分ロボットの作成にかかった時間は短いです。

![mailforword.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/660351/fc188bc5-8eab-f1e5-000e-ec7b344def8e.png)

## 作成後の感想
前回作成したロボットの内容とほぼ同じだったので、前回のロボットの大部分を使いまわせたこと、また人間の手順をロボットだとどうやってやるかを考えることをほぼしなくていい、という2つの点があったのでものすごい短時間でロボットを作成することができました。
どんな業務手順をロボットで自動化したのか、ということをロボットを作成するたびに整理して書き留めていけば、新しくロボットを作成するときに意外と役に立つかもしれません（今回は役に立った）。
Google CloudのAI Platform Notebooksで楽々コンペ環境の構築

kaggleやSIGNATEのようなデータ分析コンペでは時に大容量データを扱うことがあるので、ラップトップPCではメモリが足りなくなることがあります。そういう場合はつよつよPCを購入するかGCPやAWSのようなクラウド環境を利用するのですが、後者はプログラミング初心者には難しい面があります。Google CloudのAI Platform Notebooksを使うと簡単にコンペの分析環境を作れるため紹介したいと思います。

# AI Platform Notebookのインスタンスを作成する
1. Google Cloud Platformで新しいプロジェクトを作成する。(typoでpropjectになってしまいました)![プロジェクト作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/e5d2acdd-fe3b-4e80-309d-8f6748ab8a05.png)
2. ナビゲーションメニュー > 人工知能 > AI Platform > ノートブック を選択する。 ![ノートブック選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/d6dbdaea-d5a8-72e6-faee-04623e3fa939.png)
3. APIを有効にしていない場合は有効にする。
4. 新しいインスタンスから好きな環境を選ぶ。(今回はCustomize instanceを選択します)![インスタンス作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/959fc48a-f425-3992-e7b3-171d34f90b12.png)
5. 環境を設定する。(今回はコンペに必要なライブラリが一通りインストールされているKaggle Pythonを選択します)![インスタンス詳細](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/fc0fa49c-7763-0b24-37a2-3feee8209d1a.png)
6. 保存してしばらくするとインスタンスが作成されるので、JUPYTER LABを開くとJUPYTER LABが開ける。![おしまい](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/ed4f17c7-ac50-8f9e-e8e8-b9aa142814e7.png)

# スワップ領域を設定する
pandasで集約操作を行うときや、LightGBMで訓練前にbinを良い感じに設定する時等、瞬間的にメモリが必要になる場合があります。普段はそんなにメモリを使わないのに、ピークの時だけメモリが必要だからという理由でメモリの大きなインスタンスを立てたくはないですよね。そういう場合はスワップ領域を設定すると解決できる場合があります。

1. ノートブックインスタンス一覧から設定したいインスタンスの名前をクリックする。
2. リモートアクセス > SSH を押下する。
3. 次のコマンドを入力する。(今回は32GiBのスワップ領域を設定しています)

```
sudo dd if=/dev/zero of=/swapfile bs=1M count=32768
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
```
![SSHでの設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/40f4cd4e-25b2-30c2-1e75-88ce10be979d.png)

4. しばらく待つとスワップ領域が作成されるので、topコマンドでスワップ領域ができているか確認する。
![topコマンドでの確認](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/0f05cbbb-3c0b-d28b-610e-71364fe2f300.png)

# Google Cloud Storageからデータを転送する。
JUPYTER LABから直接データをアップロードすることもできますが、大容量のデータを複数インスタンスにアップロードしたいときはGoogle Cloud Storageを中継すると便利です。

1. ノートブックインスタンス一覧からインスタンスの名前をクリックし、サービスアカウント名をメモしておく。
![サービスアカウント名取得](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/b9087a99-f999-32d8-5ae5-a64fd0a8a66f.png)
2. ナビゲーションメニュー > ストレージ > Storage > ブラウザ を選択する。![メニューからストレージを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/2586e454-dc07-bd10-2db6-e335552e8d1d.png)
3. バケットを作成する。
4. ナビゲーションに従ってストレージの設定を行う。(よくわかっていませんがアクセス制御を均一にしています)
5. バケットが作成出来たら、権限のタブに移動し、先ほどメモしたサービスアカウントに権限を付与する。
![権限付与](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/998e2325-e7e7-b4a7-105e-4de7c1739c37.png)
6. バケットに転送したいファイルをアップロードする。(フォルダを作成してまとめておくと便利です)
7. JUPYTER LABを開きterminalを開いて以下のコマンドで転送を行う。(-rは複数ファイルを送るときのプロパティです)

```
gsutil cp -r [転送したいディレクトリ] [転送先のディレクトリ]
```

![スクリーンショット (272).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237496/85a44c22-f966-77a1-dc9d-a3338852b893.png)

# おわりに
コンペに参加してみたいけど高いPCを買うのはちょっと……という人はAI Platformを利用すると手軽にコンペに参加できます。
[最初の300$は無料](https://cloud.google.com/free?hl=ja)なのでぜひ使ってみてください。
laravel queueではまった。

laravelの非同期処理を実現するためqueue（jobテーブル）機能にて実装。
supervisorにて`php artisan queue:work`を定期実行。

しばらく運用していたが、failed_jobsテーブルにログが出るように。

```
ErrorException: include(/var/www/html/vendor/composer/../egulias/email-validator/EmailValidator/EmailValidator.php): failed to open stream: No such file or directory in /var/www/html/vendor/composer/ClassLoader.php:444
```

あれこれ調べても分らないのでcomposerのクリアや
`composer dump-autoload`してもダメだったが
supervisorのデーモンを再起動で直った。

よくわからないけど
supervisorの子プロセスはphpのclassマップのリロードしないのかもしれない。
AtCoderBeginnerContest173復習＆まとめ（後半）

# AtCoder ABC173
2020-07-05(日)に行われたAtCoderBeginnerContest173の問題をA問題から順に考察も踏まえてまとめたものとなります．
後半ではDEの問題を扱います．[前半はこちら](https://qiita.com/takaito0423/items/6015652a15f7491fa9ea)．
問題は引用して記載していますが，詳しくはコンテストページの方で確認してください．
[コンテストページはこちら](https://atcoder.jp/contests/abc173)
[公式解説PDF](https://img.atcoder.jp/abc173/editorial.pdf)

## D問題　Chat in a Circle
> 問題文
> あなたはオンラインゲーム「ATChat」のチュートリアルを終え、その場に居合わせたプレイヤー$N$人で早速とある場所を訪ねることにしました。この$N$人には$1$から$N$の番号が振られており、人$i(1 \leq i \leq N)$のフレンドリーさは$A_i$です。
> 訪ねる際、$N$人は好きな順番で$1$人ずつ到着します。あなたたちは迷子にならないために、既に到着した人たちで環状に並び、新たに到着した人は好きな位置に割り込んで加わるというルールを決めました。
> 最初に到着した人以外の各人は、割り込んだ位置から到着した時点で「時計回りで最も近い人」と「反時計回りで最も近い人」のフレンドリーさのうち小さい方に等しい 心地よさ を感じます。最初に到着した人の心地よさは$0$です。
> $N$人が到着する順番や割り込む位置を適切に決めたとき、$N$人の心地よさの合計の最大値はいくらになるでしょう？

正直，ちゃんと考えれば良かったなと思いました．
何となく問題見て難しい気がしてしまったのと，差をつけるためにE問題を解くために飛ばしてしまいました．

```python:abc173d.py
n = int(input())
a_list = list(map(int, input().split()))
a_list.sort(reverse=True)
ans = 0
for i in range(0, n - 1):
    ans += a_list[(i + 1) // 2]
print(ans)
```

## E問題　Multiplication 4
> 問題文
> $N$個の整数$A_1,…,A_N$が与えられます。
> このなかからちょうど$K$個の要素を選ぶとき、選んだ要素の積としてありえる最大値を求めてください。
> そして、答えを$(10^9+7)$で割った余りを$0$以上$10^9+6$以下の整数として出力してください。

正の数と負の数と0の数に分けて，問題を考えていましたが，$K=N$の結果が負になるときと正のときとをなぜか必死に場合分け書いてたら，タイムオーバーでした．
よくよく考えれば，全部使うときは，貪欲に計算すれば，済む話でしたね(反省)
ただ，勉強のために提出されたコード見てみると，

```
4 3
-1 -2 3 4
```

のような入力例に対応できていないものが"AC"通っていて何だかなーと思いました．
こういった場合の処理をどうしないといけないかなど，いろいろ考えている人が結局時間が足りず通せず，入力に対してあまり深く考えず，限定された，テストにある入力を運よく通って得点できている人がいるような場合，後からrateの調整とかしてほしいところですが，無料のコンテストにあまり多く求めてもしょうがないですよね（汗）
現在は，after_contest_01.txtがチェックに追加されていて，そういったコードは"WA"になります．

```python:abc173e.py
n, k = map(int, input().split())
a_list = list(map(int, input().split()))
mod = 10**9+7
a_list.sort()
ans = 1
if k % 2 == 1 and a_list[-1] < 0:
    for i in range(k):
        ans *= a_list[n - 1 - i]
        ans %= mod
else:
    l = 0
    r = -1
    mlt1 = a_list[0] * a_list[1]
    mlt2 = a_list[-2] * a_list[-1]
    count = 0
    while True:
        if count == k:
            break
        elif count == k - 1:
            ans *= a_list[r] % mod
            ans %= mod
            break
        if mlt1 >= mlt2:
            ans *= mlt1 % mod
            l += 2
            count += 2
            if l <= n - 2:
                mlt1 = a_list[l + 1] * a_list[l]
        else:
            ans *= a_list[r] % mod
            r -= 1
            count += 1
            if r >= - n + 1:
                mlt2 = a_list[r - 1] * a_list[r]
        ans %= mod
print(ans)
```

後半も最後まで読んでいただきありがとうございました．
AtCoderBeginnerContest173復習＆まとめ（前半）

# AtCoder ABC173
2020-07-05(日)に行われたAtCoderBeginnerContest173の問題をA問題から順に考察も踏まえてまとめたものとなります．
前半ではABCまでの問題を扱います．
問題は引用して記載していますが，詳しくはコンテストページの方で確認してください．
[コンテストページはこちら](https://atcoder.jp/contests/abc173)
[公式解説PDF](https://img.atcoder.jp/abc173/editorial.pdf)

## A問題　Payment
> 問題文
> お店で$N$円の商品を買います。
> $1000$円札のみを使って支払いを行う時、お釣りはいくらになりますか？
> ただし、必要最小限の枚数の$1000$円札で支払いを行うものとします。

$N$円の下三桁を使うことでお釣りの計算ができると思ったので，$N$を$1000$で割った余りを計算しました．
余りを$1000$から引き算すれば出したい出力を得ることができますが，$1000 × x$円の場合，本来お釣りが$0$円ですが余りが$0$となるため出力が"1000"になってしまうので，自分はif文で条件分岐しました．
考察の解法では，条件分岐しないで計算する方法が書いてあってなるほどなと思いました．

```python:abc173a.py
n = int(input())
k = n % 1000
if k == 0:
    print(0)
else:
    print(1000 - k)
```

## B問題　Judge Status Summary
> 問題文
> 高橋君は、プログラミングコンテスト AXC002 に参加しており、問題 A にコードを提出しました。
> この問題には$N$個のテストケースがあります。
> 各テストケース$i(1 \leq i \leq N)$について、ジャッジ結果を表す文字列$S_i$が与えられるので、ジャッジ結果が"AC", "WA", "TLE", "RE"であったものの個数をそれぞれ求めてください。
> 出力形式は、出力欄を参照してください。

愚直に入力をdictに入れていきました．

```python:abc173b.py
n = int(input())
key_dict = {"AC": 0, "WA": 0, "TLE": 0, "RE": 0}
for i in range(n):
    key = input()
    key_dict[key] += 1
print("AC x " + str(key_dict["AC"]))
print("WA x " + str(key_dict["WA"]))
print("TLE x " + str(key_dict["TLE"]))
print("RE x " + str(key_dict["RE"]))
```

公式の解説のpythonのコードみたいに書けるようになりたいです．

```python:abc173b.py
N = int(input())
s = [input() for i in range(N)]
for v in ['AC', 'WA', 'TLE', 'RE']:
    print('{0} x {1}'.format(v, s.count(v)))
```

## C問題　H and V
> 問題文
> $H$行$W$列に並ぶマスからなるマス目があります。上から$i$行目、左から$j$列目$(1 \leq i \leq H,1 \leq j \leq W)$のマスの色は文字$c_{i,j}$として与えられ、$c_{i,j}$が"."のとき白、"#"のとき黒です。
> 次の操作を行うことを考えます。
>　・行を何行か選び($0$行でもよい)、列を何列か選ぶ($0$列でもよい)。そして、選んだ行に含まれるマスと、選んだ列に含まれるマスをすべて赤く塗る。
> 正の整数$K$が与えられます。操作後に黒いマスがちょうど$K$個残るような行と列の選び方は何通りでしょうか。ここで、二つの選び方は、一方においてのみ選ばれる行または列が存在するときに異なるとみなされます。

全探索するしかと思い，再帰関数使って解きましたが，実装に時間がかかってしまいました．

```python:abc173c.py
import numpy as np
def funk(matrix, n, k, no_list, h, w):
    if n == 0:
        mask = np.ones((h, w))
        for i in range(h):
            if no_list[i] == 1:
                mask[i,] = 0
        for j in range(w):
            if no_list[h+j] == 1:
                mask[:,j] = 0
        if np.sum(matrix * mask) == k:
            return 1
        else:
            return 0
    ans = 0
    ans += funk(matrix, n - 1, k, no_list + [1], h, w)
    ans += funk(matrix, n - 1, k, no_list + [0], h, w)
    return ans

ans = 0
h, w, k = map(int, input().split())
n = h + w
matrix = np.zeros((h, w))
for i in range(h):
    line = input()
    for j in range(w):
        if line[j] == "#":
            matrix[i,j] = 1
        else:
            matrix[i,j] = 0
no_list = []
ans += funk(matrix, n, k, no_list, h, w)
print(ans)
```

前半はここまでとなります．
最近は公式の解説がとても丁寧に記述してあったので，詳しい解法はそちらを参考にしてもらえたらと思います．
前半の最後まで読んでいただきありがとうございました．

後半はDEF問題の解説となります．
[後半に続く](https://qiita.com/takaito0423/items/ddf873791e46cc6b5adb)．
ubuntu20.04で docker pull したら 'Error response from daemon: Get https://registry-1.docker.io/v2/: dial tcp: lookup registry-1.docker.io: Temporary failure in name resolution' と言われた

びっくりするほど単純だったのですが、焦って色々ググってしまったので解決法をメモしておきます

```
docker login
```

これだけですw
dockerhub にログインしないとそら動きませんわー！

新しい物理マシンを立てた直後に忘れませんように...
Dockerでテストの時だけDBを立ち上げるスクリプト

# 概要
CIでテストの時だけ一時的にDBを立ち上げ、テストが終わったら削除したいってことありませんか？
Dockerを使ってそれを行うスクリプトです。

# スクリプト

```bash
#/bin/sh

CONTAINER_ID=`docker run --rm -e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=test_db -e TZ=Asia/Tokyo -d mysql:5.6 mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci`
CONTAINER_IP=`docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' $CONTAINER_ID`

trap finally EXIT
function finally {
    docker stop $CONTAINER_ID
}

until docker run --rm busybox nc -z -v -w30 $CONTAINER_IP 3306
do
  echo "Waiting for database connection..."
  sleep 3
done

# ここでテストを実行する(DB名やパスワードなどは実行パラメータか環境変数で指定する)
```