OmniAICreator/Qiita-1.07M huggingface dataset:
pivot_tableを使う

クロス集計とかに超便利なのであーる！

```
ykishi@dezembro pivot_table % cat pivot_test.py 
```
```Python
#!/usr/bin/env python3
import pandas as pd
df = pd.read_excel('Book1.xlsx', sheet_name=0)
print(df)
print()
pt = df.pivot_table(values="Amount", index="PersonInCharge",
                    columns="ProductName")
print(pt)
print()
pt = df.pivot_table(values="Amount", index="PersonInCharge",
                    columns="ProductName", fill_value=0)
print(pt)
print()
pt = df.pivot_table(values="Amount", index=["PersonInCharge", "CustomerName"],
                    columns="ProductName", fill_value=0)
print(pt)
# CSVに出力
pt.to_csv("result.csv")
```
```
ykishi@dezembro pivot_table % ./pivot_test.py; cat result.csv 
   PersonInCharge ProductName CustomerName       Date  Amount
0            John           A         Mick 2021-09-03       5
1            Paul           A        Keith 2020-01-02      55
2          George           B          Ron 2022-01-01     333
3           Ringo           C         Bill 2021-04-05      20
4           Ringo           B        Keith 2021-05-01     203
5           Ringo           C        Keith 2021-04-03      46
6           Ringo           A         Bill 2021-08-13      11
7           Ringo           D         Mick 2021-09-15      49
8            John           C         Mick 2021-04-04     400
9            John           D         Mick 2021-02-12      22
10           Paul           A        Keith 2021-03-16      33
11         George           C          Ron 2021-12-03      77
12         George           B          Ron 2021-11-05      80
13           John           A          Ron 2021-12-30    1900
14          Ringo           A          Ron 2021-06-03     400
ProductName         A      B      C     D
PersonInCharge                           
George            NaN  206.5   77.0   NaN
John            952.5    NaN  400.0  22.0
Paul             44.0    NaN    NaN   NaN
Ringo           205.5  203.0   33.0  49.0
ProductName         A      B    C   D
PersonInCharge                       
George            0.0  206.5   77   0
John            952.5    0.0  400  22
Paul             44.0    0.0    0   0
Ringo           205.5  203.0   33  49
ProductName                     A      B    C   D
PersonInCharge CustomerName                      
George         Ron              0  206.5   77   0
John           Mick             5    0.0  400  22
               Ron           1900    0.0    0   0
Paul           Keith           44    0.0    0   0
Ringo          Bill            11    0.0   20   0
               Keith            0  203.0   46   0
               Mick             0    0.0    0  49
               Ron            400    0.0    0   0
PersonInCharge,CustomerName,A,B,C,D
George,Ron,0,206.5,77,0
John,Mick,5,0.0,400,22
John,Ron,1900,0.0,0,0
Paul,Keith,44,0.0,0,0
Ringo,Bill,11,0.0,20,0
Ringo,Keith,0,203.0,46,0
Ringo,Mick,0,0.0,0,49
Ringo,Ron,400,0.0,0,0
ykishi@dezembro pivot_table % 
```
How to load and call shared objects from Python

C言語で作った共有オブジェクトと連携してみる。

```c
$ cat greeting.c

char *
getMessage (void)
{
  return "HELLO!";
}
void
sayHowRU ()
{
  printf ("Hi, how are you?\n");
}
int
getSquare (int i)
{
  return i * i;
}
int
multiplication (int a, int b)
{
  return a * b;
}
```
```sh
$ gcc -c greeting.c && gcc -shared -o greeting.so greeting.o
$ ls -l *.so
-rwxr-xr-x 1 kishi kishi 10638 May 25 19:54 greeting.so

$ cat MyProto.py
```
```python
#!/usr/bin/env python

import ctypes

myLib = ctypes.CDLL( './greeting.so' )

"""
-- This is the case that the function has no arguments
getMessage = myLib.getMessage
getMessage.argtypes = [ctypes.c_void_p]
getMessage.restype = ctypes.c_char_p
print getMessage(None)
"""

#------------------------------------------------
# calls C function "getMessage()"
#------------------------------------------------
getMessage = myLib.getMessage
getMessage.restype = ctypes.c_char_p
print getMessage()
#------------------------------------------------
# calls C function "sayHello()"
#------------------------------------------------
sayHowRU = myLib.sayHowRU
sayHowRU()
#------------------------------------------------
# calls C function "getSquare()"
#------------------------------------------------
getSquare = myLib.getSquare
print getSquare(10)
#------------------------------------------------
# calls C function "multiplication()"
#------------------------------------------------
multi = myLib.multiplication
print multi(9,9)
```
```sh
$ ./MyProto.py
HELLO!
Hi, how are you?
100
81
```
AXONフレームワークを用いたチュートリアルをやってみた

# AXONフレームワークを用いたチュートリアルをやってみた

## 目的や背景
社内でマイクロサービスアーキテクチャ（MSA）の問い合わせや相談が増えてきたが、そんなに事例がないため、色々なパターンに対応できないので、知識習得のために、チュートリアルをやってみた。

## 参考書籍やサイトなど

* マイクロサービスパターン（Chiris Richardson著）
* Udemyのコース（AXON＋SpringCloud）
　https://www.udemy.com/course/spring-boot-microservices-cqrs-saga-axon-framework/learn/lecture/26251768?start=75#overview
* https://microservices.io/

## チュートリアルの概要と利用技術要素

業務機能としては以下のサービスに分割されている 

* UserService
* PaymentService
* ProductService
* OrderService

基本的な流れとしては、Productをある数量分登録し、それに対してOrderが入るたびに、在庫を減らしていき、Paymentが成立すると、Orderが承認されるという流れである。  
なお、何らかのエラーの場合には補償トランザクションが発行される。


直接の業務機能とは関係ないが、以下のSpringCloudのサービスも利用している。

* Eureka (Service Discovery)
* API Gateway

MSAのメッセージブローカーやイベントソーシングのフレームワークとしては、AXONを使っています。  
AXONは、フレームワークとサーバーがある。
今回はサーバーは、Dockerで構築した。
https://axoniq.io/


## ごく一部のシーケンス図

非常に見づらいがOrderを生成する部分のシーケンス図を書いてみた。
実際にAXONサーバーがどのように機能しているかは分からない部分もあるので、推測を含みます。

ざっと流れを記述すると、、、

* Controller(APIのエンドポイント）は、POSTされた内容から、CreateOrderCommandを生成し、Gateway経由で、AXONサーバーに渡します。
* AXONサーバーは、OrderAggregate（ドメインオブジェクト）を生成します。
* OrderAggregateは必要な業務処理をし、OrderCreatedEventを生成し、AXONサーバーに渡します。
* AXONサーバーは、OrderCreatedEventをOrderSaga(サーガのオーケストレータ)とOrderEventsHandlerに伝播します。
* OrderSagaはサーガのオーケストレータとして、後続のイベント処理を司ります。（条件によっては、補償トランザクションを発火させます。）
* OrderEventsHandlerは、（SpringJPA使っている場合）Repository経由でJPAを用いて永続化をします。

![Untitled Diagram-Page-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130262/ee45420b-900d-0c76-02ff-7fdca9757bcc.png)


## ソースコードサンプル
https://github.com/akiraabe/spring-boot-msa


## AXONを用いたMSAのPro/Con

### Pro

* イベントソーシング、CQRSを前提としているので、MSAの王道を行くフレームに則れる。
* ドメインロジックがAggregateに集まるため、コンポーネントの責務が明確になる（Aggregateは一部AXONのライブラリーをMockに差し替えればテストもしやすい）

### Con

* このチュートリアルでは、複数サービス横断のコマンドやイベントをcoreというプロジェクトに集めているが、この部分は、各サービスがcoreの実装に依存している。全サービスをJavaで作るなら問題ないが、そうでない場合には、ここの抽象度を高める工夫が要る
* コマンドからイベントへのデータの詰め替えなどの操作が多く、冗長に感じる。


## まとめ

実際に、チュートリアルで手を動かすことにより、実感することは多いと再認識しました。
1.4(易) 部分集合についての確率

## 答案
### 1.
$B\subset A$とすると，

```math
P[A|B^c]\neq 0,\ P[A|B]=1
```

より題意を満たす．

### 2.
$A\subset C$とすると，

```math
P[C|A]=1
```

より題意を満たす．

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
[Azure Pipeline] テストやビルド結果のファイルをダウンロードできるようにする

#経緯
E2Eテストをpipeline上で自動実行できるように実装した。
テスト結果は`PublishTestResults`タスクやログから確認できるが、
エビデンスとして撮影したスクリーンショットはスクリプト終了時にpipelineエージェントとともに消え去ってしまう...
スクショなどのファイルをpipelineエージェントから取り出せるようにしたい。

# Artifactとは
pipelineを実行した結果として出力されたファイル = 成果物 のこと。
↓のドキュメントではビルドで出力された.exeファイルやパッケージを指しているが、テスト結果のエビデンスとして出力した画像ファイルなどもアーティファクトとして扱える模様。

https://docs.microsoft.com/ja-jp/azure/devops/pipelines/artifacts/artifacts-overview?view=azure-devops&tabs=nuget

# 実装方法
https://docs.microsoft.com/en-us/azure/devops/pipelines/tasks/utility/publish-build-artifacts?view=azure-devops
## ymlファイルにタスクを追加

```pipeline 
      - task: CopyFiles@2
        inputs:
          Contents: |
            $(Build.SourcesDirectory)/evidence/**/*
          TargetFolder: '$(Build.ArtifactStagingDirectory)'

      - task: PublishBuildArtifacts@1
        inputs:
          PathtoPublish: '$(Build.ArtifactStagingDirectory)'
          ArtifactName: 'evidence'
          publishLocation: 'Container'
```
[`Build.ArtifactStagingDirectory`](https://docs.microsoft.com/en-us/azure/devops/pipelines/build/variables?view=azure-devops&tabs=yaml#build-variables-devops-services)は発行前のアーティファクトを置いておくためのディレクトリ。
`CopyFiles`で準備し、`publishBuildArticacts`で発行する。

`publishLocation`は発行先のオプションで`Container`(pipeline上)と`FilePath`(任意のパス)から選べるようだが、後者はwindowsエージェントのみ使用可能な模様。

今回はテスト結果の発行に`PublishBuildArtifacts`を使用しているが、名前的にビルド成果物のためのタスクのようなので、`PublishPipelineArtifact`を使うほうが良いかもしれない。

## pipelineの実行結果画面からダウンロードする
実行結果画面の`published`からダウンロードできるようになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547333/09f0947b-7c36-abca-f033-f48f2b751f9a.png)



microsoftのドキュメントを見ると、
　pipeline -> 外部　を「発行 publish」
　pipeline <- 外部　を「ダウンロード download」と表現している。
pipeline目線だとそりゃそうなのだが、私の場合「pipelineからファイルをダウンロードしたかった」ので「azure pipeline ファイル　ダウンロード」などのワードで検索しており適切な資料を見つけるのに手間取ってしまった。
1.3(易) 条件付き確率と同時確率

## 方針

ベイジアンネットワークなどのアイデアとなる変形方法である．条件付き確率の定義式：

```math
P[A\cap B]=P[B]P[A|B]
```

を用いて式変形をしていく．

## 答案

任意の自然数kに対し

```math
X_k=A_1\cap \ldots\cap A_k
```

と置くと，

```math
\begin{align}
P[A_1\cap \ldots\cap A_n]&= P[A_n\cap X_{n-1}]\\
&= P[A_n|X_{n-1}]P[X_{n-1}]\\
&= P[A_n|X_{n-1}]P[A_{n-1}\cap X_{n-2}]\\
&= P[A_n|X_{n-2}]P[A_{n-1}|X_{n-2}]P[X_{n-2}]\\
&\vdots\\
&= P[A_n|X_{n-1}]\ldots P[A_k|X_{k-1}]\ldots P[A_2|X_1]P[X_1]\\
&= P[A_n|A_1\cap\ldots\cap A_{n-1}]\ldots P[A_2|A_1]P[A_1]
\end{align}
```

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
Franka ローカルでexamplesをビルド・Makefile的

https://frankaemika.github.io/libfranka/examples.html のファイルをビルドする

```Makefile.simple
INCS=   -I /opt/ros/melodic/include/libfranka -I /usr/include/eigen3

LIBS=   /opt/ros/melodic/lib/libfranka.so -lPocoFoundation -lPocoNet -lpthread

EXES=\
        cartesian_impedance_control\
        communication_test\
        echo_robot_state\
        force_control\
        generate_cartesian_pose_motion\
        generate_cartesian_velocity_motion\
        generate_consecutive_motions\
        generate_elbow_motion\
        generate_joint_position_motion\
        generate_joint_velocity_motion\
        grasp_object\
        joint_impedance_control\
        joint_point_to_point_motion\
        motion_with_control\
        print_joint_poses\
        vacuum_object

OBJS=   $(patsubst %, %.o, $(EXES))
OBJS+=  examples_common.o

define link
$(1): $1.o examples_common.o
        g++ -o $1 $1.o examples_common.o $(LIBS)
endef

all: $(EXES)

$(foreach prog, $(EXES), $(eval $(call link, $(prog))))

.cpp.o:
        g++ $(INCS) -c $<

clean:
        rm -f $(OBJS) $(EXES)
```
Rails urlにユーザーのidが欲しい時！！

#####ユーザー詳細画面から、そのユーザーがいいねした投稿一覧ページを表示させたいと思ったときえに、paramsでユーザーのidを受け取りたかったけどurlにidが入っていない！

そんなときどうやってurlにユーザーidを入れるのか？

###routes.rbでusersにdoをつけて入れ子構造にすればいい！

```ruby
get 'user_likes' => 'users#user_likes' as: user_likes
```

最初は上記のようにユーザーがいいねした投稿一覧を表示するページのurlを作成していた
しかしこの書き方だと、rails routesしてみるとurlは

```ruby
/users/user_likes
```
こうなっているはず。これだとidが入っていないためparamsでidを取得することはできない

そこで resources users のルーティング内に入れ子構造にしてurlを入れてみる

```ruby
resources :users do
    get 'user_likes' => 'users#user_likes'
  end
```

こうすることでusersが親、作成したurlが子になり rails routesで確認してみると

```ruby
/users/:user_id/user_likes
```

今度はこうなっているはず! :user_idが追加され、urlの中にユーザーのidを入れることができた

名前付きurlも user_user_likes となり、user_user_likes_pathで指定できる

コントローラーでメソッドを作り

```ruby
@user = User.find(params[:user_id])
```

みたいな感じでurlからユーザーのidを受け取るといい
ちなみに、（params[:id])じゃないのは rails routes で確認したurlが /users/:user_id/user_likes で :user_id のため、ここが :id なら
paramsで取得する際は (params[:id])になる
windows10のフォントとフォントサイズ変更

# フォント変更

```my-system-font.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts]
"Segoe UI (TrueType)"=""
"Segoe UI Bold (TrueType)"=""
"Segoe UI Bold Italic (TrueType)"=""
"Segoe UI Italic (TrueType)"=""
"Segoe UI Light (TrueType)"=""
"Segoe UI Semibold (TrueType)"=""
"Segoe UI Symbol (TrueType)"=""

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes]

"Segoe UI"="変更したいフォント名"
```

作成したmy-system-font.regをmergeしてリログインする


もとのフォントに戻すには

```:restore-default-font.reg
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts]
"Segoe UI (TrueType)"="segoeui.ttf"
"Segoe UI Black (TrueType)"="seguibl.ttf"
"Segoe UI Black Italic (TrueType)"="seguibli.ttf"
"Segoe UI Bold (TrueType)"="segoeuib.ttf"
"Segoe UI Bold Italic (TrueType)"="segoeuiz.ttf"
"Segoe UI Emoji (TrueType)"="seguiemj.ttf"
"Segoe UI Historic (TrueType)"="seguihis.ttf"
"Segoe UI Italic (TrueType)"="segoeuii.ttf"
"Segoe UI Light (TrueType)"="segoeuil.ttf"
"Segoe UI Light Italic (TrueType)"="seguili.ttf"
"Segoe UI Semibold (TrueType)"="seguisb.ttf"
"Segoe UI Semibold Italic (TrueType)"="seguisbi.ttf"
"Segoe UI Semilight (TrueType)"="segoeuisl.ttf"
"Segoe UI Semilight Italic (TrueType)"="seguisli.ttf"
"Segoe UI Symbol (TrueType)"="seguisym.ttf"
"Segoe MDL2 Assets (TrueType)"="segmdl2.ttf"
"Segoe Print (TrueType)"="segoepr.ttf"
"Segoe Print Bold (TrueType)"="segoeprb.ttf"
"Segoe Script (TrueType)"="segoesc.ttf"
"Segoe Script Bold (TrueType)"="segoescb.ttf"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes]

"Segoe UI"=-
```




# フォントサイズ変更

winキー > make text size bigger と入力　> Make text bigger のカーソルを調整(100%~225%)して好みのフォントサイズへ変更
1.2(易) 和事象，積事象の性質

## 方針

和集合と積集合の関係：

```math 

A\cap(B\cup C)=(A\cap B)\cup (A\cap C)
```

と，命題1.2(4)の

```math
P[A\cup B]=P[A]+P[B]-P[A\cap B]
```

を用いて式変形していく．いずれもベン図を書いて確かめることができる．

## 答案

```math
\begin{align}
P[A_1\cup A_2\cup A_3]&=P[(A_1\cup A_2)\cup A_3]\\
&= P[A_1\cup A_2]+P[A_3]-P[(A_1\cup A_2)\cap A_3]\\
&= P[A_1]+P[A_2]-P[A_1\cap A_2]-P[A_3]-P[(A_1\cap A_3)\cup (A_2\cap A_3)]\\
&= P[A_1]+P[A_2]+P[A_3]\\
& \ \ \ \ \ -P[A_1\cap A_2]-P[A_1\cap A_3]-P[A_2\cap A_3]\\
& \ \ \ \ \ +P[A_1\cap A_2\cap A_3]
\end{align}
```

## 参考文献

- 『[現代数理統計学の基礎](https://www.kyoritsu-pub.co.jp/bookdetail/9784320111660)』(久保川達也　著)
[React Native,Expo] expo start で Cannot find module 'babel-plugin-transform-react-jsx-source と怒られる時の対処法


# エラーの概要
cloneした4,5年前のレポジトリで `expo start`したら以下のメッセージが出て怒られた

```shell
Failed building JavaScript bundle.
node_modules/expo/AppEntry.js: Cannot find module 'babel-plugin-transform-react-jsx-source' from '/Users/ironsmri/Projects/sampleCodes/React_Native_Cookbook_sampleCode/Chapter02/fake-music-player'
- Did you mean "@babel/transform-react-jsx-source"?
```
参考までにexpoのコンソール画像
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/3b7c6fd4-3747-da49-cbc9-4d95d38d95cd.png)

実行時の.babelrc

```json
{
  "presets": ["babel-preset-expo"],
  "env": {
    "development": {
      "plugins": ["transform-react-jsx-source"]
    }
  }
}
```

# 解決方法
.babelrcを次のように変更した

```json
{
  "presets": ["babel-preset-expo"]
}
```

どうやら変更前のbabelrcに含まれていたプラグイン`transform-react-jsx-source`はbabel-preset-expoに含まれているものらしく、明示的に記述する必要はないらしい。レポジトリが作成された当時はsubsetではなかったのかもしれない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366323/f859d615-9f6b-ff7b-0664-1a11f2422ebc.png)
出典: https://forums.expo.io/t/problem-upgrading-to-sdk-31-cannot-find-babel-plugin-transform-react-jsx-source/16246/5


# 参考
- [.babelrcとbabel.config.jsの違い](https://uga-box.hatenablog.com/entry/2020/06/13/000000)
- [Cannot find module '@babel/plugin-transform-react-jsx-source' when running React App](https://stackoverflow.com/questions/53327625/cannot-find-module-babel-plugin-transform-react-jsx-source-when-running-react)
- https://forums.expo.io/t/problem-upgrading-to-sdk-31-cannot-find-babel-plugin-transform-react-jsx-source/16246/5
CentOSにMySQLのインストール/アンインストール

## 備忘録

### 環境
* CentOS 7

### MySQLのインストール

[mysqlの公式](http://dev.mysql.com/downloads/repo/yum/)に、各OS毎のyumリポジトリがありますので、自分のOSに合うもののダウンロードページへ行きます。

```bash
# ここは人によって違う
$ yum install https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm

$ yum -y install mysql-community-server

$ systemctl enable mysqld.service
$ systemctl start mysqld.service

# 表示された最後の文字列がパスワード
$ sudo grep password /var/log/mysqld.log

# MySQLログイン
$ mysql -u root -p
```

### アンインストール

アンインストールは上記の逆を行う

```bash
# インストールされているMySQL一覧
$ rpm -qa | grep -i mysql

# 全部削除
$ sudo yum remove mysql*
```

### 再設定
以下を参照
https://qiita.com/MatYoshr/items/f0e8e11a7bb10c45bad6

## 参考
* https://qiita.com/ritukiii/items/f4e2fbae5d6e7b1aa5f9
Nuxt.jsでurlのクエリパラメータを取得する方法

Nuxt.jsでurlのクエリパラメータを取得する方法になります。

```
/demo?id=123
```
本記事では、クエリの例をidとして解説しています。

## template内でurlのクエリパラメータを取得する

```vue
<template>
  <div>
    <p>{{ $route.query.id }}</p>
  </div>
</template>
```
templateからは`$route.query.id`でurlのクエリパラメータを取得できます。

## コンポーネントプロパティでurlのクエリパラメータを取得する

```vue
<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  mounted() {
    console.log(this.$route.query.id)
  }
})
</script>
```
`mounted`などのコンポーネントプロパティからは、`this`をつけることでurlのクエリパラメータを取得できます。

## Nuxtのコンテキストでurlのクエリパラメータを取得する

```vue
<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  asyncData({ query }) {
    console.log(query.id)
  }
})
</script>
```

`asyncData`や`middleware`などのNuxtのコンテキストからは、上記のようにurlのクエリパラメータを取得できます。

https://ja.nuxtjs.org/docs/2.x/internals-glossary/context
Nuxt.jsで現在のurlを取得する方法

Nuxt.jsで現在のurlを取得する方法になります。

```
https://demosaite.com/demo/2?user=123
```
本記事では、上記のurlを例に解説しています。

基本的には、`Vue Router`を使用することで取得できます。

## template内で現在のurlを取得する

```vue
<template>
  <div>
    <p>{{ $route.fullPath }}</p> <!-- /demo/2?user=123 -->
    <p>{{ $route.name }}</p> <!-- demo-id -->
    <p>{{ $route.params }}</p> <!-- { "id": "2" } -->
    <p>{{ $route.path }}</p> <!-- /demo/2 -->
    <p>{{ $route.query.user }}</p> <!-- 123 -->
  </div>
</template>
```
template内では、`$route`で現在のurlを取得することができます。

## コンポーネントプロパティで現在のurlを取得する

```vue
<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  mounted() {
    console.log(this.$route.params) // { "id": "2" }
    console.log(this.$route.query.user) // 123
  }
})
</script>
```
`mounted`などのコンポーネントプロパティからは、thisをつけることで現在のurlを取得できます。

## Nuxtのコンテキストでurlのクエリパラメータを取得する

```vue
<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  asyncData({ route }) {
    console.log(route.path) // /demo/2
    console.log(route.name) // demo-id
  }
})
</script>
```
`asyncData`や`middleware`などのNuxtのコンテキストからは、上記のようにurlを取得できます。

https://ja.nuxtjs.org/docs/2.x/internals-glossary/context

## httpsなどを含む全てのurlを取得したい場合

```vue
<script lang="ts">
import Vue from 'vue'

export default Vue.extend({
  mounted() {
    console.log(window.location.href)
    // https://demosaite.com/demo/2?user=123
  }
})
</script>
```
httpsなどを含む全てのurlを取得したい場合は、`window.location.href`を使うことで取得できます。

https://developer.mozilla.org/ja/docs/Web/API/Window/location
Karabiner-Elementsをアップデートしたらキー入力がデフォルトに戻った件

## 環境
- MacOS BigSur 11.4
- [Keyboard craft](https://www.logicool.co.jp/ja-jp/products/keyboards/craft.920-008511.html)
- [Karabiner-Elements 13.5.0](https://karabiner-elements.pqrs.org/docs/releasenotes/)

## 結論
- Karabiner-Elements 13.5.0だとlogicoolのキーボードCraftを認識してくれないので、13.4のまま使用すべし
- 13.5にしちゃった場合、公式から13.4をダウンロードし直せば大丈夫
AWS Perspective とは

## 勉強前イメージ

Perspective は 視点・・・・？

## 調査

### AWS Perspective とは

AWSのリソース構成からアーキテクチャ図を自動で作成してくれるものです
アカウントとリージョン全体のAWSリソースを確認し、webUIに表示します。

### 使用方法

AWS Perspectiveはcloudformationのテンプレートが提供されてるので
簡単に構築できます。
[こちら](https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/create/template?stackName=aws-perspective&templateURL=https://s3.amazonaws.com/solutions-reference/aws-perspective/latest/aws-perspective.template) からすすめることが出来ます。

### AWS Perspective の機能

- アーキテクチャ図の作成

アカウント・リージョン全体のリソース、それらの関係をwebUIに表示します。

- 検索

検索機能があり、その機能を使用すると
リソース名・タグ名・IPアドレスなどからリソースを見つけることが出来ます。

- アーキテクチャ図の保存とエクスポート

アーキテクチャ図を保存し、他のユーザと共有することが出来ます。
また、PNG・JSON・CSV・draw.ioにエクスポート出来ます。

## 勉強後イメージ

今ぱっと出せるcloudformationのymlファイルがないのでいまぱっと出来ない・・・
一回見たことある気がするけどやってみたいなぁ
結構お金高そうな気がする

## 参考

- [AWS Perspective](https://aws.amazon.com/jp/solutions/implementations/aws-perspective/)
- [AWSがアーキテクチャ図を自動作成できるソリューション実装「AWS Perspective」を公開](https://gigazine.net/news/20200924-aws-perspective/)
- [AWS Perspective AWS 実装ガイド](https://d1.awsstatic.com/Solutions/ja_JP/aws-perspective.pdf)
【Docker】開発用Dockerfile.devがbuildする時に時間がかかる時の解決策　no.31

![パンプキン カフェ (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011305/3297b7f9-f344-8d13-af11-9060f46cd21d.png)

こんにちは。

まゆみです。

Dockerについての記事をシリーズで書いています

Docker を使う時、本番用と開発用を分けるため、Dockerfileには2種類があります

>Dockerfile  本番用

>Dockerfile.dev　　開発用


Dockerfile.devを使って開発をしている時に、

『docker build -f Dockerfile.dev　のコマンドがスタートするのに時間がかかる』という意見を周りでたくさん聞いたので、今回の記事では、その解決法を書いていこうと思います。(私の場合はCreate React Appを使っている時にbuild のスタートがやたらとかかってしまいました。)


簡単に解決できますので、ぜひ使ってください。




#解決方法

Dockerfile.devのbuildのスタートに5分ほどかかってしまう方は

『.dockerignore』ファイルを活用すれば、スタートまでの時間が短縮されます。

.dockerignoreに、

node_modules

を書いて、buildする時にnode_modulesを無視させます。


以上になります。

.dockerignoreを活用したら、build のスタートに5分ほどかかっていたものが、1分もかからなくなりました。＼(^o^)／
販売データ分析チートシート (前処理/集計編)

# EC系の販売データを分析する際に使う処理

#### 販売データは以下のcsvを想定
|userid|order_id|purchase_date|shipment_date|product_name|amount|
|:----|:----|:----|:----|:----|:----|
|1|1|2021-01-01 00:00:00|2021-01-03 00:00:00|A|100|
|2|2|2021-01-01 00:00:00|2021-01-03 00:00:00|A|100|
|3|3|2021-01-01 00:00:00|2021-01-03 00:00:00|B|200|
|1|4|2021-02-01 00:00:00|2021-02-03 00:00:00|B|200|
|2|5|2021-02-01 00:00:00|2021-02-03 00:00:00|A|100|
|3|6|2021-02-01 00:00:00|2021-02-03 00:00:00|B|200|


#### csv読み込み
```py
import pandas as pd
import numpy as np

df = pd.read_csv('sales.csv', header=0)
# xlsx形式の場合は以下
# df = pd.read_excel('sales.xlsx')
```

#### 欠損値補完
- [userid]が欠損していたら'guest'で補完

```py
df['userid'] = df['userid'].fillna('guest')
```

#### 欠損レコードの削除
- [sihpment_date]が欠損しているレコードを削除
- inplace=Trueで元のdfを変更

```py
df.dropna(subset=['shipment_date'], inplace=True)
```

#### ソート
- [userid]昇順, かつ, [purchase_date]昇順

```py
df = df.sort_values(['userid', 'purchase_date'], ascending=[True, True])
```
```
               index  userid  order_id purchase_date shipment_date  ...省略...
purchase_date                                                        
2021-01-01         0       1         1    2021-01-01    2021-01-03   
2021-02-01         3       1         4    2021-02-01    2021-02-03   
2021-01-01         1       2         2    2021-01-01    2021-01-03   
2021-02-01         4       2         5    2021-02-01    2021-02-03   
2021-01-01         2       3         3    2021-01-01    2021-01-03   
2021-02-01         5       3         6    2021-02-01    2021-02-03
```

#### キャスト
```py
# Seriesをdatetimeにキャスト(以下の例だとdatetime64型(ns)にキャスト)
df['purchase_date'] = pd.to_datetime(df['purchase_date'])
df['shipment_date'] = pd.to_datetime(df['shipment_date'])

# useridをintにキャスト(astypeメソッドで'int'を指定するとint32にキャスト)
# 今回の例では[userid]は既にint64型だが、
df['userid'] = df['userid'].astype('int')
```

#### Series内各要素の置換
- [product_name]の半角スペースを削除

```py
df['product_name'] = df['product_name'].str.replace(' ', '')
```

#### 会員購入と非会員購入(ゲスト購入)の分別(dfを分ける)
```py
df_guest = df.query('userid == "guest"')
df = df.query('userid != "guest"')
```

#### [userid]毎の購入回数[cumcount]カラムを追加
```py
df['cumcount'] = df.groupby('userid').cumcount() + 1
```

#### indexつけ直し
```py
df = df.reset_index()
df_guest = df_guest.reset_index()
```

#### indexを購入日にする
- indexを購入日にすると[yyyy-mm-dd:yyyy-mm-dd]形式でスライスできるので便利

```py
df.set_index('purchase_date', drop=False, inplace=True)
print(df[2021-01-01:2021-01-31]
```
```
               index  userid  order_id purchase_date shipment_date  ...省略...
purchase_date                                                        
2021-01-01         0       1         1    2021-01-01    2021-01-03   
2021-01-01         1       2         2    2021-01-01    2021-01-03   
2021-01-01         2       3         3    2021-01-01    2021-01-03   
```
solidの概念 5つあるうちの3番目

# リスコフのほにゃららの法則

これも回りくどいっす.. 原文を読むと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1364181/699cc6db-89bb-daf0-1aec-bcc5148d6995.png)
「汝隣人を愛せよ」並の分かりづらい経典でした...orz

ちょっとsuperclassのメソッドを変更するのはもちろんセフセフ。でも、全く唐突に違うものに置き換えたら駄目っす、レベルのことだと思います。

他の解説記事では、「サブクラスでやっていることはスーパクラスでもできないといけない」とか書いてたんですが、そんなことは言ってません。そんなことやってたらできなかったら継承の概念が崩れます。**サブクラスでスーパークラスの原点忘れて、やりすぎんなよってことです。**


```php
   
    class Superclass{

           doSomething{
               // 例えば、 バリデーションして
               // Array に詰め込んで
               // return Array 
            }

     }

    // 良い例
    class GoodSubclass extends Superclass{

           doSomething{
                super(); // superで呼び出したのは　「1バリデーション -> 2 Arrayに詰め込む -> 3 return Array
                // 2 Array に詰め込む際の処理を更に足す
                // 3 を踏襲して、ちゃんとArray をreturn
            }

     }

    // 悪い例

  class BadSubclass extends Superclass{

           doSomething{
                super();  // superで呼び出したのは　「1バリデーション -> 2 Arrayに詰め込む -> 3 return Array
                // 2 Array に詰め込む際の処理を更に足す
                // なぜか唐突に 絶対 Exceptionを吐く処理を書く or return 0とかを返しちゃう 
                // 3　と全く無関係な処理👆
            }

     }

```
静的サイト界隈の3文字アルファベットの整理とそのSSG達 (Hexo、Hugo、Jekyll、GitBook、Gatsby、VuePress、Docsify) 

タイトルそのままだが、静的サイト界隈のまとめ。
[静的サイトジェネレーター Gatsby - Qiita](https://qiita.com/umamichi/items/9bd08a21fddc71588efc) のページが親切なのでまず引用。

> Wordpressのような従来CMSの仕組みは、MySQLなどのDBをもとに、サーバーでHTMLを生成して返すものだった。

> それに対し静的サイトジェネレーターは、コンパイル時にGraphQLやAPIからすべてのデータを取得し全てのHTMLを最初に生成する

**従来**:
![image](https://camo.qiitausercontent.com/dd48eac532157b277d6959e13fea8625508ccfa4/68747470733a2f2f757365722d696d616765732e67697468756275736572636f6e74656e742e636f6d2f373436393439352f37373636303633312d65633737353630302d366662632d313165612d393534662d3436663136633163316663662e706e67)
**SSG** ([引用](https://serip39.hatenablog.com/entry/2020/08/23/225000)): 
![image](https://cdn-ak.f.st-hatena.com/images/fotolife/s/serip39/20200823/20200823222603.jpg)

## 参考

https://monotein.com/blog/what-is-ssg

https://serip39.hatenablog.com/entry/2020/08/23/225000

https://zenn.dev/rinda_1994/articles/e6d8e3150b312d




## 概要

JamStackのJam は JavaScript、API、Markup(マークアップ)の略らしく、以下でSSGの人気がわかる。

https://jamstack.org/generators/

https://qiita.com/miyamae/items/1f719cd818c62274248f

https://zenn.dev/yuri/articles/f33216517c38a6d4306b

### まとめると

- SSG ... Static Site Generator
- CSR ... Client Side Rendering
- SSR ... Server Side Rendering
- ISR ... Incremental Static Regeneration
- BFF ... Backend for Frontend

https://qiita.com/souhei-etou/items/4c3320471d23a08510e1

## 有名なもの

### Hexo
https://hexo.io/

https://qiita.com/7321hasu/items/4ffe8636d69fea228827

https://qiita.com/e99h2121/items/a52040794f8911122fbe

### Hugo

https://gohugo.io/

https://zenn.dev/komisan19/articles/5504fd8c54ee4e

https://qiita.com/shojimotio/items/06ceb712e91b94e4c99a

https://qiita.com/e99h2121/items/f8807b349f787c26d253


### Jekyll

https://jekyllrb.com/



### GitBook

https://www.gitbook.com/

https://zenn.dev/mebiusbox/articles/703e934c78fa20

### Gatsby

https://www.gatsbyjs.com/

https://qiita.com/umamichi/items/9bd08a21fddc71588efc

https://qiita.com/e99h2121/items/9d4034603fa926d21cb9


### VuePress
https://vuepress.vuejs.org/

https://qiita.com/youdie/items/88df59a3ebaf47e3d992


### Docsify

https://docsify.js.org/#/

https://qiita.com/kapioz/items/2c2353320ea96c8c43ed


今後増えるかもしれません。
以上試してみたものの比較がてら。参考になればさいわいです。
Goをherokuでデプロイした時にエラー: code=H10 desc="App crashed"が出た

#背景
**やりたいこと：**
・Goで立てたサーバーをLINEmessagingAPIに結びつけてBOTを作ろうとしている
・LINEmessagingAPIのWebhookに貼るためにherokuでサーバーをデプロイする


**現状：**
・localhostでは問題なく画面表示できている（エラーの出力等はなし）

・デプロイの方法はherokuの[公式ドキュメント](https://devcenter.heroku.com/ja/articles/getting-started-with-go?singlepage=true)を参照してください

#エラー：Application error




```
$ git push heroku master
```
上記コードでデプロイしようとしたところ

![Heroku_Application_Error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1728773/a3bb63ab-d07d-5720-5629-b614700fdd8c.png)

デプロイ先のURLに飛ぶとこのような画面が表示されました。
<br>
エラーがログに残っているはずなので、画面に表示されている通り下記のコマンドをターミナルに打ってログを表示してみます。

```
$ heroku logs --tail
```

<dr>
すると、以下のようなログが残っていました。



>heroku[web.1]: State changed from starting to crashed
heroku[router]: at=error code=H10 desc="App crashed" method=GET path="/" host=fathomless-depths-28419.herokuapp.com request_id=c14072ee-8bea-471c-b1ae-79561e840c35 fwd="180.198.134.55" dyno= connect= service= status=503 bytes= protocol=https

<br>
このログをもとに、しばらく```"heroku H10"``` ```"app crashed"```のような単語で調べてみたのですが、

**・webdynoの再起動
・アプリ自体の再起動
・再デプロイ**

など、コードそのものに問題がなく解決するパターンもあるようです。

<dr>
<dr>

参考: 
・[Herokuでクラッシュしたアプリの原因究明と再起動する方法 | SERVERSUS](https://www.serversus.work/topics/gkdjdxdigobiykvm7j0d/)
・[HerokuでApplicationErrorが発生したときの対処法 - Qiita](https://qiita.com/Oakbow/items/1565922ddcdea0ce9ab5)

<br/>
しかし、私の場合、上記の方法を試しても解決しませんでした。
<br>
#解決策
```"go heroku H10"```のようにネットで色々検索していたところ、[こちらの記事 ](https://stackoverflow.com/questions/32463004/heroku-go-app-crashing)を発見しました

表示されているエラー文は同じで、回答の方を翻訳してみると、
>herokuでアプリをデプロイする場合、ポート番号を指定することはできません。
webサービスのポート番号を8000などと指定することはできず、herokuがランタイムにポート番号を決定します。

どうやら、localhostのポート番号を自分で指定していると、herokuからアクセスできないらしい。

<dr/>
<dr>

##herokuが決定するポート番号に対応できるよう変更
変更前のコード

``` :main.go
func main() {
	http.HandleFunc("/", helloHandler)
	http.HandleFunc("/callback", lineHandler)

	fmt.Println("http://localhost:5000 で起動中")

	//サーバ起動
	log.Fatal(http.ListenAndServe(":5000", nil))
}
```
<dr>
**http.ListenAndServe(":5000", nil)**の部分を、以下のように変更
<dr>
<dr>

```
log.Fatal(http.ListenAndServe(":"+os.Getenv("PORT"), nil))
```

<dr>
これで、herokuによって決定されたポート番号に対応できるようになりました。
<dr>
<dr>
***
<dr>
今回はH10という同じエラーコードでも言語ごとにエラーの原因が違い、解決に時間がかかりました💧

<dr>
Django Rest FrameworkでAmazon S3のファイルをダウンロードするAPIを作成する

# 前提条件
- AWS S3の読み取り権限を持ったユーザを用意すること
- [AWS コマンドラインインターフェイス](https://aws.amazon.com/jp/cli/)を使って、上記ユーザでログイン済みであること  
また、本記事で扱う言語・ライブラリのバージョンを以下に示します。

```
python-3.9.5
Django==3.2.4
djangorestframework==3.12.4
boto3==1.17.91
```

# ファイルの準備
AWSコンソールからS3に入って適当なファイルをバケットに配置します。
今回は`test-qiita`バケットを作成し、`test.txt`というテキストファイルをアップロードしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247330/fb1bdc25-b320-45f8-1457-2b7135b35bc5.png)
本記事ではDjango REST Frameworkを用いて、このtest.txtをダウンロードするAPIを作成することを目指します。


# APIの準備
先に最低限のAPIをエンドポイントを用意しておきましょう。
作成するAPIは`/api/file`というURLに`GET`リクエストをする仕様とします。

まずは`file_download_test`という名前でDjangoプロジェクトを作成し、
`api`という名前でdjangoアプリケーションを作成します。

```
$ django-admin startproject file_download_test
$ django-admin startapp api
```

次にapi/views.pyを編集します。

```py3:api/views.py
from django.http import HttpResponse
from rest_framework.views import APIView


class FileView(APIView):

    def get(self, request):
        response = HttpResponse('ok')
        return response
```

そしてurls.pyでURLとFileViewを対応させます。

```py3:file_download_test/urls.py
from django.contrib import admin
from django.urls import path

from api import views # 追加

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/file', views.FileView.as_view()), # 追加
]
```

以上です。
APIを試してみましょう。 

```
$ python .\manage.py runserver
```
コマンドラインから実行しサーバを立ち上げ、ブラウザから`localhost:8000/api/file`にアクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247330/a1009167-3027-cada-a187-2431b5b26df0.png)
このようにokが返ってくれば成功です。

# S3からファイル取得
いよいよ本題に入ります。先ほど作成した`/api/file`APIをS3のファイルを返すように修正します。
まずは、PythonでAWSを利用するのによく使われる[boto3](https://github.com/boto/boto3)というライブラリをインストールします。

```
$ pip install boto3
```

## boto3を使うにあたっての注意点
boto3を使ってAWSに接続するためには認証情報が必要です。[AWS コマンドラインインターフェイス](https://aws.amazon.com/jp/cli/)でログインすると、`~/.aws/credentials` が自動で作成され、そこからその中身は以下のように認証に必要な情報が書き込まれます。

```text:credentials
aws_access_key_id = ******************
aws_secret_access_key = ************************
```  
boto3はこのファイルの情報を使ってAWSと接続します。
※Dockerコンテナの場合等`~/.aws/credentials`が見えない場合は、環境変数に以下の名前で値を設定してください。

- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY

## API修正
次にviews.pyを以下のように修正します。

```py3:api/views.py
import boto3
from django.http import HttpResponse
from rest_framework.views import APIView


class FileView(APIView):

    def get(self, request):
        s3 = boto3.resource('s3')
        BUCKET_NAME = 'test-qiita'
        FILE_NAME = 'test.txt'
        object = s3.Object(BUCKET_NAME, FILE_NAME).get()
        response = HttpResponse(object['Body'].iter_chunks(), content_type=object['ContentType'])
        response['Content-Disposition'] = f'attachment; filename="{FILE_NAME}"'

        return response
```

再度ブラウザから`localhost:8000/api/file`にアクセスしましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247330/42868bea-390c-3aee-50b7-edf6f5ca3993.png)
無事にファイルがダウンロードできました！

今回作成したファイルは[こちら](https://github.com/saikoro2007/django_s3_file_download_test)で確認いただけます。
コマンドラインで Ruby を使って YAML <=> JSON の変換を行うワンライナー

JSON => YAML

```sh
$ ruby -rjson -ryaml -e 'print JSON.load(STDIN.read).to_yaml' < foo.json
```

YAML => JSON

```sh
$ ruby -rjson -ryaml -e 'print YAML.load(STDIN.read).to_json' < foo.yml
```

YAML =>　JSON (pretty)

```sh
$ ruby -rjson -ryaml -e 'print JSON.pretty_generate(YAML.load(STDIN.read))' < foo.yml
```
DrupalをDockerでお試しで起動するまで

Drupal をひとまず試したいのであれば PHP 製ウェブアプリなので XAMPP を用いるなどでもよいのですが、Docker が入っている場合は Docker でサクッと環境を作成することができます。

以下にて Drupal の公式イメージが配布されているのでとにかく起動させてみたいのであれば、公式の説明通りのコマンドを叩けばとりあえずブラウザで確認することができます。

https://hub.docker.com/_/drupal

> ```
> docker run --name some-drupal -p 8080:80 -d drupal
> ```

ただこれだと、コンテナを削除すると全てのデータが消えてしまうので `Dockerfile` のカスタマイズと `docker-compose` を用いた永続化の例を紹介します。

### Dockerfile でベースイメージのカスタマイズ

```dockerfile:./Dockerfile
FROM drupal:latest

# Drushインストール
RUN composer global require drush/drush \
  && ln -s /root/.composer/vendor/bin/drush /usr/local/bin/drush \
  && drush --version

CMD ["apache2-foreground"]
```

上記のは公式イメージから Drupal をコマンドラインで操作するためのツール Drush を composer を用いてインストールしています。

なお、composer コマンドはベースイメージでインストールしているので特にインストール作業も無しにコマンドを用いて別途パッケージを追加することができます。

最後に `CMD ["apache2-foreground"]` で Apache を起動しています。

### docker-compose.yml で永続化設定

Docker 公式の Drupal イメージには DB サーバーがインストールされていないので、組み込み DB の SQLite を用いて CMS のセットアップをしてしまうか、別途 DB サーバーを担うコンテナを建てる必要があります。

今回は docker-compose を利用して DB （今回は mariadb）サーバーを立ち上げて接続するようにしつつ、各種リソースを永続化するように設定します。

```yaml:./docker-compose.yml
version: '3.7'

services:
  mysql:
    image: mariadb
    command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
    volumes:
      - data:/var/lib/mysql
      - ./dump:/docker-entrypoint-initdb.d
    environment:
      MYSQL_ROOT_PASSWORD: "password" # 任意で変更してください
      MYSQL_DATABASE: "drupal" # 任意で変更してください
    ports:
      - "3306:3306"

  drupal:
    build: ./
    volumes:
      - ./web/themes:/var/www/html/themes
      - ./web/modules:/var/www/html/modules
      - ./web/sites:/var/www/html/sites
      - ./config:/opt/drupal/config
      - ./composer.json:/opt/drupal/composer.json
      - ./composer.lock:/opt/drupal/composer.lock
    ports:
      - "80:80"
    depends_on:
      - mysql

volumes:
  data: {}
```

いくつか特筆すべき箇所をピックアップします。

`services.mysql.command` はDBの文字コードをデフォルトのラテン系から、日本語などマルチバイト文字を利用する場合に必要な設定となります。

`services.drupal.depends_on` で drupal コンテナから mysql コンテナにアクセスできるようにしています。

また、Docker でコンテナを立ち上げる際にマウントはホストからコンテナ方向の単一のため、予めホスト側にコンテナの資材を用意しておく必要があります。

そのために、適当なコンテナを立ち上げて tar コマンドなりでホスト側に資材を持ってくる必要があります。

以下は公式イメージのページにかかれているコマンドをほぼそのまま引用していますが、`docker cp` コマンドでもホストに資材を持ってくることが可能です。

```shell
$ mkdir -p ./web/{themes/,modules/,sites/}
$ docker run --rm drupal tar -cC /var/www/html/themes . | tar -xC ./web/themes
$ docker run --rm drupal tar -cC /var/www/html/modules . | tar -xC ./web/modules
$ docker run --rm drupal tar -cC /var/www/html/sites . | tar -xC ./web/sites
$ docker run --rm drupal cat /opt/drupal/composer.json > ./composer.json
$ docker run --rm drupal cat /opt/drupal/composer.lock > ./composer.lock
```

あとは `docker-compose.yml` を起動すれば `http://localhost` で Drupal のインストール画面へ遷移します。

```shell
$ docker-compose up
```

次回は中規模以上のサイトでよくあるケースに Drupal がそもそも対応しているのか、そのあたりの検証、知見の共有をできればと思います。
Rails Consoleなど任意の場所で任意のViewを任意条件でRenderする

# TL;DR
```rb
class DebugController < ActionController::Base
  def render_foo(argv = nil)
    @foo = 'Foo'
    render_to_string template: 'foos/show'
  end
end


DebugController.new.render_foo
=> "<!DOCTYPE html>\n<html lang='ja'>\n<head>\n<meta charset='UTF-8'>\n<title>Foo</title>\n</meta>\n</head>\n<body>\n<h1>Foo</h1>\n</body>\n</html>\n"
```

## 2022-12-26最新版

```rb
ac = ApplicationController.new
ac.instance_variable_set(:@foo, 'Foo') # インスタンス変数をインジェクション
ac.render_to_string('foos/show', layout: false)
=> "<!DOCTYPE html>\n<html lang='ja'>\n<head>\n<meta charset='UTF-8'>\n<title>Foo</title>\n</meta>\n</head>\n<body>\n<h1>Foo</h1>\n</body>\n</html>\n"
```

詳しくは: [[続] Rails Consoleなど任意の場所、Inlineで任意のViewを任意条件でRenderする](https://qiita.com/jerrywdlee/items/59f711711ccdc428083f)

# 経緯
## 何をしたい
仕事上でとある特別のCSVをConsoleで出したいが、該当CSVはViewの中の `index.csv.csvbuilder` より作成されていて、Rails Consoleでの再現は極めて難しいでした。

## わかったこと
[いろいろ調査した結果](https://stackoverflow.com/a/12170332)、`Controller`を`new`でインスタンスを作成し、`Action`を呼び出すことが可能だとわかりました。
また、Renderingの結果を次の処理に渡したい時、`render_to_string`を使えば、文字列として返してくれます。

# やり方

まずは、`ActionController::Base`を継承して、ダミーのClassを作成します。
もちろん、Helperを利用したり、他のControllerのメソッドを使いたいときは、`ApplicationController`やその他コントローラーを継承できます。

```rb
class DebugController < ApplicationController

end
```

そして、レンダリングしたいViewを指定して、Actionを作成します。
ここのActionは引数を代入できる反面、普段使っている`params`という変数は存在しません。
また、Viewに表示したいインスタンス変数も、ここで定義します。
それに一般のコントローラーと同様に、`template`を`views/`配下のファイルを指定できます。

```rb
class DebugController < ApplicationController
  def render_foo(argv = '')
    @foo = argv
    render_to_string template: "foos/show"
  end
end
```
(下記の`foos/show`が下記のViewとして進みます)

```foos/show.html.slim
doctype html
html lang="ja"
  head
    meta charset="UTF-8"
    title = @foo
  body
    h1 = @foo
```

最後は、上記 `DebugController` をRails Consoleに流して、インスタンス化し、アクションを呼び出します。

```rb
DebugController.new.render_foo('Foo')

  Rendering foos/show.html.slim
  Rendered foos/show.html.slim (Duration: 8.1ms | Allocations: 6817)
=> "<!DOCTYPE html>\n<html lang='ja'>\n<head>\n<meta charset='UTF-8'>\n<title>Foo</title>\n</meta>\n</head>\n<body>\n<h1>Foo</h1>\n</body>\n</html>\n"
```


# 参考
- [Layouts and Rendering in Rails](https://guides.rubyonrails.org/layouts_and_rendering.html#using-render)
- [Calling an ApplicationController method from console in Rails](https://stackoverflow.com/a/12170332)
DNSroboCertを使ってDNS認証による簡単Let's Encrypt証明書自動更新

Let's Encryptでは、``http://<your-domain>/.well-known/acme-challenge``にファイルを置いてドメイン所有権を確認する方法がよく取られますが、DNS認証でもドメイン認証することが可能です。

[DNSroboCert](https://dnsrobocert.readthedocs.io/en/latest/introduction.html)では、[Lexicon](https://github.com/AnalogJ/lexicon) という有名DNSプロバイダーのAPIを操作可能なライブラリを使って設定ファイルとDockerで80番ポートを開けたりインターネットに一時ファイルを公開せずに簡単にLet's Encrypt証明書の自動更新環境が作れます。

https://dnsrobocert.readthedocs.io/en/latest/introduction.html

サポートしているDNSプロバイダーはこちら。
https://dnsrobocert.readthedocs.io/en/latest/providers_options.html#providers-options

# 使い方
以下にサンプルを用意しました。
https://github.com/naoa/ssl-with-dnsrobocert

非常にシンプルでDNSプロバイダーのトークンを取得し、configファイルにDNSプロバイダーの情報とドメインを記載し、Dockerで立ち上げるだけです。

以下のファイルの``<your-email>``, ``<your-dns-provider>``, ``<your-dns-provider-token>``, ``<your-domain>``を書き換えます。

```dnsrobocert/config.yml
draft: false

acme:
  email_account: <your-email>
  staging: false

profiles:
  - name: dns_profile
    provider: <your-dns-provider> # choose your dns provider https://dnsrobocert.readthedocs.io/en/latest/providers_options.html#providers-options
    provider_options:
      auth_token: <your-dns-provider-token>

certificates:
  - domains:
      - <your-domain>
    profile: dns_profile
```

* docker-composeで起動します。  
  ちなみに、DNS認証時には、自動的にDNSのゾーンにTXTレコードが追加されていることが確認できます。
 
```
docker-compose up -d
```


```docker-comopse.yml
version: '3'
services:
  dnsrobocert:
    image: adferrand/dnsrobocert
    container_name: dnsrobocert
    volumes:
      - /etc/letsencrypt:/etc/letsencrypt
      - ./dnsrobocert:/etc/dnsrobocert
    restart: always
```

これにより、``/etc/letsencrypt/live``に証明書ができるのでそれをnginx等に利用することができます。

configファイルとdocker-composeで非常にシンプルに実現できるので、わざわざマルチホストにしたいという意図がなければ、nginx-proxyを使った方法よりシンプルに他のWebアプリ用のDockerに連携できそうです。
【ASP.NET core 　RazorPageサンプル作成】EFの移行機能を使いDB作成しようとしたらエラー

[サンプル作成の参照リンク](https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/razor-pages/?view=aspnetcore-5.0)

####状況：####
・Model作成し、スキャフォールディングも実行済み。
・startup.csにもsqlite、SQLサーバーの設定を追記。
・dotnet ef もインストール済み

####作業内容：####
EF（Entity Framework Core）の移行機能を使って、データベースを構築する

```
dotnet ef migrations add InitialCreate
```


上記コマンド実行するといくつかエラーが発生

####エラー①　```Your startup project　プロジェクト名　doesn't〜〜〜```####

```
Your startup project 'myWebApp' doesn't reference Microsoft.EntityFrameworkCore.Design. This package is required for the Entity Framework Core Tools to work. Ensure your startup project is correct, install the package, and try again.
```
パッケージ``Microsoft.EntityFrameworkCore.Design``がないとのこと。

visual studioの「Manage NuGet Packages」から
```Microsoft.EntityFrameworkCore.Tools```をインストール
※```Microsoft.EntityFrameworkCore.Design```も含まれている

加えて、ディレクトリが間違っていたためプロジェクトである「RazorPagesMovie」へ移動。

####エラー②　```No project was found. Change 〜〜〜〜```####

```
No project was found. Change the current working directory or use the --project option.
```

プロジェクトが見当たらないよ、とのこと。
ただ、現在のディレクトリはプロジェクトになっている
```hoge@hogenoMacBook-Air RazorPagesMovie %```

もしかしてと思い、lsコマンド
```RazorPagesMovie     RazorPagesMovie.sln```
やっぱり、現在のディレクトリが**プロジェクト**ではなく**ソリューション**になっていた。
※ASP.NET coreのフォルダ構成は
ソリューション＞プロジェクト＞関連フォルダ・ファイル
となっている。

####エラー③　```Build failed. Use dotnet 〜〜〜 ```####

```
Build failed. Use dotnet build to see the errors.
```

色々調べた所、リビルドすると解決できるらしいとの記事があり、試してみる。

```
Build started...
Build succeeded.
Done. To undo this action, use 'ef migrations remove'
```

おおー！ビルド成功！

ここで勘違いが一つありました、
**ビルド**と**プロジェクト起動**を同じことだと思っておりました。。
恥ずかしい。

####エラー解決の参照リンク####
[エラー①](https://qiita.com/hiesiea/items/947de641945a5bf95a34)
[エラー②](https://newbedev.com/ef-core-error-no-project-was-found-change-the-current-working-directory-or-use-the-project-option)
[エラー③](https://forums.asp.net/t/2144417.aspx?Can+t+migrate+Entity+Framework)
iOSに必要な技術一覧

iOSアプリをネイティブで開発するために必要な技術、ノウハウをまとめました

これを読む人のターゲットは
iOSエンジニアが実際のプロジェクトに従事している人が「iOSの技術がどのくらいあるだろう」と思ったときに見るのを想定しています。
またはこれから他のプラットフォームエンジニアからiOSエンジニアになろうとしている人がざっと見るものです。

# 重要度

（必須）がついているものはそれがないとiOS開発ができないレベルのものです
(ほぼ必須)は多くのプロジェクトで利用されているが、たまに使用していないプロジェクトがあるものです
（重要）はできなくともiOS開発はできるが、多くのプロジェクトで採用されているもの

## 言語

Swift（必須）
Objective-C

## Apple FrameWork

UIKit（必須）
Foundation（必須）
Autolayout（必須）

CoreDate

## プログラミング パラダイム

オブジェクト指向（必須）
プロトコル指向
オブジェクト指向分析設計
KVO
リアクティブプログラミング

リファクタリング

### スレッドプログラミング

Grand Central Dispatch (GCD)
NSTimer

## デバック手法

LLDB
View Debugger

XcodeのInstruments、Leakなど

## Database

Realm
Coredata

## アーキテクチャ

MVC（ほぼ必須)）
MVVM
MVP
VIPER
クリーンアーキテクチャ

## デザインパターン

WebAPI (ほぼ必須)
GoFのデザインパターン（一部必須、一部重要）
RxSwift

## Test

### appleが提供するTest

UnitTest
UITest
Analyze

## CI/CD

flastlane
Bitrise

## 3rd Party Libraries

### Cocoapods（重要）

Google analytics
Firebase
Alamofire
AFNetworking

### Carthage


## Apple関連

App storeへの登録
Apple Developer Program
Apple Tecnical Servive
Apple Bug Report
【Android】GeoCorderで日本の住所を取得・整形する

# はじめに
位置情報系のアプリなら住所表示機能も割とありますよね。
Androidアプリで緯度経度から住所を取得するのにGeoCorderを利用しますが、日本の住所はそのまま使うと綺麗じゃないなと思ったので整形処理を書いてみました。

# コード
```kotlin
/** 緯度経度から住所を取得する */
suspend fun getAddress(context: Context, latLng: LatLng): String? = withContext(
    Dispatchers.IO) {
    try {
        val geoResult = Geocoder(context, Locale.getDefault()).getFromLocation(
            latLng.latitude,
            latLng.longitude,
            1
        )
        geoResult.firstOrNull()?.let {
            var address = it.getAddressLine(0)

            // 日本の場合、住所を整形する
            if (Locale.getDefault() == Locale.JAPAN || Locale.getDefault() == Locale.JAPANESE) {
                // 国名を除去
                address = address.replace(it.countryName, "")
                // 郵便番号を除去
                address = address.replace("〒?\\d{3}-\\d{4}".toRegex(), "")
                // 区切り文字の連続を除去
                address = address.replace("、{2,}".toRegex(), "、")
                address = address.replace(",{2,}".toRegex(), ",")
                // 先頭の区切り文字を除去
                address = address.replace("^[、,]+".toRegex(), "")
                // 最後の区切り文字を除去
                address = address.replace("[、,]+\$".toRegex(), "")
                // スペースを除去
                address = address.replace(" ", "")
            }

            return@withContext address
        }
    } catch (e: Exception) {}
    return@withContext null
}
```
住所取得処理はネットワークにアクセスし時間がかかる処理のため、suspend関数として実装しています。

# 住所整形について
まず、Geocorder.getFromLocationでどんな値が返ってくるか確認してみます。
試しに東京の適当な緯度経度を入れてみると、次のような結果が返ってきました。

```
[
	Address[
		addressLines=[0:"日本、〒150-0002 東京都渋谷区渋谷１丁目２３−２１ キャスト1510"],
		feature=２１,
		admin=東京都,
		sub-admin=null,
		locality=渋谷区,
		thoroughfare=１丁目,
		postalCode=150-0002,
		countryCode=JP,
		countryName=日本,
		hasLatitude=true,
		latitude=35.662597,
		hasLongitude=true,
		longitude=139.70284909999998,
		phone=null,
		url=null,
		extras=null
	]
]
```

addressLines[0]の"日本、〒150-0002 東京都渋谷区渋谷１丁目２３−２１ キャスト1510"がほぼそのまま使えそうですね。
上で記載したコードはこれをベースに整形しています。メソッドの返り値は次のようになります。

```
東京都渋谷区渋谷１丁目２３−２１キャスト1510
```

# おわりに
住所は多種多様なので、これで完璧！というのは難しそうですね。
こっちの方がいいんじゃない？等、ありましたら教えていただけると嬉しいです。

最後に宣伝になりますが、このコードを組み込んだAndroidアプリ「ココメモ」をリリース中です！
現在地をメモ帳感覚でラクラク記録できます。お出かけの記録などにいかがでしょうか？
<a href='https://play.google.com/store/apps/details?id=com.allfort.locationmemo&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1'><img width=200 alt='Google Play で手に入れよう' src='https://play.google.com/intl/en_us/badges/static/images/badges/ja_badge_web_generic.png'/></a>
GAEでドメインのアクセス規制を設定


GAEにアプリ公開後に社内限定にしたい場合に設定すると社外からのアカウントからアクセス不可になります。

セキュリティのIdenttity-Aware Proxyを選択

![2021-07-08_01h03_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/89d47bce-4022-c4dc-8e6d-5b6471389795.png)


App Engineにチェックをつける

![2021-07-08_01h04_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/967a6be4-5ffc-8fa2-29ed-aa63bd72f156.png)

メンバー追加

![2021-07-08_01h05_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/300e4d83-3041-3b26-cf1a-ab0399ab3638.png)

`IAP-secured Web App User`の権限をドメインに対して付与します。


![2021-07-08_01h06_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/c5c8a9b0-882c-1232-971e-e488d9a95a06.png)

設定ドメイン外のアカウントでアクセスしようとするとエラーが表示されます。

![2021-07-08_01h07_25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428239/b3a460af-bd82-ea5c-5761-770de45f2438.png)