OmniAICreator/Qiita-1.07M huggingface dataset:
BigQueryのStreamingInsertのinsertIdって何を入れるのがいい？

## 概要

プロジェクトではtd-agentを利用してBigQueryに対してStreamingInsertしている。

なお、使わせて頂いてるgemはこちら
https://github.com/fluent-plugins-nursery/fluent-plugin-bigquery

BigQueryのStreamingInsertではデータの整合性を維持するために、insertIdというものを指定することによりレコードの重複などを防いでいる。

しかし、このinsertIdって何を指定するのがいいんだ？

## insert予定のレコードを全部引っ付けてぶん投げる

元々取っていた手法はこれ

#### 設定例
```configuration
<filter hoge>
  @type record_transformer

  <record>
    bq_insert_id ${record.values.map(&:to_s).join)}
  </record>
</filter>

<match hoge>
  @type bigquery_insert
  insert_id_field $.bq_insert_id
  ...
</match>
```

ログなどの取り扱いをする際はそうそう同じ行のログなんざでないものである。ミリ秒単位で同じログが出力されるならそれはログ出力部分の実装を修正したほうがいいとさえ思う。
なので、理論的には上の設定で重複は防げるはずである。

ただ、この方法を使うと通信の際1つのレコードにつき2倍のデータ容量を要してしまう。
出力されるログが微量であるなら問題ないが、高トラフィックのサーバーで1つのログの長さが長くなるとこの容量というのは意外と馬鹿にできない物になる。
それに余り過度にStreamingInsertしようとするとBigQuery側からエラーとしてリクエストを突き返される事になりそれがbufferとしてたまり続けてしまうという問題も引き起こしてしまう。
td-agentのbufferはたまり続けると設定値を超えた分を破棄してしまうのでログの欠損にも繋がってしまうのでなるべく避けたい。

そもそも論公式には `insertId フィールドの長さ: 128` という制限があったりする。(ただ、運用上明らかにこれより長い文字列を付与して送信したことがあったがエラーにはならなかった。td-agent側で文字列をぶった切ってる？)


## なのでInsertIdをなるべく短くする

プロジェクト仲間にこの事を相談したら下記のような方法を提案してくれた

#### 設定例
```
<filter hoge>
  @type record_transformer
  enable_ruby true

  <record>
    bq_insert_id ${Digest::SHA1.hexdigest(([Time.now.to_f] + record.values).map(&:to_s).join)}
  </record>
</filter>

<match hoge>
  @type bigquery_insert
  insert_id_field $.bq_insert_id
  ...
</match>
```

`Digest::SHA1` はrequireしないと呼び出せないと勘違いしていたが、どうもtd-agent(fluentd)内ではそのまま呼び出せるらしい。これによってハッシュ化できてしまうので文字列の長さを気にする必要がなくなった。
この方法では厳密にはユニークとは言えないが、BigQueryのStreamingBufferの中ログが存在してる時間だけユニークとみなされればいいだけなので要件はほぼほぼ満たせたと思う。
VisualStudio2019 で cmake と googletest 

VisualStudio 2019 で cmake との親和性が高くなったらしいが、端々で躓く。今後参考になりそうな箇所メモ残す。

## gtest.lib gtestd.lib gtest_main.lib gtest_maind.lib あたりが見つからない
LNK1104 のエラーは原因が多くてなかなか正解にたどり着けない。
VSのテンプレートに任せて「Google Test」でプロジェクトを作ったりすると、元のフォルダパスが少々長いと簡単に gtest.lib へのパスが深くなってしまう。
https://docs.microsoft.com/ja-jp/cpp/error-messages/tool-errors/linker-tools-error-lnk1104?view=vs-2019#paths-that-are-too-long
260文字以内に抑えるためにプロジェクトパスを短くする必要がある。

## googletest は cmake に任せたい
[Google Test勉強録 (1) CMakeでのビルド](
https://qiita.com/ktrmnm/items/667a7b7c93cd3fb78419#42-google-test%E3%82%92%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89%E3%81%97%E3%81%A6%E3%81%8D%E3%81%A6%E4%BD%BF%E3%81%86%E5%A0%B4%E5%90%88)　参考にするのがしっくり来た。

## Runtime 不一致エラー
マルチスレッドとかマルチスレッドDLLとかそういうあたりなんだけど、これも cmake で解決したほうがいい。
[CMakeでCRTライブラリを静的リンクするVisual Studioプロジェクトを出力する](https://sgry.jp/blog/2017/05/27/4465/)
上のと合わせると、ルートの CMakelists.txtは、

```
cmake_minimum_required (VERSION 3.8)

project ("sample_project")
if(MSVC)
    string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_DEBUG            ${CMAKE_C_FLAGS_DEBUG})
    string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_MINSIZEREL       ${CMAKE_C_FLAGS_MINSIZEREL})
    string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE          ${CMAKE_C_FLAGS_RELEASE})
    string(REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELWITHDEBINFO   ${CMAKE_C_FLAGS_RELWITHDEBINFO})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG          ${CMAKE_CXX_FLAGS_DEBUG})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_MINSIZEREL     ${CMAKE_CXX_FLAGS_MINSIZEREL})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE        ${CMAKE_CXX_FLAGS_RELEASE})
    string(REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELWITHDEBINFO ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
endif(MSVC)

enable_testing()
add_subdirectory(src)
add_subdirectory(test)
```
な感じになる。

ひとまず今んとこ以上
Herokuにデプロイしたアプリのビューの背景画像が表示されず困ったときのこと

##事象
ローカル開発環境では表示されていたビューの背景画像が、本番環境（Heroku）では表示されない。
それ以外は、正常にデプロイできている。

```
% git push memo-space master

    ...

remote:        Done: 88.5M
remote: -----> Launching...
remote:        Released v12
remote:        https://memo-space.herokuapp.com/ deployed to Heroku
remote: 
remote: Verifying deploy... done.
To https://git.heroku.com/memo-space.git
   c05fd9d..8919aad  master -> master

```

→　背景画像が表示されない
　　背景画像以外は正常にデプロイされている。

####前提条件
背景画像の読み込みをscssファイルで記載している。

### 試したこと

画像ファイルを読み込んでいるscssファイルを確認

```app/assets/stylesheets/modules/_contents.scss

&__contents {
  @import "mixin/mixin";
  @import "contents_left";
  @import "contents_center";
  @import "contents_right";
  @import "contents_index";

  background-image:  image-url("beach.jpg");
  // background-image:  image-path("beach.jpg");
  // background-image:  asset_path("/images/beach.jpg");
  background-size:  cover;
  overflow-y: scroll;
  overflow-x: hidden;

  width: 100%;
  height: calc(100vh - 80px);
  display: flex;
}

```

いろいろ試してみる

画像イメージの読み込むメソッドを変えてデプロイし直してみる

```
background-image:  image-path("beach.jpg");
```
→　変化なし

画像イメージの読み込むときのパス指定を変えてみる

```
background-image:  asset_path("/images/beach.jpg");
```
→　変化なし

Herokuのデプロイ手順をやり直したり

ハマること２時間

.gitignoreファイルを眺める

![スクリーンショット 2020-03-14 14.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/564329/a4040e70-9b50-9da7-3cfa-4ba1f9da57c4.png)

## 原因

背景画像を置くディレクトリが、.gitignoreにデプロイ対象外として記載されていたことでした。
Ubuntu 18.04 LTS から Anaconda をアンインストールする手順

### 参考文献
- 本記事は以下のサイトを参考に自身の備忘録として記録したものです。
- [How to Install Anaconda on Ubuntu 18.04](https://linuxize.com/post/how-to-install-anaconda-on-ubuntu-18-04/)

### 1. Anaconda をインストールしたディレクトリを削除
```bash
$ rm -rf ~/anaconda3
```

### 2. `~/.bashrc`から Anaconda への PATH を削除
```text:~/.bashrc
# Anaconda Path
export PATH=/home/<user_name>/anaconda3/bin:$PATH
```
```bash
source ~/.bashrc
```

### 3. Anaconda 関連の隠しファイルを削除
```bash
rm -rf ~/.condarc ~/.conda ~/.continuum
```

以上
【Spring-Boot】Junitを利用した単体テストでよく利用するアノテーション

# 概要
Spring-BootのJunitテストを作成する際に利用するアノテーションは多種多様であり、覚えきれないし、大量に付与されていると１つ１つ読み解くのが難しい。
そのため、よく利用するものをここでまとめていく。


# 本文
## @ContextConfiguration

指定した`@Configration`を付けたクラスをテスト実行時に読み込んでくれる。
任意のBean登録をしたいときに使う。

**例）TestConfig.java を読み込ませる場合**

```
@ContextConfiguration(classes = {TestConfig.class})
```

## @ActiveProfiles

`@profile("prduciton")`などの記載で、application.ymlで指定したアクティブなプロファイルによってBeanを切り替えることはよくある。ただし、単体テストでapplication.ymlを編集することはできない。
このようなときに利用する。

**例） profileをdefault（指定なし）の状態でテストを実行する場合**

```
@ActiveProfiles("") 
```

## @TestPropertySource

application.ymlなど外部指定する設定値を置き換える際に利用。

**例） app.setting.key1とapp.setting.key2の値を指定してテストしたい場合**

```
@TestPropertySource(
    properties = {
      "app.setting.key1 = xxxx",
      "app.setting.key2 = yyyy"
    })
```

## @EnableConfigurationProperties

ymlやpropertiesファイルの値を`@ConfigurationProperties`を付与したクラスのフィールドにマッピングさせた場合、このクラスをJunit時に有効にさせるアノテーション。
これを見つけるまで、@ConfigurationPropertiesを付与したクラスのフィールドがNullとなり、苦労した。


**例） @ConfigurationPropertiesを付与したAppSetting.javaで外部ファイルの値をマッピングできるようにする場合**

```
@EnableConfigurationProperties(value = AppSetting.class)
```

```
@Configuration
@ConfigurationProperties(prefix = "app.setting")
public class AppSetting {

  /** app.setting.key1の値. */
  private String key1;

  /** app.setting.key2の値. */
  private String key2;

}
```

## @AutoConfigureMockRestServiceServer

RestTemplateによる通信先のモック化。
これは使い方が結構難して、単体テストで常に使うかどうかは微妙。
@AutoConfigureMockRestServiceServerを付与したうえで、以下のようにすると、RestTemplateによる通信結果を操作できる。

```
    RestTemplate restTemplate = （モック化したRestTemplateオブジェクト）;
    MockRestServiceServer mockServer = MockRestServiceServer.bindTo(restTemplate).build();
    mockServer
            .expect(requestTo(expectURL)) // モック化したいURL
            .andExpect(MockRestRequestMatchers.method(HttpMethod.POST)) // リクエストメソッド
            .andRespond(MockRestResponseCreators.withStatus(HttpStatus.OK));//モックによるレスポンス

```

# まとめ

その他お作法のアノテーションも含めて全部つけると以下の状態になる。
これは最低限レベルで、いろいろやろうとするともっと多くなる。

```
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {TestConfig.class})
@EnableConfigurationProperties(value = AppSetting.class)
@ActiveProfiles("") 
@TestPropertySource(
    properties = {
      "app.setting.key1 = xxxx",
      "app.setting.key2 = yyyy"
    })
@AutoConfigureMockRestServiceServer
class JunitTest {


}
```

# 参考にさせていただいたサイト

- @AutoConfigureMockRestServiceServerについて（解説しているサイトがすくなかったので非常に感謝）  
Hatena Blog 日々常々  
https://irof.hateblo.jp/entry/2019/07/18/140046
【超初心者】VSCodeにstdio.hがない

# 状況
VSCodeでC言語の学習を進めていると突然、#include\<stdio.h>に波線が。パソコンが壊れたかもしれない。
綴りミスを疑うもいつも通りのinclude。恐る恐るカーソルを波線に近づけると、たくさん分からないことを教えてくれた。
![include1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499160/0048185b-f768-2ef2-e5a5-66e5810e9beb.png)
ほう・・・
エラーが検出されたことぐらいは分かるし、includePathというのはお初にお目にかかったし、波線は赤々としっかり出ているのに無効になっているらしい。

# 翌日
ひたすらGoogleに訴えかけるも、
![include2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499160/4fb1f265-0645-bcc7-b136-0ae0c37678ca.png)
# 二日後
![include3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/499160/193692db-3552-0b15-27db-a8cdaad41427.png)

パソコンが壊れてからはや二日、諦めてHIKAKINの後を追おうとしたとき、ついに赤々とした波線が姿を消した。
### 原因/対処法
VSCodeでフォルダを開く際、ソースコードを保存するフォルダに、.vscodeというフォルダがある。
そのさらに下の階層にファイルを保存するフォルダを作っていて、そこを毎回VSCodeで開いていた。　

**つまり、VSCodeでソースコードフォルダを開く際は、.vscodeフォルダがあるフォルダを開き、あとはVSCodeの左側のところでフォルダを開く必要がある**
ということを二日かけて理解した。

includePathさえ正しく書けばこんなことにはならないのかもしれない。が、
とりあえずエラーが消えたので満足。

壮大に書いて冗長になりましたが、以上です。
Kinx プレビュー版リリース

# Kinx プレビュー版のリリース

## はじめに

**「見た目は JavaScript、頭脳(中身)は Ruby、（安定感は AC/DC）」**でお送りするスクリプト言語 Kinx。まだまだ途中だがリリースするのも意味があるだろうとの想定から、実行可能な形でパッケージングし、まずはプレビュー・リリースすることにしました。Windows 版の実行ファイルはアイコンもつけていい感じ。Linux は /usr/bin にインストールしてしまうので、一応気にしておいてください。

## 本題

↓ここです。

* https://github.com/Kray-G/kinx/releases

もちろん、git clone して make もできます。

本題、おしまい。

### 振り返り

元々は[この記事](https://qiita.com/Kray-G/items/7d1af238b46594ff78fe)での「プログラマに馴染むシンタックスってのは C 系だよね、でも何で Ruby も Python も全然違うのでしょう」というところから始まった今回のプロジェクト。プロジェクト自体は去年末くらいから実質スタートしてたので、約 5 ヶ月くらいか。

元々からしてほぼ JavaScript な文法なので、作りながらではあるものの、既にすっかり私の手には馴染んでます。

まだ初版にはできませんが（おっとさっき気づいたのだが標準入力がない...）、結構色々試せるとは思います。

### ほんのちょっと興味があれば

何か試してみてフィードバック貰えると非常に嬉しい。まぁ、既存の何かを置き換えるようなたいそうなモノではないので、ちょっとした提案とかこんなんあるといいんじゃない、とか、そういうライトな感じのご意見ください。

すみません、見返りはあまり無いと思います…。そういうの楽しめる方か、面白そうだと思ってくださる方向け。

## おわりに

最後はいつもの以下の定型フォーマットです。

* 最初の動機は [スクリプト言語 KINX（ご紹介）](https://qiita.com/Kray-G/items/ca08b6fb40d15dd0ec76) を参照してください（もし宜しければ**「~~いいね~~ LGTM」**ボタンをポチっと）。
* リポジトリは [ここ（https://github.com/Kray-G/kinx）](https://github.com/Kray-G/kinx) です。こちらももし宜しければ★をポチっと。
UbuntuのLAMP環境にLaravelをデプロイ

UbuntuのLAMP環境にLaravelを公開することがあったので備忘録として残します。

## 環境
***Ubuntu 18***
***Laravel6***
***php72***
***Apache2.4***

## 手順

とりまアプデ
`apt-get update
`
###1.Conposerをインスコ
`curl -sS https://getcomposer.org/installer | php
`
か
`apt install composer`

##2.Laravelをインストール
`composer create-project --prefer-dist laravel/laravel [project_name]
`

###3.Laravelをデプロイ
作成したプロジェクトディレクトリをApache Webルートに移動する

`sudo mv example /var/www/html/
`
パーミッションの設定
`sudo chgrp -R www-data /var/www/html/example/
`
`sudo chmod -R 775 /var/www/html/example/storage
`
プロジェクトの新しいバーチャルホストを作成

`cd /etc/apache2/sites-available
`

`sudo nano laravel_project.conf
`

バーチャルホストのconfファイルに設定を記入

```laravel_project.conf
<VirtualHost *:80>
   ServerName thedomain.com
   ServerAdmin webmaster@thedomain.com
   DocumentRoot /var/www/html/example/public

   <Directory /var/www/html/example>
       AllowOverride All
   </Directory>
   ErrorLog ${APACHE_LOG_DIR}/error.log
   CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
```

http.confも編集

```http.conf
<Directory /var/www/html/>
  Options Indexes FollowSymLinks
  AllowOverride All
  Require all granted
</Directory>
```

作成したconfファイルを有効化
`sudo a2ensite laravel_project`

ApacheRewirteモジュールを有効にし、Apacheを再起動
`sudo a2enmod rewrite`
`sudo systemctl restart apache2`

こんな感じ

自分用の備忘録なので適当なのはあしからず
オーディオファイルのメタ情報を参照する

オーディオファイルのメタ情報を手軽に参照したいなと思ったとき、[SoX (Sound eXchange)](http://sox.sourceforge.net/) が簡単に利用でき便利です。元々 SoX はオーディオファイルの変換を主な機能とするコマンドラインツールですが、他にも様々な機能を提供しています。



macOS を利用している方なら Homebrew からインストールできます。

```bash
$ brew install sox
```


試しに次の URL で公開されている MP3ファイルのメタ情報を参照してみると、以下のようにメタ情報を参照することができます。[Sweeping Broom Shorter Sounds | Effects | Sound Bites | Sound Clips from SoundBible.com](http://soundbible.com/2112-Sweeping-Broom-Shorter.html)

```bash
$ sox --info sweeping_straw_broom-mike-koenig.mp3

Input File     : 'sweeping_straw_broom-mike-koenig.mp3'
Channels       : 2
Sample Rate    : 44100
Precision      : 16-bit
Duration       : 00:00:07.81 = 344465 samples = 585.825 CDDA sectors
File Size      : 312k
Bit Rate       : 320k
Sample Encoding: MPEG audio (layer I, II or III)

```
LINE Messaging APIの新機能でLINE公式アカウントのアイコンを変更する

# 概要
先日(2020/03/17)、LINE公式アカウントのアイコンをメッセージ送信ごとに変更できる機能が一般開放されました。
これを使うことにより、ボットの機能や担当者ごとにアイコンを切り替えたりできるようになります。

詳細はこちらの公式サイト( https://developers.line.biz/ja/docs/messaging-api/icon-nickname-switch/#%E6%A6%82%E8%A6%81 ) をご覧ください。

# イメージ
こんな感じで、1つの公式アカウントで複数のアイコンを使い分けれます。

<img width="375" alt="LINE_capture_606210822.144834.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30931/bcd22e64-1ff6-c4b5-c523-8662022158a4.jpeg">

# 使い方

※ そもそもメッセージの送信の仕方を知らないという方はこちら( https://qiita.com/fkooo/items/d07a7b717e120e661093 )などを参考にしてください。

使い方は簡単でこれまで

```json
{
  "type": "text",
  "text": "ただいま混み合っています。1時間後くらいにこちらからメッセージさせていただきます。"
}
```
みたいになっていたメッセージオブジェクトにsenderプロパティをつけて、
sender.nameに表示名、sender.iconUrlにアイコン画像をつけるだけです。

```json
{
  "type": "text",
  "text": "ただいま混み合っています。1時間後くらいにこちらからメッセージさせていただきます。",
  "sender": {
    "name": "bot",
    "iconUrl": "https://rsasage.s3-ap-northeast-1.amazonaws.com/qiita/omocha_robot-square.png"
  }
}
```


# コード

全体のコードは下記のようになります。

```javascript:index.js
const line = require('@line/bot-sdk')

const config = {
  channelAccessToken: 'YOUR_CHANNEL_ACCESS_TOKEN'
}

client = new line.Client(config)

client.pushMessage('YOUR_ACCOUNT_DESTINATION_ID', [
  {
    type: "text",
    text: "ただいま混み合っています。1時間後くらいにこちらからメッセージさせていただきます。",
    sender: {
      name: "bot",
      iconUrl: "https://rsasage.s3-ap-northeast-1.amazonaws.com/qiita/omocha_robot-square.png"
    }
  }
])
```

簡単ですね。

# 用途を考えてみた。

## #1 チャットノベル

<img width="375" alt="IMG_2086.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30931/154ecdff-827e-024b-8cf8-31790936cd70.png">

登場人物を増やせるので、別のアイコン同士で会話させて、たまにユーザに選択肢を与えたりすると面白いかもしれません。


## #2 カスタマーサポート

<img width="375" alt="IMG_2087_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30931/edc1a99d-fc50-f0a2-ad75-e40160542356.png">

人間による対応と自動通知による対応をアイコンを変えることでわかりやすくできます。
営業時間外はボットモードにして、営業時間内は人が対応することにしたり、ボットモードでも人間が対応できるように管理画面を自作したり、することになりますね。

## #3 複数人プレイのゲーム

<img width="375" alt="IMG_2090.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30931/7d6d9416-898e-a89b-b961-1a24e05f3955.png">

<img width="375" alt="IMG_2089.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30931/449f86cd-67d0-2d0b-3067-78e27cb524ac.png">

ユーザからメッセージをwebhookで受け取った時にそれをそのまま他のユーザに流してやると、擬似的にグループチャットのようなことが実現できるはずです。

グループチャットにボットを追加するのと同じですが、不特定多数とプレイできるのとリッチメニューを利用できる点が違います。
ただ、PUSHメッセージをたくさん送ることになりかねないのでお財布的に課題はあるかもしれません。

# 終わりに

他にもいろいろ工夫のしようがありそうですね。
Messaging APIを触ったことのある方なら簡単に導入できると思います。
さよならMariaDB5.5こんにちはMySQL8.0

# CentOS7以降MariaDBがデフォになっちまったよおい！
そのままである。
互換性が高いため別に問題はないのであろうと思われるが、使い慣れているMySQLにもどしちくり～と開発陣に言われたので作業することになった。
ついでに最新のMySQL8.0にしといて＾＾＾＾とも言われた。やれやれ。

# コマンドレッツゴー
#### ※別の人が作った社内開発環境で作業したため普通じゃない箇所があります(特にサービス名)。コピペで動かなくてもごめんなさい。
各種バックアップは取っておいてね！dumpやらconfigやら

`systemctl stop mysql`
何はともあれstop。確認もね。

`yum remove Maria*`
MariaDB関係を削除

まずはmysql5.7を導入だ！いきなりmysql8.0へはいけなかったぞ！

`yum install http://dev.mysql.com/get/mysql57-community-release-el7-7.noarch.rpm`
mysql5.7のRPMパッケージインストール

`yum info mysql-community-server`
mysql5.7がインストールできるか確認

`yum install mysql-community-server`
mysql5.7インストール

`mysqld --version`
バージョン確認

`systemctl start mysqld`
mysql5.7開始！確認もネモネ。

`mysql_upgrade -u root -p`
データベースをmysql用にアップグレード

ここで動作確認しておくとよいかもね！

`rpm -e mysql57-community-release`
mysql5.7のRPMパッケージを削除

`rpm -ivh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm`
mysql8.0のRPMパッケージインストール

`yum info mysql-community-server`
mysql8.0がインストールできるか確認

`systemctl stop mysqld`
mysql5.7停止！確認ｍ

`yum install mysql-community-server`
mysql8.0インストール

`mysqld --version`
バージョン確認

`systemctl start mysqld`
mysql開始！かｋ

以上！閉廷！
私の環境ではこれで問題なく動作してました。

# おまけ
`/etc/my.cnf
[mysqld]
default_authentication_plugin= mysql_native_password`
my.cnfにこれを追記しておくといいかもしれない。mysql8.0でパスワードの認証方式が変わったので古いものに戻す設定だそうです。
IBM Cloud Object Storage (ICOS) に Aspera SDK (Python) を使って高速アップロード


# はじめに
こちらを使います。

> [data-lake/upload/cos-upload at master · IBM-Cloud/data-lake](https://github.com/IBM-Cloud/data-lake/tree/master/upload/cos-upload)

# 環境準備
Python を使います。

```
# python -V
Python 2.7.12
```

ファイルをダウンロードして実行権限を付与します。

```
git clone https://github.com/IBM-Cloud/data-lake.git
cd data-lake/upload/cos-upload/
chmod +x install.sh
chmod +x cos-upload.py
```

必要なライブラリ・環境を整備します。

```
pip install virtualenv
virtualenv -p /usr/bin/python2.7 cos-env
source cos-env/bin/activate
./install.sh
```

# Aspera で高速アップロード

以下の変数を定義します。

```
export endpoint="jp-tok"
export apikey="*****"
export bucket="khayama-images"
export prefix="aspera"
export file="/root/rhcos-4.3.0-x86_64-installer.iso"
```

![Kobito.iz0lx1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/ebdde9e1-9658-7e66-b324-116c46386640.png "Kobito.iz0lx1.png")

Aspera SDK (Python) を使って高速アップロードします。

```
# ./cos-upload.py --flatten $endpoint $apikey $bucket $prefix $file

Initialize COS and Aspera Transfer Manager using endpoint: https://s3.jp-tok.cloud-object-storage.appdomain.cloud

Upload file to COS: /root/rhcos-4.3.0-x86_64-installer.iso => aspera/rhcos-4.3.0-x86_64-installer.iso
Upload file to COS completed.
```

アップロードされたことが確認できました。

![Kobito.rCQhWH.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/8b03e5ab-8393-673a-0e2f-be4551fba43e.png "Kobito.rCQhWH.png")
Lookerの権限周りについて調べてみた

何かと自由度が高いLooker。
権限周りについても同様で、何をどうするとどうなるのかが複雑だったので整理しておく。

## 前提知識
### 権限によって制御されるものは3種類
- コンテンツアクセス（≒フォルダへのアクセス）
    - 利用：フォルダに移動、フォルダ内のダッシュボード＆ルックの一覧を表示が可能
    - 管理：	フォルダ内コンテンツの操作(ダッシュボードとルックの複製、移動、削除、名前変更)、フォルダ自体の管理(フォルダの名前変更、移動、削除)、他のユーザーとグループにフォルダへのアクセスを許可
- データアクセス：ModelやExplore、View等の単位でアクセスするための権限管理が可能
- 機能アクセス：データの表示やLookMLモデルの変更等、ユーザーがLookerで実行出来る「アクション」の種類を制御

### デフォルト権限セットで出来ること抜粋（上位権限は下位権限を包含）
- Admin：すべて
- Developer：LookMLによるdevelop/deploy、SQL Runnerの利用
- User：Explore、LookML/SQLの閲覧、TableCalculationの作成、フォルダの作成（アクセスの管理権限が必要）
- Viewer：ダッシュボード等の閲覧、データのダウンロード

## 権限付与時の基本思想
* Lookerは自由度が高いものの、管理コストを考えるとできるだけシンプルに管理したい → デフォルト権限セットで管理
* データガバナンスは当面単一部署が請け負う

## 管理方法
* GroupにRoleを紐付け、アカウントをGroupに追加/削除する方法をとる
* terraformによる管理にするかSDKによる管理にするかは検討中

## 参考記事
https://dev.classmethod.jp/business/business-analytics/looker-access-control-and-permission-management/
https://dev.classmethod.jp/business/business-analytics/looker-role-permissionset-modelset-and-create-user/
DBの日時文字列をDATETIMEに変換したくてコケた話

# なにが起きましたか

* とあるDBのテーブルでは，日時データが全て別カラムの文字列で構成されていた．
    * `SELECT year, month,..., second from Hoge` みたいなやり方を強いられていた
    * これはプログラムでも扱いにくいしなんとかしたい．
* →MySQLなどでサポートされている`DATETIME`型に変換する．

変換元のHogeテーブルと変換先のPiyoテーブルは以下のような見た目である．

```sql
> SHOW CREATE TABLE Hoge;
CREATE TABLE Hoge (id, columns, year VARCHAR(4), month VARCHAR(2)...)

> SHOW CREATE TABLE Piyo
CREATE TABLE Piyo (id, columns, date DATETIME(6))
```

# やったこと

* HogeからPiyoに変換する以下のようなSQLを書いた

```sql:convert.sql
insert into Piyo(
  id,
  columns,
  STR_TO_DATE(
    CONCAT(
      year,'-',month,'-',day,' ',hour,':',minute,':',second,'.',usecond
    ),
    '%Y-%m-%d %H:%i:%s.%f'
  )
) select id, columns, from Hoge;
```

取得したそれぞれを，`CONCAT`で結合して，DATETIMEフォーマットに合わせる．それを`STR_TO_DATE`でDATETIME型に変換して，新しいPiyoテーブルにINSERTする．
さて，動くような気もするが，動かない．

```
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')) from ...
```

なんと，SyntaxErrorだと言われた．全く分からん......

# 解決

全くSQLをわかっていなかった．
INSERTするとき**INSERT先カラム名を指定しない場合，INSERT先のカラム名と一致している必要がある**当たり前だ．
もしINSERT先とINSERT元の名前を違うものにしたかったら`INSERT INTO テーブル名 (インサート先カラム名) VALUES (インサート元カラム名)` でやる．
あるいは，SELECTしたときにASでINSERT先の名前として別名をつけてやる必要がある．

# 結論

SELECT時に別名をつける手法を採用した．

```sql:convert.sql
INSERT INTO Piyo(
  id,
  columns,
  date
) 
SELECT id,columns,STR_TO_DATE(
  CONCAT(
    year,'-',month,'-',day,' ',hour,':',minute,':',second,'.',usecond
  ),'%Y-%m-%d %H:%i:%s.%f'
) as date 
from Hoge;
```

これで1時間以上溶かしてしまった...SQLのエラーがもっっっと親切だったら良かった(ない)
【Angular】ExpressionChangedAfterItHasBeenCheckedErrorの対処メモ

## この記事の概要

Angularで時々目にするExpressionChangedAfterItHasBeenCheckedErrorですが、
原因は今回記事でとりあげるものの他にも様々ありますが、
私のチームでよくやってしまいがちな
このエラー発生させるコードの記述の仕方と解決策のメモを残します。

## Chromeのコンソールに出てるエラーログ

```
HogeComponent.html:1037 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'ngIf: false'. Current value: 'ngIf: true'.
    at viewDebugError (core.js:7602)
    at expressionChangedAfterItHasBeenCheckedError (core.js:7590)
    at checkBindingNoChanges (core.js:7692)
    at checkNoChangesNodeInline (core.js:10553)
    at checkNoChangesNode (core.js:10542)
    at debugCheckNoChangesNode (core.js:11145)
    at debugCheckDirectivesFn (core.js:11073)
    at Object.eval [as updateDirectives] (HogeComponent.html:1037)
    at Object.debugUpdateDirectives [as updateDirectives] (core.js:11062)
    at checkNoChangesView (core.js:10441)
```

どうやらngIfの判定がfalseだったのにtrueに変わっているぞと怒られているようです。

## エラーとなっているコード

```html
<ng-container *ngIf="fuga.invalid && submitted">
  <span>foo</span>
</ng-container>
```

## 原因

この*ngIfの中のfuga.invalid と submittedの評価の結果が返ってくるのはそれぞれ時間差がありました。
例えば最初にsubmitがtrue、fuga.invalidがfalseと判定されたので、
Angularは変更を感知してng-container内の要素を表示をしないようにしたところ、
その直後すぐにfuga.invalidの判定がtrueで返ってきたので
ng-container内の要素を表示する判定が変わってしまいました。

## 修正

```html
<ng-container *ngIf="submitted">
  <ng-container *ngIf="fuga.invalid">
    <span>foo</span>
  </ng-container>
</ng-container>
```

これで
外側のngIfの条件判定でsubmitがtrueになった
↓
Angularは変更を感知して外側のng-container内部を表示する
↓
次に内側のngIfの条件判定でfuga.invalidがtrueになった
↓
Angularは変更を感知して内側のng-container内部を表示する

という順序で無理なく要素を表示することができます。
Azuriteでローカル環境構築（Docker + PHP + Azure Storage）

# 目的

Azuriteを利用してDocker + PHP + Azure Storageのローカル環境を構築します。
Dockerによるローカル環境構築を進めてきましたがStorageはAzureプラットフォームのを利用していたので、Azuriteを利用してローカル環境だけで完結させます。

# Azuriteとは

Azure Storageのエミュレーター。

[ローカルでの Azure Storage の開発とテストに Azurite エミュレーターを使用する](https://docs.microsoft.com/ja-jp/azure/storage/common/storage-use-azurite) (プレビュー)

## AzuriteかAzure ストレージ エミュレーターか

> Azurite は今後のストレージ エミュレーター プラットフォームです。Azurite は Azure ストレージ エミュレーターよりも優先されます。

ということなので今後もこちらを使っていけば良さそうです。

## Azuriteのインストール方法

> 3. Azurite Docker イメージをインストールして実行する

今回はDockerを利用するのでこちらを選択します。

# Docker環境

[Azurite - Docker Hub](https://hub.docker.com/_/microsoft-azure-storage-azurite)

## docker-compose.yml

```yaml
version: '3'

services:
  php:
    # 省略

  storage:
    image: mcr.microsoft.com/azure-storage/azurite
    prots:
      - "10000:10000"
    volumes:
      - ./docker/storage/data:./data
```

PHPのコンテナについては割愛します。
[公式のPHPライブラリ](https://github.com/Azure/azure-storage-blob-php) を利用してAzure Storageを利用できればAzuriteに関しても問題ないと思ってます。

また、今回は**Blobだけ**を使用するのでTableとQueueについても割愛します。

## Azure Storage Explorerから接続してみる

[Azure Storage Explorer](https://azure.microsoft.com/ja-jp/features/storage-explorer/)

接続ダイアログから「ローカル エミュレーターにアタッチする」を選択してアタッチします。

# AzuriteにBlobを作成する

phpでBlobを作成していきます。

```php
<?php
require_once '../vendor/autoload.php';

$connection = '<接続文字列>';
$client = \MicrosoftAzure\Storage\Blob\BlobRestProxy::createBlobService($connection);

$container = 'sample'; // 事前に作成しておく
$blob = 'example.txt';
$content = 'Hello Azurite!';

$client->createBlockBlob($container, $blob, $content);
```

## 接続文字列について

```php
$connection = 'UseDevelopmentStorage=true';
```

基本はこのショートカットでOK。
しかしDocker環境だと事情が異なります。
これで先程の処理を実行しようとすると・・・

> cURL error 7: Failed to connect to 127.0.0.1 port 10000

Dockerコンテナ間で接続する場合、これでは不十分のようです。
先程のショートカットを展開した接続文字列からエンドポイントを変更していきます。

`BlobEndpoint=http://127.0.0.1:10000/devstoreaccount1`

ここのホスト名をコンテナのサービス名に変更します。

`BlobEndpoint=http://storage:10000/devstoreaccount1`

最終的な接続文字列は次の通りです。

```php
$connection = 'DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;
AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;
BlobEndpoint=http://storage:10000/devstoreaccount1;';
```

AccountName、AccountKeyはエミュレーター固定です。
TableEndpoint、QueueEndpointは割愛します。

これで先程のBlob作成処理を実行すると・・・

![explorer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/595926/73717540-b16b-9fea-c8f4-f2d86c47090e.png)

作成されました。

# パブリックURLが・・・

ひとつ問題が残りました。

```php
// http://storage:10000/devstoreaccount1/sample/example.txt
echo $client->getBlobUrl($container, $blob);
```

接続文字列でホスト名をコンテナのサービス名にしたのはDockerコンテナ間で接続するためでした。
コンテナ外のブラウザからアクセスする場合は「127.0.0.1」にしなければならないです。
（パブリックアクセスの設定を変更して許可するのも忘れずに）

Docker + Azurite + ブラウザからアクセスするケース（例えばHTMLのaタグ、imgタグ等）はホスト名を書き換えなければいけません。

# まとめ

微妙な部分もありましたがローカル環境としては十分だと思ってます。
「ちょっと動かすだけなのに、AzureプラットフォームにStorage
サービスを作成しないといけない」という点は解消できました。

# 問題等（追記）

使ってるなかで気がついた問題などです。

## ~~Append Blob がサポートされていない~~ (2020/05/21更新）

[Azurite v3.7.0](https://github.com/Azure/Azurite/releases/tag/v3.7.0) でAppend Blobがサポートされました。
nekoサブドメインでにゃーんと返す実装をする

# 何をしたいか
example.comのドメインを所有していた場合、neko.example.comに対するアクセスに"にゃーん"を応答する。
APIっぽく実装する。

今回使う僕のドメインは、taro-hida.tk

# 事前準備
- DNSで、neko.taro-hida.tkのサブドメインにAレコードを設定する。conohaのDNSで設定。

```
$ dig neko.taro-hida.tk +short
150.95.153.122
```
- Apacheサーバで、neko.taro-hida.tkのvirtualhostの設定を書く。

```
<VirtualHost *:80>
ServerName neko.taro-hida.tk 
DocumentRoot /var/www/neko/
CustomLog "logs/access_log" combined
ErrorLog "logs/error_log"
</VirtualHost>
```
# APIの実装
- Documentルートに`index.php`を設置する[^1]
[^1]: [PHPで簡単なWebAPIを実装してみる](https://note.com/kazztech/n/ndb3a5468f299)のコードを拝借

一応、index.phpについては権限をapacheに与えておく。

```
$ sudo chown apache:apache /var/www/neko/index.php
```

```php
# cat /var/www/neko/index.php
<?php
header('Content-Type: application/json; charset=utf-8');
$neko = array('にゃーん');

print json_encode($neko, JSON_PRETTY_PRINT);
```

# httpクエリを投げてjsonを取得
ブラウザでアクセスしても、json_encodeされたデータのため、UTF-8でencodeされたjsonがそのまま表示されてしまいます。
以下のpythonスクリプトでデータの取得を行います。

```python
# cat get.py 
import requests
import json

url = 'http://neko.taro-hida.tk/'

response = requests.get(url)
contents = json.loads(response.text)

print(contents)
```

```
$ python3 get.py 
['にゃーん']
```

望んでいた結果が得られました。

# おわりに
思い付きの実装でしたが、API実装したの初めてだったので勉強になったように思います。
割と30分くらいで実装もできました。

nekoサブドメインへのにゃーんAPI設置、流行らないかなぁ...

# 参考
- [PHPで簡単なWebAPIを実装してみる](https://note.com/kazztech/n/ndb3a5468f299)
- [Requestsで日本語を扱うときの文字化けを直す](https://qiita.com/nittyan/items/d3f49a7699296a58605b)
- [nkmkさんのページ](https://note.nkmk.me/python-json-load-dump/)
- [requestモジュールの公式ドキュメント](https://requests-docs-ja.readthedocs.io/en/latest/user/quickstart/)
【rails db:createエラー】dependent dylib '/usr/local/opt/mysql/lib/libssl.1.1.dylib' not found for '/Library/Ruby/Gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.bundle'

エラーをいろいろ試して解決しました。（めちゃくちゃな解決法ですが初心者なのでご容赦ください）

## エラー内容
```
$ rails db:create
```
したところ

```
LoadError: dlopen(/Library/Ruby/Gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.bundle, 0x0009): dependent dylib '/usr/local/opt/mysql/lib/libssl.1.1.dylib' not found for '/Library/Ruby/Gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.bundle' - /Library/Ruby/Gems/2.6.0/gems/mysql2-0.5.3/lib/mysql2/mysql2.bundle
```
のエラーが発生。
'/usr/local/opt/mysql/lib/libssl.1.1.dylib'のファイルが無い？と書いてありました。


## 解決方法
他の方の参考にはあまりならないかもしれません。。。

homebrewでmysqlをインストールすれば、/usr/local/opt/mysql/lib/libssl.1.1.dylibファイルができると思い、
https://qiita.com/narikei/items/cd029911597cdc71c516
を参考に

```
$ brew install mysql
$ mysql.server start
$ bundle init
$ bundle install --path=vendor/bundle
```
を実施しました。

その後、アプリ内で改めて

```
$ rails db:create
```
したら、

```
Could not find mysql2-0.5.3 in any of the sources
Run `bundle install` to install missing gems.
```
というエラーが出たので、

```
$ bundle install
```
したら、

```
An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
Make sure that `gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/&#039;` succeeds before bundling.
```
のエラーが出ました。
https://qiita.com/fukuda_fu/items/463a39406ce713396403
を参考に

```
$ bundle config --local build.mysql2 "--with-cppflags=-I/usr/local/opt/openssl@1.1/include"
$ bundle config --local build.mysql2 "--with-ldflags=-L/usr/local/opt/openssl@1.1/lib"
$ bundle install
```
したところ、成功しました。改めて、

```
$ rails db:create
```
したところ、

```
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
```
のエラーが出たので、
https://qiita.com/carotene4035/items/e00076fe3990b9178cc0
を参考に

```
$ touch /tmp/mysql.sock
$ mysql.server restart
```
をした後

```
$ rails db:create
```
で無事にデータベースが作成できました。
Raspberry Pi 4 のセットアップ on Mac

RaspberryPiのセットアップなんていろんなところで書いてあるとは思うけど、自分の環境でのメモです。

# OSのインストール
まず公式からRaspbianを拾ってくる。
https://www.raspberrypi.org/downloads/raspbian/
今回はRaspbian Buster Liteを使うことにする。

microSDは32GBを用意した。SDカードを作るパソコンには、6年前のモデルのMacbookのmid 2014を使っているが、これはSDカードリーダーがついているのでこんな時に便利。まずは、SDカードがどこにあるか確認する。

```
> diskutil list
/dev/disk3 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *31.3 GB    disk3
   1:             Windows_FAT_32 NO NAME                 31.3 GB    disk3s1
```

`/dev/disk3`みたいです。一応フォーマットする。

```
> diskutil unMountDisk /dev/disk3
Unmount of all volumes on disk3 was successful
> diskutil eraseDisk MS-DOS RASP /dev/disk3
Started erase on disk3
Unmounting disk
Creating the partition map
Waiting for partitions to activate
Formatting disk3s2 as MS-DOS (FAT) with name RASP
512 bytes per physical sector
/dev/rdisk3s2: 60618240 sectors in 947160 FAT32 clusters (32768 bytes/cluster)
bps=512 spc=64 res=32 nft=2 mid=0xf8 spt=32 hds=255 hid=411648 drv=0x80 bsec=60633088 bspf=7400 rdcl=2 infs=1 bkbs=6
Mounting disk
Finished erase on disk3
```

確認して、アンマウントして、ディスクイメージを書き込みする。

```
> diskutil list
/dev/disk3 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *31.3 GB    disk3
   1:                        EFI EFI                     209.7 MB   disk3s1
   2:       Microsoft Basic Data RASP                    31.0 GB    disk3s2

> diskutil unMountDisk /dev/disk3
Unmount of all volumes on disk3 was successful

> sudo dd if=/Users/niikura/Downloads/2020-02-13-raspbian-buster-lite.img of=/dev/disk3 bs=1m
Password:
1764+0 records in
1764+0 records out
1849688064 bytes transferred in 468.550952 secs (3947678 bytes/sec)
```

面倒なので、ディスプレイとかキーボードは繋がないことにする。sshが必要なので、bootにsshというファイルを作ると良いらしい。

```
> cd /Volume/boot
> touch ssh
```

ここで、今の環境はネットワークにMacアドレスフィルターがかかっているので、単に起動してもネットワークにつながらないことに気づく。画面をつかながないでMacアドレスを見つけるのはそれなりに面倒みたいなので、諦めてディスプレイとキーボードを探してきてネットワークの設定だけは行なった。
ちなみに、初期パスワードはraspberry。

# 初期設定
sshでログインすると`Use raspi-config to set the country before use.`と書いてあるので、まずはそれをやってみることにする。

```
$ sudo rasps-config
```

一番初めにパスワード変更、というのがあるので、まずはそれをやる。他は特に必要なかったかな。日本語にする必要もないし。

あとは、aptでアップデートをしておく。

```
$ sudo apt update; sudo apt upgrade
```

これでとりあえず使えるようになりました。
adobeXD 書き出し対象を一括解除　（一括選択→書き出し対象から削除）

#問題点
現状adobeXDでは画像を配置すると勝手に（デフォルトで）「書き出し対象」になってしまう設定らしく、1ページ作り上げると相当「書き出し対象」のファイルが勝手にできてしまう。その解決方法。

#解決方法
現状自分が発見した解決方法。
プラグイン「SelectMenu」をインストール。
（導入はこちらを参考にさせて頂きました↓
https://sttk3.com/blog/tips/xd/selectmenu.html
）
プラグイン内の「Marked Items」で「書き出し対象」のものがすべて選択される。
選択されたもののバウンディングボックスの上で右クリック ⇒ 「書き出し対象から削除」もしくは（shift + E）

※グループの入れ子が深いとできない可能性あり
laravel環境構築 および　migrateができず詰まったのメモ

##環境構築の手順
1  create your own .env file / .envファイルを作る

`cp .env.example .env.local`

*　.env.local is generally included in the .gitignore / .gitignoreファイルに.env.localが基本的に含まれている

Create your database, and put the login information in the .env.local file / データベースを作成し、ログイン情報を.env.localファイルに入れる

2  Copy your .env.local file to .env / .env.local ファイルを .env ファイルにコピーする

`cp .env.local .env`

3 Run composer / composer を実行する

`composer update`

4 Run npm install / npm install を実行する

`npm install`

5 Run npm / npm を実行する。 *npm updateしないとダメかも（下のハマったことに記載）

`npm run dev`

6 Create key / key を生成させる

`php artisan key:generate`

7 Run migration and seed / migrationとseed を実行する

`php artisan migrate`

`php artisan db:seed`

8 Serve on local machine / ローカルでホストする/サーバーの起動

`php artisan serve`


当たり前にローカルにデータベース作り忘れてたらダメ
##　ハマったこと
### php artisan migrateの失敗
画像のようなエラーが発生した。
以下の記事を参考に設定したが、上手くいかず。
[【Laravel】初期設定でDB設定(MySQL)にハマったので抜け方解説
](https://niwacan.com/1408-laravel-db-ini/)
database.phpと.envの設定を確認するもだめだった..
<img width="774" alt="スクリーンショット 2020-03-18 18.13.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/417196/761b5d08-7a30-03c2-e6f9-9688b6b6d371.png">

dbへの接続を確認することにした。もしかしたらパスワードが間違っているかもしれない。
そこで、`$ mysql -u root -p`で確認したら、そもそもパスワード設定してなかったわ笑

migrateした時には.envファイルdatabase.phpより優先的に読み込まれるので、.envファイルのパスワードを変更したらいけた。
しょうもないことに時間をかけてしまった

### npm install の失敗
`npm install`を実施するとエラーが発生。
npmパッケージで脆弱性がある場合に出るらしい。そこで、
1. npm audit fix
2. npm update ←これで脆弱性のパッケージの自動修正してくれる
3. npm isntall 

```
$ npm install すると

npm install

> fsevents@1.2.11 install /Users/aki/Desktop/karute/src/node_modules/fsevents
> node-gyp rebuild

  SOLINK_MODULE(target) Release/.node
  CXX(target) Release/obj.target/fse/fsevents.o
  SOLINK_MODULE(target) Release/fse.node
added 1122 packages from 503 contributors and audited 17454 packages in 20.645s
found 40 low severity vulnerabilities
  run `npm audit fix` to fix them, or `npm audit` for details
 
```
grepコマンドの--color=alwaysオプションを使うべきではない

# TL;DR
`grep`に色を付ける際は、`--color=always`**ではなく**`--color=auto`を使いましょう、という話です。
## 環境

```terminal
$ zsh --version
> zsh --version
> zsh 5.7.1 (x86_64-apple-darwin17.7.0)
```

## 背景と問題
タスクを進める過程で、以下のような構造のCSVファイルから、`col1`または`col2`が特定の文字列である行を抽出して`col3`の値が大きい順にソートする、というような処理がありました。

```test.csv
col1,col2,col3
a,a,10
a,a_1,20
a,a_2,5
a,a_3,10
a_1,a,25
a_1,a_1,30
a_1,a_2,20
a_1,a_3,10
```

例としてここでは、`col1`または`col2`の値が`a`である行を抽出する必要があったとします。
シンプルに、`a,`で`grep`したものを`sort`すれば目的の出力が得られるはずだと考えて、以下のコマンドを実行しました。

```terminal:ターミナル
$ grep 'a,' test.csv | sort -t ',' -k 3 -rn
```

```text:出力
a,a_1,20
a,a_3,10
a,a_2,5
a_1,a,25  # numerical sortされていない
a,a,10    # 同上
```
あれ？ なんで4、5行目が降順ソートされていないんだ？
パイプを使わずに`sort`単体で挙動を試したところ、`col3`での降順ソートは問題なく実行できる様子。
となると`grep`に原因があるのか？とアタリをつけて試行錯誤すること数十分（ツラい）。
問題のコマンドの出力をファイルにリダイレクトしてみた時、ようやく原因が分かりました。
## 原因
以下が、先程のコマンドの出力をテキストファイルにリダイレクトした中身です。

```text
[01;31m[Ka,[m[Ka_1,20
[01;31m[Ka,[m[Ka_3,10
[01;31m[Ka,[m[Ka_2,5
a_1,[01;31m[Ka,[m[K25
[01;31m[Ka,[m[K[01;31m[Ka,[m[K10
```
一見して「ナニコレ？」と面食らってしまいましたが、調べた結果、この特殊文字は**色付け用のANSI escape code**だと分かりました。
`.zshrc`で`export GREP_OPTIONS="--color=always"`としていたので、`grep`の検索パターンにマッチした部分に色付け用の特殊文字が挿入されたわけです。
今回の問題は、それによって4､5行目の`col3`が数値として解釈不可能な文字列になってしまい、降順数値ソートがうまく働かなかった、ということですね。
色付け設定が原因だと分かったところで、上記の行をコメントアウトして再度実行すると案の定上手くいきました。
  
## `grep`の`--color`オプション
「とはいえ色付けできたほうが見やすいし、何かないかな」と`grep`の`--color`について調べてみると、`never`,`auto`,`always`のいずれかが指定可能であり、それぞれ以下のような仕様だと分かりました。

- `never`：色を付けない
- `auto`：**標準出力がターミナルに繋がっている場合のみ**色を付ける（パイプやリダイレクトの際は色付けしない）
- `always`：常に色付け（**文字列を変更するので後続処理に影響を与える**）

こうして見ると、基本的に**`--color=always`に設定するメリットは薄い**と言ってしまってよさそうです。
視認性を高めるためにaliasや環境変数で指定する分には、`auto`でおそらく充分でしょう。
例外があるとすれば、`grep`の結果が長大化したときに`less`に渡して閲覧する、というような状況でしょうか。
`grep`の`--color`オプションは、実行時に渡した値が環境変数のそれに優先して使われるので、その際にだけ`grep --color=always`として`less`にパイプすれば、目的は果たせるかと思います。

## 参考にさせていただいた記事
[grepコマンドに色をつける](http://te2u.hatenablog.jp/entry/2013/10/18/222733)
[Different results in grep results when using --color=always option](https://stackoverflow.com/questions/24093365/different-results-in-grep-results-when-using-color-always-option)

## 教訓
問題の根本の原因は、プログラムを書き始めた頃の自分が「とりあえずbashよりzshのが高機能らしい」「この設定にしとけば便利らしい」と、聞きかじりの知識でターミナル環境を構築してしまったところにありました。
至極当たり前のことですが、先駆者のコードや設定を使わせてもらう際は、その目的と影響範囲を正しく認識しておくのが大切ですね...
ただ、**そのマインドを維持できるのもある程度の体系的な知識が有ってこそ**だと思いますので、今後も精進していきたいと思います。

過去の自分が何気なくコピペした`.zshrc`に時を超えて困らされるという、ある意味貴重な自戒の機会でした。
このささやかなハマり事例が、もし誰かのお役に立ったなら幸いです。
storage_path メソッドでstorageディレクトリのフルパスを求める

# 概要

ファイルの入出力が必要なシステムを実装していると、メモリ不足対策などで一時保存用処理でフルパスが必要な場合があります。

そのときに役に立つのが`storage_path` メソッドです。
実行するとLaravelディレクトリ直下の `storage` ディレクトリのフルパスを返します。
文字列を引数にすると、渡された文字列をサブディレクトリとして、連結したものを返します。

# 実行例

```php
// /path/to/laravel-route/storage を出力
echo storage_path();


// /path/to/laravel-route/storage/tmp_data を出力
echo storage_path('tmp_data');


// tmp_data ディレクトリが未作成の場合、mkdirメソッドで権限のゆるいディレクトリを作成する
if (!file_exists($tmp_file_dir = storage_path('tmp_data'))) {
    mkdir($tmp_file_dir, 0777, true);
}
```

storage_path メソッドで取得したフルパスは、`SplFileObject` や`fopen()`、`mkdir()` 等ファイルの操作系を利用する際に使えます。
YARPPで関連記事オブジェクトを取得しRSSフィード用に表示を整形

# 経緯
WordPressサイトで関連記事を表示するのに[Yet Another Related Posts Plugin (YARPP)](https://ja.wordpress.org/plugins/yet-another-related-posts-plugin)というプラグインを使用していました。
サイト内で関連記事を表示するのはプラグインの設定画面で事足りていたのですが、
RSSのフィードphp内では独自のルールで整形する必要があったため
YARPPの関連記事データを取得することができるか調べました。

## 環境
- WordPress 5.2.3
- YARPP 4.4

# 問題
WordPress管理画面の[設定 > YARPP > 表示設定 RSS/Atomフィード用]で
[自動的にフィードで関連記事を表示する]にチェックを入れた場合
カスタムテンプレートを設定しても下記の要素で強制的に囲まれます。

`<div class='yarpp-related-rss'></div>`

そこで[自動的にフィードで関連記事を表示する]を無効にして下記の関数をフィードphpで使用しました。


# 関数
`yarpp_get_related( $args, $reference_ID )`

|引数|必須/任意|説明|
|:-----------------|:------------------:|:------------------|
|$args|必須項目|記事取得に関するオプション。「使用可能オプション($args)」参照|
|$reference_ID|任意項目|post_id。指定がなければ現在の記事が対象になる|

## 使用可能オプション($args)

```php

$args = array(
    // Pool options: 取得される記事を決定するオプション
    'post_type' => array('post', 'page', ...),
    'show_pass_post' => false, // show password-protected postsパスワード付きの記事を表示
    'past_only' => false, // 比較元記事よりも前に公開された記事のみ表示
    'exclude' => array(), // term_taxonomy_idのリスト。リスト内のtermを設定された記事は除外される
    'recent' => false, // 最近公開された記事を制限するには'15 day', '20 week', '12 month'のように設定する
    // Relatedness options: 関連度の計算に関わるオプション
    // 比較対象元記事と候補記事の間のマッチスコアは「Weight」で判定される
    'weight' => array(
        'body' => 1,
        'title' => 2, // 大きい値ほど大きく評価される
        'tax' => array(
            'post_tag' => 1,
            ... // 評価項目として設定したいtaxonomyをweightと共に追加する
        )
    ),
    // タクソノミーと数値のセットで最低限の共通数を設定する
    'require_tax' => array(
        'post_tag' => 1 // 例えばこの場合は少なくとも1つのpost_tagが共通している
    ),
    // マッチスコアが最低限超えていなければならない値
    'threshold' => 5,

    // Display options: 表示オプション
    'limit' => 5, // 取得件数
    'order' => 'score DESC'
);

```

# コード例
```php
<?php
$rltd_args = array(
  // 関連記事を表示する最大件数
  'limit'    => 3,
  // ソート順を指定。 ソート順の対象と昇降順（ASCかDESC）を指定
  'order'    => 'score DESC'
);
$related_posts = yarpp_get_related($rltd_args);
foreach($related_posts as $related):
  // タイトル内に特定の記号が入る場合を想定して変換
  $title = htmlspecialchars($related->post_title);
?>
  <relatedlink title="<?php echo $title; ?>" link="<?php echo esc_url(get_permalink($related->ID)); ?>" />
<?php endforeach; ?>
```

# 参考
[Can I customize how YARPP displays?](https://ja.wordpress.org/plugins/yet-another-related-posts-plugin/#does%20yarpp%20support%20custom%20taxonomies%3F)
[テスト駆動開発(TDD)] 第21章 要約

# 概要
TDD本（※）の第21章を読んで要約したのでメモしておきます。
TDD本を読んで「ここで言ってることはどういうこと？？」となっている方の参考になれば幸いです。
※https://www.amazon.co.jp/dp/B077D2L69C/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1

# 第21章 要約

### 残りTODO
- [] テストメソッドが失敗したとしてもtearDownを呼び出す
- [] 複数のテストを走らせる
- [] 収集したテスト結果を出力する ◀︎ NEXT

### 次にやりたいこと
テストメソッドが失敗してもtearDownが呼ばれるようにしたい。
しかし、失敗したときに落ちずにtearDownが呼ばれるようにすると、落ちないので失敗した場所がわからない。
なので、失敗した場所の例外をキャッチする必要がある。

テストを書く順番は重要で、筆者は次に書くテストを選ぶときは「何らかの気づきがある」か「動いたときに自信をもたらしてくれる」ものを選ぶ。
→「書こうとしているテストに少しでも不安があるときは、テストの対象を細分化して（TDD本的に言うと小さいステップに切り分けて）、目的や次のステップが明確なテストを先に書いて動かすべき」ということが言いたいのでは、と捉えたのですが、正直まだよく理解できていません。。読み進める中で理解できたら更新します。

テストが動くようになっても、その次のテストを書く手が止まってしまうようであれば、2歩戻ろう。

（２歩前） テストを考えて、書く（1つ前に書いたテスト）
↑（1歩前） テストが動く（1つ前に書いたテスト）
↑（現在） 次のテストを考えて、書く　→テストを書く手が止まっている

2歩前の「1つ前に書いたテストを考える」ステップまで戻って考え直そう、ということだと思う。


### TesyResult（テスト結果）のテストを追加する

まずは、「テストの実行数、失敗数、失敗の内容」という感じでテストツールっぽい実行結果を出したい。
ただ、いきなりフレームワーク自動的に全てのテスト結果（どのメソッドがどんな理由で落ちたかなど）をレポートさせるのは難しい（ステップが大きすぎる）。

一歩目として、1つのテストを走らせたときに結果を記録したTestResultを返すようにするのがいいのでは？
これだと一つの結果しか扱えないが、まずはこれくらいの小さいステップで着手することが大事。

>[ソース更新]
TesyResultのテストメソッド、テスト実行コードを追加。

### 仮実装

次に仮実装。

[ソース更新]
TestResultクラスを追加し、結果内容を返すsummaryメソッドを作成（仮実装なので返り値はベタがきの文字列）。
runメソッドがTestResult（テスト結果）を返すように更新。

### 仮実装を本物に近づける①

テストが通ったので、仮実装してたTestResultクラスのsummaryメソッドを本物に近づける。

>[ソース更新]
TestResultのコンストラクタでrunCount（テスト実行数）に１を代入するようにする。（まず小さいステップで進める。）
ベタがき文字列だった返り値の「テスト実行数」の表示部分にrunCountが表示されるようにする。

ひとまず定数になっているrunCountは、本来、テスト実行ごとに増えるべきなので修正する。

>[ソース更新]
runCountの初期値を０とし、テスト実行ごとにインクリメントするためのtestStartedメソッドを追加。

runメソッドの中で作りたてのtestStartedメソッドを呼ぶ。

>[ソース更新]
runメソッドの中で生成したTestResultインスタンスに対してtestStartedメソッドを実行し、runCountをインクリメントする。

### 仮実装を本物に近づける②

もう1つのベタがき数字（失敗数のほう）を本物にしたい。
テストを書こう。

>[ソース更新]
テスト失敗時のテスト（testFailedResult）を追加。
↑でテストされるテスト失敗（例外を上げる）メソッド（testBrokenMethod）を追加。

### 残りTODO
- [] テストメソッドが失敗したとしてもtearDownを呼び出す
- [] 複数のテストを走らせる
- [x] 収集したテスト結果を出力する
- [] 失敗したテストを出力する ◀︎ TODO追加

### 小さいテストを足そう

テストを実行すると、"raise Exception"をキャッチしていないため、落ちてしまう。
Exceptionをキャッチして記録するようにしたいが、（ステップが大きいので）一旦棚に上げて、もっと小さいテストを足そう。

第22章へ >>
メモリ使用率の確認

# TL;DR

[github](https://github.com/johnn26/mman)から"memory.sh"をDLしてご利用ください。  
コマンド実行後、"memory_size.txt" というファイルが生成されますので、
そちらからどのプロセスがどのくらいの使用しているか確認可能です。
使用量が多い順にソートされます。

## コマンド

```bash
./memory.sh
```

## 動作確認環境

OS : RHEL/CentOS 7.*

## シェルスクリプト解説

重要でないところは、省きます。


### 全プロセスのステータスファイルからメモリ情報を取得

```bash
# get memory data
for pid in $(grep VmSize /proc/*/status | cut -d/ -f3) ;do
name=$(grep Name /proc/$pid/status)
memorysize=$(grep VmSize /proc/$pid/status)
echo "-$name/PID:$pid/$memorysize"; echo
done
```

### 取得したデータを整形し、ソート


```bash
# shaping information
sed -i -e '/^$/d' -e 's/\t//g' -e 's/ //g' $temp
sed -i '/^grep/d' $temp 

# sort informaiton
sed "s/kB//g" $temp |sort -r -n -k 4 -t : > $output
```

### 取得したデータ確認

TL;DRでも記述しましたが、
memory_size.txtというファイルが同ディレクトリに内に生成されますので、そちらを確認してください。

#### 取得したデータ確認方法

/ がデミリタで左から

プロセス名、プロセスID、メモリ使用量(KB)

となっています。

```bash
-Name:sshd/PID:20073/VmSize:112920
```
SurfingKeysでデコードされたURLをクリップボードにコピーする

SurfingKeysのデフォルト設定では、 `yy` コマンドでコピーされるURLはエンコードされたURLです。

```
例: https://www.amazon.co.jp/%E4%BB%BB%E5%A4%A9%E5%A0%82-%E3%81%82%E3%81%A4%E3%81%BE%E3%82%8C-%E3%81%A9%E3%81%86%E3%81%B6%E3%81%A4%E3%81%AE%E6%A3%AE-Switch/dp/B084HPGQ9W
```

ですが実際にほしいURLはデコードされたURLなことがしばしばあります。

```
例: https://www.amazon.co.jp/任天堂-あつまれ-どうぶつの森-Switch/dp/B084HPGQ9W
```

現存のSurfingKeysの `yy` マッピングを上書きしてやる感じでURLをデコードされたものに変換した上でクリップボードに保存すればできます。
[公式の実装部分](https://github.com/brookhong/Surfingkeys/blob/0dea804ffb1ed6a56e59a900b4ebf833d5337a90/pages/default.js#L433-L435)を参考に実装しました

```js
// マッピングするキーはお好みで
mapkey('yy', "Copy current page's decoded URL ", function() {
    let url = window.location.href;
    Clipboard.write(decodeURI(url));
});
```

別になにかしら工夫した点は一切なく、ただ単に[decodeURI](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/decodeURI)を使用してURLをデコードするだけです。

以上
共有フォルダの設定（Linux→Windows）

#DL samba
```
sudo dnf  -y install samba
```
# 共有フォルダーの準備
```
sudo mkdir /home/share
sudo chmod 777 /home/share
sudo cp サンプルファイル /home/share/.
sudo chown nobody:nobody /home/share/
ll /home/
```
# confを編集
```
sudo vim /etc/samba/smb.conf

---
#使わない部分をコメントアウト
#[printers]
#       comment = All Printers
#       path = /var/tmp
#       printable = Yes
#       create mask = 0600
#       browseable = No

#[print$]
#       comment = Printer Drivers
#       path = /var/lib/samba/drivers
#       write list = @printadmin root
#       force group = @printadmin
#       create mask = 0664
#       directory mask = 0775
#以下のshareを追加
[share]
        comment = Sample Share
        path = /home/share
        public = yes
        browseable = yes
        writable = yes
        guest ok = yes
        guest only = yes
---

```
#samba userを作る
```
pdbedit -a -u hogehogeuser -f "Samba test user"
sudo pdbedit -L
```
firewallを開け、SELinuxの設定
 
```
sudo firewall-cmd --permanent --zone=public --add-service=samba
firewall-cmd --reload
sudo setsebool -P samba_enable_home_dirs on 
```

#smbを開始する
```
sudo systemctl restart smb.service 
sudo systemctl restart nmb.service 
sudo systemctl enable nmb.service 
sudo systemctl enable smb.service 
```

#windows側
```
ドライブを割り当て（PC>コンピューター＞ネットドライブの割り当て）
\\ipaddress\share
---
user id と　passwordでログイン
事前にコピーしたサンプルファイルを確認・編集できるようになる
---
```
R shiny-serverためのCentos 8をinstallした

# Centos 8 の install
Centos 7のyumが壊しましたので、作り直しました。
折角ですので、Centos 8にしました。

ここ (https://www.centos.org/download/) からimageを入手。
8G超えのため、単層のDVDに焼けません。
Rufus (https://forest.watch.impress.co.jp/library/software/rufus/) でBoot用USBを作りました。
以下のサイトを参考し、Centos8を入れ、言語、ユーザ、ipなどを設定しました。
https://www.rem-system.com/centos-linux8-install/

# Folderの英語化
ログインした後は、まず、Terminalを立ち上げ、以下のコメントでFolderを英語化。
（日本語のfolder名は使い勝手が悪い。）

```
LANG=C xdg-user-dirs-gtk-update
```

#日本語を入力可能にする
```
dnf  -y install ibus-kkc
```
yumも使えるけど、dnfへのlinkなので、
折角ですので、dnfを使うように。

一旦、OSを再起動します。

ログイン時にユーザ名を入力後、パスワード入力画面で
「サインイン」横の歯車マークをクリックし、「クラシック（X 11ディスプレイサーバー）」を選択します。
次にパスワードを入力します。

 
ログイン後、
右クリックー「設定（Setting)」ー「Region&Language」を選択します。
次に入力ソースで「日本語（漢字）」追加します。
これで日本語入力が出来るようになります。

切替は、Macの場合「Shift」＋「Command」＋「スペース」で選択できます。

(https://ameblo.jp/arcadia-8160/entry-12553884495.html)

# 最新にupdate
``` 
sudo dnf checkupdate
sudo dnf update
```

#selnuxを閉じる
```
getenforce

sudo vim /etc/selinux/config
---
SELINUX=disabled
---
#再確認 
getenforce
---
Disabled
---
sudo reboot 
```

#chromeを入れる
https://qiita.com/shadowhat/items/51273b3fe547fad74d2d
```
sudo dnf localinstall google-chrome-stable_current_x86_64.rpm
```

#install httpd
```
sudo dnf httpd
sudo systemctl start httpd

cd /etc/httpd/conf.d/
sudo mv welcome.conf welcome.conf.org
sudo mv autoindex.conf autoindex.conf.org
sudo httpd -t
sudo systemctl restart httpd
```
他の_config fileの設定は以下の以前書いた内容を参考。
https://qiita.com/testmemo/items/0d3a8bd62eb1b907070c
#Rを入れる
```
sudo yum install https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
sudo dnf config-manager --set-enabled PowerTools

sudo dnf install R
```

#shinyを入れる
```
sudo su - \
-c "R -e \"install.packages('shiny', repos='https://cran.rstudio.com/')\""
```

#rstudio-serverとshiny-serverを入れる
```
wget https://download2.rstudio.org/server/fedora28/x86_64/rstudio-server-rhel-1.2.5033-x86_64.rpm
sudo dnf localinstall rstudio-server-rhel-1.2.5033-x86_64.rpm
wget https://download3.rstudio.org/centos6.3/x86_64/shiny-server-1.5.13.944-x86_64.rpm
sudo yum install --nogpgcheck shiny-server-1.5.13.944-x86_64.rpm

#firewallを開けて
#3838 for Rshiny 3838 for R studio
sudo firewall-cmd --add-port=3838/tcp --permanent
sudo firewall-cmd --add-port=8787/tcp --permanent
sudo systemctl restart firewalld

sudo systemctl start shiny-server.service
sudo systemctl start rstudio-server.service 
sudo systemctl enable shiny-server.service
sudo systemctl enable rstudio-server.service 
```

#RCurlなどのR packageのインストール失敗の解決策
```
sudo dnf install libcurl-devel
```

#install mecab
```
sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
sudo dnf install mecab mecab-devel mecab-ipadic git make curl xz patch
sudo ln -s /usr/lib64/libmecab.so.2.0.0  /usr/lib64/libmecab.so
sudo su - \
-c "R -e \"install.packages('RMeCab', repos='https://cran.rstudio.com/')\""
```
Powershell 総ファイルサイズ(byte)取得

Powershellでフォルダ配下(サブフォルダを含む)の総ファイルサイズ(byte)を取得する方法です。

## 結論
```powershell
dir -r -Force | measure -Property Length -Sum | select Sum
```

## コマンド作成までの経緯
### フォルダ配下のファイル情報を取得

```powershell
dir -r -Force
```

dirはGet-ChildItemのエイリアス(別名)です。
Get-childItemはフォルダ配下のファイル情報を取得するPowershellの関数です。
そこにオプション-r(ちゃんと書くなら-Recurse)を付与することで、サブフォルダを含むフォルダは以下のファイル情報を取得することができます。

2023/05/31追記
dir -rだと隠しファイルが表示されないため、 隠しファイルも表示するオプションである-Forceを追加しました。
nさんご指摘ありがとうございます。

### ファイルサイズだけ指定して合計値を取得する

```powershell
dir -r -Force | measure -Property Length -Sum
```

先程のdirコマンドにパイプ(|)を使用して、ファイルサイズだけ取得して合計値を返却する関数を使用します。
measureはmeasure-objectのエイリアスでパイプ以前の関数から返却されたobjectのプロパティを指定して合計値を取得する関数です。
今回はファイルサイズだけ使用したいので、Lengthだけ指定しています。

### ファイルサイズの合計が格納されたプロパティを取得する
```powershell
dir -r -Force | measure -Property Length -Sum | select Sum
```

measure関数はCount、Average、Sum、Maximum、Minimum、Propertyを返却します。
上記返却値のうち欲しい情報はSumのみなのでselect関数を使用してSumを取得します。
select関数はSelect-Objectのエイリアスで、パイプ以前に返却されたオブジェクトのプロパティを選択して、出力する関数です。

## まとめ
以上でフォルダ配下(サブフォルダを含む)の総ファイルサイズを取得するコマンドが完成しました。
ぜひ皆さん使ってみてください。
pandasで特定の複数列(カラム)を抽出する

# TL;DR

strアクセサを用いることで部分一致で簡単にカラム指定のマスクが作れる。(例: `df.columns.str.contains('任意の列名')`)

## 複数列をまとめて抽出する

ポイントは

- columnsを参照してその中に含まれる文字列を参照する。
- 最終的に出来上がるのは列を含むか否かのbooleanを含んだリストになる

なので、活用するなら

```python
# この場合は任意の複数列を取り出す
include_list = df.columns[df.columns.str.contains('hoge_') * df.columns.str.contains('fuga_')]
df_prep = df[include_list]
```

```python
# この場合は任意の複数列以外を取り出す
# Point: チルダ(~)を使うことでマスクを反転させている
exclude_list = df.columns[~df.columns.str.contains('hoge_') * ~df.columns.str.contains('fuga_')]
df_prep = df[exclude_list]
```

またオプションには `case` (大文字小文字の区別), `regex` (正規表現パターンの利用) があるので、柔軟につかえる。

## strアクセサの応用

今回はカラムに対して行ったが、たとえば特定の列内から任意の文字列を抽出したいときにも同様にできる。

```python
df['user'].str.contains('Ruri')
```