OmniAICreator/Qiita-1.07M huggingface dataset:
AWS CloudFormation Master Class を受けてみた⑦「 Advanced Concepts」

##はじめに
Udemy にて Stephane Maarek 氏 が提供している「 [AWS CloudFormation Master Class](https://www.udemy.com/aws-cloudformation-master-class/) 」コースについて紹介していきます。最後の内容は「 Drift 」や「 Nested Stacks 」など CloudFormation のその他のサービスについて紹介していきます。

- これまでの AWS CloudFormation Master Class の記事
 - [その①「 CloudFormation について 」](https://qiita.com/Yoshiyuki03/items/ad21f72dbfb9c9eb32fa) 
 - [その②「 CFnを利用したS3環境の構築 」](https://qiita.com/Yoshiyuki03/items/3ad97bbb8b9d905fa9d9)
 - [その③「 CloudFormation Designer でテンプレートの作成 」](https://qiita.com/Yoshiyuki03/items/0a07133a24fc6806de15)
 - [その④「 Parameters について 」](https://qiita.com/Yoshiyuki03/items/c7506864cf8f6558dc5f)
 - [その⑤「 Resources と Mappings について 」](https://qiita.com/Yoshiyuki03/items/7bf27292df560a0fde6f)
 - [その⑥「 Conditions・Metadata・Init について 」](https://qiita.com/Yoshiyuki03/items/45a59ba38a14d10792fe)

##CloudFormation Drift
CloudFormation はインフラを構築してくれますが、update などで変更が起きた際の乖離（ドリフト）に対する サポートはCloudFormation にはありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321349/3fb598ef-75ce-d501-6364-f3bcc1d7cf5a.png)
このような問題に対応してくれるのが、CloudFormation drift です。この機能でドリフトを検出することで、スタックの設定がテンプレートの設定と異なっているかを確認できます。
※ただし、全てのリソースに対してはまだ対応できてないです。

##Nested Stacks
###Nested Stacks とは

Nested Stacks とは、他の stacks の一部として作成された stack のことです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321349/093829bf-e8ce-63a8-8f39-410f00a040be.png)
以下のような特徴があります。

- 繰り返しパターンや、一般的な構成スタックを個別に作成し、他スタックからの呼び出しが可能
- nested stack のアップデートには root stack のアップデートが必要
- nested stack に対して nested stack を用意することも可能

###Nested Stacks update and delete
Nested Stacks のアップデートと削除の際には、以下の点にそれぞれ注意する必要があります。

- Nested Stacks Update
 - アップデートされた nested stacks は 最初に S3 にアップロードする必要がある
 - その後、root stack もアップロードする
- Nested Stacks delete
 - 子 stack に対して削除や変更の設定を直接行ってはいけない
 - 常に、上層にある stack から変更させる必要がある


##Troposphere
Troposphere を利用することで CloudFormation のテンプレートを Python で作成することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321349/838a8103-86a8-ecc8-38a5-522dc569808b.png)

- メリット
 - テンプレートの type から始めることができる
 - 複雑な環境でも生成が可能

- デメリット
 - Python、JSON、そしてアップロードといった手順が必要
 - Python について理解しておく必要がある 


##Deletion Policy
Deletion Policy を利用することで、リソースを削除から保護したり、削除前にバックアップを取ったりすることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321349/475f504e-f945-a819-351d-610fd8c9d7a0.png)
Deletion Policy の種類とそれぞれの特徴は以下となります。

- Delete：AWS CloudFormation の全リソースとコンテンツの削除を実行
- Retain：スタックの削除が実行された際、リソースやコンテンツは保持する
- Snapshot：リソースの削除前に snapshot を作成する

##その他
その他にも、以下のような機能が用意されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321349/640d6249-6e47-82f9-d95d-6b7f9811551d.png)

- Custom resource 
 - テンプレートにカスタムのプロビジョニングロジックを記述し、ユーザーがスタックの作成、アップデート、そして削除を実行する度に AWS CloudFormation がそれを実行
 - Lambda 関数を使うことで、プロビジョニングすることが可能


##おわりに
AWS CloudFormation Master Class についての主な説明は以上となります。全体を通して、CloudFormation の機能とその使い方について説明してまいりました。日々の業務で活用し、そして実践することで、より本サービスについての理解を深めて参りましょう。
BeautifulSoup を使用し、キーワードを含むページを抽出する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254604/81491e96-d290-6c94-5f57-f7fb645c2ee7.png)


```python:sample.py
import requests
from bs4 import BeautifulSoup
import re
from urllib.parse import urljoin
import time

url_nikkei = 'https://www.nikkei.com/'
url_nikkei_business = 'https://www.nikkei.com/business/'
key_word = '環境'

response = requests.get(url_nikkei_business)
soup = BeautifulSoup(response.text, "html.parser")
regex = re.compile(r'm-miM\d{2}_title')
articles = soup.find_all('h3', {'class': regex})

time.sleep(3)

url_nikkei_articles = []
for article in articles:
    url_nikkei_article = article.find('a').get('href')
    url_nikkei_articles.append(url_nikkei_article)

url_list = []
title_list = []
for url in url_nikkei_articles:
    url_nikkei_article = urljoin(url_nikkei, url)
    
    response = requests.get(url_nikkei_article)
    soup = BeautifulSoup(response.text, "html.parser")

    regex = re.compile(r'cmn-section')
    temp = soup.find_all('div', {'class': regex})
    title = temp[0].find('span').string
    
    regex = re.compile(r'cmn-article_text')
    contents = temp[0].find('div', {'class': regex}).find_all('p')
    
    for content in contents:
        s = re.search(key_word, str(content))
        if s:
            url_list.append(url_nikkei_article)
            title_list.append(title)
            break
    
    time.sleep(3)
```

```python
for i, title in enumerate(title_list):
    print(i+1, title)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254604/9b02410a-234e-74f2-1cff-4af06a12dcd5.png)


```python
for i, url in enumerate(url_list):
    print(i+1, url)   
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254604/98ed8459-e728-0115-6157-ca5b6436a307.png)
Ubuntu 18.04 LTS mininalにはtzdataが入ってない

# 背景
GCEでVMインスタンス持ってて、cron使いたかったので、system timeをUTCから'Asia/Tokyo'にしようとしたら、できなくて少し悩んだのでメモ

## 動作環境
- Ubuntu 18.04 LTS mininal
- GCE VMインスタンス


## 結論
Ubuntu 18.04 LTS  mininalでは`tzdata`というtimezoneのデータが定義されているパッケージが入っていないので、追加でインストールする必要がある。
<br>
以下で、プリインストールされているパッケージについて書かれている。


:::note info
(2022.09.15更新)
~~https://www.google.co.jp/amp/s/linuxfan.info/minimal-ubuntu-released/amp~~
https://linuxfan.info/minimal-ubuntu-released
:::


仮に、

```shell:terminal
$ timedatectl
```

で、現在時刻確認するとUTCで、

```shell:terminal
$ timedatectl set-timezone 'Asia/Tokyo'
```

でtimezone変更しようとしても、変わらない。(tzdataが入っていないから当たり前。。)

以上です。ありがとうございました。
Resilience4j の TimeLimiter でメソッド呼び出しにタイムアウトをつける

## 背景
Azure CosmosDBであったり、AWS S3であったり、FAXを送信するサービスであったり、外部のサービスを呼び出すSDKを使うシーンが多くなってきた。

これまで普通に生きてきた世界は、自分で管理するデータベースサーバーの生死だけを気にすればよくて、ネットワーク的な距離もごく近傍。すべてが想定の範囲内の出来事だったが、こうした外部のサービスを利用するときには単純にはいかない。

ネットワークの遅延は安定せず、時には秒単位での遅延も起こりうる。多くのサービスはホスト名でエンドポイントが提供され、IPアドレスは予告なく変更になる。

こうした不安定なイベントが発生したとき、各サービスをHTTPなりで呼び出してブロッキングしているスレッドが急激にたまってしまい終いにはサービス全体の停止を引き起こすようなことがある。

つまりブロッキングするような呼び出しは、関数呼び出しにタイムアウトをつけてメインのHTTPスレッドを埋めないような注意が必要だ。

Rubyならばわりと簡単に書ける。

```Ruby
require 'timeout'

def callAnotherWorld
    sleep 3
    return "何か外部のサービスを呼び出した結果"
end

begin
  result = Timeout.timeout(1) do # 1秒でタイムアウト
    callAnotherWorld()
  end
rescue Timeout::Error
  result = ""
end

p result                         # タイムアウトするのでブランクになる
```

Javaでもだいたい同じようなコードになる。

```Java
private final ExecutorService threadPool = Executors.newCachedThreadPool();

private String callAnotherWorld() {
    Future<String> f = threadPool.submit(() -> innerCallAnotherWorld());

    while (true) {
        try {
            f.get(1, TimeUnit.SECONDS);  // 1秒でタイムアウト
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        } catch (InterruptedException retry) {
        }
    }
}

private String innerCallAnotherWorld() {
    return "何か外部のサービスを呼び出した結果";
}
```

RubyもJavaもバックグラウンドのスレッドでメソッドが実行され、呼び出し側スレッドはその完了を待つという動作である。

Javaの場合、スレッドプールの存在と、Futureの存在が見えてしまっており、少し残念な気持ちになる。

## Resilience4J

そこで [Resilience4J](https://github.com/resilience4j/resilience4j) である。

Resilience4J は最近のマイブームで、分散アーキテクチャにおけるシステムの安定性を向上させるべく、以下のパターンが簡単に利用できるようになる。

- CircuitBreaker
- RateLimitter
- BulkHead
- Retry
- TimeLimiter

メソッド呼び出しに対するタイムアウトを実現するには、TimeLimiterを利用すればよい。
CircuitBreakerの使い方などはすぐにヒットするが、TimeLimiterについてはあまり情報がないので、自分用の備忘として書いておく。

```Java
private final ExecutorService threadPool = Executors.newCachedThreadPool();

private final TimeLimiterConfig config = TimeLimiterConfig.custom()
        .timeoutDuration(Duration.ofMillis(1000))
        .cancelRunningFuture(true)
        .build();

private String callAnotherWorld() {

    Callable<String> callable = TimeLimiter
        .decorateFutureSupplier(
            TimeLimiter.of(config),
            () -> threadPool.submit(() -> innerCallAnotherWorld())
        );

    return Try.of(callable::call)
            .getOrElse("");
}
```

あんまり短くならないが、catchとか例外処理がなくなり、ビジネスロジックにフォーカスできるコードになる。

Resilience4Jが提供する機能は、いまどきの分散環境において、必須となるデザインパターンで、非常に勉強になる。
ruby snmpでbulkwalk

# Rubyでbulkwalkするスクリプトを組んでみた。
ネットワーク内に存在する大量装置にsnmpbulkwalkするスクリプトを従来Perlで作ってたんだけど、rubyで作り直してみた。
取得回数が限られているbulkwalkであればruby-snmpのExamplesにあったんだけど、同一ツリー内を再帰取得するコードが見当たらなかったので書いておきます。

 - v1の装置があることも考慮し、v1であればwalk、v2cであればget_bulkします。
 - 応答結果は「oid値」「応答値」「タイプ」を配列で回答します
 - ホスト単位にMIB値を連続取得します。ホスト単位にパラレルにしてもいいかも。
 - EndOfMibViewが出たときの例外処理ができていない…ループから抜けるいい方法ないかしら？（r.valueがSNMP::EndOfMiViewになった場合、抜ける必要があります）

```ruby:snmpbulkwalk.rb
#! /usr/local/bin/ruby
require 'snmp'

class SNMPWALK
	@@array = Array.new
	def self.bulk(hostname:,community:'public',oid:,max_rep:10)
		SNMP::Manager.open(:Host => hostname , :Community => community) do |manager|
			next_oid = oid
			while next_oid.subtree_of?(oid) do
				response = manager.get_bulk(0,max_rep.to_i,next_oid)
				response.each_varbind do |r|
					next_oid = r.name
					break if !next_oid.subtree_of?(oid)
					@@array.push([r.name.to_a.join('.'),r.value.to_s,r.value.asn1_type])
				end
			end
		end
		return @@array
	end

	def self.walk(hostname:,community:'public',oid:)
		SNMP::Manager.open(:Host => hostname , :Community => community) do |manager|
			next_oid = oid
			manager.walk(next_oid) do |response|
				response.each do |r|
					@@array.push([r.name.to_a.join('.'),r.value.to_s,r.value.asn1_type])
				end
			end
		end
		return @@array
	end
end

#####################################################################################
##  get_mibdata Main
#####################################################################################
['host_a','host_b','host_c'].each do |host|
	snmp_version = "v2c"
	['1.3.6.1.2.1.2.2.1.1','1.3.6.1.2.1.2.2.1.7'].each do |mib|
		oid = SNMP::ObjectId.new(oid) if !oid.kind_of?(SNMP::ObjectId)
		result = ""
		if snmp_version == 'v1'
			result = SNMPWALK.walk(hostname:host,community:'public',oid:mib)
		else
			result = SNMPWALK.bulk(hostname:host,community:'public',oid:mib)
		end
		p result
	end
end

```

自作コードをQiitaに書いたの初めてなので突っ込み歓迎です。
JavaScriptで頭文字を大文字にする方法

# JavaScriptで頭文字を大文字にする方法

Capitalize的なメソッドがありそうでなかったので調べてみました。

```javascript:index.js

const mikeWazowski = 'wazowski';

const mikeWazowskiToUppercase = mikeWazowski.charAt(0).toUpperCase() + mikeWazowski.slice(1);

console.log(mikeWazowskiToUppercase);

```

- `charAt`で名前の頭文字wを取得する。
- `toUpperCase()`で大文字Wとなる
- `'wazowski'`を`slice(1)`でスライスして、`azowski`を取得。
- それらを組み合わせて`Wazowski `となる。


[Sample](https://repl.it/@Abbiscuit/CircularTwinModules)
サトシ君も実践してる！？超絶簡単PDCA

# 概要
> サトシ君と言えば、大半の人はポケモンのイメージを想像する方がいると思います。サトシ君を例にPDCAを考えて参考にしてください

# まず、PDCA とは？
1. 計画を立てる（Plan）
2. 計画を実行（Do）
3. 改善して次に繋げる（Check）
4. 行動を評価 （Action）
その後、1に戻る

> 「PDCA」とは、「Plan＝計画」「Do＝実行」「Check＝評価」「Action＝改善」の4つの英単語の頭文字で、「PDCAサイクル」とも呼ばれます。 P→D→C→A→P…… といった具合に、4つの段階を循環的に繰り返し行うことで、仕事を改善・効率化することができる方法と言われています。

# サトシ君の行動例
1. 計画を立てる
> ポケモンマスターが最大な目標かつ実質的には大会出場のために、また、目標を細分化し、各トレーナー戦やジム巡りやアローラ島巡りまでを達成する道筋も立てることもある

2. 計画を実行
> ジム巡りやアローラ島巡りをしていく中でポケモンを捕まえ、ポケモンのレベルやトレーナーのスキルアップを目指していく。そしてなにに対しても熱さ、やる気を全力投球。

3. 改善して次に繋げる
> 経験敵わず、負けることもある。立ち止まったら、しっかり反省して、分析し、自主練習をひたすら繰り返す。全ては目の前の目標のために。またサトシ君には素晴らしい仲間もいる。時には相談でアドバイス聞いたり、バトルの協力してもらう。

4. 行動を評価
> 他トレーナーとのバトルやジム巡り、大会結果から、仲間などからのコメントをしっかり受け止め、少しずつ旅をしながら成長している。現にカントー大会出場からこれまでに少しずつ順位を伸ばしている。

#まとめ
> エンジニアにとっての目標は、お客様を喜ばせることが最大の目標だとした場合、それに向けて次のチームの目標は納期である。個々の目標を設定するなら、目標の細分化をしていき、それに対して評価をして最終的なゴールに達成させることが重要である。もし、迷ったら、サトシ君の行動を思い出してみてください。
Google Cloud Platform のwordpressのphpmyadminをMacで使う時にハマった記録

#GCPでWordPressのインスタンスを立ち上げる
「wordpress certified by bitnami」
のインスタンスを立ち上げる。
#phpmyadminしようとしてハマったところ
https://docs.bitnami.com/google/apps/wordpress-pro/get-started/access-phpmyadmin/
を参考にして
<pre>ssh -N -L 8888:127.0.0.1:80 -i {KEYFILE} bitnami@{SERVER-IP}</pre>
とコマンドを打ってsshトンネリングを試してみるが、元記事にあったアドレス
http://127.0.0.1:8888/phpmyadmin
にアクセスしてもつながらない。:frowning2:
#Macがlistenしてるポートを調査してみる
https://qiita.com/yokozawa/items/dbcb3b31f9308e4dcefc
を参考にMacがlistenしてるポートを見てみると
<pre>sudo lsof -i -P | grep "LISTEN"</pre>


どうやら、127.0.0.1:8888ではなく、
localhost:8888と認識されているらしい。
#と言うことで
http://localhost:8888/phpmyadmin/
で無事アクセスできました！:smiley:

#追記
Bitnami WordPress with NGINX and SSLでは、もう一工夫いるようです。。。
関係各位の方々にご迷惑をおかけしてしまったかも。。
font-familyが-apple-systemに指定されている状態でtext-align: justify;をかけるとiOS端末にて豆腐（文字化け文字）が出現する

元タイトル：【情報ください】WebページにてiOS端末にのみ豆腐（文字化け文字）が発生する現象に遭遇しました

タイトルの通りです。
文字コードはutf-8、HTMLや疑似要素に変な文字が入っているなんてことはありません。

## 発生条件の整理

この豆腐はiOS端末でしか再現されません。
しかし、strongやcodeなどのインライン要素に当たるタグを使っており、その中身の両端が半角文字かつ隣接する文字が半角文字でない場合にこのバグは発生します。

中身の両端が全角文字であれば隣接する文字が半角文字でない場合でも豆腐は発生しません。
中身の両端が半角文字でも隣接する文字が半角文字であれば豆腐は発生しません

また、list内ではこれらの条件に関わらず豆腐は発生しません。

## 原因の推測

まず、MacOS,Android,iOSの3環境で検証してこの事例を確認できたのがiOS端末のみであったため、これは**iOSのOS単位のバグ**と考えています。
ただし、他のサイトではあまり発生していないように見えますね。
これはおそらく、文字の揃え方に関する CSS の記述が影響していると考えられます。

当ブログでは、本文に対して `text-align: justify;` 、つまりCSSによる両端揃えを適用しています。
他のそのようなサイトを確認したわけじゃないのでなんともですが、ひとまずそこが原因だと睨んでいます。

### 190709追記

@beffell さんのコメントを受けて確認した結果、 `font-family`が`-apple-system`に指定されている状態で`text-align: justify;`をかけるとこの問題が発生することが確認できました。
情報ありがとうざいます。

## 情報ありがとうございました

自分が発見していたより明確な条件を絞り込むことが出来ました。
ありがとうございました。
引き続き、情報があると教えていただけると幸いです。
Screenコマンドで起動時にバッファを複数枚(タブみたいに)表示する.screenrc

# 概要

このエントリでは、Un*x系の1つのターミナルで複数のバッファを開けるようにするGNU Screenの設定を紹介します。

# できるもの

下図のような形で、screen起動時に複数のバッファが開くようになります。

<img width="685" alt="スクリーンショット 2019-07-09 7.17.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65002/a8e955f5-8e56-4232-7a1e-683804d1b0a7.png">

# 使い方

以下のようなコマンドを個人的にはよく使います。後述の設定ファイルをホームディレクトリの「.screenrc」ファイルとして保存すると使えるキーバインディングを含みます。

|項目|キー|備考|
|:--|:--|:--|
|コマンドを入力|Ctrl-j|ScreenのデフォルトがCtrl-Aなのですが、これだとemacs系・macOS系のバインディングとかぶるので|
|コピーモードにする|Ctrl-j ESC|こうすると、ホイールやカーソルキーでバッファを戻れます|
|コピーモードから抜ける|ESC||
|前のバッファ|F11||
|次のバッファ|F12||
|バッファを指定して切り替え|Ctrl-j 番号|例：ctrl-j 1 で2番目のバッファ|
|バッファを指定して切り替え|Ctrl-" (カーソルで選択)|バッファ上に一覧が出るので選択|
|バッファ上のプロセスを止める|Ctrl-k|シェルを抜けるにはexit|
|バッファの名前を変える|Ctrl-j A||
|選択範囲をscreenのクリップボードにコピー|space||
|screenのクリップボードからペースト|Ctrl-j [|上記でscreenのクリップボードに入っているものが対象|



# 設定ファイル

[Gist](https://gist.github.com/hrkt/defa67eef890a5469db3297d510e7a8d) におきました。

```bash
# screenrc
# 
# see also
#
# arch linux wiki
#   https://wiki.archlinux.org/index.php/GNU_Screen
# GNU Screen manual
#   https://www.gnu.org/software/screen/manual/screen.html#Overview

# scroll buffer (press Ctrl-J esc to enter copy-mode, press ESC to leave copy-mode)
defscrollback 20000

# change ctrl-a bindings to ctrl-j
escape ^Jj

# enable scrolling
termcapinfo xterm* ti@:te@

# avoid editors not to quit abnormally
altscreen on

# status line (show buffers)
hardstatus alwayslastline "%{= cd} %-w%{= wk} %n %t* %{-}%+w"

# do not show startup message
startup_message off

# do not change width & height on startup
termcapinfo  xterm Z0=\E[?3h:Z1=\E[?3l:is=\E[r\E[m\E[2J\E[H\E[?7h\E[?1;4;6l

# press F11 to previous tab 
bindkey -k F1 prev
# press F12 to previous tab 
bindkey -k F2 next

# show some buffers on startup
screen -M -t Shell 0 
screen    -t Shell 1 
#screen    -t Shell 2
#screen    -t Shell 3
select 0
```

curlを使ってGistからローカルにコピペして使うことができます。
``
curl -L -o ~/.screenrc  https://gist.githubusercontent.com/hrkt/defa67eef890a5469db3297d510e7a8d/raw
``


# 参考サイト

- [Arch Linux wiki](https://wiki.archlinux.org/index.php/GNU_Screen)
- [GNU Screen manual](https://www.gnu.org/software/screen/manual/screen.html#Overview)
パラメータをループしてggplotしたい

モデルのパラメータの調整をする時、色んなパラメータの値を試してはプロットを見たいときってあるじゃないですか。`ggplot`を含んだ関数を`for`に渡してもいいけど、`lapply`に渡したほうが（多分）早い＆コードもすっきり。

以下は、サンプルデータに異なる次元のpolynomialでlinear modelをfit する例のコードです。


```R
library(ggplot2)

# create simulation data
N <- 100 # number of observation
K <- 10 # number of covariates

X <- rnorm(n = N, mean = 0, sd = 1)
Y <- X**3 + rnorm(n = N, mean = 0, sd = 1)
data <- data.frame(Y = Y, X = X)


# function to plot predicted values of linear regression
# with i'th degree polynomial
plotPoly <- function(.i, .data){
  # make sure to set the first argument as the variable to be iterated over
  
  fit <- lm(Y ~ poly(X, degree = .i, raw = T), data = .data)
  data$pred <- predict(fit)
  
  ggplot(data) + 
    geom_point(aes(x = X, y = Y)) + 
    geom_line(aes(x = X, y = pred), color = 'red') + 
    ggtitle(paste('Degree = ', .i, sep = " "))
}

out <- lapply(X = 1:5, FUN = plotPoly, .data = data)

# see the plots
out[[1]]
out[[2]]
out[[3]]
out[[4]]
out[[5]]

```

関数の最初のargumentを変化させるパラメータにすることがみそ。
PWA+FirebaseでTwitterのようなWEBアプリを作るハンズオン

WEBのフロントに詳しくない若者向けにハンズオンやりました。

最終的に作った成果物はこんな感じです。

リアルタイムで投稿が反映されたり、プッシュ通知が飛んできたりします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201603/fd979752-30f0-5b8c-6223-369a867578a6.png)

※リプライ、リツイート、DMのボタンはダミーです



# 対象レベル

- HTML/CSS -- 読める（事前準備済み）
- JavaScript -- 読める（ほぼ事前準備済み）
- Firebase -- サーバーレスについて意味を知っている


# マイルストーン

基本的にクライアント側はほぼ実装済みなので、作業はFirebaseのセットアップ周りがメインです。

1. Twitterのようにメッセージを投稿、表示できる。<br>
「いいね」が送れる。ただし、無認証。<br>
**狙い**：MBaaSを使ってサーバーレスなアプリ構築を体験する。<br>
**キーワード**：FireStore, Functions<br>
**所要時間**：1時間<br><br>
2. 1.で作ったアプリにユーザー登録、認証機能を追加する。<br>
ただし、全ての機能が一つの画面に並んで表示されている。<br>
**狙い**：MBaaSを使ってサーバーレスなアプリ構築を体験する。<br>
**キーワード**：Authentication<br>
**所要時間**：0.5時間<br><br>



# マイルストーン１：Twitterのようにメッセージを投稿、表示できる

GitHubにハンズオンの手順を書いてます。

　https://github.com/uemegu/HandsOnTwitterLike1

説明しながら実施して1時間だったので、黙々とやれば30分で終わるかもしれません。

クライアントの実装については、JavaScriptを普段書かない人でもなんとなく意味がわかるようにjQueryを使ってます。


# マイルストーン２：アプリにユーザー登録、認証機能を追加する

GitHubにハンズオンの手順を書いてます。

　https://github.com/uemegu/HandsOnTwitterLike2

説明しながら実施して30分だったので、黙々とやれば15分で終わるかもしれません。

アカウントの収集はしたくないのでこちらの成果物は非公開です。


# 次のステップ

こんなに簡単にリアルタイムで動くものが作れると、なんだか簡単にアプリが作れちゃう気分になりますよね。

次は今時のJSフレームワークを使ってSPAにしたいところですが、事細かに説明資料を書くのは大変なので今回はそこまで踏み込みません。

実際にちゃんとTwitterっぽくしようと思うと、フォロー/フォロワーの関係や、リツイートなど必要で、FireStoreだけでは表現できない部分やスキーマレスな構造での表現など悩みどころ満載だと思います。

でも、設計で悩むのは開発の醍醐味なので是非楽しみましょう！

特に個人開発においては完璧じゃないからダメなんてことはないので、多少無茶な設計でもやってみれば良いと思います。とりあえず動かした後に悩めば良いと思います。

以前、[終：どこまでショボいアプリがAppleの審査に通るのか試してみた](https://qiita.com/megumu-u/items/576e0967bc357314df1b)の中で二つ名オンラインというアプリを作った時、「設計が適当なとこあるし、Firebaseの無料枠に収まらなかったらどうしよう」と思っていましたが、全く無料枠を超えることはなかったです・・・
個人的メモ

sshしてコマンド結果取得
https://kamotora.net/system/linux/linux-ssh-command/

```bash:renshu.bash

#!/bin/bash

code="cd01\ncd02"
report="test01\nsample01"

echo -e $code | while read line1
do
        echo "while:"$line1
        echo -e $report | while read line2
        do
                echo "while:"$line2
                ls -l ./*$line2*$line1*20190709* > tmp
                echo `wc -l tmp` | awk '{print $1}'
                file_cnt=$(`wc -l tmp` | awk '{print $1}')
                cat tmp
                echo $file_cnt
                if [ $file_cnt != 1 ]; then
                        echo "要確認"
                else
                        echo "次"
                fi
        done
done

```
attrメソッドについてのメモ書き

attrメソッドは、HTML要素が持つ**属性**の値を取得するメソッドである。
属性には、id属性やclass属性がある。

以下の例では、変数であるadd_user_idの中にdata-user-idという具体的な数字が代入されているかをconsole.logで確認する。

```js

$(document).on("click",".user-search-add.chat-group-user__btn.chat-group-user__btn--add",function(){
    var add_user_name = $(this).attr('data-user-name');
    var add_user_id = $(this).attr('data-user-id');
 console.log(add_user_id);
```

ちゃんとid属性の数字がattrメソッドで取得できている。
https://gyazo.com/9dbfd4c0aad2f75c9a07f07e3897f8fb


＜参考記事＞
https://www.sejuku.net/blog/37402
後から(動的に)追加された要素に対してイベントを設定する

Jsを用いて、後から(動的に)追加されたHTML要素に対してイベントを設定するためには、以下のような通常通りの方法を用いても動作させることはできない。なぜなら、動作させたいHTML要素は、もともと存在していたものではないからである。もし、もともと存在していたものであれば、通常通りの方法を用いて動作させることができる。

```js

$(セレクタ).on('click', function(){ 処理 })
```


では、どうやってイベントの設定を行うのかというと。**document**を用いて実装すればできる。documentとは、、Webページを構成しているHTML要素をすべて取得する便利なオブジェクトのことである。

```js

$(document).on("click",".user-search-add.chat-group-user__btn.chat-group-user__btn--add",function(){
 console.log(document)
```

以下の動画では、documentの中には、Webページを構成しているHTML要素が取得されていることがわかる。
https://gyazo.com/8f8f4a4b9c9b1f887609ca5a8a0e07e4
https://gyazo.com/234ebc303cd8f50645c0076f75b81442
https://gyazo.com/2d23fa09614613d42bf3b98d3d62c3a1


＜参考記事＞
・https://qiita.com/negi/items/6ec0d3cedba499eac81a
・https://www.sejuku.net/blog/30970#document
jQueryで様々なHTML要素を取得する方法

jQueryを使って、取得できるHTML要素は様々ある。そのため、今回はそれらに種類と取得方法を解説する。


#1.IDセレクタ
IDセレクタとは、HTML要素のid属性で指定するセレクタのことである。クラス名が同じHTML要素であっても個々の要素は別々であること。たとえば、ツイッターの１つ１つのツイート画面やLINEのメッセージ画面は、同じHTML構造をしている。しかし、厳密には、並んでいる１つ１つのHTML構造はそれぞれidが違う。一番最初にツイートされたHTML構造のidは１であり、２番目にツイートされたHTML構造のidは2であるように、それそれの順番が異なるということ。
IDセレクタは、取得したいHTML要素のid属性の値に**#（ハッシュ）**を付けたものをセレクタとして利用する。

```js
$("#idSelector") 
```

#2.クラスセレクタ
クラスセレクタとは、HTML要素のclass属性で指定するセレクタのことである。よく、<div class~>と表記されているものを指す。クラスセレクタは、取得したいHTML要素のclass属性の値に**.（ドット）**を付けたものをセレクタとして利用する。自分は、よく.（ドット）をつけ忘れてしまう癖があるので、要注意！

```js
$(".classSelector") 
```

#3.要素セレクタ
要素セレクタとは、h1やpのようなHTML要素を対象としたセレクタのことである。要素セレクタは取得したいHTML要素の要素名をそのままセレクタとして利用する。

```js
$("h1")
```
リストボックスの項目追加

tkinterでのGUIプログラミング
今回はリストボックスの項目をボタンを押すことで増やしていくプログラムをまとめる。



```python
import tkinter as tk
import tkinter.ttk as ttk

root = tk.Tk()
root.geometry('300x300')

def select_now(event):
    for i in lb.curselection(): #現在選択されている項目を取得
        print(str(i)+'番目を選択中')
    print('')

#リストボックス
listarray = ['項目1', '項目2', '項目3', '項目4']
txt = tk.StringVar(value=listarray) #文字列なのでStringVar()でオブジェクトを生成
lb = tk.Listbox(root, listvariable=txt, width=28, height=15)
lb.bind('<<ListboxSelect>>', select_now) #項目が選択されたときの処理

#スクロールバーの生成・配置
scrollbar = ttk.Scrollbar(root, orient=tk.VERTICAL, command=lb.yview)
scrollbar.pack(fill='y', side='right')

#ボタンの生成・配置
button_page = ttk.Button(root, text='+', width=4)
button_page.bind('<1>', lambda event: lb.insert(tk.END, '新規'))
button_page.pack()
lb.pack() #リストボックス配置

root.mainloop()
```

実行すると、
![listbox1_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280072/d5370291-ef62-8aa3-8f15-0a284c196b2d.png)　　　![listbox2_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280072/371e79fb-6edd-ec86-8460-687dc833b730.png)


<code>Listbox(object, listvaliable)</code>...objectに値listvaliableのlistboxを生成する
オプションの<code>listvariable</code>にはVariable オブジェクトを指定する。サブクラス StringVar,　IntVar, DoubleVar, BooleanVarの中から選び、今回は文字列なので<code>StringVar()</code>でオブジェクトを生成。
StrinVar 文字列 ex.)'hello'
IntVar 整数 ex.)12345
DoubleVar 実数 ex.)1.2345
BooleanVar 論理値 ex.)True False

<code>Listbox.insert(tk.END, value)</code>...リストボックスの項目末尾にvalueを挿入する

参考文献
https://ameblo.jp/hitochan007/entry-12011753728.html
https://toolmania.info/post-13014/
kaminariのgemを用いたページネーションの実装方法

ページネーションとは、長い文章を複数のページに分割して、各ページへのリンクを並べアクセスしやすくすること。
https://gyazo.com/7acc560088bf6fb2c04b90dda3b3d38e

#実装手順

#１．kaminariのGemをインストールしてサーバーを立ち上げ直す

Gemfileの最後の行にgemを記述する。

```
gem 'kaminari'
```
Gemをインストールする。

```
$ bundle install
```

rails s(サーバー)を立ち上げ直す。

```
rails s
```

#２．コントローラファイルを編集する

kaminariのgemをインストールすることで使えるメソッド

1.pageメソッド

```ruby

params[:page]
```

2.perメソッド
1ページあたりに表示する件数を指定するメソッドである。

```ruby

per(1ページあたりに表示する件数)
```


3.「page」と「per」メソッドを利用して、コントローラに記述すると以下のようになる。

```ruby

def index
    @tweets = Tweet.includes(:user).page(params[:page]).per(5).order("created_at DESC")
end
```


#３．ビューファイルを編集する

paginateメソッド
ページネーションのリンクを表示したいときに使用するメソッドである。

```
paginate(インスタンス変数)
```

ビューファイルにはルビータグで囲って使用する。

```html
<div class="contents row" >
    <% @tweets.each do |tweet| %>
      <div class="content_post" style="background-image: url(<%= tweet.image %>);">
        <%= simple_format(tweet.text) %>
        <span class="name"><%= tweet.name %></span>
      </div>
    <% end %>
  <%= paginate(@tweets) %>
</div>
```
フロントエンド開発の言語選定 (TypeScript vs FlowType)

## 目的

-   フロントエンド開発で、静的型付け言語の選定のための比較・判断材料。
-   めんどくさいので、メジャーな TypeScript と FlowType のみ比較する。
    -   Scala.js とか PureScript とかもあるが、プロダクトコードで採用されることは稀であろう。
-   「TypeScript も FlowType も使わない」みたいな原始生活は論外なので触れない。

## 比較表

調査実施日 : 2019-07-09

|                       | TypeScript | FlowType   |
| --------------------- | ---------- | ---------- |
| Development Corp.     | Microsoft  | Facebook   |
| Current ver.          | 3.5.2      | 0.102.0    |
| 1st release date      | 2014-09-18 | 2014-11-19 |
| Latest release date   | 2019-06-13 | 2019-06-25 |
| Weekly DLs (npm)      | 5,694,392  | 455,270    |
| Used by (GitHub)      | 1,295,137  | 64,764     |
| Star (GitHub)         | 51,143     | 19,724     |
| Contributors (GitHub) | 394        | 636        |
| Implemented lang      | TypeScript | OCaml      |

### Google Trends

<https://trends.google.co.jp/trends/explore?date=2012-06-01%202019-07-01&q=TypeScript,FlowType,Flow-type>

### 補足

#### 1st release

<https://github.com/facebook/flow/releases?after=v0.2.0>
<https://github.com/microsoft/TypeScript/releases?after=v1.5.4>

## 総評

### FlowType を選ばない理由

-   Google Trends の結果が低い。
    -   「Flow」という単語を除外しているためフェアな比較になってない。
    -   しかし、ググラビリティが低く無関係な結果まで含まれてしまうため、しょうがない。
    -   このググラビリティの低さは、減点ポイントである。
-   ビルド・設定が複雑。
    -   flow-typed のインストール、.flowconfig の設定、など。
-   ver が未だに 1 未満である。
    -   <https://semver.org/lang/ja/>
    -   > メジャーバージョンのゼロ（0.y.z）は初期段階の開発用です。いつでも、いかなる変更も起こりえます。この時のパブリック API は安定していると考えるべきではありません。
    -   > またもし安定した API を持ち、それに依存しているユーザーが複数いるのなら、それは 1.0.0 であるべきでしょう。もし後方互換性について多大な心配をしているのなら、それは 1.0.0 であるべきでしょう。
        -   事実、後方互換がないことが多々ある。
        -   例えば、「今まで問題なかったコードが、アップデート後に型チェックエラー」「flowconfig のオプションがなくなった」など
        -   量が多いと対応しきれず、「アップデートできない」となってしまう。

### TypeScript を選ばない理由

-   ビルド・設定が複雑化する。
    -   Babel 7 (2018-08-28) 以前は、 TypeScript のビルドには ts-loader が必要
        -   例えば、 React 開発で create-react-app を使っていた場合、2.1.0 (2018-10-29) 以前で静的型付けをしたくば、下記 2 択だった。
            -   eject して TypeScript を導入する
            -   eject せず FlowType を使う
    -   今は、 create-react-app の eject なしで TypeScript を使用可能。
    -   自分でビルド組む場合も、Babel でトランスパイルできる。
        -   → （FlowType より）ビルド・設定が複雑、とはならない。
-   （FlowType より）型推論が弱い
    -   逆に、明示的に型を書かせたい場合はこの方がよい。

## 結論

-   TypeScript を選ぶ
objectのlistの和を取る

holoviewsのobjectをlistに収めていきまとめて和ととるとsumを使ったらうまく行かなかったのでメモ

```
import quandl
import holoviews as hv
hv.extension('bokeh')

curve_lst = []
df = quandl.get("TSE/1321", start='2018-01-01', end='2018-12-31')
curve_lst.append(hv.Curve(df, 'Date', 'Low'))
curve_lst.append(hv.Curve(df, 'Date', 'Low'))
curve_lst.append(hv.Curve(df, 'Date', 'Low'))

sum(curve_lst)
```

これはerrorになる
TypeError: unsupported operand type(s) for +: 'int' and 'Curve'

```
import quandl
import holoviews as hv
hv.extension('bokeh')

curve_lst = []
df = quandl.get("TSE/1321", start='2018-01-01', end='2018-12-31')
curve_lst.append(hv.Curve(df, 'Date', 'Low'))
curve_lst.append(hv.Curve(df, 'Date', 'Low'))
curve_lst.append(hv.Curve(df, 'Date', 'Low'))

import functools
functools.reduce(lambda x, y: x+y, curve_lst)
```

これで動く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53186/f1721c97-f8f7-f949-485c-9042d288b0be.png)
[考えてみた]セッション変数から素直?に値を取り出したい

## nilか？明示的に調べる方法

こんな感じの実装を見かけることがあります。
`session[:hoge] == nil` だったときに備えているわけです。

```.ruby
if session[:hoge]
  fuga = session[:hoge][:fuga]
  piyo = session[:hoge][:piyo]
end
```

しかし、ifを読むと、ビジネスロジック的になにか意味があるのかな？と思えてしまうので、プログラムの都合のifはなるべく減らして、なるべくビジネスロジックだけに集中した書き方をしたいです。

## nilか？を暗黙のうちに済ます方法

~~rubyにはぼっち演算子（`&.`）というレシーバがnilのときはnilを返してくれる演算子があります。素直か？というと少し微妙かもしれませんが、~~

[Hash#dig](https://docs.ruby-lang.org/en/2.6.0/Hash.html#method-i-dig)を使うことで、ifを減らしてロジックな素直に書くことができそうです。

```.ruby
fuga = session.dig(:hoge,:fuga)
piyo = session.dig(:hoge,:piyo)
```

---
（追記）
文字列とシンボルで明確にしていしないと、nilとなってしまう場合があります。
その場合は、 `with_indifferent_access`を途中に入れるか、

```.ruby
fuga = session.with_indifferent_access.dig(:hoge,:fuga)
piyo = session.with_indifferent_access.dig(:hoge,:piyo)
```

しっかり指定するか


```.ruby
fuga = session.dig('hoge',:fuga)
piyo = session.dig('hoge',:piyo)
```

すれば、取れるようです。
クラスメソッドの使いどころを考えたけど分からなかった

## 目的
* クラスメソッドの効果的な使い方を考える
* 中の人が初めてクラスメソッドを学んだので、使い方の備忘録として記述する

## ポイント
* classmethodはインスタンス化しないでクラス内の要素にアクセスできる
* @classmethodでクラスメソッドを修飾する
* classmethodは引数に自分自身のクラスを持ち、自分自身をclsと記述する

### 中の人が考えたclassmethodの使いどころ

* 以下の状況が重なったとき
    * クラスが何かのソースを参照したデータを持っている
    * ソースが変わったときに別のクラスを生成したい
    * ソースごとにサブクラスを定義するのは冗長である
    * （インスタンス生成前にクラスにデータを持たせたい）

##　結論
今回の例はインスタンス生成時にソースを指定するコンストラクタを書いておけばいいんジャマイカ・・・
中の人の技量が足りなかったため、効果的な使い方を提示するに至らなかった。

また、下記コードは意図しない動作になっていることが判明しました。
中の人のレベルが上がったら修正します。
誤解誤認されませんよう、お気をつけください。

## コード

### データソースの準備

```sample_data_for_clasmethod1.csv
0,10
1,20
2,30
3,40
```

```sample_data_for_clasmethod2.csv
0,1
1,2
2,3
3,4
```

### クラスの定義

* pandasで読み込んだdfを保持するcls.dataを有するクラス
    * クラスメソッドで指定したデータソースをdfにしてcls.dataに保持する機能を持たせる
    * インスタンスメソッドで各列の合計を計算する機能を持たせる

```classmethod_for_learning.py

import pandas as pd

class SampleData:

    data_kind = 'CSV'

    def __init__(self, data_name):
        """ 初期化 """
        self.data_name = data_name

    def show_sum_1st_column(self):
        return self.data.iloc[:,0].sum()
    
    def show_sum_2nd_column(self):
        return self.data.iloc[:,1].sum()


    @classmethod
    def load_data_source(cls, data_path):
        cls.data = pd.read_csv(data_path)
        return cls
```

### 実行コード
* プリント関数内の文書のように動作確認を行うコード
* データのソースはsample_data_for_clasmethod1.csv
* データソース指定後は、クラスオブジェクトをsample1と定義する

```main1.py

print('sample1を与えたクラスメソッドの動作を確認する')
sample1 = SampleData.load_data_source('sample_data_for_clasmethod1.csv')
print(sample1.data_kind)
print(sample1.data)
print()
sample1_ins = sample1('sample1_dataを与えたクラスで生成したインスタンスであるsample1_ins')
print(sample1_ins.data_name)
print('sample1_insのデータを確認する(クラスメソッドから呼び出す)')
print(sample1_ins.data)
print('sample1_insのメソッドを確認する')
print('0列目合計', sample1_ins.show_sum_1st_column())
print('1列目合計', sample1_ins.show_sum_2nd_column())
```

 * 同様にデータのソースをsample_data_for_clasmethod2.csvに変更して実行
 * データソース指定後は、クラスオブジェクトをsample2と定義する

```main2.py
print('sample2を与えたクラスメソッドの動作を確認する')
sample2 = SampleData.load_data_source('sample_data_for_clasmethod2.csv')
print(sample2.data_kind)
print(sample2.data)
print()
sample2_ins = sample2('sample2_dataを与えたクラスで生成したインスタンスであるsample2_ins')
print(sample2_ins.data_name)
print('sample2_insのデータを確認する(クラスメソッドから呼び出す)')
print(sample2_ins.data)
print('sample2_insのメソッドを確認する')
print('0列目合計',sample2_ins.show_sum_1st_column())
print('1列目合計',sample2_ins.show_sum_2nd_column())
```

### 実行結果

* クラス内にデータを保持していることが確認できた
* クラス内のデータをクラスメソッドで変更できた。
* データのソースが異なるクラスを、それぞれ別名のクラスオブジェクト（sample1とsample2）に定義できた
* インスタンス化してもクラス内のデータは保持された
* それぞれのインスタンスのメソッドにより異なるソースの処理を行えた

```
sample1を与えたクラスメソッドの動作を確認する
CSV
   0  10
0  1  20
1  2  30
2  3  40

sample1_dataを与えたクラスで生成したインスタンスであるsample1_ins
sample1_insのデータを確認する(クラスメソッドから呼び出す)
   0  10
0  1  20
1  2  30
2  3  40
sample1_insのメソッドを確認する
0列目合計 6
1列目合計 90



sample2を与えたクラスメソッドの動作を確認する
CSV
   0  1
0  1  2
1  2  3
2  3  4

sample2_dataを与えたクラスで生成したインスタンスであるsample2_ins
sample2_insのデータを確認する(クラスメソッドから呼び出す)
   0  1
0  1  2
1  2  3
2  3  4
sample2_insのメソッドを確認する
0列目合計 6
1列目合計 9
```


## 参考にさせていただきました
[PythonエンジニアによるPython3学習サイト](https://www.python.ambitious-engineer.com/archives/308)
Pythonで行列の転置

#転置行列

行列転置の方法を備忘録しておく。


```python:test.py

A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
I = [[1, 0, 0], [0, 1, 0], [0, 0, 1]]

#転置行列
AT = list(zip(*A))
#[(1, 4, 7), (2, 5, 8), (3, 6, 9)]
IT = list(zip(*I))
#[(1, 0, 0), (0, 1, 0), (0, 0, 1)]

```

以下は処理内容についてわからなければどうぞ。

#謎のアスタリスク(スター)*
print文内の*(アスタリスク、スター)は積ではなく展開を意味しており、たとえばさっきのAに対して


```python:test.py

A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

print(A)
#[[1, 2, 3], [4, 5, 6], [7, 8, 9]]

print(*A)
#[1, 2, 3] [4, 5, 6] [7, 8, 9]

```

というふうにリスト等の中身をばらそうねという指示になる。
Aが「2次元行列を1つ渡した」のであれば*Aは「1次元配列を3つ渡した」ということになろう。


ところで物理界隈では"*"をスターと呼んでたけど情報屋さんは何と呼ぶのがメジャーなんだろう。

#zip()
zip()関数は与えられた複数のリストやタプルをそれぞれインデックスごとに組み合わせし直してタプルで返してくる。

```python.test.py
name = ("hoge", "hogege", "hogee")
yo = (20, 30, 40)
location = ("hiroshima", "fuchu", "abashiri")

data = list(zip(name, yo, location))

for i in range(len(name)):
	print(data[i])
#('hoge', 20, 'hiroshima')
#('hogege', 30, 'fuchu')
#('hogee', 40, 'abashiri')
```

そんなわけでlist(zip(*A))でAを転置できているのだ。
KotlinでSpringRestTemplateを試してみた

# 背景
RestTemplate使ってWebAPIを呼ぶことがあったので、備忘録としてまとめようと思います。
※ URLは仮です。

# Get
## パラメータなし
```kotlin:Get,パラメータなし
val restTemplate = RestTemplate()
restTemplate.getForObject("http://localhost/", String::class.java)
```

## パラメータ有り
```kotlin:Get,パラメータあり
val uriVariables = mutableMapOf<String, String>()
uriVariables.put("hoge", "hoge")
uriVariables.put("huga", "huga")
val restTemplate = RestTemplate()
restTemplate.getForObject("http://localhost/{hoge}?huga={huga}", String::class.java)
```

## exhangeの場合,パラメータあり
```kotlin:exchangeの場合
val headers = HttpHeaders()
headers.set("Accept", MediaType.APPLICATION_JSON_VALUE)

val builder = UriComponentsBuilder.fromHttpUrl("http://localhost/")
        .queryParam("hoge", "huga")

val entity = HttpEntity<String>(headers)

val restTemplate = RestTemplate()
val response = restTemplate.exchange(
        builder.build().encode().toUri(),
        HttpMethod.GET,
        entity,
        String::class.java
    )
return response.body
```

Post等も同じ感じなので割愛しちゃいます。


# 終わりに
基本的にはgetForObjectを使用すればいいのかなと思っております。
Getで取得した情報でHeader内に詰まってる情報が欲しい場合はgetForEntity、
Headerとかにtoken等を詰めてリクエストしたい場合はexchangeを使用で善いのかなと考えてます。
ある社内SEと初心者向けRuby on Rails関連の本ご紹介


## Rubyを学ぶ人、Ruby On Railsを学ぶ人へ本のご紹介
[プロを目指す人のためのRuby入門](https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%92%E7%9B%AE%E6%8C%87%E3%81%99%E4%BA%BA%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AERuby%E5%85%A5%E9%96%80-%E8%A8%80%E8%AA%9E%E4%BB%95%E6%A7%98%E3%81%8B%E3%82%89%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA%E3%83%BB%E3%83%87%E3%83%90%E3%83%83%E3%82%B0%E6%8A%80%E6%B3%95%E3%81%BE%E3%81%A7-Software-Design-plus%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA/dp/4774193976/ref=zg_bs_754376_4/355-1904711-6523239?_encoding=UTF8&psc=1&refRID=H4RTJGNJE7917A524TAW)
Railsやるなら、上の本は必ず読んだほうがいい。仕様が簡潔にまとまっているし、読みやすい。
すぐにRailsでアプリを作り始めるより、まずは上記の本でRubyの仕様を理解すると、
詰まった時に大いに役立つ。いわゆるコピペで動かない問題への対応。
仕様を理解しておかないと、コード読めなくてなんで詰まったかすら分からないから。
難しいところやめんどくさいところは飛ばしてOK。私はテスト周りや正規表現、最後らへんの章は飛ばしました。
他の言語から入ってきたので、ほんとによくできてる言語だなと感心しました。
とくに型の排除、式の結果自体が返り値になる(if文書くとよく分かります)、
メソッドチェーンって言うんだっけ？コロンでつなげるやつ、ループ周り
強力なORマッパー的なやつSQL書かずにコードだけでDBのトランザクション発行できる。（これはRailsか。）

で、次に
[改訂4版 基礎 Ruby on Rails (IMPRESS KISO SERIES)](https://www.amazon.co.jp/%E6%94%B9%E8%A8%824%E7%89%88-Ruby-Rails-IMPRESS-KISO/dp/429500460X/ref=sr_1_2?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=rails&qid=1562599646&s=books&sr=1-2)
立ち読みして、サンプルが分かりやすく書かれてたので買い。これが良かった。
動くアプリを真似ながら習得するのが一番早いので、私は必要な部分を真似して習得しました。
Google先生とこの本が5体5って感じ。
あ、ちなみにRailsアプリはscaffoldが推奨されているのをよく見ますが、お勧めしません。
だって意味が分からないまま、動いてしまうからです。
ルートも１つ１つ書いたほうがよいと思います。汚くてもいいから自分の書き方で書く。動けばいいの精神で。
ここでまっとうなやり方にこだわっていたら、私は挫折していたと思います。
あとでまっとうなやり方を学んでソースコードをリファクタリングすればよいのです。自分の書き方で書いていれば、
リファクタリングもほんとにスムーズにいきます。びっくりするくらい。
また、ルートをしっかり書こうとすると、RESTFULな考えを自然に覚えさせられます。それが分かれば、scaffold
使ってもいいかなと。だってscafflodってRESTFULな感じでCRUD操作を簡単に実装してくれるやつだし。

あとはRails 〇〇　でぐぐって、ひたすらソースコードを真似る。

です。これでWebサービスを１つ作ることができました。
（検証・本番環境の構築も激しく詰まったけど、また後日書きます）

## 蛇足ですが、本のお勧め読み方
ある程度分からなくてもいい、適当でもいいから、まず斜め読みで全部読む。
それから手を動かしながら本のソースコードを書くといい感じ。
この前東大生が言ってた。本を読んで最初から100%理解できるわけないと。
まず斜め読みして全部の20％把握してから（たぶん東大生は70%くらいだと思うけど）、
もっかいしっかりやったほうがはるかに効率よいと。
実践してみたら、ほんとでした。高校生の頃にこの真理を学んでおけば。。。と悔やむくらい。
20%把握しておけば、これは難しいからあとでいいやとか、これは大事だからしっかりとかもある程度
事前に分かっているから、とても効率よいのです。本を読むぞって構えなくてもいいのも〇。隙間時間でざっとね。
最後にしっかり時間とってやる。章ごとくらいが集中力続く限界かな。
だまされたと思ってお試しあれ。
Spreadのように、DataGridViewを使用する場合のTips

※随時追加予定です。

# TL;DR

- GrapeCity（ActiveX）のように列と行を指定して値を設定する場合のTips

# （１）RowCountプロパティを変更すると、指定した値がどんどん下にずれていく

## 原因

新規行が有効だと、RowCountプロパティは新規行も含めた行数となる。
つまり実際に追加しているのは新規行であるため、行数を増やすと新規行が一番下に来る、という理屈になる

## 対応策

新規行を無効（`AllowUserToAddRows = False`）とすればよい。
`ReadOnly = False`なら、`AllowUserToAddRows = False`とセットで考えておくとよい。
GrapeCity（ActiveX）に合わせるなら、`AllowUserToDeleteRows = False`と設定してもよいだろう。

## ソース
### 修正前

```vb:Form1.vb
    Private Sub Form_Load(sender As Object, e As EventArgs) Handles Me.Load
        DataGridView1.MultiSelect = False
        DataGridView1.ReadOnly = False
        DataGridView1.ColumnCount = 1
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        DataGridView1.RowCount += 1
        DataGridView1.Rows(DataGridView1.RowCount - 1).Cells(1 - 1).Value = $"No{DataGridView1.RowCount}"
```

### 修正後

```vb:Form1.vb
    Private Sub Form_Load(sender As Object, e As EventArgs) Handles Me.Load
        DataGridView1.AllowUserToAddRows = False
        DataGridView1.MultiSelect = False
        DataGridView1.ReadOnly = False
        DataGridView1.ColumnCount = 1
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        DataGridView1.RowCount += 1
        DataGridView1.Rows(DataGridView1.RowCount - 1).Cells(1 - 1).Value = $"No{DataGridView1.RowCount}"
```

# （２）カスタム列の実装

.NET DataGridViewのカスタムセルを実装する場合の注意点
https://qiita.com/tfukumori/items/6e5876e19d126fdcb85b
GAE/JのDatastore関連備忘録

# Datastoreで使用できるタイプ
以下に一覧がある。新しいjava.timeパッケージ関連は使えないのでDate型でなんとかする必要あり。
https://cloud.google.com/appengine/docs/standard/java/datastore/entities#Java_Properties_and_value_types

#ローカルサーバーでDatastoreを参照する方法
使用言語によって細かな手順は違うらしいけど、Javaの場合は以下
1. ローカルサーバーを立ち上げる
2. 開発コンソール http://localhost:8080/_ah/admin にアクセスする
https://cloud.google.com/appengine/docs/standard/java/tools/using-local-server#browsing-datastore
NeoVim備忘録

# NeoVimを用いたGolang開発に伴う便利技
Golangの開発にvim-goを用いる。
:GoRunを行なった際画面が自動で分割される、自動展開されたウィンドウを一々削除するのは面倒である。
&lt;Ctrl-w&gt;o
カレント以外の不要ウィンドウを全て削除することができる。

今後も学習を重ねるごとにこの場をお借りしメモとして残していきたいと思う。
active_model_serialiser 使い方

## active_model_serialiser とは？
（アクティブ・モデル・シリアライザー） は jbuilder の代わりに API を返すための gem 。

## 導入

gem ファイルに追記し bundle install をする。
このとき jbuilder 削除してよし。

```:Gemfile
gem 'active_model_serializers'
- gem 'jbuilder'
```

## 設定の数々

#### ディレクトリの作成
API 設計の観点からいくつかディレクトリの整理をすることがベスト。

**app/controllers/api/v1/**
/api/v1/ ディレクトリを自分で作成し上記の配置にする。

#### controller の配置
**app/controllers/api/v1/〇〇_controller.rb**
先ほど作成したディレクトリに controller ファイルを移動させる。

**作成ファイル(雛形)**

**base_api_controller.rb**

```ruby:base_api_controller.rb
class Api::V1::BaseApiController < ApplicationController
end
```

**各controller**

```ruby
module Api::V1
  class ArticlesController < BaseApiController

    def index
      articles = Article.all
      render json: articles
    end

    def show
      @article = Article.find(params[:id])
      render json: @article
    end
  end
end
```

#### ルーティングの設定

```ruby:routes.rb
Rails.application.routes.draw do
  namespace :api, format: :json do
    namespace :v1 do
      resources :users
      resources :articles
    end
  end
end
```

ディレクトリの配置に合わせている感じ？

#### JSON の出力方法を設定

**config/initializers/active_model_serializers.rb**の作成

ファイルは自作

```ruby:config/initializers/active_model_serializers.rb
ActiveModel::Serializer.config.adapter = :json_api
```

data がついて出力されるようになる。

 

## 使い方

## 関連ファイルを作成するコマンドの実行

```
$ be rails g serializer ControllerName
```

上記のコマンドで、 app ディレクトリ配下に serializers ディレクトリが自動で作成され、指定したモデル名のファイルが作成される。
それに詳細を記述していく。

```ruby
class UserSerializer < ActiveModel::Serializer
  attributes :id,:name,:email,:password ← 出力したい key

  has_many :articles ← リレーション関係 〇〇.rb そのままでオケ
end
```


## 参照

> https://qiita.com/yuta-ushijima/items/d503addc7c5061ff3c6b#_reference-dd11c4dea4bc2078de0d

> https://qiita.com/k-penguin-sato/items/adba7a1a1ecc3582a9c9

> http://yu0105teshi.hateblo.jp/entry/2018/03/23/151725
Docker で Amazon S3 に定期的に差分バックアップをとる

Docker Volume やディレクトリを Amazon S3 に定期的に差分バックアップをとるための [hoto17296/backup-s3](https://hub.docker.com/r/hoto17296/backup-s3) という Docker Image を作ったので、その紹介。

## やりたいこと
**Docker で運用しているサーバに関するデータを Docker Volume に保存しているとして、その中身を定期的にバックアップをとりたい。**[^state]

[^state]: ちゃんとした Web サービスなどを運用するなら、そもそも「状態」は外部 DB に切り出せという話はある

バックアップを保存する場所としては Amazon S3 が無難で、Amazon S3 にバックアップをとるときによく使われるツールとして AWS CLI の S3 Sync がある。

[sync — AWS CLI Command Reference](https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html)

S3 Sync には様々なオプションがあってバックアップの方法を柔軟に指定できるのだけど、それは他の記事を見てもらえればいいとして、問題は「定期的に」バックアップする部分にある。

AWS CLI とそれを動かすための Python を入れて、バックアップ対象の Volume を Amazon S3 に Sync するシェルスクリプトを書いて、あとはそれを cron で定期実行するように設定して・・・で出来るかと思いきや OS ごとに cron の癖があってハマるのでググりながら修正して・・・と、思ったよりも面倒だったりする。

ていうか Docker が入ってるなら Docker で解決すれば良さそう。

## 作ったもの
[hoto17296/backup-s3](https://hub.docker.com/r/hoto17296/backup-s3)

Docker コンテナの中で crond と AWS CLI が動くので、ホスト OS に Python を入れる必要がないし OS ごとの cron の挙動の違いを意識する必要もない。いくつか必要な設定をしてコンテナを起動するだけでいい。

使い方は簡単で、

- いくつか環境変数を指定する
    - `SCHEDULE` バックアップをとるスケジュールを crontab フォーマットで指定する
    - `S3_URL` バックアップ先の S3 バケットを指定する
    - `AWS_*` コンテナ内から S3 バケットにアクセスするための認証情報を指定する
- `/src` にバックアップ対象のディレクトリもしくは Docker Volume をマウントする

これだけ設定して、コンテナを起動する。

その他にも、タイムゾーンを指定できたり、S3 Sync のオプション (`--delete` とか) を追加できたり、除外設定 `--exclude` をまとめて設定できたり、いくつかのオプションがある。詳しくは README を参照。

## Docker Compose の例
Jupyter Notebook を Docker で動かしており、その Notebook を `notebooks` という Docker Volume に保存している場合の例。

``` yaml:docker-compose.yml
version: '3'

services:

  backup-s3:
    image: hoto17296/backup-s3
    environment:
      TZ: Asia/Tokyo
      SCHEDULE: '0 21 * * *'
      AWS_ACCESS_KEY_ID: XXXXXXXXXXXXXXXXXXXX
      AWS_SECRET_ACCESS_KEY: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      S3_URL: s3://backup/notebooks
      SYNC_OPTIONS: --delete
      EXCLUDE_FILES: '*.git/*, *.ipynb_checkpoints/*'
    volumes:
      - notebooks:/src
```

上記の指定をすると、 `notebooks` Volume の中身を日本時間 21 時に `s3://backup/notebooks` にバックアップをとってくれる。

追加で `--delete` オプションも指定しているので、削除されたファイルは自動的に S3 バケットからも削除される。

## 参考
- [DockerでcronしたいときはBusyBox crondが便利 - shimoju.diary](https://shimoju.org/2017/10/09/busybox-crond/)
PandocでPowerPointを作成する。(On Google Colab)

# PowerPoint書式をpandocで作る
pandocでは、Markdown記法で記載した文書を様々な書式に出力できる。ここでは、PowerPointへの出力を試みた。

##pandocのインストール
pandocでPowerPoint書式を出力するには、[2.0.5](https://pandoc.org/releases.html#pandoc-2.0.5-12-december-2017)以上の版数を使う必要がある。しかし、デフォルトでは、pandoc 1.19.2.4がインストールされている。このため、新しいpandocをインストールする。これは、Ubuntu 18.04LTS全般の問題であり、Ubuntuの次のLTSがリリースされた時点で解決すると思われる。
以下の手順で、インストールできるが、stackの処理が2000秒強かかるので、40分程度待つ必要がある。

```
!curl -sSL https://get.haskellstack.org/ | sh
!stack install pandoc --verbose >& pandoc.log
!/root/.local/bin/pandoc --version
```
##pandocでPowerPointの作成
以下のようにMarkdownファイル(test.md)を作成する

```
%%writefile test.md
% Habits
% John Doe
% March 22, 2005
# In the morning
## Getting up
- Turn off alarm
- Get out of bed

## Breakfast
- Eat eggs
- Drink coffee

# In the evening
## Dinner
- Eat spaghetti
- Drink wine
```
以下のようにして出力する。

```
!/root/.local/bin/pandoc test.md -f markdown  -o test.pptx
```

##PPTXファイルのダウンロード
PPTXファイルのGoogle Driveのダウンロードは以下のスクリプトで出来る。

```
!pip install -U -q PyDrive

from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials

auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)

upload_file = drive.CreateFile()
upload_file.SetContentFile("test.pptx")
upload_file.Upload()
```
#参考資料
- [Haskell Tool Stack Install/upgrade](https://docs.haskellstack.org/en/stable/install_and_upgrade/)
- [Installing the development version of pandoc](https://github.com/jgm/pandoc/wiki/Installing-the-development-version-of-pandoc)
機械学習の「解釈」入門（翻訳）- Part 1

## 機械学習の「解釈」入門
本記事は、Navdeep GillとPatrick Hallによって執筆された"An Introduction to Machine Learning Interpretability"の翻訳です。

### 出版情報
出版日: 2018年4月
ISBN: 9781492033141


##　本の概要
イノベーションと競争が進むにつれ、データサイエンティストは、一層複雑な機械学習予測アルゴリズムを作ることに駆り立てられています。より複雑なモデルを作ることで、精度はあがりますが、その分、解釈が難しくなります。正確性が解釈性より重視された場合、ビジネス分野での採用、適用や規制の見落とし、モデルの説明等に影響を与えながら、人々の信頼を損ないます。[原文: When accuracy outpaces interpretability, human trust suffers, affecting business adoption, regulatory oversight, and model documentation. "human suffers"以降が具体的に何を示しているのか明確に理解できておりません。]


銀行、保険、医療などの予測モデルは、特に解釈性が求められます。本書では、H2O.aiのPatrick HallとNavdeep Gillが機械学習の「解釈」の入門書として、データサイエンティストがモデルの解釈性を維持しながら、精度度を向上させる機械学習の手法やアルゴリズムについてご紹介します。下記が本書の主なポイントです。

* 機械学習と予測モデルの実践的応用法
* 社会やビジネスの観点から、機械学習の解釈性を学ぶ意義（公平性、説明責任、透明性）
* 線形モデルとより精度の高い手法の違い
* そもそも「解釈性」とは何か？解釈性の最先端研究グループの活動
* 解釈可能な機械学習アプローチの分類や用語説明
* 実践的な解釈可能な機械学習モデルの訓練方法、複雑なモデルの説明の生成とデータの可視化方法
* モデル解釈性の自動的テスト方法


（今後、続きます）

筆者について
* 技術をより深く学ぶために、技術書を書きたい。Teching is the best way to learn. 
* ただし、いきなりはハードルが高いので、まずは翻訳を通して「執筆」と「発信」を習慣化したい。
* Compare yourself with who you were yesterday
と考えている、マイペース・データサイエンティストです。

本記事について
* Qiitaでの投稿は初ですが、何かフィードバックをいただけたら幸いです。
SQLアンチパターン-6章 ポリモーフィック関連-まとめ

##  複数のモデルにまたがって存在しているモデルの扱い
1対多、多対多の関係性のあるモデルについて考えます。

本(book)モデルと
コメント(comment)モデルがあったとしましょう。

- 本に対してコメントをつけられる事ができます。
- 本に対してコメントは複数つける事ができます。

ここで、本の執筆者である
著者(author)モデルを考えてみましょう。

- 著者に対してコメントをつけられる事ができます。
- 著者に対してコメントは複数つける事ができます。

このとき、コメントモデルには外部キーが2つ出現しています。
`book_id` と `author_id` です。
この2つのキーが被ってしまう恐れがあるので
単純にテーブル結合をしてデータを取り出すことはできなくなります。

## ポリモーフィック関連
上記のパターンになったときに、思いつかれる解決策があります。
それがポリモーフィック関連と言います。

単純に `book_id` と `author_id` を扱う場合、
コメントテーブルに列をそれぞれ作成すれば良いです。
しかし、他にもコメントがつけられるようなモデルが新たに作成されたらどうなるでしょうか。
例えば本だけでなく、映画、テレビ、などなど・・・。
それぞれ ` movie_id`　や `tv_id` など、何かしらNULLの値が入ってしまう列を作ってしまうことになります。

それでは、コメントをつけるモデルのidと、その種類分けを定義した列、
`comment_type` と `commented_id` 
を追加したらどうなるでしょうか。

ある行では

```
comment_type = book
commented_id = 2
```

また、ある行では

```
comment_type = author
commented_id = 3
```

というように、表す事ができるようになります。

## デメリット
しかしポリモーフィック関連を使って設計すると
外部キーとして扱っている `commented_id` が、実際には外部キー宣言をせずして扱うことになってしまいます。外部キーは1つのテーブルにしか紐づける事ができないからです。
そのため、その外部キーがあるテーブルと紐づいたときに、値が存在しているのかを保証するための参照整合性制約を設ける事ができなくなります。


また、コメントテーブルのデータを取得する場合、
外部結合で複数のモデルを結合し、結合する必要があります。

ポリモーフィック関連を使うと、DBのでデータ制約を利用する事ができなくなるので
アプリケーション側で調整する必要があります。


## Railsはこの問題に対応している
フレームワークによってはこの問題に対応しているものもあります。
例えばRailsでは、polymorphic属性を宣言する事で、1つのモデルを複数のモデルに紐づけて外部キーを設定する事ができます。


## ポリモーフィック関連を使う場面
外部キーのように紐づけたいモデルが、複数存在し、かつ、どのようなモデルが現れうるのか、将来的に不透明であるという確度が高いときには利用せざるを得ないかもしれません。


## ポリモーフィック関連の代替策

### 交差テーブルを作成する
最初の例を元に説明すると
`books_comments` テーブルと
`authors_comments` テーブルを作成する方法です。
交差テーブルが存在する事で、どのモデルを示すかを表していた `comment_type` を利用する必要が無くなります。

注意点としては、UNIQE制約を利用しないと、自然と多対多の関連づけが作成されてしまう事です。
また、両方の交差テーブルに同じ `comment_id`が存在しうるので、
アプリケーション側で対応する必要もあります。

### 共通の親テーブルを作成する
`book` , `author`, `comment` の全ての親となる `reputation` モデルを作成したとします。
`book` , `author`, `comment` の全てが外部キーとして`reputation_id`という擬似キーを持たせる事で、コメントモデルを元に同じ`reputation_id`に紐づいた`book`、`author`モデルのデータを引っ張る事が可能になります。逆も然りで、`book`から同じ`reputation_id`に紐づいた`comment`データを引っ張る事もできるようになります。
交差テーブルを作らなくても、擬似キーだけでデータの整合性制約を利用した設計をする事が可能になります。