OmniAICreator/Qiita-1.07M huggingface dataset:
Python + py-staticmaps で OpenStreetMap や地理院地図の画像を取得する

## 概要

- Python 用ライブラリの [py-staticmaps](https://github.com/flopp/py-staticmaps) を使って OpenStreetMap や地理院地図の画像を取得する

## 今回の環境

- macOS Catalina + Python 3.9.0 + py-staticmaps 0.1.1

## py-staticmaps のインストール

py-staticmaps パッケージをインストールする。

```
$ pip install py-staticmaps
```

依存ライブラリとして pycairo や s2sphere 等もインストールされる。

## OpenStreetMap の地図画像を取得する

ソースコード。

```py
import staticmaps

# Context オブジェクトを生成してズームレベルと緯度・経度を指定
# 緯度・経度は create_latlng で生成した s2sphere.LatLng オブジェクトを指定
context = staticmaps.Context()
context.set_zoom(17)
context.set_center(staticmaps.create_latlng(35.170560, 136.882090))

# 画像の横幅と縦幅を指定して pycairo の cairo.ImageSurface オブジェクトを取得
image_surface = context.render_cairo(800, 600)

# 地図画像 PNG ファイルを出力
image_surface.write_to_png('osm.png')
```

実行結果。

![osm.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/65d2452e-f42f-14bd-8e91-01e4a8f6e313.png)

## 地理院地図の地図画像を取得する

ソースコード。

```py
import staticmaps

# 国土地理院の地理院タイル用の TileProvider オブジェクトを生成
tile_provider_chiriin = staticmaps.TileProvider(
  name='chiriin',
  url_pattern='https://cyberjapandata.gsi.go.jp/xyz/std/$z/$x/$y.png', # 地理院タイルURL
  attribution='Source: Geospatial Information Authority of Japan', # 日本語が使えないので英語表記
  max_zoom=18, # 使用可能な最大ズームレベル
)

# Context オブジェクトを生成して TileProvider とズームレベルと緯度・経度を指定
context = staticmaps.Context()
context.set_tile_provider(tile_provider_chiriin)
context.set_zoom(14)
context.set_center(staticmaps.create_latlng(35.170560, 136.882090))

# 画像の横幅と縦幅を指定して pycairo の cairo.ImageSurface オブジェクトを取得
image_surface = context.render_cairo(800, 600)

# 地図画像 PNG ファイルを出力
image_surface.write_to_png('chiriin.png')
```

実行結果。

![chiriin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139365/584e29f0-efa3-0f0a-775d-366e18aee446.png)

## 参考資料

- [GitHub \- flopp/py\-staticmaps: A python module to create static map images with markers, geodesic lines, etc\.](https://github.com/flopp/py-staticmaps)
- [Tiles \- OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/Tiles)
- [Zoom levels \- OpenStreetMap Wiki](https://wiki.openstreetmap.org/wiki/Zoom_levels)
- [Tile Usage Policy (OSMF Operations Working Group)](https://operations.osmfoundation.org/policies/tiles/)
- [地理院地図｜地理院タイルについて](https://maps.gsi.go.jp/development/siyou.html)
- [地理院地図｜地理院タイル一覧](https://maps.gsi.go.jp/development/ichiran.html)
- [Surfaces — Pycairo documentation](https://pycairo.readthedocs.io/en/latest/reference/surfaces.html#cairo.ImageSurface)
- [API — s2sphere 0\.2\.5 documentation](https://s2sphere.readthedocs.io/en/latest/api.html#s2sphere.LatLng)
インターネット、web、ネットワークの違いを小学生でもわかるように説明してみた

なんとなく使っているネットワーク(ネット)、インターネット、webの違いについて明確にわからなかったので図を使って説明しようと思います。

##ネットワークとは?
複数のコンピュータを、ケーブルや無線などを使ってつなぎ、お互いにデータをやりとりできるようにした仕組み。複数のコンピュータを接続して、データを共有化したり、他のコンピュータの機能を利用したり、通信網のこと。 もっとも小さな単位のネットワークは、家庭や会社において、何台かのコンピュータを接続したものになる


##インターネットとは?
インターネットは、家や会社、学校などの単位ごとに作られた１つ１つのネットワークが、さらに外のネットワークともつながるようにした仕組み。世界のコンピュータが繋がるネットワーク（通信網）でもある。


##ネットワークとインターネットのイメージ
![スクリーンショット 2020-11-01 14.56.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/e0e80e79-e3b9-4608-ca34-1aa50f8e646e.png)


##webとは?
インターネットという通信網を利用して、文書データで表された画像や文章、映像・音楽などの情報を発信したり見たりすることができる仕組みのこと


##インターネットとwebのイメージ
![スクリーンショット 2020-11-01 14.57.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/ceb02848-2f13-2be4-6fee-f391d48d68ae.png)

##まとめ
「ネットワーク」
データを遠隔でやりとりできるようにした仕組み。
「インターネット」
ネットワークとネットワークの繋がり
「web」
インターネットを活用して利用できるデータ

※専門的な用語を使わないようにしているので正確性に欠けるかもしれません。
Go言語の特徴満点なHello world

以前ツイートしていたGo言語の特徴満点なHello worldを、Qiita記事とて残しておきます。

"Hello, #番号 world" を0〜99番、goroutineで並列処理して表示させる、というシンプルな目標を実装しているだけです。しかし、意外とGo言語の中枢に踏み込むコードが必要で、面白いです。

チャネルを使わないと途中で終わっちゃいますし、ちゃんとgoroutineに引数を渡してあげないと番号が重なってしまいます。実はツイートした時はこれらの対応をしておらず、今回記事化するために真面目に実行してみて、途中で終わっているとか変なことに気付きました。笑

ソース

```Go
package main

import "fmt"

func main() {
	max := 100
	quit := make(chan bool, max)
    for i := 0; i < max; i++ {
        go func(j int) {
			fmt.Printf("Hello, #%v world\n", j)
			quit <- true
		}(i)
	}
	for i := 0; i < max; i++ {
		<- quit
	}
}
```

実行結果

```
Hello, #4 world
Hello, #0 world
Hello, #1 world
Hello, #14 world
Hello, #16 world
Hello, #15 world
Hello, #20 world
Hello, #9 world
Hello, #5 world
Hello, #3 world
Hello, #6 world
Hello, #17 world
Hello, #21 world
Hello, #18 world
Hello, #12 world
Hello, #7 world
Hello, #11 world
Hello, #10 world
Hello, #23 world
Hello, #19 world
Hello, #2 world
Hello, #22 world
Hello, #24 world
Hello, #8 world
Hello, #25 world
Hello, #63 world
Hello, #27 world
Hello, #59 world
Hello, #28 world
Hello, #60 world
Hello, #66 world
Hello, #99 world
Hello, #67 world
Hello, #62 world
Hello, #68 world
Hello, #44 world
Hello, #85 world
Hello, #87 world
Hello, #58 world
Hello, #33 world
Hello, #72 world
Hello, #39 world
Hello, #45 world
Hello, #41 world
Hello, #74 world
Hello, #90 world
Hello, #36 world
Hello, #46 world
Hello, #91 world
Hello, #47 world
Hello, #26 world
Hello, #55 world
Hello, #71 world
Hello, #97 world
Hello, #57 world
Hello, #75 world
Hello, #76 world
Hello, #37 world
Hello, #92 world
Hello, #43 world
Hello, #13 world
Hello, #61 world
Hello, #65 world
Hello, #32 world
Hello, #38 world
Hello, #31 world
Hello, #54 world
Hello, #98 world
Hello, #48 world
Hello, #94 world
Hello, #49 world
Hello, #77 world
Hello, #95 world
Hello, #89 world
Hello, #93 world
Hello, #51 world
Hello, #56 world
Hello, #70 world
Hello, #88 world
Hello, #73 world
Hello, #34 world
Hello, #35 world
Hello, #52 world
Hello, #42 world
Hello, #79 world
Hello, #82 world
Hello, #53 world
Hello, #64 world
Hello, #83 world
Hello, #78 world
Hello, #96 world
Hello, #80 world
Hello, #86 world
Hello, #30 world
Hello, #40 world
Hello, #29 world
Hello, #69 world
Hello, #84 world
Hello, #81 world
Hello, #50 world
```
user-data-dirを設定しているSelenium WebDriverでChromeのheadlessモードだと落ちる


```ruby
profile_dir =  File.expand_path("profile",__dir__).encode("UTF-8")

U_d_Dir = "--user-data-dir=" + profile_dir
options = Selenium::WebDriver::Chrome::Options.new(args: ["--headless" ,'--no-sandbox', U_d_Dir])
driver = Selenium::WebDriver.for :chrome, options: options
```

参考
【未解決】user-data-dirを設定しているSelenium WebDriverでChromeのheadlessモードが利用できない
https://teratail.com/questions/142395
chromedriver で headless と user-data-dir のオプションを同時に指定するとエラーが発生する
https://ja.stackoverflow.com/questions/51441/chromedriver-%E3%81%A7-headless-%E3%81%A8-user-data-dir-%E3%81%AE%E3%82%AA%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%90%8C%E6%99%82%E3%81%AB%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B%E3%81%A8%E3%82%A8%E3%83%A9%E3%83%BC%E3%81%8C%E7%99%BA%E7%94%9F%E3%81%99%E3%82%8B
MySQL5.7のパスワード変更方法

MySQL5.7をインストールした際に、初期パスワードが何かわからず困惑したため残しておきます。

## パスワード確認方法
~~~bash
$ sudo cat /var/log/mysqld.log | grep root@localhost
# パスワードが表示される。
[Note] A temporary password is generated for root@localhost: 12桁の文字列
~~~

## パスワード変更方法
~~~bash
$ mysqladmin -uroot -p password
Enter password:古いパスワード
New password:新しいパスワード
Confirm new password:新しいパスワード
# Warnigがでても変更はできています
Warning: Since password will be sent to server in plain text, use ssl connection to ensure password safety.
~~~

**パスワードポリシー**

* パスワード長　8文字以上
* 大文字　1文字以上
* 小文字　1文字以上
* 数字　1文字以上
* 記号　1文字以上

## 参考
[Passwordのポリシーについて](https://blog.pinkumohikan.com/entry/workaround_for_mysql_password_policy)
POSIXErrorCode: Connection reset by peer

SwiftのTCP/IPクライアントで送信した時、
failed POSIXErrorCode: Connection reset by peer
というメッセージが出る時は、サーバー側の問題らしい

自分用メモ

参考
https://www.366service.com/jp/qa/891b10c5977a31cd4c76dd0027f33a4c
MMSeq2 を導入する

# はじめに
MMSeq2を使うと、高速でblastができるらしいので入れてみる
（DiamondよりE-valueの扱いが適切らしい）
raw readを直で遺伝子に当ててHGTを探すとかの利用を想定

元論文
https://www.nature.com/nbt/journal/vaop/ncurrent/full/nbt.3988.html

githubのページ
https://github.com/soedinglab/MMseqs2

#　インストール
cmakeでいれる

K生研biasのヒトは

`scl enable devtoolset-3 bash`

を売ってGCCを4.9に上げる

ソースをおとしたら中に入って　

`mkdir build`

する

そして

`cmake -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=. ..`


makeファイルが無事できたら

`make`

`make install`


ディレクトリ中に
/MMseqs2/build/bin/mmseqs
/MMseqs2/build/util/bash-completion.sh

ができる。

`/MMseqs2/build/util/bash-completion.sh`
が初期化用スクリプトなので

.bash_profile　で毎回読み込むように書いておく

`source path/to/mmseqs/util/bash-completion.sh`

#　テスト
githubに草が生えない

##githubのContributionsに草が生えない

```
git config user.email
```
でローカルのemailとgithubに登録してるemailが一致しているか確認。何もでない場合は登録されていないです。ローカルにemailを登録していない、もしくは違ってた場合、下記のコマンドを実施。

```
git config --global user.email example@exampl.com
```
example@exampl.comの所にgithubに登録してるメールアドレスを入力し実行。これで全リポジトリ共通のe-mailアドレスをローカルに登録したことになります。リポジトリごとにuser.e-mailを変えたい人はオプションがあるので調べてみてください。

#解決
だいたい草が生えていないのはgithubとローカルの登録しているemailが違う場合がほとんどです。
setTimeoutの使い方

#setTimeout

```html
<h3>全ての色が混ざり合うと白くなるものは何か？</h3>
<h4 id="temporaryBox" class="temporaryBox">加法減色
 <p><img src="img/rgb.png" alt=""></p></h4>
<p>
<input type="button" value="答えを見る" id="btnShowBox" class="btn" onclick="showBox();">
</p>
```

```js
let timerId;

// ボックスを表示して、タイマーを開始
function showBox() {
  document.getElementById("temporaryBox").style.display = "block"; // ボックスを表示
  timerId = setTimeout( closeBox , 5000 ); // タイマーを開始
  document.getElementById("btnShowBox").disabled = true; // 表示用ボタンを無効化
}
// ボックスを消して、タイマーを終了
function closeBox() {
  document.getElementById("temporaryBox").style.display = "none"; // ボックスを消す
  clearTimeout( timerId ); // タイマーを終了
  document.getElementById("btnShowBox").disabled = false; // 表示用ボタンを有効化
}
```

![スクリーンショット 2020-11-01 14.52.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/633943/5258005a-f6a3-cff2-29d6-6be4d6653de2.png)
Laravelプロジェクトを作った後の動き

Laravelプロジェクト作った後に何をするか！フロー

【環境】
サーバー：ubuntu 
web：   apache2

【フロー】
①Apache2のドキュメントルート変更
②AllowOverride All変更奴
③RewriteEngine on
④サーバー再起動
⑤オーナー・パーミッションを調整


①Apache2のドキュメントルート変更
---

```
cd ~
cd /etc/apache2/sites-available/
ls
000-default.conf  default-ssl.conf←この２つを変更する

```
```
000-default.conf

上の方にある
DocumentRoot /var/www/laravelプロジェクト名/public に変更
```

```
default-ssl.conf

上の方にある
DocumentRoot /var/www/laravelプロジェクト名/public に変更
```

②AllowOverride All変更奴
---
```
cd ~
cd /etc/apache2/
sudo vim apache2.conf ←変更してゆく
```
```
最下層から少し上がったとこに、似たようなのが複数あるから以下を追記

<Directory /var/www/laravelプロジェクト名/public> 
        Options Indexes FollowSymLinks
        AllowOverride All
        Require all granted
```

③RewriteEngine on
----
```
sudo a2enmod rewrite
```
④サーバー再起動
----
```
 sudo service apache2 restart
```

⑤オーナー・パーミッションを調整
---
```
cd ~
cd /var/www/

sudo chown -R ubuntu:www-data laravelプロジェクト名

sudo find laravelプロジェクト名 -type d -print | xargs -i chmod 750 {}

sudo find laravelプロジェクト名 -type f -print | xargs -i chmod 640 {}

sudo chmod -R 770 laravelプロジェクト名/storage/

sudo chmod -R 770 laravelプロジェクト名/bootstrap/cache/
```
Terraformとは？

#Terraformとは？

> HashiCorp社が提供するTerraformは、
マルチクラウド上のコンピュータやネットワークの構築を自動化する、
エンジニアにとても人気のあるツールです。

---

##特徴
- インフラの構成をコードで宣言 
- コードを元に、構築・変更・破棄ができる 
- AWS GoogleCloud Heroku Dockerなど、様々なインフラに対応

---

##Terraformのメリット

- インフラをコードで管理できるようになった
- バージョン管理もできるようになり変更も容易

- GUIを使わず、構築・変更・破棄ができる
ポチポチからの解放
- コードを共有・再利用ができるパクれる。
車輪の再発明は、しない。させない。ゆるさない。
- コードのバージョン管理(Git)ができる
インフラの変更が容易に（変更、破棄も簡単）
- 設定適用前にコードレビューができる
インフラ構築の安全性向上

---

##Terraformの使い方

1. コードで、インフラリソースを定義 
`.tfファイル `

1. ドライ・ラン機能を実行　内容確認 
`$ terraform plan`

1. 設定を適用
`$ terraform apply`(少し時間がかかる)

1. 構築結果を確認
`$ terraform show`

---

##今回の構成

- 権限を持ったIAMユーザーを作成済
- IAMユーザーのアクセスキー、シークレットキーを発行済
- pemファイルはコンソール上で作成済み
- MacにTerraform,AWSCLIをインストール済

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313771/7a81c361-f396-8dee-b241-84ba18bce634.png)


---

##参考にした記事（いつもありがとうございます。）


[5分で分かるTerraform（Infrastructure as Code）
](https://www.lac.co.jp/lacwatch/service/20200903_002270.html)

---
スマブラSPの今開催されているトーナメントが大乱闘なのか1on1なのか判定するスクリプトを作った

気になったらいつでも判定できるようにブックマークレットにした。

```javascript
javascript:(
  function(){
    let basis = new Date(2020, 9, 31, 15, 0, 0);
    let now = new Date();
    let elapsed = now - basis;
    let range = 48 * 60 * 60 * 1000;
    let quotient = elapsed / range;
    let digit = Math.floor(quotient) % 2;
    let result = '1 on 1';
    if (!digit) {
      result = '大乱闘';
    }
    let remainder = elapsed % range;
    let until = new Date(now.getTime() + range - remainder);
    let day = ['Sun.', 'Mon.', 'Tue.', 'Wed.', 'Thu.', 'Fri.', 'Sat.'];
    result += ` until: ${until.getMonth() + 1}/${until.getDate()} (${day[until.getDay()]}) ${until.getHours()}:${('0'+until.getMinutes()).slice(-2)}`;
    alert(result);
  }
)();
```

実行するとこんな↓感じ。
![Capture.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/607235/a26422e6-618f-8f13-bdb0-5277b148747a.png)
満足。
Aura Enabledリクエストでは、セッションIDがAPI呼び出しを行うことができない

\:cloud: Metadata API
原文：https://salesforce.stackexchange.com/questions/110515/getting-session-id-in-lightning

#概要
1. 現在、Lightningコンポーネントには＄Apiグローバル変数はありません。 {！ ＄Api.whatever}は常に失敗します。
2. これは現時点では意図的なものです。 LightningコンポーネントでAPI対応のセッションIDを取得するための公式/サポートされている方法はありません。繰り返しますが、これは仕様によるものです。
3. ほんの少しの創造性と巧妙さで、{！を使用して必要最低限​​のVisualforceページを作成できます。 $ Api.SessionID}、次にApexからgetContent（thatPage）を呼び出して、API対応のセッションIDを含むページを取得します。これは簡単にパースできるはずです。

そこから、AuraEnabledメソッドを介してそのセッションIDをLightningコンポーネントに渡すことは難しくありません。

ただし、明確にしましょう。これはハックであり、パフォーマンスが低下します。また、API対応のセッションIDをLightningコンポーネントコードから除外するのには十分な理由があります。

#回避策
そのため、Lightningで機能するための回避策として、推奨されないハックを作成することになりました。

次のように単純なVisualforceページを作成するだけです。

```MetadataSessionId.vfp
<apex:page>
    Start_Of_Session_Id{!$Api.Session_ID}End_Of_Session_Id
</apex:page>
```


次に、visualforce_Page.getContent（）メソッドを使用してセッションIDを取得します。次のようになります。

```
public static MetadataService.MetadataPort createService()
{
    MetadataService.MetadataPort service = new MetadataService.MetadataPort();
    service.SessionHeader = new MetadataService.SessionHeader_element();
    //service.SessionHeader.sessionId = UserInfo.getSessionId();
    PageReference pageRef = new PageReference('/apex/MetadataSessionId');
    service.SessionHeader.sessionId = MetadataUtils.getSessionIdFromVFPage(pageRef);
    return service;
}
```

```
global class MetadataUtils {
    global static String getSessionIdFromVFPage(PageReference visualforcePage){
        String content = visualforcePage.getContent().toString();
        Integer s = content.indexOf('Start_Of_Session_Id') + 'Start_Of_Session_Id'.length(),
                e = content.indexOf('End_Of_Session_Id');
        return content.substring(s, e);
    }
}
```
そして、使用できる有効なセッションIDを取得しました。
IFTTTでTwitter投稿をDiscordにも自動投稿できるように簡単実装してみた

#完成形
Twitterで投稿したツイートをDiscordにも自動で投稿して共有できるようにしてみました。
比較的簡単にできるIFTTTを利用してます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725039/e1b0b2bc-bc16-b02a-c0e6-7be928a41333.png)

Qiita投稿記事やnote投稿記事を色んな人に読んでほしいので、TwitterだけでなくDiscordでも連携出来ると良いなと思い作成。Twitter投稿だけでDiscordにも送信されるのでちょとだけ楽になる。

#実装手順
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725039/407dc58c-77fe-df9d-9b29-270bb9edea5e.png)
※Twitter検索にしている理由は、Discode連携するタグや内容を絞り込みたかったから。

###Discode側でWebhookを設定

１．投稿先のチャネルに移動し、「連携サービス」から「新しいウェブフック」を作成
　　※スマホ版アプリでは設定不可。Web版かDesktop版アプリから設定が必要。

２．ウェブフックURLをコピー（IFTTTでWebhooksのURLに貼り付け）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725039/7cac8a3f-472b-771e-ad5c-632eb7f6c489.png" width="600">

###IFTTT側でアプレット作成
１．【If This】で、「Twitter」→「New tweet from search」を選択

２．「Search for」に検索条件を入力。　※[Twitterの検索条件は別記事にメモ](https://qiita.com/PmanRabbit/items/202e12808c787988c423)
　・ユーザーID：自分のユーザID
　・タグ：#protooutを含む　かつ　#Qiita　か　#note　を含む
　・種類：リプライ、リツイートを含まない

```
  (from:@PmanRabbit) #protoout (#Qiita OR #note) lang:ja -filter:replies -filter:retweets
 ```

３．【Then That】で、「Webhooks」→「Make a web request」を選択

４．設定内容
　**URL**：DiscodeのウェブフックURL
　**Method**：POST
　**Content Type**：application/json
　**Body**：{"content":"{{CreatedAt}}\n{{LinkToTweet}}"}
　　CreateAT：ツイート時間
　　LinkToTweet：ツイートのURL
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/725039/113641bd-9023-1576-e9c2-ddbf762335e9.png" width="700">

#まとめ
IFTTTを使えばかなり簡単にアプリ連携できることが分かりました。
単純な自動化ならまずIFTTTで実装を試してみると良いかもしれない。ほんとに簡単なことしかできないみたいなので。。
rails+postgresqlのDocker構築を公式通りやったけどうまく行かなかったので一部修正した

## 前提
macOS Catalina
Docker for Mac 2.3.0.5

## 公式
[Quickstart: Compose and Rails](https://docs.docker.com/compose/rails/)

## コード
### Dockerfile
公式通りの記述でやっていったらいきなり諸々エラーになった為、ググって足りないもの追加しました。
他、公式のrubyはバージョン2.5ですが、2020/11/1最新の2.7.2にしました

公式

```Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

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

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]
```

↓

```Dockerfile
FROM ruby:2.7.2
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y nodejs postgresql-client yarn
# 以下同じ
```

### Gemfile
公式ではrailsのバージョンは5ですが、2020/11/1最新の6にしました

公式

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

↓

```Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6.0.3', '>= 6.0.3.4'
```

### docker-compose.yml

公式や他の記事通りにしてもなぜかDBが永続化されずに心折れかけましたが、こちらの方法で解決しました。
https://github.com/docker/compose/issues/5012#issuecomment-316518185


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

↓

```docker-compose.yml
version: '3'
services: 
  db:
    image: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
      PGDATA: /var/postgres_data # 追加
    volumes: 
      - ./tmp/db:/var/postgres_data # 修正
    ports:
      - "5432:5432"
  web: # 同じ
```

※フロントをReact等のportが3000のもので作成する場合は、競合を避ける為
```ports:　"3001:3000"```
にしてrailsサーバーに接続する時は3001を指定します。
(or フロント側のportを変える)

## 手順
基本的な手順はこちらの動画がわかりやすかったので参考にしてください。
[【rails環境構築】docker + rails + mysql で環境構築（初心者でも30分で完了！）](https://www.youtube.com/watch?v=Fq1PH0Gwi8I)
※こちらの動画はpostgresqlではなくmysqlでrails5、ruby2.5です

## DB接続

※コンテナ起動していないとつながりません
![スクリーンショット 2020-11-03 9.55.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566220/2a8fc39b-a393-d577-f135-21c61a2d8697.png)

`Name` 自由
`User` docker-compose.ymlのPOSTGRES_USERに記述されているものを設定
`Password` docker-compose.ymlのPOSTGRES_PASSWORDに記述されているものを設定
`Database` `myapp/config/database.yml`　の`development:database`に記述されているものを設定
【備忘録】エラー集

内容：
<details><summary></summary>
原因：
<br>
対策：
</details>


#apache

#laravel

内容：
<details><summary>publicを省略したエイリアス設定をした時、ウェルカムページ以外がサーバーエラーとなる。</summary>
原因：
無限リダイレクトしている<br>
対策：
pablic配下にある.htaccessに
RewriteBase /アプリ名
を追記する。
</details>

内容：
<details><summary>419：Page Expired
</summary>
原因：
@csrf　が抜けている　or セッションによるエラー<br>
対策：
@csrfを記載　or　strage/flamework/session　の中身削除

内容：
<details><summary>Access denied for user 'root'@'localhost' (using password: NO)
</summary>
原因：
phpmyadminとローカルのmysqlの場所は異なる。
<br>
対策：
phpmyadminのポートが８８８８でローカルのポートが３３０６の場合、laravelのdatabase.phpと.envのポートを作成したデーターベースのポートに合わせる。

内容：
<details><summary>SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client (SQL: select * from information_schema.tables where table_schema = quick_laravel and table_name = migrations and table_type = 'BASE TABLE'<br>
php artisan migreteで発生
</summary>
原因：
認証方式に問題あり
<br>
対策：
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'uepon8888';でrootの認証方式を変更する。

#VirtualBox

内容：
<details><summary>VirtualBoxが起動しない場合 Error relaunching VirtualBox VM Process: 5
</summary>
原因：
HPのパソコンにインストールされている「HP　Sure　Sense」というセキュリティーソフトがはじいている。
<br>
対策：
（１）「HP Sure Sense」を開く。
（２）設定
（３）「脅威から強化された保護」をオフにする。

内容：
<details><summary>sambaを導入し、ホストPCからVirtualPC上のCentOSのファイルにアクセスできないエラー</summary>
原因：
Windows Updateにより「SMBv1を無効化」されたため、アクセスできなくなった。
<br>
対策：
コントロールパネル
↓
Windowsの機能の有効化または無効化
↓
SMB 1.0/CIFS ファイル共有のサポート
↓
自動的にインストール開始
↓　
再起動<br>
ファイルアクセス可能となっている。
</details>

内容：
<details><summary>VirtualBox上でCentOSを動かし、設定を変更し反映させるべくrebootをかけると設定が元に戻ってしまう。
</summary>
原因：
OSイメージで
CentOS-6.4-i386-LiveDVD.iso
liveDVDは、仮想光学ディスクにDVDをマウントしているだけの状態なので、そこからインストールしなければ、当然rebootをかけると初期化される
<br>
対策：
仮想DVDからハードディスクにインストールする。
もしくは
CentOS-6.4-i386-bin-DVD1.iso
CentOS-6.4-i386-bin-DVD2.iso
の２つをダウンロードしてフォーマットする。
</details>

#Docker

内容：
<details><summary>docker-compose run --rm -dするも
npm WARN saveError ENOENT: no such file or directory, open '/package.json'
怒られる。</summary>
原因：
runした位置が悪いのか？確かに/配下にpackage.jsonはない。あるのは、/src配下。
<div>

```Dockerfile.
FROM node:12
RUN npm install ejs
```
</div>
対策：
そこで下記にしてみる。
<div>

```Dockerfile.
FROM node:12
WORKDIR /src
RUN npm install ejs
```

</div>
エラーは生じず。
</details>
gitコマンドで、未追跡ファイルを一括削除

# tl;dr
`git clean`コマンドで未追跡ファイルを一括削除できます。

# デモ
現在のカレントブランチを初期状態に戻したいとします。
`git status`コマンドでブランチの状態を確認すると、変更ファイルが１つ、未追跡ファイルが２つあります。

```
$ git status
On branch develop
Your branch is up to date with 'origin/develop'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   src/index.js

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        core.33
        core.43
```

`git checkout .`コマンドを実行したあと、再度`git status`コマンドでブランチの状態を確認すると、未追跡ファイルが２つ残っています。

```
$ git status
On branch develop
Your branch is up to date with 'origin/develop'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        core.33
        core.43
```

そこで、`clean`コマンドで未追跡ファイルを一括削除します。

```
$ git clean -df
Removing core.33
Removing core.43
```

一括削除前に、どのファイルが削除対象なのか確認することもできます。

```
$ git clean -n
Would remove core.33
Would remove core.43
```

未追跡ファイルがクリアされ、完全に初期のブランチの状態に戻りました。

```
$ git status
On branch develop
Your branch is up to date with 'origin/develop'.

nothing to commit, working tree clean
```

以上。
Decoratorって知ってる？

# Decoratorとは、、？
既存のオブジェクトを新しいDecoratorオブジェクトでラップすることで既存の関数やクラスの中身を直接触ることなく、その外側から機能を追加したり書き換えたりする。また、既存のクラスを拡張する際にクラスの継承の代替手段として用いられます。

「（プログラムで管理しやすい）データ」を「（ユーザーが理解しやすい）情報」に変換する役割。使うためには「draper」というgemをインストールして利用する。app/decorators配下にファイルを生成する。

##使い方
1.Gemfileに以下を記述する。

```ruby

gem 'draper'
```

合わせてこちらも実行する。

```ruby

$ budle install
```

2.以下コマンドを実行して、application_decorator.rb を作成する。

```ruby

$ rails generate draper:install
```

3.以下コマンドを実行してデコレーターを作成する。

```ruby

# rails generate decorator モデル名

$ rails generate decorator Article
```

モデル

```app/decorators/article_decorator.rb

class ArticleDecorator < Draper::Decorator
  delegate_all

  def publication_status
    if published?
      "Published at #{published_at.strftime("%A, %B %e")}"
    else
      "Unpublished"
    end
  end
end
```

ビュー

```ruby
・
・
・
<%= @article.publication_status %>
・
・
・
```

##小技集
- モデルインスタンスにアクセス

```ruby

object.published_at.strftime("%A, %B %e")

model.published_at.strftime("%A, %B %e") # modelはobjectのalias
```

- 全てのメソッドを委譲
    - 内部的にはmethod_missingを使い委譲している
    - メソッド探索の順番: デコレータ -> 親デコレータ -> モデル

```ruby

class ArticleDecorator < Draper::Decorator
  delegate_all
end
```

- 指定のメソッドを委譲
    - deleageメソッドはActive Supportのdelegateとほぼ同じ。ただしto: :objectを省略できる。

```ruby

class ArticleDecorator < Draper::Decorator
  # titleで、object.titleにアクセスできるようになる
  delegate :title, :body

  # 指定のメソッドを指定したオブジェクトに委譲する
  delegate :name, :title, to: :author, prefix: true
end
```

##参考
[Rails Viewの表示のためにDecoratorを用意してHelperとModelを助ける](https://qiita.com/shizuma/items/ce9e863e9c94e88e0a57)

[Decoratorの役割とDraperについて](https://qiita.com/jonson29/items/00077b54bb91ed74fdb8)

[Draperの使い方 まとめ](http://nekorails.hatenablog.com/entry/2018/10/13/070437)
RDSの作成・ログ設定・ローカルからの接続方法

#読者対象
RDSの作成やログ設定をしたことがない方。
ログの種類やbassionを用いたローカルからRDSへの接続方法まで解説します。
新卒エンジニアがプライベートや業務で得た知見をまとめた内容になっています。

#RDSの基本的な構成
![スクリーンショット 2020-11-20 16.41.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510817/f5142404-8adb-d0ff-04d3-845995cf12b2.png)


#RDSには作成前やること
####RDSサブネットグループを作成
RDSサブネットグループとは、RDS作成時にどのネットワークに割り当てるか決める時に必要になる。
まずRDSを配置するVPCを選択する、そのVPCに割り当てられたサブネットを選択する。
その時に、2種以上のAZに割り当てられたサブネットを割り当てないといけない。
例えばこんな感じ。。
ap-northeast-1c. 10.0.2.0/24
ap-northeast-1a 10.0.1.0/24

補足：CIDRとAZに関して。
CIDRとAZは分けて考えた方が良いかと思いました。
VPCの中にCIDRを分けてサブネットを作る、そのサブネットを様々なAZに置けるよって感じ。そう考えるとスッキリ考えれる気がします。

####RDSのためのセキュリティーグループ作成
セキュリティーグループはインスタンスに設定するもの。
RDSはプライベートサブネットに置き、EC2やlambdaからの接続のみ許可することが多い

#RDS作成
DBエンジンやネットワーク、ログ設定などを行って作成します。

ちなみにRDSの内容を変更する際は、メンテナンス日に適用するか、すぐに適用するかの二択が選べる。

#ログ設定
ログには大きく分けて4種類ある。一般ログ、スロークエリログ、エラーログ、監査ログである。

####一般ログ
sqlのクエリの実行内容が出力される。接続元の情報は出力されないのでそれがしたければ監査ログを設定する。
https://weblabo.oscasierra.net/mysql-log-1/

設定する際にはパラメーターの変更が必要になり、RDSに紐づいているパラメーターグループのパラメータを変更する必要がある。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.MySQL.html#w607aac21c26c35c23b9:~:text=general_log%20%3D%201

####スロークエリログ
遅いsqlのクエリの実行内容が出力される。
https://weblabo.oscasierra.net/mysql-log-1/

設定する際にはパラメーターの変更が必要になり、RDSに紐づいているパラメーターグループのパラメータを変更する必要がある。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_LogAccess.Concepts.MySQL.html#w607aac21c26c35c23b9:~:text=slow_query_log%20%3D%201

####エラーログ
RDSの接続などに失敗したときなどのエラーを出力する。パラメータの変更は不要。

####監査ログ
RDSへの接続に関するログを出力。
https://weblabo.oscasierra.net/mysql-log-1/#text-ad1:~:text=%E7%9B%A3%E6%9F%BB%E3%83%AD%E3%82%B0,-(MySQL
4つめの出力パラメーターで接続元のhostがわかったりする。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Auditing.html#AuroraMySQL.Auditing.Logs

設定するのにオプションの値を変更しなければいけない。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.MySQL.Options.AuditPlugin.html
これに関しては、オプショングループのオプション値を変えて設定する場合やパラメータグループのパラメータを設定する場合などがある。詳しくはわからない。

補足
今のRDSの接続元の情報をログ出力ではなく、SQL文で知りたい場合は以下のSQLを実行するとわかる。

```sql
以下に挙げている二つのうちどちらかを実行すると、わかる
SELECT * FROM INFORMATION_SCHEMA.PROCESSLIST;

show processlist;
```
https://qiita.com/snaka/items/b6e7500c96e04c131d9e

#ローカルからRDSに接続する方法
基本的にRDSはプライベートサブネットに配置するので、ローカルから直接接続することはできない。
なのでその仲介サーバとしてbassionをEC2で立てて接続してあげる。

https://dev.classmethod.jp/articles/rds-portforward/
https://harmful-spam.link/fcf8a825-40a9-4d94-8c00-e49698633e64/
https://qiita.com/nago3/items/1cd6daa5ad6377e325ed

注意
ポートフォワーディングをしてローカルからEC2を介してRDSにいく設定をしてあげないといけない。それをローカルでバックグラウンド実行(-f)でやってあげるのを忘れない
【Python】コロナについてのツイートをWordCloudで可視化してみた

#はじめに
機械学習に使うためにツイートを収集したのですが、せっかくなので可視化をしてみました。
その方法を、ここに残しておきます。
#対象者
・Pythonのプログラムをある程度書ける
・wordcloudに興味がある方
#環境
Python 3.8.3
mecab-python3 
##WordCloudとは
WordCloudは、文章中で出現頻度が高い単語を複数選び出し、その頻度に応じた大きさで図示する手法。ウェブページやブログなどに頻出する単語を自動的に並べることなどを指す。文字の大きさだけでなく、色、字体、向きに変化をつけることで、文章の内容をひと目で印象づけることができる。(デジタル大辞泉の解説より)

簡単に言うと、単語の出現頻度を分かりやすいように可視化するというとです。
これを容易に実装してくれるライブラリがpythonにあります。
本記事を読んでいただくと、下図のようなものを作れるようになります。
![Figure_2 1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/842766/3f6daf6c-9997-82db-a205-0d53e0230790.jpeg)
#MeCabとは
文章を形態要素解析してくれるライブラリです。
文章・フレーズを「意味を持つ最小限の単位」に分解すること。
例えば、
「私は会社でプログラミングをします」 という文章を形態素解析を行うと、
「私 / は / 会社 / で / プログラミング / を / し / ます」　のように最小限の単位に分割できます。

このライブラリを用いることで、上のWordCloudのように単語のみを抽出できます。
#データ収集
実際にはTwitterAPIを用いたツイート取得を行い約7万件のデータ収集しましたが、その方法は今回は割愛します。
今後、自分の中で最適なプログラムが組めたらまた別で記事を書くかもしれません。

#WordCloudの生成
最後にWordCloudを生成するのですが、WordCLoudは日本語のフォントに対応ていないため、ここから
(https://moji.or.jp/ipafont/ipa00303/)
4書体パック(Ver.003.03)をダウンロードし、適当な場所に回答した後、**ipag.ttf**という名前のファイルを、下のプログラムと同じ階層においてください(わかる方はフルパスでも大丈夫です)。
word_except_fileには「コロナ」「感染」など、その単語と関係することが容易にわかるような単語を除外できるように、「コロナ」に近しい言葉が入っています。
また、形態要素解析でどうしても出てきてしまうような不要単語も除外リストに入っています。

**実行方法**
python3 makeWordCloud.py colona_data.txt except_word_list.txt

分かる方は適宜自分の環境に書き換えてください。

```makeWordCloud.py
import MeCab
import sys
from matplotlib import pyplot as plt
from wordcloud import WordCloud

args = sys.argv
input_file = args[1]
word_except_file = args[2]

# テキストファイル読み込み
with open('input_file', mode='rt', encoding='utf-8') as fi:
    source_text = fi.read()

# MeCabの準備
tagger = MeCab.Tagger()
tagger.parse('')
node = tagger.parseToNode(source_text)

# 名詞を取り出す
word_list = []
while node:
    word_type = node.feature.split(',')[0]
    if word_type == '名詞':
        word_list.append(node.surface)
    node = node.next

# 除外ワードの読み込み
except_word_list = []
f = open(except_word_file)
for i in f:
    except_word_list.append(i.rstrip())

# リストを文字列に変換
word_chain = ' '.join(word_list)

# ワードクラウド作成
W = WordCloud(width=640,height=480,background_color='white',font_path="./ipag.ttf",stopwords = except_word_list).generate(word_chain)

plt.imshow(W)
plt.axis('off')
plt.show()

```
#最後に
初めてQiitaに投稿したので、分からない点なども多かったですが、楽しかったです。
不明な点や、改善すべき点などがあればコメントでお願いします。
またなにか思いついたら投稿してみようと思います。
それでは。
Amazon Cognito / ユーザープール 概要

Amazon Cognitoのユーザープール(認証機能提供サービス)機能の概要についてまとめる。

## 概念
### ユーザープール
* 独自のユーザーディレクトリ、アプリへのアクセスに利用できるトークンを提供する機能

### ユーザー
* 作成方法：ユーザー自身 or 管理者

  * 外部 IDプロバイダーのユーザは、初回サインイン時に情報が自動的に登録される。

* 属性情報
  * Cognito固有情報：ユーザー名、ステータス、ロール、...
  * 標準属性(OIDC準拠):メールアドレス、電話番号、...
  * カスタム属性：上記で定義されていない独自情報
  * サインインに用いたデバイス情報：デバイスキー、名前、IP、...
* サインイン
  * 利用可能な情報
        * ユーザープール作成時に、設定※作成後の変更不可。
        * ユーザー名、メールアドレス、電話番号...+パスワード＋MFA系情報

* ステータス(ライフサイクル)
  ![AWS_cognito_user_lifecycle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/a52ee479-526c-0e7a-3552-a41abbfaceb3.png)


* グループ

  * ユーザーの管理単位
  * 1ユーザーは複数のグループに所属可能
  * IAMロールの割り当てや優先順位の指定可能

### アプリクライアント

* Cognitoに登録したユーザープールにアクセスするアプリケーション。

* 利用可能な機能や権限の設定が可能。

* IAMクレデンシャル不要

* Cognitoはアプリケーション向けに払い出したクライアントID、シークレットで識別を行う。

* 設定項目※利用するAPIによって異なる。

  * 全般設定：ID、シークレット、認証フロー
  * アプリ統合：連携外部IDプロバイダー、コールバックURI(リダイレクトURI)、サインアウトURL、許可するOAuthフロー

  ![AWS_cognito_app_client.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/16bb1969-91f4-ebbf-30ab-59396b1800f6.png)


## サインイン実装
### Cognito Identity Provider API利用

* サインイン/アップ、ログイン、パスワード変更/再設定、ユーザー属性変更などを行うことができるAPI。
* ユーザープール独自のユーザーを利用する場合に推奨。
  * 外部 Id プロバイダーにサインインするための認可エンドポイントへのリンクをUIに配置する。
  * ユーザ名・パスワードの入力フォームをUIに用意する。
* Admin API
  * 管理者としてサーバーから呼び出す。
  * API認証情報として、IAMロールクレデンシャルを利用する。サインイン時はアプリクライアントID必要。
* 非Admin API
  * ユーザーとして、サーバーおよびクライアントから呼び出す。
  * API認証情報として、クライアントID(+シークレット)を利用。サインイン後は、ユーザー向けに払い出したトークンを利用する。
* サインインに利用する認証フロー
  * `USER_SRP_AUTH`：SRPプロトコルに基づいた方法。パスワードを基にしたチャレンジレスポンスで認証する。サーバー側でも元のパスワードは不明な状態になるなど安全なフロー。 
  * `CUSTOM_AUTH`：認証時に Lambda ファンクションがトリガーされ、ファンクション次第で追加の認証を行って認証する。 
  * `USER_PASSWORD_ AUTH`：SRPプロトコルを使用せず、パスワード自体を送って認証する。**クライアントからは `USER_SRP_AUTH` の利用を推奨**。 
  * `ADMIN_USER_PASSWORD_AUTH`：`USER_PASSWORD_AUTH` と類似したフロー。違いはサーバー用 API からのみ呼び出せる点。 
  * `REFRESH_TOKEN_AUTH`：リフレッシュトークンから新しいトークンを取得する。 

### Cognito Auth API と Hosted UI 利用

* Cognito がマネージドサービスの一部として、サインアップ、サインイン、パスワード忘れの対応を行うことができる `Web  UI `を提供する。
* ユーザープール独自のユーザーを利用しない場合は、こちらを推奨。
  * 外部 Id プロバイダーにサインインするための認可エンドポイントへのリンクのみを配置したUI を用意する。
* 多要素認証（MFA）に対応。 
* ドメイン名、UI のロゴ、CSS のカスタマ イズが可能
* **日本語対応は不可**
* 対応するOAuthフロー
  * Authorization Code Grant **※こちらのほうがセキュアなため推奨**
  * Implicit Grant

## サインイン後実装
### トークン

* **IDトークン**
  * 有効期限：1時間
  * 用途
    * Cognito IDプールにアクセス
    * アプリAPIにアクセス
* **アクセストークン**
  * 有効期限：1時間
  * 用途
    * アプリAPIにアクセス
    * Identity Provider API にユーザとしてアクセス
* **リフレッシュトークン**
  * 有効期限：1～3650日
  * 用途：IDトークン・アクセストークンを更新

※各トークンはJWT形式(OAuth,OIDCと同様)

### サインアウト実装方法

* トークンをアプリ or SDKでクライアントから破棄。
* Identity Provide API(ユーザーとして呼び出し)のグローバルサインアウト利用。
* Auth APIでログアウトエンドポイントで無効化。


## 参考情報

* [[AWS Black Belt Online Seminar]Amazon Cognito](https://d1.awsstatic.com/webinars/jp/pdf/services/20200630_AWS_BlackBelt_Amazon%20Cognito.pdf)
LaravelなしでEloquent ORMを使う方法

## Eloquent ORMインストール

```sh
composer require illuminate/database
```

## bootstrap.php作成

`bootstrap.php`ファイルは`composer.json`と同様の位置に保存すること

```php
require "vendor/autoload.php";

use Illuminate\Database\Capsule\Manager as Capsule;

$capsule = new Capsule;
$capsule->addConnection([
   "driver" => "mysql",
   "host" => "localhost",
   "database" => "test_db",
   "username" => "root",
   "password" => "root",
   "port" => "3306",
]);

$capsule->setAsGlobal();
$capsule->bootEloquent();
```

## モデル作成

モデルを`<document-root>/db`の中に格納する前提で作成

```php
// <document-root>/db/Notice.php
use Illuminate\Database\Eloquent\Model as Eloquent;

class Notice extends Eloquent
{
   protected $fillable = [
       'title', 'contents',
   ];
 }
```

## Autoload設定追加 & autoload再設定

`composer.json`に下記設定追加

> モデルのフォルダーがdbであるため、値がdbになります。

```json
"autoload": {
    "classmap": [
        "db" 
    ]
}
```

設定後、

```sh
composer dump-autoload --optimize
```

## `Notice.php`使用

`<document-root>/index.php`で使用する場合を想定して作成

```php
<?php

require('bootstrap.php');

$noticeList = Notice::all();

var_dump($noticeList);
exit();
```
Combine.Futureのイニシャライザに渡すクロージャを非同期に実行するExtension

### なにこれ？

FutureってFutureパターンのFutureじゃないの？
なんで生成時既に値が確定してるの？
それってJustじゃね？

クロージャ内でDispatchQueueを使って非同期にしてみたけど、面倒くさい。
ということで作ってみました。


```swift
import Combine

extension Future {
    
    convenience init<S: Scheduler>(on scheduler: S, _ attemptToFulfill: @escaping (@escaping Promise) -> Void) {
        
        self.init { promise in
            scheduler.schedule {
                attemptToFulfill(promise)
            }
        }
    }
}
```


### 使い方

```swift

let future = Future<Int, Error> { promise in
                 DispatchQueue.global().async {
                     sleep(1)
                     promise(.success(1))
                 }
}
```

これが

```swift
let future = Future<Int, Error>(on: DispatchQueue.global()) { promise in
                 sleep(1)
                 promise(.success(1))
}
```

こうなります。
Twitterの検索演算子（メモ）

#IFTTT
####New tweet from search
新しいツイートが検索クエリに一致するたびに発生するトリガー。

#Twitter検索演算子
　[Twitter公式（高度な検索）](https://help.twitter.com/ja/using-twitter/twitter-advanced-search)
　[twitterの検索術 -GitHub](https://gist.github.com/cucmberium/e687e88565b6a9ca7039)

**・(from:[userID])　**
　特定のユーザーからの投稿
**・to:[userID]**
　特定のユーザー宛の投稿
**・#[hashtag]**
　特定のハッシュタグを含む
**・[keyword]**
　特定のキーワードを含む
**・-[keyword]**
　特定のキーワードを含まない
**・[keyword1] OR [keyword2]**
　どちらかのキーワードを含む
**・filter:links**
　リンクを含む
**・filter:images**
　画像を含む
**・filter:videos**
　動画を含む
**・lang:ja**
　日本語のツイート

※filterは打消しも可
**・-filter:replies**
　リプライを含まない
**・-filter:retweets**
　リツイートを含まない

####例
**(from:@PmanRabbit) #protoout (#Qiita OR #note) lang:ja -filter:replies -filter:retweets**
　ユーザー：@PmanRabbit からのツイート
　タグ：#protooutを含む　かつ　#Qiita　か　#note　を含む
　言語：日本語
　その他：リプライを含まない　リツイートを含まない
[Rails]enumをもっと使いやすく！Enumelizeさん！

# enumelizeとは、、？
I18n と ActiveRecord/Mongoid/MongoMapper/Sequel のサポートを伴った enum 型の属性。
あるモデルをstatus(ステータス)で分類したい時などに使います。

##設定方法
1.Gemfileに以下を追記する。

```ruby

gem 'enumerize'
```

合わせてこちらも実行する。

```ruby

$ bundle install
```

2.モデルに以下の記述を追記する。

```ruby

class User
  extend Enumerize

  enumerize :sex, in: [:male, :female]
end
```

3.yamlファイルに以下の記述をする。

```yaml

ja:
  enumerize:
    user:
      sex:
        male: 男
        female: 女
```

##使い方

- 値を出力したい場合

```ruby

User.sex.values  # => ["male", "female"]

User.sex.options # => [["男", "male"], ["女", "female"]]

user = User.new

user.sex_value # => "male"
user.sex_text # => "男"
```

- セレクトボックスに利用したい場合

```ruby

<%= form_for @user do |f| %>
  <%= f.select :sex, User.sex.options %>
<% end %>
```

##参考
[RailsでEnumerizeの使い方](https://doruby.jp/users/TM/entries/Rails_Enumerize_)

[gem enumerize の README を翻訳しました](https://qiita.com/ikamirin/items/debb31a75a3b8abbb710)
Unityインストール （Mac編）


Unityのインストールと設定の手順を記載します。

少し情報が古いですが、こちらも参考になります。
https://techacademy.jp/magazine/1436


##

1. https://unity3d.com/beta/2020.2b
にアクセスして下さい。
1. [Download Unity Hub]をクリックします。
<img width="500px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41011/3bf9527c-ba0f-a57a-2249-3df1a836debc.png" />

1. Unityをインストールするにはまずこの「Unity Hub」というものが必要なので、UnityHubをインストールします。[Install version from Unity Hub]をクリックします。
<img width="500px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41011/775ef0a2-1736-c3d9-d3b5-a1e649df2921.png" />

2. インストール出来たら、UnityHubを開きます。（このSSは「2021.1.0a2」バージョンを既にインストールしている状態です。)
[ADD]をクリックします。
<img width="500px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41011/f105663c-1762-6ec4-4e95-dfaf2b46d619.png" />

2. Unityのバージョン選択する画面になるので、インストールしたいバージョンを選択して、「NEXT」
<img width="500px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41011/f69eee1f-77de-b5a8-8a09-778b249bc592.png" />

3. 次に追加したいモジュールを選択する画面になるので、選択して「DONE」。自分はiOSと連携されたいので、「iOS Build Support」モジュールのみ追加しました。
<img width="500px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41011/200766f8-7250-7f7f-c775-a94e61d1b5e0.png" />

3. 作成されたUnitがインストールできると下記のように「Installs」タブ画面に追加されます。
![スクリーンショット 2020-11-01 12.15.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41011/d2933d80-7007-35be-837b-7c5d60571067.png)
Word VBA 表( Table )の中( Cell)のハイパーリンクを削除するマクロ


#コード

```vb
Sub WordDeleteHyperlinksInCelofTable()
' For Microsoft Word
' Delete Hyperlinks All.
Dim wDoc As Word.Document: Set wDoc = ThisDocument
Dim wTbl As Word.Table, wTbls As Word.Tables
Set wTbls = wDoc.Tables
Dim i As Long
Dim wCel As Word.Cell, wCels As Word.Cells
Dim wRng As Word.Range
Dim wHyp As Word.Hyperlink, wHyps As Word.Hyperlinks
For Each wTbl In wTbls ' Tableがあることが前提。ないとエラー。エラー処理してないです。
wTbl.Select
For Each wCel In wTbl.Range.Cells 'Rangeに注意。Cellsというコレクションで受ける
If wCel.Range.Hyperlinks.Count > 0 Then
Set wHyps = wCel.Range.Hyperlinks '次にCellのRangeのHyperlinksになり、それを削除
For Each wHyp In wHyps
wHyp.Delete
Next
End If
Next
Next
End Sub
```
vue.jsを初めて学ぶ ⑤ [フィルターとミックスイン]

前回までの記事

[vue.jsを初めて学ぶ ① [hello world]](https://qiita.com/uechikohei/items/4e44380848d29bf3fd6a)

[vue.jsを初めて学ぶ ② [テンプレート構文]](https://qiita.com/uechikohei/items/dd857da50a3f0237c22b)

[vue.jsを初めて学ぶ ③ [レンダリング] ](https://qiita.com/uechikohei/items/6433c89813cde1c7f1f1)

[vue.jsを初めて学ぶ ④ [VueCLI 3.7.0 + Vue.js 2系のインストール] ](https://qiita.com/uechikohei/items/5f89c785177b7b5581f5)

[vue.jsを初めて学ぶ ⑤ [コンポーネントの扱いについて] ](https://qiita.com/drafts/61a12a977d2892c6167d/edit)

目次
---

[1. Vue.jsのフィルターとは？](#フィルターとは)
[1. Vue.jsのミックスインとは？](#ミックスインとは)


---

# フィルターとは

```text:main.js

Vue.filter("upperCase", function(value) {
 return value.toUpperCase();
});
```

```text:App.vue

//テンプレートタグ内
<h2>{{ title | upperCase}}</h2>

//スクリプトタグ内
export default {
  data() {
    return {
      title: "welcom vuejs"
    }
  }
}
```

**大文字に変換するupperCase関数がfilterにより適用された**


## ローカルフィルタを定義する

```text:App.vue

//テンプレート --->
    <h2>{{ title }}</h2>
    <h2>{{ title | upperCase }}</h2>
    <h2>{{ title | lowerCase }}</h2>
    // upperCaseが適用される
    <h2>{{ title | lowerCase | upperCase }}</h2>



//スクリプト --->
export defalut {
  filters: {
    lowerCase(value) {
      return value.toLowerCase();
    },
    upperCase(value) {
      return value.toUpperCase();
    }
}
```

**フィルターでは、thisが使用できない**
**thisでアクセスするためには、computedプロパティを使用する**
**リロードが高頻度の環境では、filterよりcomputedが便利**

---

# ミックスインとは

**コードの再利用**

```text:LikeNumber.vue

//テンプレート
    <p>いいね({{ harfNumber }})</p>
    <button @click="incriment">+1</button>

//スクリプト
import { likeNumber } from "@/likeNumber";
export default {
  mixins: [likeNumber],
};
```

```text:likeNumber.js

export const likeNumber = {
  props: ["totalNumber"],
  computed: {
    harfNumber() {
      return this.totalNumber / 2;
    }
  },
  methods: {
    incriment() {
      this.$emit("my-click", this.totalNumber +1);
    }
  }
}
```

1. **jsファイルに分離する**
2. **使用したいファイル内で、インポート**
3. **mixinsプロパティで、配列指定で呼び出す**
Anaconda3 × Pycharm環境構築メモ

Pythonド素人がAnaconda3とPycharmで環境構築を行いました。
備忘録として残しておこうと思います。

#####◆環境

- OS：Windows 10 Enterprise
- OSバージョン：1809
- OSビルド：17763.1518
- Pythonバージョン：3.8（Anaconda3）
- IDE：Pycharm Community（2020.2.3）

#####◆環境構築の流れ
まずはAnacondaとPycharm Communityをインストール。
[こちら](http://web.sfc.wide.ad.jp/~tinaba/tutorials/pythonsetup/index.html)のページを参考に実施。
つつがなくHello Worldまで実行完了。

※最初はPython公式とか色んなページ見ながらAnacondaとPycharmのインストールを行ったのですが、なぜかopenpyxlがインポートできない事態が発生。ちなみにエラーは次の通り。

```python:python
ModuleNotFoundError: No module named 'openpyxl'
```
実行環境ではopenpyxlをインストール済みで、コマンドプロンプトからopenpyxlをインポートする場合は問題なく実行できる。

・原因
　Pycharm（厳密にはPycharm上で作成したExcel処理プロジェクト）で使用している実行環境で、openpyxlがインストールされていなかった（Pycharm（というかPython？）では、各プロジェクトで個別に仮想の実行環境を持たせることができる。一つの仮想実行環境を使い回すことも可能）。

・対策
　Anaconda Navigatorで仮想環境を作成し、そこにopenpyxlをインストールすることで解決。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679836/ac834426-0655-1323-5d9c-5e1cf32327c6.png)

・対策（詳細手順）
1. Anaconda Navigatorを起動
2. Create（"+"のボタン）をクリック
3. "Name"でNaturalLanguage01、"Packages"でPython3.8を選択し、"Create"をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679836/98c5267f-7544-3bc0-5d7d-003947823f95.png)
4. ドロップダウンリストで"All"を選択し、検索ボックスで"anaconda"と入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679836/efd710de-7000-d59e-14b3-59957e655816.png)
5. "anaconda"にチェックして"apply"をクリック

対策っていうか、これがあるべき姿のような...ｗ

以上の手順で、"openpyxl"が（結果的に）インストールされたAnacondaの仮想実行環境が作成される。ここで作成された仮想実行環境のパスは後で必要になる。
※今回の場合は"C:\users\ユーザー名\Anaconda3\envs\NaturalLanguage01\python.exe"

続けてPycharmで、この実行環境を指定したインタプリタを追加する。

1. Pycharmを起動し、"File" → "Settings" → 任意のプロジェクト（今回は"Project: sampleOpenPyExcel"）→ "Python Interpreter"を開く
2. 画面右上の歯車アイコンをクリック → "Add"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679836/886d5e6c-c6c3-e6ac-4114-61c816b483e8.png)
3. "System Interpreter"をクリック → 画面右上の"..."をクリック
4. Anacondaで作成した仮想実行環境の直下にある"Python.exe"を探して選択し、"OK"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679836/8eaaae3a-a674-24a2-1294-158d0007a97c.png)
5. "Settings"ウィンドウを閉じ、"run" → "Edit Configrations"をクリック
6. 環境を適用したいプログラムファイルを選択し、"Environment" → "Python Interpreter"で先ほど追加した仮想実行環境を選択し、"OK"
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679836/713bdd03-3c46-8804-3f0c-33114f8e781d.png)

以上で設定完了。
ライブラリのインポートも行えるようになっていた。
react-railsでReactをRailsに導入

皆さんこんにちは、今回は「react-rails」というgemを使ってRailsにReactを導入する方法を紹介します。RailsにReactを導入する方法は複数ありますが、恐らくこれが容易で一般的なので選びました。注意点としてはRailsに依存した記述方になるので、好き嫌い分かれると思います。

因みに公式ドキュメントは下記のURLからアクセスできます。
react-railsのURL: https://github.com/reactjs/react-rails#server-side-rendering

下記の流れに沿って紹介していきます。

- 前提
- react-railsの導入
- componentの作成
- veiwで出力

## 前提
①既にrails-newなどでappを作成されている。
②rails5.0以降を使用

## react-railsの導入
Gemfileの一番下に下記を記述して下さい。

```Gemfile
gem 'webpacker'
gem 'react-rails'
```
※railsのバージョンによっては「webpacker」がデフォルトで入ってる場合があるのであらかじめご確認ください。
cdコマンドなどで対象のアプリディレクトリまで移動して下さい。
続いて下記のコマンドを順に実行しましょう。

```
$ bundle install
/*①*/ $ rails webpacker:install
/*②*/ $ rails webpacker:install:react
$ rails generate react:install
```
①と②のコマンドはrailsが5.0以降のバージョンでなければ実行できないので注意！

ひとまずこれで準備完了です！！

## componentの作成
Reactを記述するにはcomponentsというディレクトリの中にファイルを作っていくことが一般的です。
手動で作成するでも問題ないですが、公式ドキュメントに沿って作成してみましょう。
ターミナルなどで下記のコマンドを実行して下さい。

```
$ rails g react:component HelloWorld greeting:string
```
すると下記のファイルが作成されます。

```app/javascript/components/HelloWorld.js
import React from "react"
import PropTypes from "prop-types"
class HelloWorld extends React.Component {
  render () {
    return (
      <React.Fragment>
        Greeting: {this.props.greeting}
      </React.Fragment>
    );
  }
}

HelloWorld.propTypes = {
  greeting: PropTypes.string
};
export default HelloWorld

```

これでファイルの作成は完了です。

## veiwで出力
作成したcomponentからReactの内容を出力してみましょう。

```app/views/posts/index.html.erb
<%= react_component('HelloWorld', greeting: 'Mike') %>
```

ブラウザで出力内容を見てみましょう。
「Greeting: Mike」と出力されているはずです。

因みにcomponentsディレクトリ以外にも、自分でディレクトリを作成することもできます。
下記のコマンドを実行して下さい。

```
$ rails g react:component my_subdirectory/HelloWorld greeting:string
```

すると先ほど実行したコマンドではcomponentsディレクトリ下にjsファイルが作成されていましたが、今回は下記のようになります。

```app/javascript/my_subdirectory/HelloWorld.js
import React from "react"
import PropTypes from "prop-types"
class HelloWorld extends React.Component {
  render () {
    return (
      <React.Fragment>
        Greeting: {this.props.greeting}
      </React.Fragment>
    );
  }
}

HelloWorld.propTypes = {
  greeting: PropTypes.string
};
export default HelloWorld

```

コマンドで指定した「my_subdirectory」下にjsファイルを作成できました。
viewに呼び出す場合は下記を記述して下さい。

```app/views/posts/index.html.erb
<%= react_component("my_subdirectory/HelloWorld", { greeting: "Hello from react-rails." }) %>
```

ブラウザを確認すると「Greeting: Hello from react-rails.」と出力されているはずです。

react_componentメソッドで簡単に呼び出せるので便利ですね。
私もまだ導入したてなので、これから色々いじってみようと思います。

余談ですが、最近冷え込む日が多くなって来ましたよね。
悴み過ぎて、マネキン状態の手でキーボード打っています。（暖房付ければええやろ...）

最後まで読んでいただきありがとうございました！！
Vue.js 1ヶ月使ってみて まとめ１

## １ヶ月Vueを使って、実際に繰り返し見て、使った事のまとめ

## 基本的なテンプレート構文

```html:index.html

<div id="app">
   <p>{{ message }}</p>  <!-- Hello World と表示される -->
   <a>{{ sayHi() }}</a>  <!-- Hello World　と表示される -->
</div>

<script>
 new Vue({
    el: '#app',
    data: {
      message: 'Hello World' 
    },
    methods: {
      sayHi: function() {
        return this.message //vueでデータにアクセスしたい場合はthis.をつける
      }
    }
 })
</script>
```

##v-bindについて
aタグのhref属性にdataのurlを入れたい時

```html:index.html

<div id="app">
  <a href="{{ url }}">Google</a>　<!-- 誤 これではエラーが出てしまう -->
  <a v-bind:href="url">Google</a> <!-- 正　v-bind:hrefと記述すると正しくhref属性に値が入る -->　
  <!-- v-bindの省略記法として　<a :href="url">Google</a>　とも書ける -->
</div>

<script>
 new Vue({
   el: '#app',
   data: {
     url: 'https://google.com'
   }
 })
</script>
```
## v-bindの応用的な書き方

```html:inedx.html
<div id="app">
  <a v-bind:href="url">Google</a> 
  <a :[attribute]=“url”>Google</a> <!-- :[データ]と書くことで v-bindの属性をデータで扱える -->
</div>

<script>
 new Vue({
    el: '#app',
    data: {
    url: 'https://google.com',
    attribute: ‘href',
    },
 });
</script>
```
## 複数の属性をオブジェクト形式で指定できる
```html:index.html

<div id="app">
 <a v-bind=“twitterObjact">Twitter</a>   
 <!-- <a class=“twitter" href=“https://twitter.com” >Twitter</a>という表示になる -->
</div>

<script>
 new Vue({
    el: '#app',
    data: {
    twitterObject: { //オブジェクトをv-bindに使える
      class: 'twitter',
      href: ‘https://twitter.com'
    }
  }
});
</script>
```

## v-onについて
```html:index.html
<div id="app">
  <p>現在{{ number }}回クリックされています</p>
  <button v-on:click=“number += 1">カウントアップ</button> <!-- クリックした場合　numberが +1される -->
    <!-- <button v-on:click=“countUp>カウントアップ</button> でメソッドを使って同じように動く -->
</div>

<script>
 new Vue({
    el: '#app',
    data: {
    number: 0
    },
    methods: {
     countUp: function() {
      this.number += 1
      // thisをつけることによってデータにアクセスできる
     }
    } 
})
</script>
```
## eventの取得について
```html:index.html

<div id="app">
  <p v-on:mousemove=“changeMousePosition($event, num)”>マウスを載せてください</p>
  <p>X:{{ x }}, Y:{{ y }} </p> 
</div>

<script>
 new Vue({
    el: '#app',
    data: {
     x: 0,
     Y: 0
    },
    methods: {
     changeMousePosition: function(event, num) { // mousemoveイベントで発火した情報が $event　に入っているのでその値をデータに代入して使える
       this.x = event.clientX; 
       this.y = event.clientY;
     }
   } 
})
</script>
```
## イベント修飾子　.prevent
```html:index.html 
<div id="app">
  <a v-on:click.prevent href="https://google.com”>Google</a>
  <!-- v-on:clickの後にpreventとつけることで、.preventDefault();と同じ制御をしてくれる -->
  <!-- クリックしてもイベントは起きない -->

  <a v-on:click=“noEvent” href="https://google.com”>Google</a> <!-- 上と同じ意味 -->
</div>

<script>
 new Vue({
    el: '#app',
    data: {
    },
    methods: {
     noEvent: function(e) {
       e.preventDefault(); 
     }
   } 
 })
</script>
jQuery テキストエリアに文字が入力されたらsubmitボタンを有効にする

##経緯
Laravelで検索機能を実装しようとしてキーワードが入力されていないときのバリデーションをどうしようかと思ったけどボタンを押せなくすればいいじゃん。

多分同じ記事は腐るほどあると思うけど自分みたいなLaravel初心者がいるとしてここにたどり着いてくれるように祈りを込めて。（備忘録でもある）

##HTML

```html
<form action="#" method="GET">
    <input type="text" id="key_word_input" name="key_word" placeholder="キーワードを入力してください">
    <button type="submit" id="search_button">検索</button>
</form>
```

##jQuery
テキストボックスに変更があるたびにvalue属性を調べてdisabled属性を切り替える。

```javascript
var keyWord = $('#key_word_input');
var searchButton = $('#search_button');

$(searchButton).prop('disabled', true);

$(keyWord).on('change', function() {
    if($(keyWord).val()) {
        $(searchButton).prop('disabled', false);
    } else {
        $(searchButton).prop('disabled', true);
    }
});
```

##おわりに
調べなくてもちょっとずつjQuery書けるようになってきて嬉しい。

ちなみに肝心の検索機能はまだできていない。
できたらまたメモするかもしれないです。