OmniAICreator/Qiita-1.07M huggingface dataset:
asdf で Ruby 3.0.0 をインストールする

*Ruby 3.0.0* がリリースされたので、早速 *asdf* でインストールしてみます。

# 前提
asdf をすでに導入している状態を前提とします。

*asdf-ruby* プラグインを追加していない場合は、
以下のコマンドを実行し追加します。

```shell:shell
asdf plugin-add ruby https://github.com/asdf-vm/asdf-ruby.git
```

# 問題
`asdf list-all ruby` コマンドを実行してみても、
まだ `3.0.0-rc1` までしかリストされていないようです。
(2020/12/26時点)

```shell:shell
..
2.7.2
3.0.0-dev
3.0.0-preview1
3.0.0-preview2
3.0.0-rc1
artichoke-dev
jruby-1.5.6
jruby-1.6.3
..
```


# 解決
下記コマンドでビルドバージョンを指定してインストールします。

```shell:shell
ASDF_RUBY_BUILD_VERSION=v20201225 asdf install ruby 3.0.0
```

# 確認

```shell:shell
# インストールを確認
asdf list ruby
  3.0.0

# グローバルに指定 & shim 再生成
asdf global ruby 3.0.0
asdf reshim ruby


# シェル再起動 or リロード

# バージョン確認
ruby -v
ruby 2.6.3p62 (2019-04-16 revision 67580) [universal.x86_64-darwin20]

# 実体の確認
where ruby
/Users/username/.asdf/shims/ruby

asdf which ruby
/Users/username/.asdf/installs/ruby/3.0.0/bin/ruby

```

無事インストールできました:cat2:

---
Source:
https://github.com/asdf-vm/asdf-ruby
https://github.com/asdf-vm/asdf-ruby/pull/192
https://asdf-vm.com/#/core-commands
[Rails] タイムゾーン情報のない UTC の日付文字列をローカルのタイムゾーン (JST など) に変更する

`2020/01/01 00:00:00` という文字列がある。これを UTC の日付文字列だと解釈してローカルのタイムゾーン、例えば JST の時刻オブジェクトに変換したい。

```rb
Time.zone.name
#=> "Tokyo"
```

以下だと `2020/01/01 00:00:00` のままタイムゾーンが JST に変わるだけ。

```rb
'2020/01/01 00:00:00'.in_time_zone
#=> Wed, 01 Jan 2020 00:00:00 JST +09:00

Time.zone.parse('2020/01/01 00:00:00')
#=> Wed, 01 Jan 2020 00:00:00 JST +09:00
```

そこでこうする！

```rb
time_zone = ActiveSupport::TimeZone.new('UTC')
time_zone.parse('2020/01/01 00:00:00').in_time_zone
#=> Wed, 01 Jan 2020 09:00:00 JST +09:00
```

できた 😉
Xamarin Advent Calendar 2020 まとめ

こんにちは。エクセルソフトの田淵です。

最後の 1日です。ご参加いただいた皆様のおかげで、埋まるか心配でしたが無事埋まりました～！ありがとうございます！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">今年もやります。（埋まるかな？埋まると良いな… <a href="https://twitter.com/hashtag/Xamarin?src=hash&amp;ref_src=twsrc%5Etfw">#Xamarin</a> <a href="https://twitter.com/hashtag/JXUG?src=hash&amp;ref_src=twsrc%5Etfw">#JXUG</a> <br> » Xamarin Advent Calendar 2020 - Qiita <a href="https://t.co/I4mHOFqL6w">https://t.co/I4mHOFqL6w</a></p>&mdash; 田淵 義人＠エクセルソフト (@ytabuchi) <a href="https://twitter.com/ytabuchi/status/1328863464563953664?ref_src=twsrc%5Etfw">November 18, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

最終日が空いたままなので、まとめ記事でキレイに終わりたいと思います笑

各記事は [Xamarin Advent Calendar 2020](https://qiita.com/advent-calendar/2020/xamarin) のページをご覧ください。

記事としては Xamarin.Forms に関する内容が多かったですね。バージョンも [4.8.0](https://github.com/xamarin/Xamarin.Forms/releases) になり、.NET 5 もリリースされました。

[［速報］マイクロソフト「\.NET 5」正式リリース。1つのフレームワークでWindows／Mac／Linuxのデスクトップ、サーバアプリ、Webアプリなどが開発可能に － Publickey](https://www.publickey1.jp/blog/20/net_51windowsmaclinuxweb.html)

当初予定されていた Xamarin との統合は .NET 6 に先送りになりましたが、以下の記事にあるように MAUI がどのようになりそうか？というところはある程度想像ができそうになっています。

- [我々は MAUI で Goodbye Xamarin できるのか？ \- Qiita](https://qiita.com/amay077/items/3442f76cf417c6763da0)
- [Comet で \.NET MVU を先行体験してみる](https://zenn.dev/tan_y/articles/80c1de66d74c52)

Xamarin.Forms は上物なので、.NET 5, .NET 6 になり、MAUI が下回りをある程度は吸収してくれるだろうと思っていますが、既存のプロジェクトがある方はある程度の準備をしておいた方が良いと思います。

Xamarin.Forms 自体は着実に進化を続けており、iOS／Android 共通のコントロールだけでなく、チェックボックスやラジオボタン、カルーセルビューなども標準のコントロールとして提供されています。

これに、Xamarin Essentials や Community Toolkit などもあり、かなりのことを共通化できるようになっています。

- [Xamarin\.Essentials 入門 \- \#1 Xamarin\.Essentials とは \- tafuji's blog](https://tafuji.hatenablog.com/entry/2019/12/23/000000)
- [Xamarin Community Toolkit カタログ（ビヘイビア・コンバーター編） \- Qiita](https://qiita.com/f-miyu/items/98939b750d70cd65d625)
- [Xamarin Community Toolkit カタログ（エフェクト・XAMLマークアップ拡張・コントロール編） \- Qiita](https://qiita.com/f-miyu/items/bb3959645879fd6f6abb)
- [Xamarin Community Toolkit カタログ（MVVM編） \- Qiita](https://qiita.com/f-miyu/items/6c7114bd36a641a226b8)

Xamarin は C# で書けるというところに一番の利点があるプラットフォームですので、チーム、各人のスキルセットに応じて、適材適所で使っていただければ皆さんも Xamarin も幸せなのではないかと思います。

当初の勢いはなくなっているように見えますが、しっかりとアップデートがされていますし、.NET Core と共に進化していくと感じますので、今後も使っていけるプロジェクトに対しては積極的に使っていきたいということで締めたいと思います。

以上です。
Jupyter NotebookでHtml出力できない時


- nbconvertのversionを6未満、例えば5.6.1にすると良いらしい

```shell
conda install "nbconvert=5.6.1"
```

## 参考

- https://github.com/ipython-contrib/jupyter_contrib_nbextensions/issues/1529

    - これは、nbconvert6.0がtemplate_pathをtemplate_pathsに変更したという事実と関係があります。 このプロジェクトが変更されるまでは、nbconvert <6が必要です。(原文:It has to do with the fact that nbconvert 6.0 changed template_path to template_paths. Until this project changes that you should require nbconvert<6.)
社内ISUCON参加した経験から考えるISUCONのコツ

社内で開かれたISUCON(問題は本家の[ISUCON9](https://isucon.net/archives/53789931.html)を使用)に参加してみて、自分なりに考えたISUCONのコツ?について書いてみた。

前回の予習編は[こちら](https://qiita.com/peko858/items/538ef6554e36f680e000)。

## ①モニタリングツールを入れてボトルネックを発見し、まずはインパクトが大きいところから改善

限られた競技時間であることを考えると効率的にスコアを伸ばす必要がある。
これは元々考えていた方針で、過去問会でも本番でもある程度のスコア改善が行えた。

### 発見と改善の実例

1. `GET /user/transaction.json` が特に遅いことがわかる。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91546/225f94c8-a308-2ba7-2b2e-dddf36be60bf.png)

2. 外部サービスへのPOSTが何度も行われていることがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91546/1e27caad-1a20-0658-b8a2-5d792e91a308.png)

3. コードを見ると、ループの中でPOSTが行われておりN+1的に外部APIが実行されていることがわかる。
https://github.com/isucon/isucon9-qualify/blob/34b3e785ebdd97d5c39a1263cbf56d1ae5e3ef91/webapp/nodejs/index.ts#L699

4. キャッシュ化できないかなど考えるが、よく考えたらそもそもこの外部API実行で取得できる結果はDBで腹持ちしていることに気づく。単純に外部APIの実行をなくす。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91546/3790c691-a29a-bd81-23b2-deec01285dd2.png)

5. 修正後、計測ツール上から改善されていることはわかる。（ベンチを回すとスコアは +2000 くらいになっていた）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91546/af7cae98-e375-4b28-e1a6-590b2421b0e7.png)

## ②アプリケーションの性質からあるべき論から修正する
今回のISUCONでは計測ツールからボトルネックを探す方針としていたが、①に書いたようなわかりやすく無駄である実装以外は改善点を見つけることが少し難しかった。

そこで他にどんな修正ができたか[ISUCON9 オンライン予選 関連エントリまとめ : ISUCON公式Blog](https://isucon.net/archives/53789734.html)を読んだところ、あまり労力をかけずにできそうなことがいくつか見つかった。

例えば...

- DBから取得するカテゴリー情報はマスターデータなのでキャッシュ化する
- ログインユーザーの情報はログイン以降再取得する必要がないためキャッシュ化する
- 商品別のユーザー・カテゴリー情報の取得をN+1にせず複数まとめて取得する
- データ量の多いテーブルの絞り込み条件やソート条件のカラムにインデックスを貼る（ORやNULLなど、インデックスが聞かない書き方に注意する必要がある）

この辺りは計測ツールから見つけなくても、あるべき論で考えれば見つけられると思う。
比較的修正も軽微なので、改善インパクトがあまり大きくないとしてもサクッと直すのをコツコツ積み上げれば効率的に確実にスコアが伸ばせそう。

結局のところ、**既存実装を短い時間で読み取って、効率的だが同じ意味に翻訳する**という作業が重要そう。

## 終わりに
小難しい専門知識がなくとも、①②を愚直に行うだけである程度のスコア改善はできると思う。
とはいえ、インフラ周りの改善には一切触れていなく、本家の予選突破ラインとなるともう一押し必要だと思おう。

次回はインフラ周りの改善の知識も少しつけた上で、冷静に速やかに①②を進めることでまた頑張りたい。
【サルが書く】PHP8のunion typesとmixedについて考える

わきゃ！

GIGアドベントカレンダー23日目になります(遅れてすみません！)
GIGメンバーの投稿はこちら👇 から見てみてね！
https://qiita.com/organizations/gig-inc

PHP8がついにリリースされましたね！

そこで気になった新機能であるUnionTypesとmixed型についてまとめてみました。

# 1. UnionTypes

PHP8以前はプロパティ、パラメーター、および戻り値の型に対して単一の型しか宣言できませんでした。
またPHP7.1以降のバージョンではnull許容型があります。
PHP8以前は限定的なUnionTypesしかできませんでした。
ちなみにnull許容で書く場合は型の前に?をつけることでできます。 `例) ?string`

PHP8以前ではPHPDocを使用してのUnionTypesはありました。

```php
class Test {  

 /**  
  * @var int|float  
  */  
  private $test;  

  /**  
   * @param int|float $foo
   * @return int|float  
   */  
  public function square(int $foo): int {  
    return $foo * $foo;  
  }
 }
```

PHP8ではこのように書けるってことですね！
この場合はPHPDocは書くべきなんですかね？
`@param`と`@return`の型についてのPHPDocはいらなくて、メソッドについての説明だけは残すって感じですかね？

```php
class Test {  
  private int|float $test;
  public function square(int|float $foo): int|float {  
    return $foo * $foo;  
  }
 }
```

## voidの扱いについて
voidはUnionTypesでは使用できません。
なので以下のような指定はできません。
`strign|void`

## null許容型について
UnionTypesとnull許容型についてですが
`?int|float`のようには書けず、`int|float|null`のように書きます。

## 型の重複について
`int|float|INT` のように型は重複して書くことはできません。

## false疑似型
falseリテラルの型が、UnionTypesの一部としてサポートされています。
これは内部関数の多くが、失敗時にnullではなくfalseを返すために実装されています。
またこれは単独で使用することはできません。
なので、`false`, `?false`, `false|null`のようなものは使用できません。

## union型と型強制
strict_typesが有効でない場合、スカラー値は暗黙の型変換の対象となります。
例えば `bool|int`に対して`"0"`が渡ったときには`false`と`0`が暗黙の型変換の対象になります。
型変換の優先順位は以下のようになっているので、優先順位1のintへの型変換が働き`"0"`は`0`へ変換されます。

**型変換の優先順位**
`1.int 2.float 3.string 4.bool`

# 2. mixed型
mixed型は以下のunion型と一緒です。
`array|bool|callable|int|float|object|resource|string|null `

最初こんな型があっても宣言しないのと同じじゃんとは考えていましたが、もちろん導入されたのには理由があります。
理由については[こちらの記事](https://qiita.com/rana_kualu/items/4685f2c7693ce0394fe8) で詳しく書いてあるので、ユーザー目線からの意見をまとめました。

## メリット

- mixedと宣言することで、ここはすべての型が入りうるということを注意喚起できる
- すべての場合で型宣言ができるので統一感のあるコードを書くことができる
- 静的解析がやりやすくなる
- 型指定へのハードルが下がる
- リファクタリングの際にmixedをつければ検収済みだというマークになる

## デメリット
- あまり型宣言に精通していない人がコード書いた場合にTypeScriptのanyのように乱用される可能性がある

## mixed型まとめ
メリットもデメリットもありますが、個人的にはmixed乱用はかなり有り得そうな話だと思っています。なので型宣言を適切に行えている前提かつ、miexdを乱用しなくても良い設計を心が得ける必要は出てきそうですね。


## 参考文献
https://www.php.net/manual/ja/language.types.declarations.php#language.types.declarations.union
https://php.watch/versions/8.0/union-types
https://speakerdeck.com/kawanamiyuu/phpkansai-2018-lt-mixed-typehint-dis?slide=20
第八・九回：イコール判別の関数作成



# 目標

assert\_equalを作成する．


# はじめに…

以下のようにassert\_equal.rbを作成する．

```ruby
p 1==1
```

実行すると以下のようになる．

```
$ ruby assert_equal.rb
true
```

1=1は正しいので，trueと出る．


# assert\_equalを作る．

では，以下のように変更する．

```ruby
def assert_equal expected, result
   return expected==result
end

p assert_equal 1,1
```

この場合，括弧は省略されている．

実行すると以下のようになる．

```
$ ruby assert_equal.rb
true
```

次のように変更する．

```ruby
def assert_equal expected, result
   if expected==result
      puts 'true'
   else
      puts 'fasle'
   end
end

assert_equal 1,1
assert_equal 1,2
```

これで実行すると，以下のようになる．

```
$ ruby assert_equal.rb
true
false
```


# 色付け

上記の結果表示でもよいのだが，色を付ける．先ほど作成したassert\_equal.rbを変更する．

```ruby
require 'colorize'
def assert_equal expected, result
   if expected==result
      puts 'true'.green
   else
      puts 'fasle'.red
   end
end

assert_equal 1,1
assert_equal 1,2
```

こうすることで，trueの時は緑，falseの時は赤でそれぞれtrue，falseが表示されるようになる．


# 参考サイト

参考にしたサイトは以下の通り．

-   <https://qiita.com/daddygongon/items/f6cea87314ee26e130ea>



------
 - **source** ~/grad_members_20f/members/yuhsuzu/r8and9.org
【初心者でもわかる】CSSで画像の好きな位置で丸くトリミングする方法

# どうも7noteです。丸くトリミングする方法

画像を配置する際に正方形や長方形の画像を丸くトリミングさせたい時に使える方法です。

本来であれば丸い画像を用意して配置するところを、CSSを使って画像の任意の位置でトリミングできるようにします。

![sample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/c553b728-6750-3a23-7543-0e554ad77d32.png)


## 画像が正方形の場合でトリミング位置を気にしない場合の方法

```index.html
<div class="circle"><img src="sample.jpg" alt="正方形の画像"></div>
```

```style.css
.circle img {
  width: 100px;
  height: 100px;
  border-radius: 50%;  /* 円形にする */
}
```

imgタグに`border-radius`をかけることで丸くなっていますが、正円にしたいときに長方形の画像を使うとこのように画像が潰れてしまいます。なので正方形の画像を用意しましょう。

**潰れてしまっている画像**

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/b5bd2c3b-5ee3-bc50-4a69-3518a30bab66.png)


## 長方形の画像でもposition指定ではみ出した分を非表示にして対応できる

```index.html
<div class="circle"><img src="sample.jpg" alt="長方形の画像"></div>
```

```style.css
.circle {
  width: 100px;
  height: 100px;
  border-radius: 50%;  /* 円形にする */
  position: relative;  /* 基準値とする */
  overflow: hidden;    /* はみ出た部分を非表示 */
}

.circle img {
  position: absolute;  /* 相対位置に指定 */
  top: 0;
  left: 0;
  width: auto;
  height: 100%;
  object-fit: cover;   /* 画像の表示サイズを調整 ※IE非対応 */
}
```

**結果**

![sample3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/0b919735-c7dc-1676-7f89-2ba97436298a.png)

この方法なら画像の好きな位置で好きなサイズにしてトリミングすることができます。

## CSSのbackgroundに画像を入れてトリミング

```index.html
<div class="circle"></div>
```

```style.css
.circle{
  width: 100px;
  height: 100px;
  border-radius: 50%;
  background: url(sample.jpg);
  background-size: auto 150px;
  background-position: center center;
}
```

**結果**

![sample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/bff32abd-aefa-0b2c-1f22-51b6e3b21d39.png)

この方法でも画像の大きさや切り抜く位置が自由自在です。
`background-size`や`background-position`の設定を調整して任意の位置で切り抜くことができます。


ただgoogleのクローラーに画像として認識されないため、重要なワードが含まれているような画像などには使わないようにしたほうが無難です。
SEOとか特にきにしない場合であれば自由につかうことができます！



## まとめ

少しCSSが長くなりますが2つ目の方法が一番綺麗な書き方かなと思います。
SEOを気にしなければ3つ目の方法でもいいかもしれませんね。

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
Windowsで作成したZIPをLinuxで開く

# Windowsで作成したZIPをLinuxで開く

Windowsで作成されたZIPファイルは、文字コードがSJISになっていることが多く、そのまま unzip すると文字化けする。

```bash
unzip -Ocp932 zipfile.zip
```

これで文字化けしないで開ける。
24日目：花火から学ぶエフェクト作成(Unity・Script編)

この記事はアドベントカレンダー「[【VCI】テーマパーク を作ろう](https://adventar.org/calendars/5855) 」の記事です。

# 今回の内容
今回は前回作成した花火のエフェクトを取り込んで行きたいと思います

今回は学ぶ技術は以下となります。
　・Effectを実行する方法
　・ランダム要素のあるスクリプトの書き方

# Unity概要
早速Unityに取り込みます。詳細な手順は以下の公式ページを御覧ください。
　・[Effekseer (VCI対応)](https://virtualcast.jp/wiki/vci/component/sdk/effekseer)
wikiの説明ではエクスポートしたファイルをD&Dする説明になっていますが、
プロジェクトをEffekseer1.5のefkefcファイル形式で作成していれば、efkefcファイルをD&Dしても行けるそうです。
ただし、その場合も画像ファイルの相対パスの維持は必要です。

今回は連続で花火を打ち上げる方式で作成します。
たくさん花火が上がるので他の人と同期はしなくて良いとし、子オブジェクトとしていくつか作成しておきます。
Effect付きオブジェクトを選択した際にSceneの右下にEffect用のパネルが出てきます。こちらで再生して内容を確認できます。
<img width=60% src="https://cdn.discordapp.com/attachments/407897870876934147/793365210836238396/fireworks_1.gif">

# コードの作成
Effectの再生はスクリプトより行います。詳細は以下の公式ページを御覧ください。
　・[Effekseer (エフェクト)](https://virtualcast.jp/wiki/vci/script/reference/effekseer)



上記を参考に作成したコードが以下となります。
花火の間隔と位置をバラけさせるためにmatn.randomを使用しています。

``` lua
--- 次の花火が再生される時間。
local nextExplosionTime = vci.me.Time.TotalSeconds
--- 次のエフェクト再生対象となる花火のNo
local targetFireWorkNo = 1

function updateAll()
  local minute = tonumber(os.date("%M"))
  if minute == illminateMinute and nextExplosionTime < vci.me.Time.TotalSeconds then
    --花火の出現位置をランダムなるように設定
    local x = math.random(-50,50)
    local y = math.random(-20,20)
    local z = math.random(-4,4)

    --アイテムを取得して位置と大きさを設定
    local item = vci.assets.GetTransform("Fireworks "..targetFireWorkNo)
    item.SetLocalPosition(Vector3.__new(x,y,z))
    item.SetLocalScale(2*(Vector3.one+ Vector3.one*math.random(-5,10)/10))

    --エフェクトを取得して再生
    local effect = vci.assets.GetEffekseerEmitter("Fireworks "..targetFireWorkNo)
    effect.PlayOneShot()

    --次実行する花火の番号と実行する時間を設定
    targetFireWorkNo = targetFireWorkNo%20 + 1
    nextExplosionTime = vci.me.Time.TotalSeconds + math.random(1,15)/10
  end
end
```

実際に動かすと以下のようになります。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ちょべりパークに花火がやってきました！٩( &#39;ω&#39; )و<br>記事も書きました！これで後1日分です！٩( &#39;ω&#39; )و <a href="https://t.co/cj3UuStLEN">https://t.co/cj3UuStLEN</a> <a href="https://t.co/yaS7TG3hWx">pic.twitter.com/yaS7TG3hWx</a></p>&mdash; ＃らいと（きょろ、ちょべりば→ぐ） (@lightjug) <a href="https://twitter.com/lightjug/status/1343832028618268672?ref_src=twsrc%5Etfw">December 29, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


# 終わりに 
いかがでしたでしょうか？
今回は花火がいきなり空中に出る方式で作成しましたが、アニメーションやスクリプトで地上から玉を発射してから爆発エフェクトを再生させることも可能だと思います。
次回はRoomの設定を公開について説明します。
form形式でレスポンスを返したい時に使えるオブジェクト指向設計

## 背景

現在開発中のシステムのバックエンドを担当しており、一部のAPIレスポンスを 「form形式で返す」というような実装をしました。この時に用いた設計が汎用的だなと思ったので記事にしようと思いました。

本質的な意味合いは異なりますが、見方によってはデザインパターンでいうアダプタっぽいかなと思っています。正しいかどうかは定かではないです。。

言語はruby、フレームワークはrailsを想定しています。
## 要件

### Testsテーブル

| カラム | 型 |
|:-:|:-:|
| id | int8 |
| first | varchar(255) |
| second | varchar(255) |


上記のようなテーブルがあり、その1レコードを以下のようなJSONレスポンス形式で返したいとします。

```json
{
	"form_items" : [
		{
			"item_name" : "first",
			"value" : "hoge" # firstカラムの値
		},
		{
			"item_name" : "second",
			"value" : "fuga" # secondカラムの値
		}
	]
}
```

実際のシステムではitem_name, valueだけでなくメタデータなどが含まれて複雑な構造になっているのですが、今回は便宜上シンプルな設計にしています。今後カラム数が増えて１つ１つのカラムに対してform_itemsの配列の要素が比例すると想定してください。

### 設計と実装

5つのクラスを用意しました。

3つはFieldを定義するクラスです。抽象クラスとしてFieldBaseクラスを作成しています。

一見なぜこのような設計したか疑問に思うかもしれませんが、カラムとカラムに付随するメタデータが増えることを考えるとこのような設計が無難かなと思いました。

```ruby

class FirstField < FieldBase
  COLUMN_NAME = 'first'
end

class SecondField < FieldBase
  COLUMN_NAME = 'second'
end

class Base
  def initialize(record)
    @record = record
  end

  def value
    @record.send(self.class::COLUMN_NAME)
  end
end
```

4つ目と5つ目はセットで説明します

まず、FormItemクラスではitem_nameとvalueのセットをインスタンスとして保持するために作成しています。具体的には5つ目のクラスを見ればわかると思います。

```ruby
class FormItem
  attr_reader :item_name, :value

  def initialize(field_instance)
    @item_name = field_instance.class::COLUMN_NAME
    @value = field_instance.value
  end
end
```

5つ目はform_itemの配列を作成するクラスです

```ruby
class FormItemList
  attr_reader :form_items

  def initialize(record)
    @form_items = []

    # 以下form_itemの順番がレスポンスとして送るformの順番に直結する
    form_item(FirstField.new(record))
    form_item(SecondField.new(record))
  end

  private

  def form_item(field_instance)
    @form_items += [FormItem.new(field_instance)]
  end
end
```

あとは以下のようにcontrollerで呼び出してあげると、form形式にオブジェクト化されたものが要素となる配列が得られます

```ruby
record = Test.first
form_items = FormItemList.new(record).form_items

pp form_items
# => [FirstFieldインスタンスから作成したFormItemインスタンス, FirstFieldインスタンスから作成したFormItemインスタンス]
```

ここまできたら配列内のオブジェクトをjsonへserializeするだけです。

serializeの方法は色々あるので説明は省きます。

## まとめ

カラム数やメタデータが少ないとあまり恩恵を受けられていないように感じますが、増えた際にカスタマイズしやすいようになっているのがよかったかなと思います！

最近Twitterを始めたので是非フォローお願いいたします！
Qiita投稿を始めて3か月の振り返り。


## 概要
- 10月からQiita投稿を初めて、3か月が経過。3か月間にあった出来事、感じたことをまとめたいと思います。

## 1か月目（10月）
#### 主な出来事
- 初めてのQiita投稿

　初めての記事は[こちら](https://qiita.com/kuro_take/items/8dec9dbce4b0a89a4e90)。初めてLGTMをもらったときは、心臓が5分ぐらいバクバクして嬉しかった。
　投稿を始めた理由は、エンジニアのスキルをあげたい、LGTMを沢山もらって自己肯定感を高めたい、など欲望丸出しの理由です。今思うと、欲望丸出しで始めた結果、トレンド入りすることができました。自分に正直になるのは大切だと実感しました。

## 2か月目（11月）
#### 主な出来事
- 初めてのトレンド入り

　[生命保険](https://qiita.com/kuro_take/items/ad0a696fb680a07882b2)の記事がトレンド入りしました。嬉しくてスクショを取りました。生命保険の苦情件数をまとめた理由は、グラフにして可視化した方がどれが一番苦情が多いのかわかりやすいと思ったからです。
　自分にとって便利でわかりやすいと思ったことが、意外に周りに受けると実感しました。


## 3か月目（12月）
#### 主な出来事
- Qiita Advent Calender 2020に初参加

　Advent Calenderでは10件投稿。Pythonや自然言語処理、湯婆婆といった様々な分野に参加。一番LGTMが多い記事は[湯婆婆](https://qiita.com/kuro_take/items/3ff7d71a9be4a20898e9)。湯婆婆パワーおそるべし。
　Advent Calenderの中で一番のLGTMをもらおうと頑張ったけど、現実は非常なり。上には上がいると実感した12月でした。
 
## 1月からの目標

1月からはいくつかの目標を立てたいと思います。

- トレンド1位にランクイン
- LGTM100達成

## まとめ

　3か月前までの自分がQiita投稿をすると思っていませんでした。
　来月の自分、来年の自分がもっと上のエンジニアになれるのを目標にこれからも投稿を続けていきたいと思います。
　




　日本語として、文章があっているか不安、、、、文章力も磨こう、、、、
YouTube生放送のコメントをニコ動みたいに画面に流れるようにしてみた

タイトル通り、生放送でのコメントが画面に流れるようにしました（こんな感じ↓）
![ニコニコカット_4.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/751408/8deac92b-ef8b-5bb2-744f-eeab93e3648d.gif)


# デバッグ
12/30 20:00 からこれを使った生放送をやろうと思います（1時間くらい）。
お時間ある方はぜひコメントいただけると嬉しいです。

# 仕組み

画面上に、 **透明** で **クリックできない** 画面を **常に最前面** に出しています。
YouTubeの Live Streaming APIで定期的にコメントを取得し、新しいコメントがあればそれを表示するようにしています。
コメントはアニメーションで右から左に流しています。
コメントが流れ終わると、上から詰めてコメントが表示されるようになってます。


# 使った技術

- electron
- React(TypeScript)
- YouTube Live Streaming API
- anime.js

## Electron

Webの技術でデスクトップアプリを作れる技術。
https://www.electronjs.org/

ものすごく簡単にデスクトップアプリが作れます。
今回は、 electron forge という配布、インストール、アップデートなどを良い感じに面倒見てくれるものを使っています。
https://www.electronforge.io/


BrowserWindow の設定項目を見れば、簡単に透明化や常に最前面などを設定することができます。

https://www.electronjs.org/docs/api/browser-window

始め方も

```
yarn create electron-app my-app
```

とめちゃくちゃ簡単に始められます。


## React(TypeScript)

electron は簡単に TypeScript , React を使うことができます。
https://www.electronforge.io/guides/framework-integration/react-with-typescript

超お手軽。


## YouTube Live Streaming API

生放送の情報は下記API
https://developers.google.com/youtube/v3/live/docs/liveBroadcasts

コメントの情報は下記API
https://developers.google.com/youtube/v3/live/docs/liveChatMessages

で取得可能。残念ながらリアルタイムにコメントをくれるAPIはない。
また、コメント取得のAPIがなんと `order` パラメータがないので、並び替えられない（衝撃）。
一度に2000件までデータ取得できるけど、人気YouTuberだと辛い。

また、生放送の情報を取得するには `OAuth` が必要なのも面倒(Service AccountやAPI Keyでは取得できない)。
https://developers.google.com/youtube/v3/live/registering_an_application


なお、APIのクオータは、ここを参照と書いてあるが、リソースにLiveStreamingのリソースが存在しない…
https://developers.google.com/youtube/v3/determine_quota_cost

おそらく無料だと1万回までリクエスト可能。やっすんのような弱々YouTuberなら余裕だが、人気YouTuberだとあまりもたないかも。

## anime.js


JSでアニメーションを簡単に実装できるライブラリ。

https://animejs.com/

今回は、CSSでのアニメーションだとうまく動かず（Reactのリストの追加、削除に引きずられる）、Anime.jsをラップしているという `react-anime` も動かなかった。
https://github.com/hyperfuse/react-anime

仕方なく自分で `anime.js` を使ってコンポーネントを作成しました。

# 最後に

YouTubeの生放送で、コーディングしているとコメントに気づきにくいという問題を良い感じに解決できないかと思っていましたが、作ってみたらすごく良いものになりました。
今はまだ配布できる状況じゃないですが、配布できる状況になったら他のYouTuberさんたちが利用できるようにしたいと思います。
OSSにもしたいなと思ってます。
Locustで合否判定結果をSlack通知する

# 概要

- システムの更新後、都度負荷試験を行っているが、めんどうになったので自動化したい😇
- Locustのheadlessモードを定期実行すれば行けそうだなと思ったので定期実行するlocust_fileを作ってみた

※ごりごりに実装しているだけですが、自分用のメモとして

# 通知内容

![Screen Shot 2020-12-29 at 16.47.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361020/d51f3469-3405-1eef-8cbb-102b24fc6cfa.png)

- 単なる情報は水色で、テスト合格であれば緑で、テスト不合格であれば赤色で通知
- 合否判定は「失敗件数」と「レスポンスの99%ile」
- 合否判定で、どちらかが失敗となったときに`@here`でメンション
    - 性能に問題があるときだけ気付ける！

# 実装

```locust_file.py
from locust import HttpUser, TaskSet, task, constant_pacing, events
import slackweb
import os

class UserTaskSet(TaskSet):
    @task(1)
    def sample(self):
        self.client.get(url="/sample", verify=False)

class WebsiteUser(HttpUser):
    tasks = [UserTaskSet]
    wait_time = constant_pacing(1)

    host = 'http://localhost:8080'

@events.test_stop.add_listener
def test_stop(**kwargs):
    slack = slackweb.Slack(url="<incoming webhookのURL>")

    # テストOKのカラー
    color_success = "#00ff00"
    # テストNGのカラー
    color_failed = "#cc3366"
    # infoのカラー
    color_info = "#99ffff"

    failure_threshold = int(os.environ.get("FAILURE_NG_THRESHOLD", 1))
    percentile_threshold = int(os.environ.get("PERCENTILE_NG_THRESHOLD", 1000))

    for v in kwargs['environment'].stats.entries:
        item = kwargs['environment'].stats.get(v[0], v[1])

        is_failure_ok = item.num_failures < failure_threshold
        is_percentile_ok = item.get_response_time_percentile(99) < percentile_threshold
        mention = "<!here>\n" if not is_failure_ok or not is_percentile_ok else ""

        rps = {
            "title": "rps (info)",
            "color": color_info,
            "text": "{:.1f} r/s".format(item.total_rps),
            "mrkdwn_in": ["text"]}
        failure = {
            "title": "Failure",
            "color": color_success if is_failure_ok else color_failed,
            "text": "{} ( {}% )".format(item.num_failures, item.fail_ratio),
            "mrkdwn_in": ["text"]}
        percentile = {
            "title": "99 Percentile",
            "color": color_success if is_percentile_ok else color_failed,
            "text": "{} ms".format(item.get_response_time_percentile(99)),
            "mrkdwn_in": ["text"]}
        # slack通知を行う
        slack.notify(
            text="{}Load test result of *{} {}*".format(mention, v[1], v[0]),
            attachments=[rps, failure, percentile])
```

# 実装ポイントやドキュメント

- locustのイベントハンドリング
    - https://docs.locust.io/en/stable/api.html#event-hooks
- slack通知（slackweb）
    - https://github.com/satoshi03/slack-python-webhook

あとは`@events.test_stop.add_listener`のメソッドで受け取る`kwargs`で何が取得できるのか`dir()`を使ってひたすら調べました😇
機械学習の実装の勉強の記録⑥（全結合するときはflattenせよ）

#やろうとしたこと
mnistのデータをgzから読み込んだ2次元データを、
全結合して出力する2層モデルを試そうとした。

#失敗したこと
なぞのエラーが発生した。今回はこのエラーの解決方法を、自分の戒めのために記事に残しておく。
>ValueError: Shapes (None, 10, 10) and (None, 28, 10) are incompatible


#処理の流れ
1. [gzデータの読み込み](https://qiita.com/python_walker/items/e4d2ae5b7196cb07402b)
2. 正規化
3. [モデルの作成](https://gist.github.com/oscasierra/cbca3195b8dfc7fdf6795e752cdc8f15)
4. 学習実行

※各処理で参考にしたリンクを付けた

#モデル
入力層：28*28のデータをインプットする。
出力層：全結合してsoftmaxで0～9までの予想値を出力する

loss関数：categorical_crossentropy
最適化アルゴリズム：adam
メトリクス：accuracy（正答率）

#エラー

>ValueError: Shapes (None, 10, 10) and (None, 28, 10) are incompatible

メッセージの意味を調べてみると、どうやら特定のレイヤーにおける入出力データの形が期待しているものと異なる
ということのようだ。



#原因の見つけ方と判明した原因
エラーが発生したときに、model.summary()を実行してみると、
現在のモデルの各層における出力データの形式が分かる。

ここで以下のように、全結合層において期待していた出力データのshapeが異なっていた。
（0～9の予想値をonehot表現で出力することを期待していたため、output shapeは当然(10)となると思った）

こちらの期待：(10)
実際：(28,10)

```
以下model.summary()の実行結果

Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 28, 10)            290       
=================================================================
Total params: 290
Trainable params: 290
Non-trainable params: 0
_________________________________________________________________
```

#根本原因（全結合層に関する一時的な勘違い）
全結合層(Dense)は1次元データを1次元データにして出力する。
ここで、2次元データ(28*28)を全結合層へ入力しても1次元データにしてくれると期待してしまった。
（よく考えたら、畳み込みのモデルでは1次元データに直していたなと後で思い出した。）

#解決
全結合層の直前に、Flattenを追加することで正常に動くようになった。

```
#モデルの構築
model = Sequential()
model.add(InputLayer(input_shape=(28,28)))
model.add(Flatten())
model.add(Dense(10,activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
```
Chrome Remote Desktop をLinuxで使う

Chrome Remote Desktopに限らない話ではあるが、操作する側はクライアントアプリ、操作される側はホストアプリが必要となる。
今回はクライアント側はWindows、ホスト側はLinux（Ubuntu 20.04）を使うことにする。

ホスト側は実機・VMどちらでも可能。GCPのVM上でもこれと同じ方法でリモートデスクトップ接続が出来る。
GCPのVMで行う際は先にUbuntuデスクトップ版をインストールしておく。

# Chrome Remote Desktop Hostをインストール

ホスト側（Ubuntu）に、Chrome Remote Desktop Hostをダウンロードしてインストール。

```bash
$ wget https://dl.google.com/linux/direct/chrome-remote-desktop_current_amd64.deb
$ sudo dpkg --install chrome-remote-desktop_current_amd64.deb
$ sudo apt install --assume-yes --fix-broken
```

これでインストールできた。さらに以下のようにしてユーザアカウントの情報を変更。
（最初に設定する時はこれを忘れ、再起動後、ログインできない現象に見舞われた）

```bash
$ sudo usermod -a -G chrome-remote-desktop $USER
```

ここまでやったら、クライアント側の作業に戻る。

# Chrome Remote Desktop クライアントの操作

https://remotedesktop.google.com/headless?hl=ja

このページから、接続に使いたいGoogleアカウントを選択。ログイン操作などを進めていくと、以下のようにコマンドが表示される。
![設定画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/33225096-23e2-4154-7fa7-8d75a9b7f490.png)


```bash
DISPLAY= /opt/google/chrome-remote-desktop/start-host --code="XXXXXXX_XXXXXXX_-XXXXXXX" --redirect-url="https://remotedesktop.google.com/_/oauthredirect" --name=$(hostname)
```

こんな感じで入れろと出る。
今回はホスト側がUbuntuなので「Debian Linux」の部分のコマンドを、そのままホストとなるUbuntuのコンソールに入力。画面出力をリダイレクトしている。

このコマンドを入力すると、「Enter a PIN of at least six digits」と最低6桁のPIN入力を求められる。
設定して忘れないようにしておく。

# 接続

改めて[Chrome Remote Desktopのページ](https://remotedesktop.google.com/access)にクライアント側から入ると、以下のように表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/3836ed5e-875a-0cfe-494c-a1709bf7ac63.png)

初回接続時は先程求められたPINの入力が求められる。
設定したPINコードを入力し、リモート接続成功。

# トラブルシューティング

経験したトラブル。

## Chrome Remote Desktopから入るとsudoを受け付けない

これはGCP上のLinux VMにリモートデスクトップで入った時の経験。

GUI上のTerminalからsudoコマンドを実行しようとした際、

```bash
(ユーザ名) is not in the sudoers file.  This incident will be reported.
```

と出て拒否されるが、GCPのコンソールからやると通る。

```bash
$ sudo usermod -G sudo $(whoami)
```

GCPのコンソールからユーザを追加。

```bash
$ sudo cat /etc/group
```

このあと一度ログアウトし、再ログインし直せば、GCPのVM上でsudoが出来る。

## 再起動後にChrome Remote Desktopが接続できない

GCP上の出来事。

sshからreboot後、VMインスタンスは立ち上がったようだが、Chrome Remote Desktopが動かない現象が発生。

![再起動後にリモートデスクトップ不可.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/915263/3e75da1e-4977-3533-b16e-1fb309815aa8.png)

こんな感じ。

```bash
$ sudo systemctl status chrome-remote-desktop
```

確認するが問題なし。Activeになっている。

```bash
$ sudo usermod -a -G chrome-remote-desktop $USER
```

このコマンドを忘れていた。

## パスワードを求めるダイアログが頻繁に出る

VMでも実機でも発生。
以下のようなダイアログが頻繁に出て、うざい。

- カラープロフィアルを作成するには認証が必要です
- カラーマネージメントされたデバイスを作成するには認証が必要です
- Authentication is required to refresh the system repositories

これについては独立した記事を書いたのでそちらを参照してほしい。
[Linuxにリモートデスクトップで入った時に出るダイアログを消す](https://qiita.com/HirumaT/items/36a7209814a157f62cec)
【Qiita】画像の大きさ調整を少しだけ楽にする方法

## 前提 : Qiitaのマークダウンで画像のリサイズは出来ない

Qiitaに画像をアップロードすると、マークダウン形式のテキストになってくれます。

```markdown
![image.png](sample.png)
```
執筆者としては**記事を読みやすくするため**に適切なリサイズをしてあげたいのですが、**[Zenn](https://zenn.dev/ohbashunsuke)(Qiitaのような技術系SNS)**と違ってQiitaのマークダウンは**画像サイズのリサイズ機能はありません**。

```markdown
![image.png](sample.png =450x)
```
Zennでは上記のようにマークダウン上で画像のリサイズが可能です。


## imgタグを使って画像のリサイズ

仕方が無いので`imgタグ`を使ってリサイズすることになります。
**※リサイズした画像をアップロードする方法もありますが、効率が悪いので非採用**

```html
<img src="sample.png" width=450 />
```


## 課題 : 置き換え作業がめんどい

画像を沢山アップロードした記事では、imgタグに置き換えるのが非常にめんどいです。手動作業にはオペミスが付きもので、更に時間がかかります。ただ画像の大きさを変えたいだけなのに。

という事で、本記事では**少し楽**をして画像の大きさ調整をする方法を紹介していきます。


## 条件

- 無料でやりたい
- わざわざプログラムを書いて実行したくない

テキストエディタAtomを使用します。

## 正規表現で一括変換

ショートカット`⌘+F`で`Find in Buffer`(検索窓)を開きます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/c08f6a7c-3dcc-14ac-842d-baa98840ac47.png" width=450 />
このように設定します。

### 置き換えパターン

```
\!\[.*\]\((.*)\)
```

### 置き換え文字列

```html
<img src="$1" width=450 /> 
```
※450のところは適宜サイズを設定



## デモ

置き換えたい文字列をエディタにコピペして`Replace All`します。

![Dec-29-2020 16-31-38.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328771/98186119-c4fb-d336-1214-01c6e4ea2512.gif)

テキストをコピペする一手間はありますが、一括で置き換わって便利。

## 最後に

Atomでなくとも、正規表現機能をもつエディタであれば可能です。たまたま手元にAtomがインストールされていたので採用したに過ぎません。

Qiita上で正規表現を実行できるようにすれば更に効率は上がりそうですが、とりあえずエディタを通した文字列置き換えでも、かなりの効率化が図れそうです。

## 参考

- [執筆したいメディアが豊富な今だからこそMarkDownでネタを書き溜めてコンパイルするだけにしちゃおう！ - Qiita](https://qiita.com/ohbashunsuke/items/5307e0b05429178c89f0)
機械学習の実装の勉強の記録⑤（MNISTのオリジナルデータの読み込み）

#やりたいこと
オリジナルデータから読み込み、そのデータをkerasで扱う方法を勉強しておきたい。

##理由
MNISTデータを準備する方法として、下記のようにkeras.datasetsからの読み込む方法は最初の学習用としては良いが、
それだとデータの読み込みや前処理に関しての理解が深まらない。
オリジナルデータから読み込んでそのデータをkerasで扱う方法を勉強しておきたい。
以下はkerasから読み込む場合の方法。
なお、kerasのデータセットについては[こちらの記事](https://qiita.com/fktm/items/376ccfaf8cf543376b82)で触れた。

```
from keras.datasets import mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()
```

#MNISTのオリジナルデータについて
##データの入手先
以下のヤン・ルカンのサイトにMNISTのオリジナル（多分？）データが置いてある。
http://yann.lecun.com/exdb/mnist/

##データの拡張子
上記サイトにおいてあるデータは、gzで圧縮されている。
gzだからと言って、7zipで展開してもただのバイナリファイルとしてしか解凍できない。

##データのフォーマット
上記のサイトの下の方に「FILE FORMATS FOR THE MNIST DATABASE」というタイトルで
バイナリファイルののフォーマットが説明されている。
このフォーマットはとりあえずは読んでふーんと思っておけばよい。

##オリジナルデータの読み込み方法
実際には先人たちがその読み込みの実装方法を紹介しているため、
[こちらの記事](https://qiita.com/python_walker/items/e4d2ae5b7196cb07402b)を参照
Windowsのバッチファイルで、管理者権限で実行を促すシンプルなコマンド例


```sample.bat
@echo off
openfiles >nul 2>&1
if errorlevel 1 (
    echo "管理者権限で実行してください。"
    pause
    exit
)
:: これ以降に処理を書く
echo "管理者権限OK"
pause
```

- `openfiles`は、管理者権限が無い場合失敗し、`%errorlevel%`に`1`が入ります。画面に出ないよう表示は捨てています。
- その次の`if`構文により、管理者権限が無い場合メッセージを表示し確認後、終了します。管理者権限がある場合、以降の処理に進みます。

`if`構文については、「`if /?`」でヘルプ見れるので、応用したい方は見てみてください。
`%errorlevel%`としなくても、専用の命令が用意されているので、それを使っています。
また、コマンドプロンプトは大文字小文字区別されませんが、基本大文字なので、気になる人は大文字で記述してください。
強制的に昇格ダイアログ出す方法も、あるにはあるようですが、vbs を使ったりするので、これが一番シンプルだと思います。


かなり参考にさせて頂いたリンク（ほぼ、そのままコピペに近い）

バッチファイルが管理者権限で動作しているか確認 - 有限会社ルートリンクス
https://www.rootlinks.net/2014/08/28/%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%81%8C%E7%AE%A1%E7%90%86%E8%80%85%E6%A8%A9%E9%99%90%E3%81%A7%E5%8B%95%E4%BD%9C%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E7%A2%BA/

【バッチファイル】管理者権限が無い場合に付与して実行 - Qiita
https://qiita.com/YamEiR/items/7f2734510544090611db
タスクスケジューラが時間遅延で起動しない

# 前置き
Windowsのタスクスケジューラのタスクが、手動で実行すると起動するのに、自動だと起動しないという不具合に悩まされて直った話。

ネット上で報告されているのは、カレントディレクトリが指定されていないと自動起動しないという謎現象。
この方は、カレントディレクトリを、「開始（オプション）(T)」に指定するとなおったらしい。

【タスクスケジューラ】手動では起動するのに、設定したタスクだと起動しないタスクを起動できるようにする方法 - pyonsupyonsu’s blog
https://pyonsupyonsu.hatenablog.com/entry/2019/02/02/201139

# 遭遇した現象と解決方法
こちらの環境は、「メインのWindows」と「時刻同期用のLinuxのNTPサーバ」があり、共にバックアップ電池が内蔵されておらず、時計が保持できません。
この子たちは起動時、Windowsの時計は2018年、NTPサーバ側の時計は2016年になります。
WindowsからNTPサーバにアクセスする周期は1分程度（2^6=64秒）にしています。
Windowsには自動ログオン設定がしてあり、起動したいタスクの起動トリガは「ログオン時」「遅延1分」です。
これで、何故か起動しない。

結果的に、以下のような挙動しているようです。

- Windowsは起動時、2018年になっている
- Windowsがログオン直後にNTPクライアントが動いて2016年にセットされる
- 時間巻き戻りにより、内部的に1分間が経過せず、起動しない

なので、date コマンドで日付を2020年にしてやると、即座に起動します。


# まとめ

- タスクスケジューラの「ログオンから1分後」というのは、どうやら単調増加時間ではなく、絶対時刻！
gem Fakerでリアルなダミーデータを作るよ

### 何をしたか
Railsの課題を実施しています。アウトプットを何かするまでが課題なのですが...。
スクールを卒業して以来、１回も触っていなかった、gem `Faker`が出てきたので、こちらについて、使用方法をまとめたいと思います。

尚、実行環境は下記の通りです。

- `Rails 5.2.3`
- `Ruby 2.6.0`

### 導入方法

まずは[公式の情報](https://github.com/faker-ruby/faker)の確認から。[公式のノート](https://github.com/faker-ruby/faker#note)によると、

- デフォルトではユニークなデータを生成するとは限らないから、ユニークなデータが欲しい時にはオプションをつけてね。
- `master` ブランチには、まだリリースされていないデータが含まれることがあるから、利用可能なメソッドはREADMEで確認してね。

とのことだそうです。了解ですー

インストールはとても簡単で、Gemfileに以下を記入し、

```Ruby:Gemfile
gem 'faker'
```
`bundle install`で完了です:relaxed:

### 早速試す

Fakerで生成できる要素は、[こちら](https://github.com/faker-ruby/faker#generators)に一覧がありました。コンソールで早速色々実験してみます。

```
> Faker::Dessert.variety
=> "Upside Down Pineapple Cake"
> Faker::Address.city
=> "千葉市"
> Faker::Address.street_name
=> "真央"
> Faker::Address.zip
=> "191-3257"
> Faker::Address.street_address
=> "73696 桜"
> Faker::App.name
=> "Alpha"
```
システムのタイムゾーンを東京、デフォルトの言語を日本語にしているためか、日本語のデータにも対応してくれていますね:relaxed:

### Seedファイルを作る

では、コレで早速Seedファイルを作っていこうと思います。

```Ruby:db/seeds.rb
5.times do
  user = User.create!(
    username: Faker::JapaneseMedia::StudioGhibli.character,
    email: Faker::Internet.email,
    password: 'foobar',
    password_confirmation: 'foobar',
  )
  puts "\"#{user.username}\" has created!"
end
```

`password`と`password_confirmarion`を同じデータにする方がわからなかったのと、ランダムなパスワードが生成されたら、ログインがしにくくなってしまい開発環境では不便なので、`username`と`email`だけFakerで生成することにしました。名前にジブリキャラの名前を採用しているのは、趣味です:grin:

最後に`puts`を利用して、出力されるキャラクターの名前を書き出しています。
上記の結果、出力された文字列は下記の通り。

```
"Donald Curtis" has created!
"Chihiro Ogino" has created!
"Yupa" has created!
"Yupa" has created!
"Haku" has created!
```

おお。ユパ様が２人作られてしまった。。。。

### ユニークなデータを作る

同名の人が２人いるのはややこしいので、`username`の部分は、下記の通り書き換えました。

```Ruby:db/seeds.rb
# 抜粋
username: Faker::JapaneseMedia::StudioGhibli.unique.character,
```

`unique`オプションをつけると、デフォルトでユニークなデータが生成されるようになります。
DBをリセットして、もう一度`rails db:seed`を実行すると。。。

```
"Traveling Soot" has created!
"Lettie Hatter" has created!
"Jhil" has created!
"Mr. Piccolo" has created!
"Haku" has created!
```
今度はユニークなユーザーが作成されました＾＾

### 最終的なファイル

最終的なファイルは、以下のように書き換えました。どのテーブルのデータが読み込まれたのかわかりやすくなっています。

```
db 　# 関係あるファイルだけ表示
├── seeds
│   ├── users.rb
│   └── posts.rb
└── seeds.rb
```

```Ruby:db/seeds.rb
require './db/seeds/users'
require './db/seeds/posts'
```
```ruby:db/seeds/users.rb
puts 'users ...'
5.times do
  user = User.create!(
    username: Faker::JapaneseMedia::StudioGhibli.unique.character,
    email: Faker::Internet.email,
    password: 'foobar',
    password_confirmation: 'foobar',
  )
end
```
```ruby:db/seeds/posts.rb
puts 'posts ...'
User.limit(10).each do |user|
  user.posts.create!(body: Faker::Hacker.say_something_smart,
    image: "https://picsum.photos/350/350/?random")
end
```
以上で、実装はおしまいです＾＾

### 感想など

以前、こちらの記事（『[Rails環境ごとにSeedデータ切り替えるseeds.rbの書き方](https://blog.cloud-acct.com/posts/u-rails-user-seeddata/)』）を読んで、「読み込んだデータの情報が出力される書き方が便利だな」と思っていたのですが、

今回カリキュラムで同じ書き方がされていて、「あ、コレって普通に使われている書き方なんだ:grinning:」と認識できました。
個人的には、`create`ではなく`create!`にして、エラー内容を出力させる書き方がお気に入り:relaxed:

とにかくにも、スクールを出て以来一度も触っていなかった`Faker`にまた出会えてよかったです:grinning:
今度は、やり方をしっかり把握できたので、またダミーデータの生成に使っていきたいです:star:
「Webpacker::Manifest::MissingEntryError」対策

#はじめに
Rails　「Webpacker::Manifest::MissingEntryError」エラーの対策について、
備忘録として投稿します。

#開発環境
・cloud9
・Rails 6.1.0

#エラー内容
```ruby:application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Myapp</title>
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>
```
上記で「rails s」でサーバーを立ち上げた際に、「**Webpacker::Manifest::MissingEntryError**」
エラーが出た。
色々調べると、webpackerを使う際は下記コードが要らないらしい。

```ruby:application.html.erb
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
```

**javascript_include_tag**はSprockets経由で読み取るので、
webpackerを使う際は下記の**「javascript_pack_tag」**を使う必要がある。

```ruby:application.html.erb
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```
ただ、上記に変更してもエラーは解消せず、現在は上記コードを削除して使用しています。
恐らくjavascript_pack_tagの書き方に問題があるので、そこを重点的に調べて解決策を
見出せればと思います。
JavascriptでブラウザからAsia/Tokyoのようなタイムゾーン名を取得する方法

以下のような感じに取得できる。

```javascript
const tz = Intl.DateTimeFormat().resolvedOptions().timeZone
console.log(tz) // 東京のブラウザで実行するとAsia/Tokyoが表示される
```

Intlからは、タイムゾーンだけでなく、言語など、国際化に関連したAPIを他にも利用できるらしい。

参考
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl
https://stackoverflow.com/questions/6939685/get-client-time-zone-from-browser
ドライバがSeleniumのテストでPOSTしたくなったらドライバをRack::Testに変える

## 結論

[`Capybara.current_driver=`](https://rubydoc.info/github/teamcapybara/capybara/master/Capybara#current_driver=-class_method)というメソッドを使うとテストの途中でもWebDriverを切り替えられる

## 問題

CapybaraのドライバにSeleniumを用いたWebDriverを指定してfeature specを実行すると、WebDriverを通じて実際にブラウザを動かしてテストできる。

OAuth認可サーバをテストでのアクセストークンの取得のように、ブラウザで操作したあと、さらにAPIコールすることで完結するシナリオをひとまとまりのexampleにしたいことがある。しかし、実際のブラウザと同じで、いきなりPOSTやPUTをリクエストとして発行できない。


## 解決策

exampleの途中で`Capybara.current_driver=`を使ってWebDriverを`:rack_test` ([Rack::Test](https://github.com/rack/rack-test))に切り替えると、Rack::Testは各種HTTPリクエストを発行できるメソッドを持つので、exampleの中でPOSTやPUTを発行できる。

```ruby:spec/rails_helper.rb
Capybara.default_driver = :selenium
```

```ruby:spec/features/authorization_spec.rb
# `js: true`を指定したテストなので最初はドライバが`:selenium`になっている
# cf. https://github.com/teamcapybara/capybara#using-capybara-with-rspec
scenario '利用者が認可してクライアントがアクセストークンを取得する', js: true do
  # ブラウザ操作を書く
  visit oauth_authorization_path
  fill_in id: 'id', with: id
  fill_in id: 'password', with: password
  click_button 'ログイン'

  # ...

  # ここでは`page.driver.post`はNoMethodErrorを投げる

  # ドライバをRack::Testに変える
  Capybara.current_driver = :rack_test

  # pageから引けるRack::Testドライバのオブジェクトが
  # 各種HTTPメソッドを持つのでPOSTを発行できる
  page.driver.post oauth_token_path # ...

  # ...
end
```
CircleCI コードチェックしHerokuへ自動デプロイする方法

# はじめに

本記事は以下を読んでいることを前提に作成しました。
[Github の masterブランチへ commit が行われたら CircleCI に Heroku へのデプロイを実行させる](https://qiita.com/NaokiIshimura/items/a897fba536caa4dd3338)

本記事はCircleCIを用いてHerokuとのCI/CDパイプラインを構成する方法について自分用も兼ねて解説していきます。
基本的に公式ドキュメントを参考にしたので、こちらも合わせて読んでみるのをおすすめします。

[デプロイの構成](://circleci.com/docs/ja/2.0/deployment-integrations/#heroku)

# 開発環境

Ruby 2.6.5
Rails 6.0.0
Bundler 2.1.4
MySQL 5.6.50

# HerokuへのCI/CDパイプラインを構築

Herokuのアプリをセットアップしてあることが前提になりますので、まだの方は[こちら](https://devcenter.heroku.com/start)を参考にして、Herokuに手動でプロイしてから、行いましょう。

## 1)環境変数の追加

CircleCIで自動でプロイするためにHerokuアプリケーション名と、Heroku APIキーを環境変数として追加します。(CircleCIでの環境変数の設定は[こちら](https://circleci.com/docs/ja/2.0/env-vars/#%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A7%E3%81%AE%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0%E3%81%AE%E8%A8%AD%E5%AE%9A))
以下、アプリケーション名を`HEROKU_APP_NAME`、Heroku APIキーを`HEROKU_API_KEY`という変数名で扱います。

`HEROKU_APP_NAME`はherokuにデプロイしているアプリ名を代入します。
`HEROKU_API_KEY`はターミナルにて以下コマンドを実行したときの値を代入します。

```ruby:ターミナル
アプリ名 % heroku auth:token
xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx
```
出力されたものを全てコピーし、Circleci上に環境変数として設定します。

## 2)git pushでmasterブランチを自動デプロイ

以下がそのコードである。

```ruby:.cricleci/config.yml
deploy:
    docker:
      - image: buildpack-deps:trusty
    executor: heroku/default
    steps:
      - checkout # push/mergeされたコードのチェック
      - run:
          name: Heroku への master のデプロイ
          command: |
            git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git master
```

このコードを書くことでコードをチェックし自動デプロイを実行してくれる。

## 3)workflowの設定

```ruby:.cricleci/config.yml
workflows:
  version: 2.1
  build-deploy:
    jobs:

      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: master
```

公式ドキュメントではカスタマイズも可能だが初心者の僕はその領域には達していないため、まずはパイプラインを組むことを目標に用意されているワークフローを使用しました。

### 完成コード

```ruby:.circleci/config.yml
version: 2.1
orbs:
  ruby: circleci/ruby@0.1.2 
  heroku: circleci/heroku@1.2.3
jobs:
  build:
    docker:
      - image: circleci/ruby:2.6.5-stretch-node
    executor: ruby/default
    steps:
      - checkout
      - run: gem install bundler -v 2.1.4
      - run:
          name: Which bundler?
          command: bundle -v
      - ruby/bundle-install

  deploy:
    docker:
      - image: buildpack-deps:trusty
    executor: heroku/default
    steps:
      - checkout
      - run:
          name: Heroku への master のデプロイ
          command: |
            git push https://heroku:$HEROKU_API_KEY@git.heroku.com/$HEROKU_APP_NAME.git master

workflows:
  version: 2.1
  build-deploy:
    jobs:

      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only: master
```

これでHerokuとのCI/CDパイプラインを結ぶことができた。

![4201a35bf1d8f48736248ac20ee8fe56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/879778/4ca83f6b-14c0-3e84-b5ea-ac1b05653a6e.png)

しっかりと`build`の下に`deploy`が表示されている。
この書き方は、あくまで初級編のため、RSpecによるテストの実行までは記述していないが、そういう記述もできることを頭に入れておいてほしいと思います。
deviseでユーザー情報の編集ができない！〜update_resourceしたらココを見よう〜

ユーザー情報の更新ができない＆バリデーションで止められるというエラーが起こった。


前提として、ユーザー情報の更新にパスワード入力を省くために以下を追記した。

```
registrations_controller.rb
def update_resource(resource, params)
    resource.update_without_password(params)
  end
```


しかし、以下２つの原因から更新できなかった


## devise_parameter_sanitizer
:sign_upのときだけになっていたことが原因。
:account_updateを以下のように作成

```
application_controller.rb
def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:email, :nickname])
    devise_parameter_sanitizer.permit(:account_update, keys: [:email, :nickname])
  end
```

 
## モデルのバリデーション

以下のpresence: true によって「can’t be blank！」と警告された。

```
users.rb
with_options presence: true do
    VALID_PASSWORD_REGEX = /\A(?=.?[a-zA-Z])(?=.?\d)\w{6,}\z/.freeze
    validates :nickname,length: { maximum: 12 }
    validates :password, format: { with: VALID_PASSWORD_REGEX, message: '半角6文字以上で英字と数字の両方を含めて設定してください' }
  end
```

以下のように記述を変更

```

with_options presence: true do
    VALID_PASSWORD_REGEX = /\A(?=.?[a-zA-Z])(?=.?\d)\w{6,}\z/.freeze
    validates :nickname,length: { maximum: 12 }

    with_options on: :create do
    validates :password, format: { with: VALID_PASSWORD_REGEX, message: '半角6文字以上で英字と数字の両方を含めて設定してください' }
    end
  end
```


補足
on: :create(コントローラーのcreateアクションの時のみ動作する様にするオプション)

これにより、create（ユーザー情報変更時）は空欄でもOKになった！
Pure JS数行で、フェードインのスクロールボタンを実装しよう

## このテーマについて書こうを思ったきっかけ
jQueryを使えば、巷にはたくさん参考記事があるが、「jQuery」を使いたくない場面もままある。
そんな時に参考になる記事が少なく、手間取ったため、ここに記事を書くことになった。

## 実装する前に、実装イメージを
シンプルに考えれば、例えば画面を100pxスクローしたときにフェードインさせるためには
ボタンとなる要素において、
・出現用のクラスをスクロール量が100pxを超えた時につける
・出現用のクラスをスクロール量が100px未満の時に外す
・出現用のクラスにopacityが1のCSSを記述
・出現用のクラスがついていないとき、opacityが0のCSSを記述
すれば、実装できそうである。

## 実装してみる
上のプロセスで実装できた！
![スクリーンショット 2020-12-29 16.11.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411851/4e07ccb2-e98d-fa6c-bc3d-7b302c968b69.png)
![スクリーンショット 2020-12-29 16.11.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411851/ff4b08b5-a8ae-c551-01ea-43a6c0302532.png)



```html:html
<div href="" class="arrow-for-scrolling-top" id="js-scroll-top">
    <span class="arrow"></span>
</div>
```

```css:css
div.arrow-for-scrolling-top {
    opacity: 0; /* 完全に透明 */
    transition: 1s; /* ゆっくり透明にする */
    -webkit-transition:1s;
    -moz-transition:1s;
    -ms-transition:1s;
    -o-transition:1s;
    background-color: #0367d6;
    color: #fff;
    position: fixed;
    bottom: 10px;
    right: 10px;
    display: block;
    width: 40px;
    height: 40px;
    border-radius: 50%;
    -webkit-border-radius: 50%;
    -moz-border-radius: 50%;
    -ms-border-radius: 50%;
    -o-border-radius: 50%;
}
div.arrow-for-scrolling-top.show {
        opacity: 1; /* 完全に出現させる */
        transition: 1s; /* ゆっくり出現させる */
        -webkit-transition: 1s;
        -moz-transition: 1s;
        -ms-transition: 1s;
        -o-transition: 1s;
}
span.arrow {
        width: 10px;
        display: inline-block;
        height: 10px;
        border-top: 1px solid #fff;
        border-left: 1px solid #fff;
        position: absolute;
        top: 56%;
        left: 50%;
        transform: translate(-50%, -50%) rotate(45deg);
        -webkit-transform: translate(-50%, -50%) rotate(45deg);
        -moz-transform: translate(-50%, -50%) rotate(45deg);
        -ms-transform: translate(-50%, -50%) rotate(45deg);
        -o-transform: translate(-50%, -50%) rotate(45deg);
}
```

```js:js
  const PageTopBtn = document.getElementById('js-scroll-top')
  // 以下で、「ボタンをクリックした時に、画面トップに移動させる」を実現
  PageTopBtn.addEventListener('click', (e) => {
    window.scrollTo({
      top: 0,
      behavior: 'smooth'
    })
  })

  // 以下で、「スクロール量によってクラスのつけはずし」を実現
  window.addEventListener('scroll', function () {
    const y = document.documentElement.scrollTop // get the height from page top
    if (y < 100) {
      // スクロール量が100未満の時、ボタンの「show」というクラスを外す
      PageTopBtn.classList.remove('show')
    } else if (y >= 100) {
      // スクロール量が100以上の時、ボタンに「show」というクラスをつける
      PageTopBtn.classList.add('show')
    }
  })
```

できましたかね？
お疲れ様です！！
ご要望、ご質問などございましたら、
[Twitter](https://twitter.com/facultyoflaw11)
こちらにお願いします！
Managed Workflows for Apache Airflow (MWAA)でAirflowコマンド実行

ただのメモシリーズ

MWAAのAPIで環境のリスト

```bash:
$ aws mwaa list-environments
{
    "Environments": [
        "demo-env",
        "demo-env-2"
    ]
}
```

MWAAへのAirflowAPIでAirflowバージョン取得

```bash:
$ export WEB_SERVER_HOSTNAME="<MWAA Airflow UI Name>"
$ export CLI_TOKEN=`aws mwaa create-cli-token --name <MWAA Env Name> | jq -r .CliToken`
$ curl --request POST "https://$WEB_SERVER_HOSTNAME/aws_mwaa/cli" --header "Authorization: Bearer $CLI_TOKEN" --header "Content-Type: text/plain" --data-raw "version" | jq -r .stdout | base64 –d
1.10.12
```

>CreateCliToken
AmazonMWAA環境でのApacheAirflowオペレーションのAWSCLIリクエストを認証するために使用されるトークンを作成します。

https://docs.aws.amazon.com/mwaa/latest/userguide/access-airflow-ui.html#CreateCliToken

#### Airflow CLI

https://airflow.apache.org/docs/apache-airflow/1.10.12/cli-ref.html
【M5StickC-Plus】×【UIFlow】HttpRequestが飛ばなかったのを解決した話

前回、kintoneにレコード登録することに成功しました。
→https://qiita.com/juri_don/items/97824bc435564acc20fb

が、一時的に動かす（デバッグモードのような？）Runでは動くのに、
M5StickC-Plus（以下、デバイス）にダウンロードした場合は動かない(TдT)
なんでなんで～～～となっていました。

StatusCodeすら取れなくてディスプレイ真っ赤w
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/9709ae5c-85f1-b5a7-acac-475d25ae091c.png" width=200px>

そんな顔真っ赤にして起こらなくてもいいじゃん👀
（って、駄目だったら赤くするとプログラミングしたのは私だけど）

# 原因はなんだ！

## StatusCodeが返ってこない

私は考えました。考えていたら少し意識を失っ（昼寝）・・・ってしまいました。
目が覚めてからも考えました。

StatusCodeが400とかなんか表示されたりしたらわからないじゃないか・・・。

まてよ、StatusCodeが取れてないということは、HttpRequest自体が送れてないってことやん👀

そう、大切なことに気づいたのです。

StatusCodeって、HttpRequest送った結果のコードなので、
HttpRequestが送れてない場合はそもそもCode自体返ってこないのです。

## ネットワークはつながっているのか！？

SetupブロックにWifiと接続しているを表示をセットしてみると・・・
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/50043745-cc7a-e63a-9ad6-1d477957cb22.png)

↓False! やっぱりね😨

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/15469537-66aa-4867-ad9e-71741c15b63e.png" width=300px>


## Wifiにつなげる

どのブロックでつながるのか探した結果、

wifi connect？
たぶんこうすればいい（野生の勘）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/a6b113e4-fc83-b8bc-cc02-19ee28706022.png)

↓True! つながった！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/1ebc2863-5a1a-d1b6-5d61-22f60e046123.png" width=300px>

↓キタ！

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/62f577d2-93d8-fbfc-a4b5-a96a744ed795.png" width=300px>

# プログラム
kintoneにHttpRequest投げつつ、LINEにもHttpRequest投げています。
kintoneの方は前回記事にしたので、LINEの方。こんな感じ～。日本語文字化けするのでエンコードしなきゃいけない感じ。
（どのブロックを使えば良いんだ問題）

LINE Notifyを使ってますが、それについてはググってね👀

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/16c7dd1e-c7fb-b7d3-bca0-5e13e6a0f8c4.png" width=700px>

# まとめ
M5StickC-PlusxUIFlow初心者な私がハマったところについて書いてみました。
M5Stackシリーズ全般の初心者にがハマるハマリポイントだったりして👀？