OmniAICreator/Qiita-1.07M huggingface dataset:
GTMでUA計測する場合にはトラッカー名の指定が必須

:::note warn
この記事はGoogle Analytics 4ではなく、Universal Analyticsを対象としています。
:::

## 課題

GTMでanalytics.jsを配信した場合にフロント側で `ga('send', 'event', 'Video', 'play', 'cats.mp4');`という形で実行しても、イベントが送信されません。

## GTMでトラッカー名を指定

いろいろ試した結果、GTM側でトラッカー名を指定することで飛ぶようになりました。

![Google-タグ-マネージャー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/b2b69140-cbaf-1813-f39c-7d68dfc1e025.png)

## いつからトラッカー名が必須になったのか

あるサイトのイベントが2020年2月から欠落しているので、その辺から仕様変更されているかもしれません。同様の事象は色んな場所で発生しているのではないでしょうか。

![アナリティクス.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147689/3611d4b7-8488-71db-48b7-76bc540cf114.png)

## その他
GTMにてUAとGA4でトラッキングしている場合には `ga('send', 'event', 'Video', 'play', 'cats.mp4');`を叩くとGA4側にはイベントが飛んでいます。

・・・そろそろgtag.jsを使う前提で進めた方がいいのかな？
Git ローカルリポジトリ 特定のコミットまでリポジトリの状態を戻す

# 目的

- ローカルリポジトリの状態を特定のコミットまで戻す方法をまとめる。

# 方法

- 下記コマンドを実行してローカルリポジトリの状態を特定のコミットまで戻す。

    ```terminal
    $ git reset --hard コミットID
    ```
【初心者でもわかる】CSSでカッコいいオシャレな検索窓（検索ボックス）の作り方

# どうも7noteです。マウスホバーしたらシュッと出てくるオシャレな検索窓の作り方

このようなシャレた検索窓を作ります。ヘッダーなどにあるといい感じになるかも？

![sample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/57349dd0-8e0b-9919-eb21-32ee2b0b44a1.gif)


## オシャレ検索窓の作り方

※画像サイズは16px×16pxです。

```index.html
<div class="searchbox">
  <a href="#"><img src="icon.png" alt="虫眼鏡"></a>
  <input type="text" name="search" placeholder="検索ワード入力">
</div>

```

```style.css
.searchbox {
  width: 200px;        /* 入力フォームの横幅 */
  position: relative;  /* 基準値とする */
  text-align: right;   /* 画像を右寄せにする */
}

.searchbox:hover {
  cursor: pointer;    /* hover時にカーソルを指の形にする */
}


.searchbox img {
  width: 16px;        /* 画像サイズと同じ横幅を指定 */
  border-radius: 50%; /* 正円にする */
  padding: 4px;       /* 余白4pxをとる */
  transition: .3s;    /* アニメーションの時間指定 */
}

.searchbox:hover img {
  background: rgba(200, 200, 200, .5);  /* 背景色にうすいグレーを指定 */
  position: relative;                   /* z-indexを指定するため。 */
  z-index: 10;                          /* ほかよりも前面に表示 */
}


.searchbox input {
  width: 24px;          /* 横幅を24pxに指定 */
  height: 24px;         /* 高さを24pxに指定 */
  border: 1px solid #666; /* グレーの線を表示 */
  border-radius: 12px;  /* 高さの半分の角丸を指定 */
  padding: 2px 5px;     /* 適度な余白を指定 */
  box-sizing: border-box; /* 計算を簡単にするため */
  transition: .5s;      /* アニメーションの時間を指定 */
  opacity: 0;           /* 透明にする */
  position: absolute;   /* 相対位置に指定 */
  top: 0;               /* 上から0pxの位置に指定 */
  right: 0;             /* 右から0pxの位置に指定 */
  outline: none;        /* カーソルがあたった時のアウトラインを消す */
}

.searchbox:hover input {
  width: 100%;          /* ホバー時は幅いっぱいまで大きくさせる */
  opacity: 1;           /* ホバー時は透明度を解除する */
}
```


## 解説

親要素(.searchbox)に検索ボックスのエリアを作ります。
中のaタグ（画像）を右寄せで配置。そして入力ボックスの**inputは`opacity`を使って透明度を変えて見えなくしておきます。**

親要素(.searchbox)がホバーした時に、**画像は背景色を入れ、inputは透明を解除しつつ横幅を長くして右からみょーんっとでてくるような動きを入れます。**

## まとめ

動きのあるサイトが多くなってきたので、ユーザーがよくカーソルを置くような箇所には邪魔にならない程度のアニメーションをいれるなどの工夫が施されているのとよく見かけます。
いろいろなサイトを見て、**「この動き、どうやったら実装できるのかな？」**と考えながらやるのも勉強になって、スキルアップに繋がると思います。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
RailsアプリにELBを導入

# 概略
RailsアプリをAWSでデプロイ後、ELBを導入し負荷分散を試みた。
AMIから２つ目のEC2インスタンスを作成し、ロードバランサーを作成。
しかし、２つ目のインスタンスのみ、ヘルスチェックでunhealthy。ターミナルからインスタンスへのログインは可能。



## ログの確認
エラーとなっているEC2インスタンスでログを確認。
`cat`コマンドだと膨大な量になるので、自分は`tail -n (行数)`　などで確認した。

```/var/www/アプリ名/current/log/production.log
ActionView::Template::Error (Webpacker can't find application in /var/www/kangolog/releases/20210112152601/public/packs/manifest.json. Possible causes:
1. You want to set webpacker.yml value of compile to true for your environment
   unless you are using the `webpack -w` or the webpack-dev-server.
```

webpackのエラーかな？

##bundle exec cap productionした際のログを確認
コンパイルのログがない！

`RAILS_ENV=production bundle exec rails webpacker:compile`
して見たが、
`Everything's up-to-date. Nothing to do`
となり、もちろん挙動も変わらず、、、むむむ。

# 解決方法

サーバーの指定の問題でした。

```config/deploy.production.rb
server 'Elastic IP', user: 'ec2-user', roles: %w{app db web}
server 'IP', user: 'ec2-user', roles: %w{app db web2}
```

なぜかwebとweb2に分けてしまっており、これが原因で2つ目のインスタンスのみデプロイされなかったようです。
以下に修正。

```config/deploy/production.rb
server 'Elastic IP', user: 'ec2-user', roles: %w{app db web}
server 'IP', user: 'ec2-user', roles: %w{app db web}
```

## 学び
ローカル環境ではエラー画面で内容を教えてくれるので、ログを確認することが疎かになってました。
本番環境ではあの真っ赤なエラー画面がデフォルトでは出ないので、（当たり前のことですが）ログを確認するようになりました。

インフラ面の導入は、アプリ自体に変化は見えませんが、自分の中ではアプリが成長した実感がありなかなか楽しいです。
今まで触れてこなかったネットワークやセキュリティなど、web開発の土台となる部分の勉強になり、とても有意義でした！
自作Webアプリ作成に向けて要件定義からワイヤーフレームまでを作成する

#Webアプリ製作をする前に
Railsの練習として、ツイッタークローン的なものを作成することにしました。
Webアプリの製作する前に、「一体どんなアプリをつくるのか」を整理する必要があります。
自分なりに調べた結果、以下のものを作成することにしました。

#要件定義
アプリの「目的」、「目標」、「手段」を明確にします。
以下に簡単にまとめてみました。

```
【ツイッタークローンアプリ】

[目的]
様々な人のつぶやきを共有する。

[目的達成のための製作物]
すべての利用者が見ることの出来る投稿掲示板

[製作物の説明]
・一般利用者
    投稿は文字データのみ
    会員登録なしで投稿ができる(Create)
    すべての利用者の投稿を一覧で見ることができる(Read)
    すべての利用者の投稿を更新できる(Update)
    すべての利用者の投稿を削除できる(Delate)

[利用者]
・一般利用者

[利用者が得られる便益]
・他の利用者の考えを知ることができる。

[開発環境]
・個人開発

[製作期限]
・未定

```

#テーブル定義
使用するDBの定義を行います。
データの型や、コラム名、空白を許容するのか、といったことを表にまとめます。
![90437237-6AEA-4C4B-8069-FF27FACA632E_1_105_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999125/96d47fad-337e-8960-87f3-508cb9ae3be1.jpeg)

#ER図
DBどうしの関係を明らかにする図です。
今回は使用するDBは一つしかないので（本当？）、意味はないですが図だけ作ってみました。
使用したツールはCacooです。

#画面遷移図
アプリの画面間の関係をあらわした図です。
![3CBF312D-CA4C-47D0-8CDA-F063026F9FF1_1_105_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999125/818ab366-64ff-f4d2-ddc2-a49be794d967.jpeg)

#ワイヤーフレーム
一画面のレイアウトです。以下は投稿一覧のページのものです。
![0D2B9AB1-BB85-4088-979A-DADE4DBFE3CE_1_105_c.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/999125/a4c194f7-7125-7212-2cea-cad14292c3a6.jpeg)

#計画通り？
おおざっぱですが、開発の計画段階としてするべきことをやってみました。
大まかな方針（海で泳ぐのか、山に登るのかを選択する程度）は決まったかなと思います。
おそらく、いや絶対に計画通りにいかないと思うので、開発をしながら細かいところは修正していきたいです。
Pythonビルトインの分数を扱うfractionsパッケージについて軽く調べてみた。

今更ながら分数を扱うPythonビルトインのfractionsパッケージという存在を知ったので、どんな挙動をするものなのかを軽く調べておきます。

# 記事内で使う環境

Python 3.8.6を使います。残りはビルトインのfractionsパッケージだけ使っていきます。

# 基本の使い方

まずは扱うためにfractionsパッケージのimportが必要になります。特にFractionクラスが利用のメインとなるため、そちらをimportします。

```py
from fractions import Fraction
```

Fraction（分数）クラスはnumerator（分子）という第一引数とdenominator（分母）という第二引数を受け付けます。

```py
f = Fraction(numerator=3, denominator=4)
```

インタラクティブシェルやJupyter上でFractionクラスのインスタンスを表示してみると、分子と分母の値を含んだ形でrepr的に表示されます。

```py
>>> f

Fraction(3, 4)
```

print関数を通してみると、`3/4`といったような形で表示されます。

```py
>>> print(f)

3/4
```

# intやfloatとの比較ができる

Fractionインスタンスはそのままintやfloatと比較ができるようです。

```py:intとの比較
>>> f = Fraction(numerator=4, denominator=4)
>>> f == 1

True
```

```py:floatとの比較
>>> f = Fraction(numerator=3, denominator=4)
>>> f == 3 / 4

True
```

# intの値であれば四則演算してもFractionが返る

Fractionのインスタンスに対してintなどで四則演算した場合はそのままFractionのインスタンスが返ります。

```py
>>> Fraction(3, 4) + 1

Fraction(7, 4)
```

```py
>>> Fraction(5, 4) - 1

Fraction(1, 4)
```

```py
>>> Fraction(3, 4) * 2

Fraction(3, 2)
```

# Fraction同士の四則演算もFractionが返る

Fraction同士を加算したりすると結果もFractionのインスタンスになります。

```py
>>> Fraction(1, 4) + Fraction(1, 4)

Fraction(1, 2)
```

Fraction + Fraction + intみたいな計算でもFractionがそのまま返ります。

```py
>>> Fraction(1, 4) + Fraction(1, 4) + 1

Fraction(3, 2)
```

# floatの値で四則演算するとfloatが返る

Fractionとfloatの値で四則演算すると結果はfloatになります。

```py
>>> Fraction(3, 4) + 1.5

2.25
```

# 分母（denominator）の引数は省略できる

第一引数の分子（numerator）の引数にfloatを指定することで、分母のdenominator引数を省略してもFractionインスタンスを作ることができます。

```py
>>> Fraction(numerator=0.25)

Fraction(1, 4)
```

```py
>>> Fraction(numerator=0.26)

Fraction(1170935903116329, 4503599627370496)
```

```py
>>> 1170935903116329 / 4503599627370496

0.26
```

# numerator引数には文字列も指定できる

`1/4`といったような、半角のスラッシュを使った文字列もnumerator引数に指定することができます。

```py
>>> Fraction(numerator='1/4')

Fraction(1, 4)
```

# 自動で約分される

Fractionのインスタンスを作ったり計算などをした際に約分できる場合には約分が自動で実行されます。

```py
>>> Fraction(2, 4)

Fraction(1, 2)
```

```py
>>> Fraction(1, 6) + Fraction(1, 6)

Fraction(1, 3)
```

# limit_denominator メソッドで無理数の近似の値を取得することができる

無理数を指定した場合などに、最大の分母の値（max_denominator引数）を指定することで、その値以下になる範囲で近似値を取得することができます。

```py
>>> Fraction(3.14159265359)

Fraction(3537118876014453, 1125899906842624)
```

```py:分母が10以下に制限される設定
>>> Fraction(3.14159265359).limit_denominator(max_denominator=10)
Fraction(22, 7)

>>> 22 / 7
3.142857142857143
```

```py:分母が150以下に制限される設定
>>> Fraction(3.14159265359).limit_denominator(max_denominator=150)
Fraction(3.14159265359).limit_denominator(max_denominator=150)

>>> 355 / 113
3.1415929203539825
```

# 参考文献・参考サイト

- [Doing Math with Python: Use Programming to Explore Algebra, Statistics, Calculus, and More!](https://www.amazon.com/Doing-Math-Python-Programming-Statistics/dp/1593276400/)
- [fractions --- 有理数(公式ドキュメント)](https://docs.python.org/ja/3/library/fractions.html)
- [Python, fractionsで分数（有理数）の計算](https://note.nkmk.me/python-fractions-usage/)
IEで開いたはずなのにEdgeで表示されるのを回避する設定

## IEで開いたはずなのにEdgeで表示されるのを回避

Edgeの設定を開き、`internet`で検索。
以下設定を確認。

> Internet Explorer に Microsoft Edge でサイトを開かせる

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/bb3a919c-945d-767c-2156-b2382600e304.png)

| 設定 | 動作 |
|:--|:--|
| なし | Edgeで開かない |
| 互換性のないサイトのみ（推奨）| dllに登録されているURLの場合、Edgeで開く |
| 常に表示 | 常にEdgeを利用する |


## IEからEdgeを起動するaタグの書き方

```html
<a href="microsoft-edge:https://qiita.com/">EdgeでQiitaを開く</a>
```

## レジストリを調べてみたが未定義だった

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25728/b8449ccd-c3fb-b7a0-eb31-4be43048fe86.png)

以前、[windows10のIE11からローカルのexeを実行 (URIスキーマ,ActiveX) - Qiita](https://qiita.com/tukiyo3/items/40bff09692bfd0792a0f)を調べた。

`HKEY_CLASSES_ROOT\note\shell\Open\command`
が命令になるので、
`HKEY_CLASSES_ROOT\microsoft-edge\shell\Open\command` を上書きすればコントロールできるかも。

## 2021年8月17日に Microsoft 365 apps の IEサポートを終了予定

* https://techcommunity.microsoft.com/t5/microsoft-365-blog/microsoft-365-apps-say-farewell-to-internet-explorer-11-and/ba-p/1591666
* IEは[製品のライフサイクル ポリシー](https://docs.microsoft.com/en-us/lifecycle/faq/internet-explorer-microsoft-edge)に従う。


## IE側での対処

* [Internet Explorer から、Microsoft Edge にリダイレクトされる: パソコンのツボ　～ Office のTIP](https://pcclick.seesaa.net/article/477069852.html)
    * Autoruns for Windows を使う例。
Flask-Cachingを使ってPython + Flask でページキャッシュ

# Flask-Cachingを使ってPython + Flask でページキャッシュ

## パッケージインストール
[Flask-Caching](https://flask-caching.readthedocs.io/en/latest/)パッケージを使う

```
$ pip install Flask-Caching
```

## Blueprint で使う方法

ディレクトリ構成
Blueprintのディレクトリ構成 の説明は[こちら](https://qiita.com/morita-toyscreation/items/8471a2ccc481a840c372)

```HTML
weekend-hackathon/  
|-- app  
|   |-- views  
|   |    `-- sample.py  
|   |-- cache.py
|   `-- __init__.py  
|-- app.py  
|-- Dockerfile  
`-- requirements.txt 
```
*cache.py*

`simple` を使うとページキャッシュ、他にもmemcached、redis などがある

```Python
from flask_caching import Cache

cache = Cache(config={"CACHE_TYPE": "simple"})
```

*\_\_init\_\_.py*

`cache.init_app(app)` をすることでappにcache設定を適応

```Python
from flask import Flask

from app.cache import cache
from app.views.about import about
from app.views.main import main


def get_app() -> Flask:
    app = Flask(__name__)
    cache.init_app(app)
    _register_blueprint(app)
    return app


def _register_blueprint(app: Flask) -> None:
    app.register_blueprint(about)
    app.register_blueprint(main)
```

*sample.py*

`@cache.cached(timeout=50)` デコレーターを付けることで対象ページがページキャッシュになる

```Python
from flask import Blueprint

from app.cache import cache

sample = Blueprint("sample", __name__)


@sample.route("/")
@cache.cached(timeout=50)
def index():
    print("sample.index")
    return "sample.index"
```
(2021年)Ruby on Rails　管理者（admin）ログイン作成

###前提条件
* deviseでcosutomerログインできること

```:ターミナル
$ rails g devise Admin
$ rails db:migrate
```
adminでログインするユーザー作成する。

```ruby:db/seeds.rb
Admin.create!(
   email: 'admin@admin',
   password: 'testtest'
)
```

```:ターミナル
$ rails db:seed
```

adminのユーザーデータが入っているか確認する。

```:ターミナル
$ rails c
$ irb(main):001:0> Admin.all
＄ irb(main):002:0> exit
```
次はviewとcontrollerの作成します。

```:ターミナル
$ rails g devise:views admins
$ rails g devise:controllers admins
```

ルーティングを編集をします。

```ruby:config/routes.rb
devise_for :admins
↓
devise_for :admins, controllers: {
  sessions: 'admins/sessions'
}
```

ログイン後のヘッダー画面を追加します。

```:application.html.erb
<% if customer_signed_in? %>
 <li>
  <%= link_to "ログアウト", destroy_customer_session_path, method: :delete %>
 </li>
<% elsif admin_signed_in? %>
 <li>
  <%= link_to "ログアウト", destroy_admin_session_path, method: :delete %>
 </li>
<% else %>
 <li>
  <%= link_to "新規登録", new_customer_registration_path %>
 </li>
 <li>
  <%= link_to "ログイン", new_customer_session_path %>
 </li>
<% end %>

```

管理者のログイン後ページ遷移とログアウト先を作成します。

```ruby:controllers/admins/sessions_contoller.rb
protected
  def after_sign_in_path_for(resource)
    admin_items_path
  end

  def after_sign_out_path_for(resource)
    new_admin_session_path
  end
```
【007_必勝法】コマ大数学科

# 【007_ヨセフスの問題】コマ大数学科
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1017176/5308a89a-f6d0-e78f-25db-09b6b762d232.png)

```latex
\begin{tikzpicture}
  \foreach \x in {0,1,2}
{
  \filldraw[fill=cyan!50!white] (\x,0) circle (0.3) node {A};
}
\end{tikzpicture}
\\
\begin{tikzpicture}
  \foreach \x in {0,1,...,4}
{
  \filldraw[fill=red!50!white] (\x,0) circle (0.3) node {B};
}
\end{tikzpicture}
\\
\begin{tikzpicture}
  \foreach \x in {0,1,...,6}
{
  \filldraw[fill=green!50!white] (\x,0) circle (0.3) node {C};
}
\end{tikzpicture}

```
Docker と開発環境構築の忘備禄

初学者だが、今後もノートパソコンなど環境構築することになるので、メモをする。
Vagrant 2.2.14
Ubuntu 14.04.6 LTS
Docker version 1.6.2

勉強していたら講師が使用しているコマンド実行してエラー。
動画通りにいかない。調べたら、私の環境が古い。
Dockerのコマンドが新しく変わっている。
バージョンＵＰにはVagrant 上のUbuntu 14.04.6 LTSからUbuntu 16.04.7 LTSにアップグレードする必要がある。
OSアップデート

[Ubuntu 14.04LTSから16.04.6 LTSにアップデートしてみた](http://naked123.hatenablog.com/entry/2019/04/14/221729 )
を参考にアップグレード
Dockerのバージョンを別に上げると思っていたら一緒にアップグレードできた。
最新は
Dcoker version  18.09.7

これで、新しいDockerコマンドが実行できるようになった。

Vagrant上でVSCodeを使いたいので、VS codeのインストールと設定が必要。

[「Vagrant上のファイルをVSCodeで編集する」　For Windows](https://qiita.com/johnslith/items/be349aca9ad96489008b#vagrant%E6%8E%A5%E7%B6%9A%E7%94%A8%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E4%BD%9C%E6%88%90)を参考にインストール設定をする。
CentOS8君、日次の再起動前にゴリラアップデートをしてくれたまえ（dnfコマンド）

#再起動はあくまで再起動だけ
[CentOS8を毎日定時に再起動させたいんだよなあ](https://qiita.com/waokitsune/items/d86bcec70cf06254c4c8) の記事でCentOS8君を毎日再起動させる環境を作りました。

でも一つ気づいたことがありました。
**あ、この子、再起動しかしてないわ…**
そりゃそうだよね。。再起動でパッケージまで自動更新されたら面倒な場合もあるもんね。。
（依存関係とか宗教上の理由とかで **あえてパッケージの更新をさせていない** のが崩れちゃう）

ということでパッケージ更新のスクリプトを日次の再起動に組み込むことにしました。

#まずはどんな更新が来ているか確認

下記ね。

```sh:
dnf check-update
```
こんな感じね。何か来てますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/4ed6b863-63bc-2a01-cf77-ff165acf4e79.png)

ということで、 ```dnf``` コマンドでパッケージの更新まわりのあれやこれやを操作できます。

#ゴリラアップデート

ゴリラアップデートとは…
**何でもいいから来てるの全部アップデートしろや！後のことは何とかしてやるぜ！**
という強者のみに許された力強い更新方法です。

```sh:ゴリラアップデートコマンド
dnf upgrade -y --allowerasing
```

* 普通は ```upgrade``` の後にパッケージ名を指定するのですが、それを書かないことで **全てのパッケージ** を対象にできます。
* ```-y``` のオプションを付けることで『実行していいですか？』の確認のステップをすっ飛ばします。
* ```--allowerasing``` のオプションを付けることで『依存関係解決の為にインストール済パッケージの削除も辞さない覚悟』をCentOS8君に伝えています。（これが無いと依存関係解決の必要が出た時に『これどうします？』的なエラーになり、アップデートが走りません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/bf03da53-35e9-b547-ccaf-0a27da8801a2.png)

#オランウータンアップデート

オランウータンアップデートとは…
**セキュリティとか重要な更新だけはひとまず自動更新！それ以外は『ちょ、まてよ！』で更新しない**
という賢者的な更新方法です。

```sh:オランウータンアップデートコマンド
dnf upgrade-minimal -y --security
```

* ```upgrade-minimal``` を付けることで **重要な更新のみ** に限定しています。
* ```--security``` を付けることでセキュリティ更新が必要なパッケージのみに絞り込みしています。
* ```--allowerasing``` を付けていないので、依存関係解決の必要が出たらアップデートは走りません。

#蛇足

お家サーバーとか開発サーバーなら、下記のような使い方がバランスが取れていいかなと思います。

* セキュリティや重要なものは自動で更新。
* 上記以外は更新内容をテキストに書き出す or メール等で通知して、更新するかどうかは個別に検討。



#参考サイトさん

https://qiita.com/yasushi-jp/items/0dc7f413632927f92286
https://www.atmarkit.co.jp/ait/articles/2001/09/news018.html
https://www.atmarkit.co.jp/ait/articles/2002/06/news010.html
https://blog.luispc.com/entry/2019/12/05/214513

#バージョン
CentOS Linux release 8.3.2011
リモート時代のプレゼンサービスSlide Actをリリースしました


エンジニアの皆様、いかがお過ごしでしょうか。
エンジニアであれば3度の飯よりプレゼンが好き！なんて変態も少なくないと思います。
しかし、コロナ禍でリモートのプレゼンばかり・・・いまいち盛り上がりませんよね。

例えば、

- 画面越しに話を振ってシーンとなってしまった。
- 軽妙なジョークを飛ばしても返ってくるのはPCのファンの音だけ。

こんな悲惨な目にあった人もいるのではないでしょうか。（私です）
そこで、あの楽しかったプレゼンを取り戻すべくWebサービスを作ってみました。

## Slide Act
https://slide-act.web.app/

Slide Actと名付けました。
Activation（活性化）とかAct（演劇）とかまぁそのへん掛けた感じです。
それではSlide Actのイカした機能を紹介します。

### リアルタイムにスライドを参加者と共有
発表者はスライドをサイトにアップすることで、パワーポイントで発表するのと同じように、フルスクリーンでスライドを操作できます。
以下は発表者の画面です。
![feature01presenter.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130099/5bb92877-5dad-98d5-4f0e-359cb2592d24.jpeg)

発表者が画面に表示されるURLを共有すると、参加者は自分のPCでそのスライドを閲覧できます。
発表者がスライドを動かすと、参加者の画面も連動して動きます。
以下は参加者の画面です。
![feature01participant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130099/99eb266f-f851-e431-9a12-c893c37d1564.png)

### メッセージング機能
参加者がメッセージを送信すると、発表者を含む、参加者全員の画面に共有されます。
以下は参加者の画面です。
![feature02participant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130099/00bf05de-7867-aea0-f897-79c5bf66a4d4.png)

以下のように発表者の画面にも共有されます。
![feature02presenter.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130099/255bc519-0f76-940a-17d0-cdd5ce76704e.jpeg)

### スマホから参加可能
リモートでなく、対面でプレゼンする場合は参加者にPCが無い、なんてことも考えられます。
なので、参加者はスマホからも参加できるようにしました。
![feature03participant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130099/46e7347e-70da-185d-73db-44d079b68bb7.png)

機能としてはそれだけです。
アイデア次第で色々使い道があると思っています。
私が使ったときはこんな感じでした。

- 最初に拍手をタイピングしてもらう
- 問いかけに回答してもらう
- クイズに答えてもらう
- 笑い声をタイピングしてもらう
- 発表中に思ったこと呟いてもらう
- ヤジ
- 荒らし

いい使い方思いついたら教えてください。

## がんばったこと
とにかくストレスフリーで使えることを意識しました。
アカウント登録なし、ダウンロードなし、簡単アップロード、スライドと同じ操作感、それから、うーん、いや、それぐらいですね。

## 動作確認済みのスライド
以下のスライドで動作確認しています。

- Microsoft Power Point
- Google Slide
- beautiful.ai

beautiful.aiは洒落たスライド簡単に作れるのでおすすめです。
https://www.beautiful.ai/

## アーキテクチャ
よくあるVue.js + Firebaseです。
ほんと爆速です。開発もストレスフリー。

- Vue.js
- Firestore
- Firebase Hosting
- Firebase Storage

## 最後に
自分で何度か使ってみましたが、楽しくプレゼンできました。
結局ジョークは滑りました。コロナのせいじゃなかったみたいです。
もちろん対面でも使えますので是非使ってみてください。
フィボナッチ数列の初歩メモ

<br>
・フィボナッチ数列

**フィボナッチ数列**は、イタリアの数学者レオナルド・フィボナッチが考えた「[ウサギ算](https://talavax.com/usagizan.html)」から導かれる数列です。この数列は、自然界の現象に数多く出現し、ヒマワリの種の[配列](https://talavax.com/array.html)にも**フィボナッチ数列**の法則が働いているといわれている。

n番目のフィボナッチ数をFnで表すと、Fnは再帰的に

```jsx
F0 = 0
F1 = 1

Fn+2 = Fn + Fn+1　(n≧0)
```

で定義される。


<br>
1番目と2番目の値を足すと3番目の値になる。
言い方を変えると、ひとつ前とふたつ前の値を足した数が次の数となる。

・実際に書いたコード

```java
public class TryJava0120 {
	
	public static void main(String[] args) {
		
		int f0, f1, fn;
		
		f0 = 0;
		System.out.println("f0= " + f0);
		
		f1 = 1;
		System.out.println("f1= " + f1);
		
		for (int i = 2; i <= 20; i++) {
			fn = f0 + f1;
			
			System.out.println(fn);
			f0 = f1;
			f1 = fn;
			
			System.out.println(f0 + " + " + f1 + "は");
		}
		
	}
	
}
```
<br>
・実行結果

```java
f0= 0
f1= 1
1
1 + 1は
2
1 + 2は
3
2 + 3は
5
3 + 5は
8
5 + 8は
13
8 + 13は
21
13 + 21は
34
21 + 34は
55
34 + 55は
89
55 + 89は
144
89 + 144は
233
144 + 233は
377
233 + 377は
610
377 + 610は
987
610 + 987は
1597
987 + 1597は
2584
1597 + 2584は
4181
2584 + 4181は
6765
4181 + 6765は
```

前々回の計算結果(f0) + 前回の計算結果(f1)のイコールとして、変数fnに値が代入され出力される。
SlackでUNCパスのリンクをクリックして直接ファイルが開けるようになるツール「Liwing」

# はじめに

SlackでUNCパスのリンクをクリックして直接ファイルが開けるようになるツール「Liwing」の紹介です。
例えば、`\\servername\test.xlsx` というExcelファイルパスのリンクを Slack に投稿すると、そのリンクをクリックするだけで Excel を起動してそのファイルを開きます。

# ツールの使い方

## インストール方法
以下の GitHub ページの How to install と書かれれている所から LiwingSetup.msi というインストーラをダウンロードしてインストールしてください。C#で開発したWindows専用のツールです。
[LiwingのGitHubページ](https://github.com/kojimadev/Liwing)

## Slackにリンクを投稿する方法

例えば、`\\servername\test.xlsx` のファイルパスのリンクを作成したい場合、そのファイルを選択して、エクスプローラーのコンテストメニューの [送る] - [Liwing] というメニューを実行します。
(Liwingをインストールすることで、[送る]メニューが追加されます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403606/25956f0a-6b28-57a6-7bee-658a9254c413.png)
上記を実行すると、クリップボードに `lw://file/servername/test.xlsx` というカスタムURLスキームという技術を用いた形式のURLがコピーされます。

そのURLをSlackに投稿すると、下図のようにリンク形式で表示します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403606/88248a18-7c83-156d-3320-61e557525c7b.png)

# 対象のファイルを開く方法
上記の「lw:」から始まるリンクをクリックすると、下図のダイアログが表示されます。
ここで[リンクを開く]を選択すれば、対象のファイルを開きます。ファイルがxlsxの拡張子であれば、Excelを起動します(拡張子ごとの既定のアプリケーションで起動します)。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403606/1e3fafc8-2b05-c40a-d5e9-9b4c33a76d6f.png)

# 便利な使い方

## チーム全員でLiwingをインストール
「lw:」から始まるカスタムURLスキームのリンクを開くためには、Liwingのインストールが必要です。
従って、ネットワーク上のUNCパスにファイルを格納しているチームの場合、チーム全員がLiwingをインストールしておくと便利です。

## 複数ファイルのURLをコピー
エクスプローラーで複数ファイルを選択して [送る] - [Liwing] メニューを実行すれば、複数ファイルのURLをクリップボードにコピーします。

## htmlファイルに利用
Slackに貼り付けるだけでなく、htmlファイルのリンクにも利用できます。
通常はブラウザからUNCパスのファイルを直接開くことはできませんが、以下のようにLiwingでコピーしたURLをリンク先パスに書くことで、ブラウザからUNCパスのファイルを開くリンクを作成できます。
` (例) <a href="lw://file/servername/test.xlsx">test.xlsx</a>`

## ローカルのファイルを開くリンクに利用
UNCパスだけでなく、ローカルのパス(C:ドライブなど)のリンクにも利用できます。
従って、GitHubのリポジトリをクローンするローカルのパスをチーム全員で統一すれば、Slackから対象ドキュメントを直接開くリンクが作成できます。
(例) チーム全員がLドライブに対象リポジトリをクローンしていた場合、以下のリンクで対象ファイルを開く 
`lw://file/L:/docs/DesignDocuments/FeatureDesign.md`

# ツールの実現に用いた技術

Windowsには、URI スキームという概念があり、特定のアプリはブラウザからでもリンクをクリックすることで起動できます。
さらに、上記をカスタマイズするために、カスタム URL スキーム という概念があり、それを用いることで任意のデスクトップアプリを起動できるようになります。
技術の詳細は以下の記事に記載しています。
[ブラウザ上のリンクから任意のデスクトップアプリのファイルを開けると超便利](https://qiita.com/kojimadev/items/74100c8557a92939ef69)

# まとめ
SlackでUNCパスのリンクをクリックして直接ファイルが開けるようになるツールを紹介しました。

ちなみに私は、普段はエンジニアリングマネージャーとして、チームの皆で楽しく開発する施策を色々実施しています。詳しくは以下を参照ください。
[1年以上かけて生産性倍増＋成長し続けるチームになった施策を全部公開](https://qiita.com/kojimadev/items/4b28f801863cf4e8f0da)

Twitterでも開発に役立つ情報を発信しています → [@kojimadev](https://twitter.com/kojimadev)
C#でAtCoder Beginners Selection（ABC081A - Placing Marbles）

####準備
[C#でAtCoderデビューのための準備]
(https://qiita.com/azumabashi/items/7aa9e4b77c10970cc30a)
のあとで AtCoder Beginners Selection　をやってみました。

####問題文
ABC081A - Placing Marbles
[https://atcoder.jp/contests/abs/tasks/abc081_a]
(https://atcoder.jp/contests/abs/tasks/abc081_a)

####提出結果

```
using System;
 
class Program
{
	static void Main(string[] args)
	{
		string input = Console.ReadLine();
		int okCount = 0;
		for(int i = 0; i < 3; i++)
		{
			char c = input[i];
			if (c == '1') okCount++;
		}
		Console.WriteLine(okCount);
	}
}
```

####テスト実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/0f0a14b1-1ccf-e07b-95a0-c05baeee4da6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/158ce0b3-7a57-52b3-3fc0-9e8b0565617c.png)
[Oracle ADS] 回帰と分類はどう決まるのか？

Oracle Data Science Cloudで使用できる、adsについて。

# 結論

targetとして指定したSeriesの型がfloatであれば回帰。intであれば分類。

# 決定ロジック

### パッケージの場所

adsパッケージのコードを見ていく。

```py

import sys

sys.path

['/tmp/dask-worker-space/worker-_4k3q1mv',
 '/home/datascience/conda/mlcpuv1/lib/python36.zip',
 '/home/datascience/conda/mlcpuv1/lib/python3.6',
 '/home/datascience/conda/mlcpuv1/lib/python3.6/lib-dynload',
 '',
 '/home/datascience/conda/mlcpuv1/lib/python3.6/site-packages', <=ここ
 '/home/datascience/conda/mlcpuv1/lib/python3.6/site-packages/IPython/extensions',
 '/home/datascience/.ipython']

```

### 変数「ml_task_type」で決まる。

ads/automl/driver.py

```py

def get_ml_task_type(X, y, classes):
    target_type = TypeDiscoveryDriver().discover(y.name, y)
    if isinstance(target_type, DiscreteTypedFeature):
        if len(classes) == 2:
            if helper.is_text_data(X):
                ml_task_type = utils.ml_task_types.BINARY_TEXT_CLASSIFICATION
            else:
                ml_task_type = utils.ml_task_types.BINARY_CLASSIFICATION
        else:
            if helper.is_text_data(X):
                ml_task_type = utils.ml_task_types.MULTI_CLASS_TEXT_CLASSIFICATION
            else:
                ml_task_type = utils.ml_task_types.MULTI_CLASS_CLASSIFICATION
    elif isinstance(target_type, ContinuousTypedFeature):
        ml_task_type = utils.ml_task_types.REGRESSION
    else:
        raise TypeError("AutoML for target type ({0}) is not yet available"
                                   .format(target_type.meta_data["type"]))
    return ml_task_type
```

### TypeDiscoveryDriver().discover(y.name, y) の型で決まる

from ads.type_discovery.type_discovery_driver import TypeDiscoveryDriver

ads/automl/type_discovery/type_discovery_driver.py

```py
class TypeDiscoveryDriver:

    #
    # takes a pandas series
    #
    def discover(self, name, s, is_target=False):
　　　　　：
　　　　　：

        if is_target and ContinuousDetector._target_is_continuous(s):
            return ContinuousTypedFeature.build(name, s)

```

### ContinuousDetector._target_is_continuous(s) がTrueなら回帰

from ads.type_discovery.continuous_detector import ContinuousDetector

ads/automl/type_discovery/continuous_detector.py

```py

class ContinuousDetector(AbstractTypeDiscoveryDetector):

    @staticmethod
    def _target_is_continuous(series):
        if str(series.dtype) in ['float16', 'float32', 'float64']:
            return True # treat target variable as continuous
        elif str(series.dtype) in ['int16', 'int32', 'int64']:
            if series.nunique() >= 20:
                return True # treat target variable as continuous

        return False
```
OpenMayaのイテレータを使って階層名を取得する

#はじめに

選択した階層以下のノード名を取得したいとします。
まず最初に思いつくのが、listRelativesコマンドだと思います。
listRelativesコマンドを使えば、子階層が取得できます。

https://help.autodesk.com/view/MAYAUL/2020/JPN/index.html?contextId=COMMANDS-INDEX

```Python
cmds.listRelatives( ad=True, c=True, typ="transform" )
```

ただこの方法で取得すると、リスト内の順番が階層順でないため使いにくいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/491414/606060c2-2805-87c4-aa13-f94cb20581bc.png)

```Python
# 結果: [u'_03', u'_02', u'_01', u'_05', u'_07', u'_06', u'_04'] # 
```

上記は"_00"を選択して、コマンドを実行した結果です。
取得したリストを reverse() すれば階層順にはなりますが、スマートではないです。


そこで、OpenMayaを使って解決していきます。

#コード
```Python
import maya.OpenMaya as om

def getHierarchicalNameList(): 
    list = [] 
    selList = om.MSelectionList() 
    om.MGlobal.getActiveSelectionList(selList)

    for i in range(selList.length()): 
        dag = om.MObject() 
        selList.getDependNode( i, dag ) 

        dagIterator = om.MItDag( om.MItDag.kBreadthFirst, om.MFn.kInvalid ) 
        dagIterator.reset( dag, om.MItDag.kBreadthFirst, om.MFn.kTransform )  

        fDn = om.MFnDagNode() 
        while ( not dagIterator.isDone()): 
            currentObj = dagIterator.currentItem() 
            fDn.setObject(currentObj) 
            fName = fDn.name() 
            list.append( fName ) 

            dagIterator.next() 

    return list 
```	

#解説

OpenMayaのイテレータを使っていきます。
イテレータとはデータ集合構造です。親子階層は、DAGの集合構造ですので、MItDagクラスを使用します。

```Python
        dagIterator = om.MItDag( om.MItDag.kDepthFirst, om.MFn.kInvalid ) 
```

イテレータを作成します。引数は【type】と【filter】です。
Typeは、捜索タイプを指定します。

- kDepthFirst 　　： 子階層を捜索後、兄弟階層に移動します。
- kBreadthFirst　 ：　兄弟階層を捜索後、子階層に移動します。

それぞれのTypeを実行すると下記のような違いがあります。

```Python

#　kDepthFirst 
[u'_00', u'_01', u'_02', u'_03', u'_04', u'_05', u'_06', u'_07']

#　kBreadthFirst　
[u'_00', u'_01', u'_04', u'_02', u'_05', u'_06', u'_03', u'_07']
```

filter で、フィルタを設定することができます。
kTransform　はフィルタを無効にしています。
その他のフィルタは[ココ](https://download.autodesk.com/us/maya/2010help/API/class_m_fn.html#a89f9fd6c3157993508e460683cc948b)を参照してください。


```Python
        dagIterator.reset( dag, om.MItDag.kBreadthFirst, om.MFn.kTransform ) 
```

イテレータをリセットしています。
ここで捜索したいDAGノードを指定しています。
Transform のみを取得したいので、MFn.kTransform でフィルタを設定しています。

```Python
        while ( not dagIterator.isDone()): 
            dagIterator.next() 
```

while でイテレータが終わるまでループさせます。
next() メソッドで、次のノードに移動します。next が無いと永久ループとなりますので気を付けてください。


#まとめ
イテレータクラスは、MItDag 以外にも、ノードネットワーク（MItDependdenctGraph）や頂点（MItVertex）・ポリゴン（MItMeshPolygon）などがあります。
上記のポイントを押さえれば、どれも似たような感じで扱えます。
cmdsより、高速に処理を行うことができますので、活用してみてください。
C#でAtCoder Beginners Selection（ABC086A - Product）

####準備
[C#でAtCoderデビューのための準備]
(https://qiita.com/azumabashi/items/7aa9e4b77c10970cc30a)
のあとで AtCoder Beginners Selection　をやってみました。

####問題文
ABC086A - Product
[https://atcoder.jp/contests/abs/tasks/abc086_a]
(https://atcoder.jp/contests/abs/tasks/abc086_a)

####提出結果

```
using System;
class Program
{
	static void Main(string[] args)
	{
		string[] input = Console.ReadLine().Split(' ');
		int a = int.Parse(input[0]);
		int b = int.Parse(input[1]);
		int amari = (a * b) % 2;
		if (amari == 0) Console.WriteLine("Even");
		if (amari == 1) Console.WriteLine("Odd");
	}
}
```

####テスト実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/091311ae-a150-8144-7852-af2fb9e56046.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/225878/39a285f4-fd00-c9b2-d82e-43527ae7c62f.png)
【Swift】SafeAreaの高さを取得する

SafeAreaの高さを取得したかったので調べました。

##SafeAreaの高さ

```swift:
//上部のSafeArea
let safeAreaTop = self.view.safeAreaInsets.top
print(safeAreaTop)

//下部のSafeArea
let safeAreaBottom = self.view.safeAreaInsets.bottom
print(safeAreaBottom)
```

##ちなみに
`viewDidLoad`の時点ではSafeAreaの値は取得出来なかったので`viewWillLayoutSubviews`の時に取得するのが良さそうです。
マウスホバー時の構文覚書

#JavaScriptを使った時のマウスホバー時のイベント構文について、自身への覚書きです。

```
 let textChange = document.getElementById('about');
  function mouse(word,word2){
  textChange.addEventListener('mouseover',()=>{ 
  textChange.innerHTML=word;
  });
  textChange.addEventListener('mouseleave',()=>{ 
    textChange.innerHTML=word2;
    });
  };
  mouse("こんにちは","さようなら");
```
[Vue.js] v-ifの使い方


##はじめに
vue.jsでv-ifを使ったので備忘録として記事を作成

##v-ifとは
要素の表示・非表示を操作することができる

```
表示：true
非表示：false
```

#実装方法
一部の要素を非表示にしたい場合はfalseを指定する

```sample1.vue
<input v-if='false' />
```

非表示にしたい要素が複数ある場合はtemplateで囲む

```sample2.vue
<template v-if='false'>
  <input />
  <input />
  <input />
</template>
```

##参考
https://jp.vuejs.org/v2/guide/conditional.html
AMD GPU のクロック制御のメモ

## rocm-smi

https://github.com/RadeonOpenCompute/ROC-smi

とりあえずお手軽に underclock とか powerlimit したいむけ.

`--setsclk 2` などとして制御できます.

## amdcovc など

https://github.com/matszpk/amdcovc

https://github.com/sibradzic/amdgpu-clocks

細かく制御したい向け. もしくは `/sys/class/*` のパラメータを直接叩いてもいいかも(最新 GPU だとカーネルが対応していなかったりするかも)

デフォルトの Linux kernel(少なくとも Ubuntu 20.04 の 5.4)では, 細かいクロック制御はできないので,  上記ツールを使う場合は kernel parameter に

`amdgpu.ppfeaturemask=0xffffffff` を追加する.


Ubuntu であれば `/etc/defaults/grub` で追加して, `sudo update-grub2` して反映させる.
(`/etc/modprobe.d` に `amdgpu.conf` をつくり追加したほうがナウいかも?)

```
printf "0x%08x\n" $(cat /sys/module/amdgpu/parameters/ppfeaturemask)
```

で現在の状態を確認できる.


## amdmemorytweak

https://github.com/Eliovp/amdmemorytweak

メモリタイミングの制御
migrate出来なかった時のお話

# 凡ミスでmigrate出来なかった時のお話

>1. [rails g modelコマンド](https://qiita.com/iamu_TECH_CAMP/items/f40c475a46cfa6e5f30b#rails-g-model%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89)

>2. [rails db:migrateコマンド](https://qiita.com/iamu_TECH_CAMP/items/f40c475a46cfa6e5f30b#rails-dbmigrate%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89)

>3. [本題のerror発生](https://qiita.com/iamu_TECH_CAMP/items/f40c475a46cfa6e5f30b#migration%E3%81%8C%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84)

>4. [仮設・検証](https://qiita.com/iamu_TECH_CAMP/items/f40c475a46cfa6e5f30b#error%E3%81%AE%E4%BB%AE%E8%A8%AD%E6%A4%9C%E8%A8%BC%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88)

>5. [解決](https://qiita.com/iamu_TECH_CAMP/items/f40c475a46cfa6e5f30b#%E8%A7%A3%E6%B1%BA)

**上記の5段構成で進めていきます。**

本題に急いでいる方は
[本題のerror発生](https://qiita.com/iamu_TECH_CAMP/items/f40c475a46cfa6e5f30b#migration%E3%81%8C%E5%AE%9F%E8%A1%8C%E3%81%A7%E3%81%8D%E3%81%AA%E3%81%84)から飛んで下さい。
以降、一部補足をしながら進めていきます。


## rails g modelコマンド

`rails g modelコマンド`でモデルを作成したとき、
db/migrate/ディレクトリに`migrationファイルが同時に生成`される。

migrationファイルの中身はこんな感じ

```ruby:db/migrate/20XXXXXXXXXXXX_create_複数形のモデル名.rb
class Createモデル名の複数形 < ActiveRecord::Migration[6.0]
  def change
    create_table :モデル名の複数形 do |t|

      t.timestamps
    end
  end
end
```


>`% rails g model 単数形モデル名`
generateの略で、生成するの意味がある。
>基本的に、コントローラー名は複数形、モデル名はそれに対応する単語の単数形になる。

>>補足情報 :`% rails d model 単数形モデル名
`destroyの略で、削除するの意味がある。

## rails db:migrateコマンド

migrationファイルにデータベースに保存したい`カラムの型とカラム名を指定`して、
`% rails db:migrate`とコマンドを打ち込みmigrationを実行する流れになるのだが...

>`% rails db:migrate`
>この動作は、マイグレートと呼ばれることがある。

## migrationが実行できない

migrationが実行できず、ターミナルには以下のerror文が...

```
== 20210119052352 CreateAddresses: migrating ==================================
-- create_table(:addresses)
rails aborted!
StandardError: An error has occurred, all later migrations canceled:

undefined method `steing' for #<ActiveRecord::ConnectionAdapters::MySQL::TableDefinition:0x00007fbc8955f760>
Did you mean?  string

~~省略~~

bin/rails:3:in `load'
bin/rails:3:in `<main>'

Caused by:
NoMethodError: undefined method `steing' for #<ActiveRecord::ConnectionAdapters::MySQL::TableDefinition:0x00007fbc8955f760>
NoMethodError: undefined method `steing' 

~~省略~~

bin/rails:3:in `load'
bin/rails:3:in `<main>'
Tasks: TOP => db:migrate
(See full trace by running task with --trace)
```

## errorの仮設・検証スタート

長々と出てきましたが、現状の私が着目したのは以下の3点

```
1. StandardError: An error has occurred, all later migrations canceled:`
2. undefined method `steing' for #
3. Did you mean?  string
```
カラムの型を指定した際に手打ちしていた事によってスペルミスの可能性が浮上してきました。

追求はしませんでしたが、`StandardError`とある上記のerror文に関しても
こうして整理していくと気になってくる。

>検索結果 ：`rails db:migrate:reset`
データベースのリセットを行ってerror解決している記事を発見。
だが、今回の場合`Did you mean?  string`の表記が
決め手になっていた様に捉えて間違いなかったようだ。


## 解決

この後migrationファイルを見直して予想通り`steing`を発見。


```
== 20210119052352 Createモデル名の複数形: migrating ==================================
-- create_table(:モデル名の複数形)
   -> 0.3171s
== 20210119052352 CreateAddresses: migrated (0.3174s) =========================
```

無事migration完了
>もし仮にカラム名を間違っていたらerrorも吐かれずrollbackしていた事でしょう。
Overleafで執筆してPDF化した文章のフォントを埋め込む方法(Mac)（裏技？）

※プログラミングは用いないのですが，自分と同じ状況に陥った人の助けになるよう本記事を執筆致します．

皆さんこんにちは．
初めての記事執筆になります．
今後このプラットフォームにお世話になると思いますので，自分もまずは書いてみようと思い，書きます．
今後とも宜しくお願い致します．


【問題】
上記のタイトルからも想像がつくかもしれませんが，
#「Overleafで執筆してPDF化した論文のフォントが埋め込めていなかった……」

です．

※解決方法をすぐ知りたい方は【背景】を飛ばして【解決方法】に進んでください．本質的な部分ではないので．

【背景】
修士論文執筆に当たり，
texで執筆しようと思い検索したところ，
>LaTeXで修論を書く（Overleaf使う）
https://qiita.com/ishigaki/items/8da80e4da3e2249a85f8

というドンピシャな記事を見つけました
（執筆者の方，とてもお世話になりました．ありがとうございました）

上記のテンプレを用いながら，
場合によって自分で少しずつ加工しながら修士論文の執筆を行なっていきました．

そして提出に当たり，大学側から
「フォントの埋め込み」の要求がなされました．
※ちなみに
>フォントを埋め込むメリットは何ですか （Acrobat X）
https://helpx.adobe.com/jp/acrobat/kb/725.html#:~:text=PDF%20%E3%81%AB%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88%E3%82%92%E5%9F%8B%E3%82%81%E8%BE%BC%E3%82%80,%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82

に依ると，フォントを埋め込むメリットは，任意の環境下でも文字化けさせないこと，だそうです．Adobe Illustratorで言うところのアウトライン化と同じような話ですかね．

しかし，
OverleafからDownload PDFによって生み出したPDFには埋め込みができいていないフォントがいくつか…
>ちなみに
PDFに於いて，フォントが埋め込まれているかどうかを確認する方法
https://www.too.com/support/faq/adobe/23200.html#:~:text=Acrobat%E3%80%81%E3%81%BE%E3%81%9F%E3%81%AFAcrobat%20Reader%E3%81%A7,%EF%BC%89%E3%80%8D%E3%81%A8%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82

色々試したものの全く出来ず八方塞がりだった自分に，研究室同期のO氏から救いの手が……（マジで助かった！ありがとう！！！）

#【解決方法】
1: OverleafのDownload PDFで生み出したPDFをMacのデフォルトのアプリである「プレビュー」で開く
2: オプションの「ファイル」>「PDFとして書き出す…」で新たなPDFを生み出す
たったのコレだけ！！！笑

極限状態だった自分はかなり拍子抜けしてしまいました（笑）
O氏曰く「学部の時に裏技として教えてもらったんだ〜」と．
（ので，どんな状況でも適用できるかは正直わからないです）

彼が居なければどうなっていたか……想像するだけでも怖いです😭

そんなこんなで無事に修士論文の提出は出来ました（ﾖｶｯﾀ）
そして来週末に最終報告会を迎えます．

無事に修了できることを願って初記事の筆を置きたいと思います．
色々な記事が書けるように鋭意勉強していきたいです．
では，最近全国的に寒いので，何卒ご自愛くださいませ．
Pythonのクラスの書き方

#目的
pythonを勉強しているうえで、クラスの書き方に理解が一度で追いつかなかったので、アウトプットして定着させる。

#クラスとインスタンス

- クラス・・・プログラミングにおいて、「モノ」を生成するためのレシピ的なもの

- インスタンス・・・レシピをもとに生成された「モノ」

##クラスの宣言方法
クラスを扱うには、宣言する必要がある。

```python:sample.py
#クラスの宣言
class SampleClass():
```

##クラスの使い方
クラスの中で関数を定義することができる。
クラスの中で定義された関数のことを**メソッド**という。

メソッドの定義の方法は通常の関数と同じだが、第1引数にselfを使う。

```python:sample.py
#クラスの宣言
class SampleClass():
    def hello(self):
        print("Hello World!")
```

##インスタンス変数の生成
インスタンスには色々な情報を定義することができる。
八百屋さんで売っていそうな品物を例にしてみる。
下記のプログラムで、家電の名前を出力する。
「インスタンス.インスタンス変数名」とすることで、インスタンスの変数を利用することができる

```python:yaoyaclass.py
#クラスの宣言
class YaoyaItem():
    def vegetable(self):
        print(self.name)

#YaoyaItemクラスの値を代入
yaoyaitem1 = YaoyaItem()
#yaoyaitem1のnameが「大根」である情報を追加
yaoyaitem1.name = "大根"

#クラスの中で定義したメソッドを呼び出す
yaoyaitem1.vegetable()
```

vegetableメソッドが呼び出されて、以下の結果が得られる

```
大根
```

##メソッドに引数を持たせる場合
メソッドに引数を持たせる場合は、第2引数以降に引数名を記載する

```python:yaoyaclass.py
#クラスの宣言
class YaoyaItem():
    def payment(self,count):
        #戻り値に合計金額を設定
        total_price = self.price * count
        return total_price

#YaoyaItemクラスの値を代入
yaoyaitem1 = YaoyaItem()
yaoyaitem1.name = "りんご"
yaoyaitem1.price = 50

#第2引数のcountに、4を代入する
result = yaoyaitem1.payment(4)
print(yaoyaitem1.name+"を4個買いました。合計"+str(result)+円です)
```

結果は下記のように表示される。

```
りんごを4個買いました。合計200円です
```

#感想
とりあえず書いてみましたが、少しは定着できたかな。
俺的、FLOCSSのまとめ

## はじめに
皆さんCSSを書くときに設計は取り入れていますでしょうか。
SMACSSやBEMなど様々あると思いますが自分は業務上FLOCSSを使う事が多くあるんですが今だに迷うことがあったりすることがあります。
そこで今回は（自分の為に）基本原則などを自分なりにまとめてみようと思います！

この記事は順次更新していきたいなと思っています。

## まずFLOCSS is 何？
FLOCSSとは
> いくつかある有名なCSS設計手法の中のひとつで、その有名どころのOOCSSやSMACSS、BEM、SuitCSSのコンセプトを取り入れたのがFLOCSSです。オブジェクト志向で設計されています。

上述した設計の良いところを取り入れて作られたのがFLOCSSという事ですね！

## 基本原則
FLOCSSは基本的に3つのレイヤーとObjectの子要素のレイヤーで構成されています。

### 1. Foundation
このレイヤーではサイトで使用するデフォルトスタイルを管理します。
そのプロジェクトで使用する基本的なスタイルの定義ですね。
`base.scss`
`reset.scss`
`mixin.scss`
...etc

### 2. Layout
ヘッダーやフッターなど大枠のレイアウトに関する定義をこちらのレイヤーで定義します。
`l-header.scss`
`l-footer.scss`
...etc

### 3. Object
サイト全体で利用ができるモジュールを管理する。
細かく以下の3つに分けられます。

#### 3-1 Component
再利用が可能な最小単位のパーツ、基本的にどのページであっても使用出来るのが好ましいと思ってます。
`c-btn`
`c-card`
...etc

#### 3-2 Project
サイト固有で使用するパーツ、Componentと他の要素が集まったものがProjectに当たります。
`p-article`
`p-contact`
...etc

#### 3-3 Utility
Component, Projectのモディファイアで解決することができないスタイルをここに記述していきます。
要するに細かく見た目の調整を行うときにUtilityにスタイルを定義することが多いです
`u-text`
`u-color`
`u-size`
...etc

色々ここに書きましたがFLOCSS作者様がGithubに詳しく詳細を書いてくださっているのでご興味を持たれた方は是非こちらを参照してください

◆ [FLOCSS](https://github.com/hiloki/flocss)

## ComponentとProjectの使い分け難しい問題
これは非常にわかります、僕自身今でも結構な頻度で「え、これどっち？」ってなっています。

上述しましたがComponentは最小単位のパーツを定義する部分なので`c-~`で命名しようと思ったときにこれ以上細分化出来ないかどうかで判断するといいと思います。
例えば`c-card`とした時にそのカード内はそれ以上細分化することは出来ないのかどうか。

出来ないのであればComponentが適切だと思いますが出来そうなのであればそれはProjectにしてしまった方がいいのでは？と個人的には思っています。
あくまでProjectはComponentの集まりだと思っているのでこのような考え方で命名していけば問題ないのかなと思います。


## 命名規則について
FLOCSSでは**MindBEMding**という命名規則が使われています。

### MindBEMdingって？

>MindBEMdingとはBlock, Element, Modifierで構成する命名規則。
・Block：構成の元となる要素、機能上独立したページの構成要素で、再利用できるもの
・Element：Blockの中に存在する子要素、構成要素、そして別Blockに移動すると使えないもの
・Modifier：BlockまたはElementが変化した状態の要素、見た目や状態、挙動を定義するもの

必ずBlockが一番先頭に来て、そのあとにElementやModifierが付く形となる。
Elementが付く場合はアンダースコア二つで区切り、Modifierが付く場合にはハイフンで区切る

1. Block : 一番大きな塊 ElementとModifierの親に当たる　`p-footer` 例）
2. Element : \_\_で繋げる、Blockの中で使われる部品 `p-footer__label` 例）
3. Modifier : --で繋げる、BlockやElementと見た目が異なるもの（少し小さい、色が違うなど） `p-footer__label--small` 例）
2021年にもなって pyenv-virtualenv の可能性を主張してみる

# なにこれ？
pipenvやpoetryを皆が使っている2021年に、とある目的にpyenv-virtualenvがぴったりということに気が付いたので、紹介します。

# pyenv-virtualenv って何？
pythonの仮想環境構築ツールの一つです。pyenvの拡張機能です。通常のpyenvでは`pyenv local 3.8.7`のように、pyenv公式が用意したバージョン名を指定して環境を制御しますが、pyenv-virtualenvを使うと`pyenv local saishinban`のように好きな環境名が指定でき、この環境名で環境を切り分けることができます。

Qiita内にpyenv-virtualenvの記事はたくさんあるので、これくらいの雑な説明にとどめます。より詳しく知りたくなったら、[公式のREADME](https://github.com/pyenv/pyenv-virtualenv)や他の記事を参考にしてください。

# 何に気づいたの？
皆さんは、趣味や仕事で俺が考えた最強のCLIツールをpythonで書いていることでしょう。そして、今風に（2021年）poetry等を使ってパッケージ管理していることでしょう。そんなこんなでそれっぽいツールができてきたとしましょう。さて、このCLIツールはどうやって動かすのが良いでしょうか？

1. dockerこそ至高
2. 開発と同じpoetry/pipenvの環境をそのまま
3. システムのpythonにえいやー
4. その他

すぐ答えを言ってしまうと、4のその他で、pyenv-virtualenvがぴったりです。

## ダメ出し（1,2,3）
まず、1,2,3のダメ出しすると次のようになります。

|ケース|問題点|
|---|---|
|1. docker|CLIツールはローカルのディレクトリやファイル等を扱ったりすることが多く、マウント・権限管理が必要で、手間やリスク（下手に`/`をマウントしてファイル全消し等）がつきまとう|
|2. 開発と同じ|poetryやpipenvを使う場合、まずそのディレクトリに行ってから操作する必要があり、面倒（CLIの引数のパスの扱いも面倒）|
|3. システム|依存関係の管理はどこに行ってしまったのか・・・|

まあ、気合で頑張ったりリスクを無視するのならできなくも無いですが、どれもやりたくは無いですね。

## 答え（pyenv-virtualenv）
次のようにpyenv-virtualenv環境を作成します。

```terminal
$ pyenv install X.X.X  # 好きなバージョンのインストール（すでにインストール済みなら不要）
$ pyenv virtualenv X.X.X mytoolenv
$ pyenv shell mytoolenv
$ pip install -e PATH/TO/mytool  # ここで、あなたの最強のCLIツールをインストールします（poetryを使う場合setup.pyがなく、`pip install -e`が使えないため注意）
```

そして、適当にPATHの通ったディレクトリにツール名と同じ名前のファイルを作成し（例ではツール名がmytoolとします）、以下の内容を記述して実行権限を与えておきます。

```bash
#! /bin/bash
eval "$(pyenv init -)"
pyenv shell mytoolenv
mytool $*
```

これで、mytoolと叩くと、専用の仮想環境で動作させれます。setup.pyを排除したやり方を取っていて、`pip install -e`が使えない場合は、インストールし直すスクリプトを用意するとはかどります。

この方法の魅力は、どのディレクトリにいてもツールが使え、それでいてそれなりの仮想環境（dockerほどではない）を準備できる点です。

# まとめ
2021年でもpyenv-virtualenvを使うと良いケースがあります。似た悩みに直面している方は一考してみてください。
リーダブルコード読んで意識していきたいことをまとめる part5

[前回](https://qiita.com/gal1996/items/e35f7351e4814d857704)の続き

# 11章　一度に一つのことを

この章では一度に行う処理は一つにしようということが書いてある。単一責務の原則とは違うけど、一つの関数が一つの処理をするみたいな内容。ほかにも、似た処理はまとめて書くとか、デフォルトの値を入れるときは最初にまとめてからそれらの値を更新するとかといったことが書いてあった。この章に書いてあることでそこまで目新しいことはなかったのでこの辺で。

# 12章　コードに思いを込める

この章ではコードを書く際にそのロジックを言葉に書き出してからコードに落とすという手法が書かれていた。確かにいつも脳内ではまず言語で考えてそれをコードに落としているから理に適っている気がする。（直でコード書ける人はすごい）これをやると関数をどの粒度で切り出すといいかなどが見えてくる。「〇〇してから、△△する。」なら〇〇部分と△△が関数に切り出す候補になる。これはコード書いてて汚くなったなと思ったらやってみるとよさそう。

# 13章　短いコードを書く

この章では各コードは短く、不要ならコードは書かないほうがいいということを言っている。コードが少なければメンテのコストも低い。また、膨大にコードが膨れると消えるコードもある。それは効率が悪い。そのために、「仕様を詰めて、必要な要件のみを実装する」、「標準ライブラリを読んで不要に自分ですでにあるものを作ってしまわないようにする」などが挙げられている。これはとても共感する。特に仕様を詰めて必要な要件を実装するというのは最近自分も意識していたことで、つまりそれがコードが短くなるという具体的な指標につながるイメージが持てたのがよかった。

# 14章　テストと読みやすさ

この章ではテストは読みやすく、手が入れやすいものであるべきだということが書かれている。特に意識したいと思ったことは「テストを意識しながらコードを書く」と、「テスト関数は極力説明的な名前を付ける」で、両方とも全く意識できてなかったのでこれから意識したい。特に前者が全く意識できてなかったので、意識したらコードがどうなるか気になる。

# 15章

この章は実践がメインだったので省略。

よしゃー読み切った。正直人に伝えるより自分のメモとして書いてたから、あまり伝わってないだろうけど、自分がこれ見て意識することを思い出すようにしていこう。
Wildfly 22.0.0.Final インストール・設定

Wildfly の 2021/01/15 時点の最新 22.0.0.Final をセットアップしてみる。
JBossEAP v7.2 を業務で使うがライセンスでお金かかるので Wildfly でお試し！
環境は Windows2019 を想定して Windows10 で実施。
JDK は OpenJDK11 使用。

## zipダウンロード, 解凍
1. Wildfly のサイトよりダウンロード(Jakarta EE Full & Web Distribution)<br>
https://www.wildfly.org/downloads/
1. 適当な場所に解凍（今回の手順では以下となるようにする）<br>
`c:\jbosss\wildfly-22.0.0.Final\* # 直下に bin, modules, etc...`

## 環境変数設定
JBoss でJava, JBoss の環境変数設定が推奨になっていた3つを設定
bin の中を見たら JBOSS_HOME を参照してるので JBoss と併用する場合、注意が必要
その時は各 bat とかに直接書けば対応できそう

|#|Name|Value|備考|
|:--|:--|:--|:--|
|1|JBOSS_HOME|c:\jbosss\wildfly-22.0.0.Final|wildfly\binある親パス|
|2|JAVA_HOME|c:\java\java-11-openjdk|jdk\bin ある親パス|
|3|NOPAUSE|1|サービス登録するとき必要、ないと固まるっぽい|

## ユーザ登録
Wildfly のWeb管理コンソールにアクセスするにはユーザが必要になるため `add-user.bat` を使ってユーザ登録する

```
# add-user.bat 実行(対話式, 、パスワード注意受けるけど気にせず yes、group なし、)
%JBOSS_HOME%\bin\add-user.bat
    # ManagementUser選択
    # Password簡単だと注意受けるけど気にしないで yes (設定によってはNGになる)
    # groupなし
    # 追加確認は yes
    # 他APプロセス使用は no

# add-user.bat 実行(非対話式 standalone のみ)
%JBOSS_HOME%\bin\add-user.bat -u %userName% -p %userPassword% -sc %JBOSS_HOME%\standalone\configuration
```

## standalone 起動・接続確認・停止
`standalone.bat` で起動して接続確認してから停止してみる

```
# standalone 起動
%JBOSS_HOME%\bin\standalone.bat

# Webブラウザでアクセス（8080:アプリ(Welcome ページ), 9990:管理コンソール(basic認証あり)）
# ※ ホスト名(localhost), ポート(8080, 9990)は設定により変更
http://localhost:8080
http://localhost:9990

# CLIで管理コンソールアクセス
# ※ ホスト名(localhost), ポート(9990)は設定により変更
%JBOSS_HOME%\bin\jboss-cli.bat -c --controller=localhost:9990

# standalone 停止
# ※ ホスト名(localhost), ポート(9990)は設定により変更
%JBOSS_HOME%\bin\jboss-cli.bat -c --controller=localhost:9990 --command=shutdown

```

## サービス登録モジュール移動（コピー）
サービス登録したい場合、以下を　`%JBOSS_HOME%\bin` に移動（コピー）すると `service.bat` が実行できる

```
# ディレクトリ：%JBOSS_HOME%\docs\contrib\scripts\service
xcopy /e/i %JBOSS_HOME%\docs\contrib\scripts\service %JBOSS_HOME%\bin\service 

# 実行スクリプト：%JBOSS_HOME%\docs\contrib\scripts\service\service.bat
copy %JBOSS_HOME%\docs\contrib\scripts\service\service.bat %JBOSS_HOME%\bin\service.bat
```

## サービス登録(インストール)・削除(アンインストール)
```
# サービス登録（インストール）
%JBOSS_HOME%\bin\service.bat install
%JBOSS_HOME%\bin\service.bat install /name %serviceName% /jbossuser %userName% /jbosspass %userPass% /controller %host%:%port% /base %domainOrStandalone% /logpath %logPath% /startup
# ※ /logpath は標準出力の logpath になるだけっぽい
# ※ -Djboss.server.log.dir は別途、standalon.conf.bat とかで指定が必要。。。 

# サービス削除（アンインストール）
%JBOSS_HOME%\bin\service.bat uninstall
%JBOSS_HOME%\bin\service.bat uninstall /name %serviceName%

# ※詳細はヘルプで確認（引数なし実行）
%JBOSS_HOME%\bin\service.bat

```

## サービス起動・停止・状態確認（デフォルトサービス名は Wildfly）
```
# サービス起動
%JBOSS_HOME%\bin\service.bat start
%JBOSS_HOME%\bin\service.bat start /name %serviceName%
sc start "%serviceName"

# サービス停止
%JBOSS_HOME%\bin\service.bat stop
%JBOSS_HOME%\bin\service.bat stop /name %serviceName%
sc stop "%serviceName"

# サービス状態確認
sc queryex "%serviceName"
```

## 管理CLIから各設定
管理CLIから設定するときに使うコマンドをざっと記載
`tab` 押下で入力保管あるので確認しながらやると良さそう

- 基本操作

```
# 設定確認
/<xml-path>:read-resource
/core-service=management:read-resource

# 設定追加
/<xml-path>:add(<属性>=<値>)

```

- 詳細設定
<Ruby> No template for interactive requestの対処法

RubyでCRUD処理の勉強していたら、
`No template for interactive request`
というエラーが出ました。

解決方法は、

UsersControllerに対するviewディレクトリの中のusersディレクトリのnew.html.erbを作る。


`UsersController#new is missing a template for request formats: text/html`
とあり、UsersControllerに対するviewディレクトリの中のusersディレクトリのnew.html.erbに問題がありました。

私の場合は、
viewディレクトリの中の
最初からあるlayoutsディレクトリの中に
usersディレクトリが入っていました。

これをviewディレクトリの中に移動するだけでエラーが出なくなりました。

ディレクトリの場所をちゃんと確認することが大切だとわかりました。
Jamstack とは何か（ 2021 年 1 月時点）

Jamstack 公式サイト
https://jamstack.org/

# Jamstack とは何か（ 2021 年 1 月時点）

>Jamstack is the new standard architecture for the web. Using Git workflows and modern build tools, pre-rendered content is served to a CDN and made dynamic through APIs and serverless functions. Technologies in the stack include JavaScript frameworks, Static Site Generators, Headless CMSs, and CDNs.

Jamstack は、ウェブの新しい標準アーキテクチャ。Git ワークフローと最新のビルドツールを使用して、あらかじめレンダリングされたコンテンツを CDN に提供し、API とサーバーレス機能を介して動的なものにする。スタックに含まれるテクノロジーには、JavaScript フレームワーク、スタティックサイトジェネレーター、ヘッドレス CMS 、CDN などがある。




> The core principles of pre-rendering, and decoupling, enable sites and applications to be delivered with greater confidence and resilience than ever before.

プリレンダリングとデカップリングの基本原則により、サイトやアプリケーションをこれまで以上に信頼性とレジリエンス（変化に対処する能力）を持って配信することができる。

# （参考）これまでの Jamstack / JAMstack

- Matt Biilmann (Netlify 社）が 2016 年頃に提唱し始めたもの。
- もともとは **JAM**stack 。 **J**avaScript 、**A**PIs 、**M**arkup の頭文字と言われていた。
- [2019 年 12 月頃](https://github.com/jamstack/jamstack.org/commit/41c0b767694c1f8c7e3fabcb1e0d770b154c00d7)から [2020 年 4 月頃](https://github.com/jamstack/jamstack.org/commit/d2ecce1afae3d86bb19a308b9f93d01b027a798e) にかけて **JAM**stack から **Jam**stack 表記へ変わった。
- 定義／構成要素は当初の「 JavaScript 、API 、Markup という要素を含むもの」から、「 Web サーバを介さないもの」、そして現在の「プリレンダリングとデカップリングするもの」、といった具合に世の中の浸透具合にあわせて広義に変化している模様。

# Jamstack とはつまり何か
- Google の [Rendering on the Web](https://developers.google.com/web/updates/2019/02/rendering-on-the-web) の以下図における **CSR with Prerendering** であると言える。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230524/a0db1bb9-b8de-38f4-489f-9083efbd1cde.png)
- SSR するのではなく静的 HTML を**プリレンダリング**するもの。SPA がそうであるように、サーバサイドとクライアントサイドが**分離（デカップリング）**している構成であるもの。

# Jamstack がなぜ理解しにくいのか
- SSR (Server Side Rendering) 、CSR (Client Side Rendering) という概念を理解する必要があること
- 前述の図にもあるように、SSR や CSR は更に細分化され、複数の種類があることを理解する必要があること
- 静的レンダリングとプリレンダリングといったように似た用語で異なる概念があり混乱しやすいこと
- SSR 、CSR 等を理解するのにアプリのビルド・デプロイのフローを理解していないと混乱しやすいこと
- ISR (Incremental Static Regeneration) といった新しい概念も登場していること
- 概念の実装例／具体例（例えば Next.js といったフレームワーク）が日々進化し機能拡張されていることから、一概に定義できず（ SSG であり SSR である等）複雑化していること

# 参考記事
公開時期された時期に注意。
- [JAMstackってなに？実践に学ぶ高速表示を実現するアーキテクチャの構成](https://eh-career.com/engineerhub/entry/2019/12/10/103000) (2019/12/10)
- [Jamstackとは何か？まずは基本を理解しよう！ - microCMS](https://microcms.io/blog/jamstack-introduction/) (2020/08/07)
- [Next.jsにおけるSSG（静的サイト生成）とISRについて（自分の）限界まで丁寧に説明する](https://qiita.com/thesugar/items/47ec3d243d00ddd0b4ed) (2020/11/11)
- [Jamstackって何なの？何がいいの？](https://qiita.com/ozaki25/items/4075d03278d1fb51cc37) (2020/02/08)