OmniAICreator/Qiita-1.07M huggingface dataset:
Autify community Meetup #9 イベントレポート

こちらは[Autify Advent Calendar](https://qiita.com/advent-calendar/2022/autify) 23日目の記事です。

12/22に、コロナ以降初めてのオフラインでのCommunity Meetupが開催されました！
私も直接多くのお客様に会う機会があまりなかったので、今日のイベントをとても楽しみにしておりました。

https://autifyjapan.connpass.com/event/268839/

Community Meetup#9のアジェンダはこちらです。

- 自己紹介
- 2022年こんなことに取り組みました
- 今年リリースのお役立ち機能
- Autify機能ロードマップ
- コミュニティのこれから

Autifer(Autifyユーザ様）な方々、続々と集まってきております...!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532308/5bf3df1b-b890-cc4e-7a80-073a844c22af.png)


## まずは自己紹介
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532308/24dfc263-f5af-9f15-6e1e-6bd30e76651d.png)

まずは自己紹介です。
会社、お名前、役割、好きな〇〇についてなど、テーブルに分かれてお話しいただきました！
アイスブレイクもバッチリです👍

最近使い始めたお客様、猛者な方など様々なAutiferな皆様がいらっしゃり、遅い時間にも関わらず16名にご参加いただきました🙌

## 2022年取り組んだこと

最初のトピックはこちらです。
- QA/テスト自動化に取り組む皆様の「2022年の大きな取り組み」と「個人的一大イベント」
- 来年取り組みたいこと

### 今年の取り組み、一大イベントは？
- QAになった。Autifyのテスト結果が失敗したまま放置されていたが、リリースする前にAutifyが回り成功するサイクルを作った。
- 一旦Autifyを止めている。テスト仕様書、テストシナリオ書き換えている途中です。
- 自分のチームができた。マネジメントむずかしい...。
- 自分のチームにAutifyのスケジューラーが稼働した。
- 新卒なので社会人になった。チームとしてAutifyテストを開始した。一人暮らし始めて楽しい。
- Salesforceのテストに取り組み中。

### 来年取り組みたいことは？
- 来年は自分も含めもっとみんな外に出てコミュニティイベントに参加してほしい。
- Autify使いすぎてコストが気になっている。ちょっと整理と使い方を見直した方がいいかも。 (👀
- もっとAutify活用したい！
- Figmaテストできないかな。
- ビジュアルリグレッションテストをやりたいと思っている。
- 来年の機能追加お楽しみにしてください！(当社エンジニア）


## 今年リリースされたお役立ち機能 

続いて、今年リリースされた機能で役に立ったものは？というお題です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532308/4bda0779-ed7b-f0f7-ba3b-7f8351b45607.png)

### 今年リリースされたお役立ち機能
- JSステップの戻り値がテスト結果で見れるようになった。
- ベータ版で出ているクイック要素更新機能、超うれしい！
- 失敗したテストの再実行機能。失敗した時もこの機能のおかげでテストの実行回数の制限気にせず使える。
- どこでもステップグループが使えるのは嬉しい。
- ビデオログ。どこで失敗したか振り返りしやすくなった。
- JSステップのスニペット集嬉しい！
- 機能ではないがヘルプがとてもみやすい。


## 来年のロードマップ

ここで当社のエンジニアチームマネージャーの守屋から、来年のロードマップを紹介しました。
アサーション機能の拡充、変数を利用したテストシナリオやテストプランの作成、ユーザ権限設定、AI機能の強化など、お客様のご要望の多かった機能が今後追加されます! 

[Autify Product Roadmap](https://autifyhq.notion.site/Autify-for-Web-Product-Roadmap-af01e5f1d58c43d8bdc76ecd39e549e7)もご覧ください。

※ロードマップは予告なく変更することがあります。

![IMG_8588.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532308/908b5e7b-ca39-2321-e4dc-8a5d3f129b11.jpeg)

## Autify Communityのこれから

最後に、Autifyコミュニティでどんなことが聞きたいか、どんな話をしたいか、皆さんでお話しました♪

### コミュニティに期待すること、聞きたいことは？
- 皆さんがどんなテストで使っているのか知りたい。
- 全体のテスト戦略。テスト自動化 E2E、ユニットテストなどどうやっていこうとしているのか？
- 品質管理、保証を語りたい！
- 運用方法。テスト実行するのはいいけど、失敗がほって置かれたりする。リソースも足りない。😭😭
- 手動テストとのバランスが知りたい！皆さん、どう工夫されていますか？
- 投資対効果、どうやって出していますか？
- Autifyのシナリオプロフェッショナルの話が聞きたい!自分も今後ナレッジを提供できる側になれるかも。
- JSスニペットなどを共有する場が欲しい！Autifierユーザ、QAのつながりの場があると嬉しい。
- コミュニティ独自のナレッジ集、ここ困ったみたいなのを聞ける場があると嬉しい。
- アンチパターンの共有をしたい。しくじり先生みたいなもの。😂😂😂
- QA採用、育成について。

皆さんコミュニティへの期待が高く、ご自身でもアウトプットしたい、という思いのある方も沢山いらっしゃいました🙌🙌🙌

AutifyはこのコミュニティをAutiferの皆さんと一緒に充実、拡大していきたいと思っています。
次回Community Meetupにご期待ください！！

最後に全員で記念写真📷

![IMG_8577 2 copy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532308/68d10d19-fbe7-5484-8986-a2710605d6ff.png)

私自身皆さんのお話をお聞きでき、とても楽しい時間でした。
ご参加いただいた皆様、ありがとうございました！！🙌🙌🙌
【ルール説明・basic】inline-env-var

こちらの記事は [Ansible lint Advent Calendar 2022 カレンダー2](https://qiita.com/advent-calendar/2022/ansible-lint) 6日目の記事になります。


今回はルール [inline-env-var](https://ansible-lint.readthedocs.io/rules/inline-env-var/) について説明します。

### inline-env-var

[inline-env-var](https://ansible-lint.readthedocs.io/rules/inline-env-var/) は [ansible.builtin.command](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html) モジュールで環境変数が定義されていないか検証します。

Ansible ではコマンドを実行する処理で環境変数を定義する必要がある場合は [ansible.builtin.shell](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/shell_module.html) を利用します。

#### 問題のあるコード

```yaml
---
- name: Example playbook
  hosts: all
  tasks:
    - name: Set environment variable
      ansible.builtin.command: MY_ENV_VAR=my_value # <- command　モジュールで環境変数が定義されている
```

#### 修正されたコードその１

環境変数を定義してコマンドを実行する

```yaml
---
- name: Example playbook
  hosts: all
  tasks:
    - name: Set environment variable
      ansible.builtin.shell: echo $MY_ENV_VAR
      environment:
        MY_ENV_VAR: my_value # <- 環境変数を environment キーで定義する
```

#### 修正されたコードその２

環境変数を定義する処理のみ実行する

```yaml
---
- name: Example playbook
  hosts: all
  tasks:
    - name: Set environment variable
      ansible.builtin.shell: MY_ENV_VAR=my_value # <- shell モジュールで環境変数を定義する
```

### 参考サイト

* [inline-env-var — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/inline-env-var/)
1年間でQiitaの記事を100個書いた話

## はじめに
Qiitaのアドベントカレンダー最終日を担当する河村康治です。普段はGolangやTypeScriptで開発をしており、その日学んだことや気がついた事をこまめにQiitaの記事にしていました。振り返ったら１年間で１００個書いていたので、振り返りも兼ねて記事を書いてみようと思いました！！

## Qiitaの初投稿
Qiitaの初投稿は`2020年12月15日`で、保険系SIerを退職するまでの有給消化期間でした。元々、前職がSNS等の発信は十分に気をつけた上で発信する様にと言われていたので、記事の投稿などは控えておりました。退職を契機に色々な事に取り組み、アイディア商品「HDMI エミュレータ」を発見。当時はなんだこれ？？？ディスプレイに移した状態を作るの？？何に使うの？？って疑問ばっかりだったのですが、使い方をみると感動。
ノートPCやデスクトップ等でリモート接続する場合、ディスプレイに映し出されている事が接続要件になるのですが、それを回避するためのもの。ディスプレイと接続してなくても、小さなHDMIのエミュレータを取り付ける事でそれが回避されるのです。ディスプレイ接続するために、結構労力をはたいた経験があるだけに、この商品はいいなぁとすごい感動しました。この感動を誰かに共有したい、同じ様な境遇で困っている人に届けたいという思いから、Qiitaの１投稿目を実施しました。
![スクリーンショット 2022-12-14 22.04.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/d031979c-7ea6-b0ca-2ffa-bb741750afe0.png)

https://qiita.com/kouji0705/items/231b360b94c6c6097943

## 毎日投稿
`２０２1年7月20日〜2021年8月7日`までの３週間弱Qiitaの記事を毎日投稿。最初は自分の学習した内容の理解の落とし込み、備忘録として記事を残し始めたのですが、LGTMや閲覧数が伸びていく内に、「毎日投稿」したら伸びるのかなと思い、毎日記事書いて投稿しました。投稿時間も夜ではなく、朝8時〜9時の出勤時間に合わせて投稿すると伸びやすいとの事なので、朝早起きして記事を投稿していました。(やってわかった事なのですが、朝よりも帰宅時間の17時頃に合わせるとよさそうです。)この頃からGoogle Analyticsを導入し、LGTMやセッション数、新規ユーザ数などをWatchし、毎日ニヤニヤ眺めていたのを覚えています😏

https://twitter.com/kkfactory0705/status/1422002842034790411

## 100投稿目
`２０２２年8月11日`に１００投稿目を達成しました。嬉しくて思わずTwitterで呟いていました。９０記事載った位からずっとソワソワしていたので、１００投稿目を発信した時は達成感と安堵感で、しばらく余韻に浸っておりました。

https://twitter.com/kkfactory0705/status/1557717466205212673

## 月次投稿数とアナリティクス
Qiitaの記事を投稿する上で、僕のモチベーションになっていたのがLGTMや新規ユーザ数です。`Google Analytics`で、これまでの動向を振り返っていきます！！

![スクリーンショット 2022-12-17 12.35.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/0af17ad8-2b32-22a8-fc14-646a5351246d.png)
![スクリーンショット 2022-12-17 12.37.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/fe427081-b541-9b2b-3e76-88625dc64c43.png)

## 最後に
記事を書く事で、成長の実感やモチベーションに繋がっていきます！！また、記事経由でお仕事にも繋がる事があるので、これからもバシバシ書いて行こうと思います！！！
Rails上でBootstrapの使い方

# はじめに
Railsアプリ開発の際、フロントエンドのコーディング時にBootStrapというフレームワークを利用し、CSSやJavaScriptのコーディングが簡略化する事ができます。そのBootstrapの導入方法についてまとめます。

# 方法1
※tarminalのディレクトリの位置はアプリ内に位置する様にcdコマンドで予め移動させてください。

1\. Bootstrapを導入
```.terminal
% yarn add bootstrap@next
```
:::note info
コマンド実行後、バージョンを設定する画面が表示されます。ベータ版は不具合が生じる可能性がある為、注意が必要です。
:::

2\. popper.jsを導入
```.terminal
% yarn add @popperjs/core
```

3\. app/javascript/packs/application.js を読み込む

```app/views/layouts/application.html.erb
<%= stylesheet_pack_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
```

4\. ディレクトリを作成
- [ ] app/javascript/stylesheetsを作成
- [ ] stylesheetsディレクトリの直下にapplication.scssファイルを作成

5\. bootstrapを読み込む
```app/javascript/stylesheets/application.scss
@import "bootstrap"
```

6\. bootstrapとapplication.scssを読み込む
```app/javascript/packs/application.js
+ import "bootstrap"
+ import "../stylesheets/application"
```

# 方法2
1\.Gemにbootstrapをインポート
```.Gemfile
+ gem 'bootstrap-sass', '~> 3.3.6'
+ gem 'sass-rails', '>= 3.2'
```

``` .terminal
% bundle install
```

2\.app/assets/stylesheets/application.scssのファイル名を変える
- [ ] application.cssファイルの拡張子を「.css」から「.scss」に変える
```app/assets/stylesheets/application.scss
+ @import "bootstrap-sprockets";
+ @import "bootstrap";
```

```
# Gemを使う場合は以下のコードを削除
*= require_self
*= require_tree
```

3\. JavaScriptを読み込み

```app/assets/javascripts/application.js
+ //= require jquery
+ //= require bootstrap-sprockets
```
Ruby on Rails の ActiveRecord における attr_accessor と attribute メソッドの違い

Ruby on RailsでActiveRecordのモデルに属性を追加する時に`attr_accessor`と`attribute`という2つのメソッドが使えますが、この2つの違いって何？ということを簡単にまとめました。

# 結論
Ruby on Railsの`ActiveRecord::Attributes`モジュールのメソッドである[`attribute`](https://api.rubyonrails.org/classes/ActiveRecord/Attributes/ClassMethods.html#method-i-attribute)を使用してモデルに追加した属性は、
- その値が変更された時にダーティフラグが立つ、
- 定義時にキャスト型を指定する事により、モデルがインスタンス化される時に型をオーバーライドできる（第2引数）、
- デフォルト値を指定できる（第3引数）、

等の特徴を持ちます。一方で、Rubyの組み込みライブラリである`Module`クラスのメソッド[`attr_accessor`](https://docs.ruby-lang.org/ja/latest/method/Module/i/attr_accessor.html)を使用した場合は、単純にそのモデルにアクセサを定義するのみであり、以下のコードと完全に等価となります。

```ruby
# attr_accessor :name
def name
  @name
end
def name=(val)
  @name = val
end
```

Railsで`save`メソッドを使用するとダーティフラグにより何を保存すべきかを自動で判別してくれたりするので、単にそのインスタンスが存在する時に値が保持できれば良いならば`attr_accessor`で十分ですが、モデルの状態に関わるような属性を追加したい場合は`attribute`を上手く使うとコードがスッキリ書けるということになりそうです。
laravel タスクスケジューラー 「毎日何時に実行する」と設定する

:::note info
この記事は[miriwoお一人様 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/miriwo)の24日目の記事です
:::

# 概要

- タスクスケジューラーにて「毎日〇〇時に実行する」と設定する方法をまとめる

# 方法

- `dailyAt('時間')`をメソッドチェーンで記載することで設定する事ができる。
- 例えば毎日AM09:00に実行したい場合下記の様に指定する。

    ```php
    $schedule->command('hogehoge')
        ->dailyAt('09:00');
    ```

- ちなみに毎日深夜12時に実行したい場合は`daily()`を設定すれば良い

    ```php
    $schedule->command('hogehoge')
        ->daily();
    ```
    
# 参考文献

https://readouble.com/laravel/8.x/ja/scheduling.html#schedule-frequency-options
【ルール説明・basic】deprecated-module

こちらの記事は [Ansible lint Advent Calendar 2022 カレンダー2](https://qiita.com/advent-calendar/2022/ansible-lint) 5日目の記事になります。


今回はルール [deprecated-module](https://ansible-lint.readthedocs.io/rules/deprecated-module/) について説明します。

### deprecated-module

[deprecated-module](https://ansible-lint.readthedocs.io/rules/deprecated-module/) は非推奨のモジュールが利用されていないか検証をします。このルールを有効にする場合は基本的には [Ansible Community Package](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html) がインストールされている必要があります。

非推奨モジュールは [Ansible lint](https://ansible-lint.readthedocs.io) のバージョンではなく [Ansible Community Package](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html) のバージョン、もしくはモジュールが該当する collection に依存します。例えば同じバージョンの [Ansible lint](https://ansible-lint.readthedocs.io) を採用していても [Ansible Community Package](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html) 6.1.0 と 7.1.0 では同じ検証結果になりません。

また非推奨モジュールが利用さている場合 Ansible では警告になりますが [Ansible lint](https://ansible-lint.readthedocs.io) の検証ではエラーになります。また [Ansible Community Package](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html) や該当する collection がインストールされていないと [deprecated-module](https://ansible-lint.readthedocs.io/rules/deprecated-module/) の検証が有効にならないため注意が必要です。


#### Ansible Community Package に含まれる Collection のバージョン

それぞれのバージョンの [Ansible Community Package](https://docs.ansible.com/ansible/latest/reference_appendices/release_and_maintenance.html) に含まれる collection のバージョンは[こちらのリポジトリ](https://github.com/ansible-community/ansible-build-data)で確認できます。



#### 問題のあるコード

```yaml
---
- name: Example playbook
  hosts: localhost
  tasks:
    - name: Configure VLAN ID
      ansible.netcommon.net_vlan: # <- 非推奨モジュールが採用さている
        vlan_id: 20
```

#### 修正されたコード

```yaml
---
- name: Example playbook
  hosts: localhost
  tasks:
    - name: Configure VLAN ID
      dellemc.enterprise_sonic.sonic_vlans: # <- 推奨モジュールへ変更する
        config:
          - vlan_id: 20
```

### 参考サイト

* [deprecated-module — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/deprecated-module/)
* [ansible-community/ansible-build-data: Holds generated but persistent results from building acd](https://github.com/ansible-community/ansible-build-data)
DataFrame型？Datatable型と違うの？と指定範囲のデータ取得を練習します。

## はじめに

・この記事は、「Python Advent Calendar 2022」の24日目の記事です。
https://qiita.com/advent-calendar/2022/python

・この記事の情報は2022/12時点のものです。

・今回使用するのは「Google Colaboratory」です。


## 今回は
筆者は普段RPAツール(UiPath)を使った業務支援を中心に要件定義等も行っています。
ただ、Pythonの実績は自己学習の範囲内にとどまっています。

UiPathでは、Excelからデータを取得&格納するときに「Datatable型」を使います。
PythonでもDatatable型に相当するものはあるのでしょうか。
ちょっと調査してみましょう。

## PythonでExcelを読み込むと...
(事前にPandasをインストールするようにしましょう)
PythonでExcelを読み込むと、以下の様に表形式でデータが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/29eff133-d9da-5b87-25c5-6f232b7d4e55.png)

この時、取得する変数を調べてみると「<b>DataFrame型</b>」というらしい。
Datatable型と違うのかな？

## DataTableとDataFrame
よくわからなかったので調べてみると、以下のURLにわかりやすい図と説明がありました。
記事ではC#とPythonを比較をしていますが、UiPathではVB.NetもC#も使用可能です。

【入門】C#技術者の為のPython独学！データフレーム基礎編
https://resanaplaza.com/2021/06/06/%E3%80%90%E5%85%A5%E9%96%80%E3%80%91c%E6%8A%80%E8%A1%93%E8%80%85%E3%81%AE%E7%82%BA%E3%81%AEpython%E7%8B%AC%E5%AD%A6%EF%BC%81%E3%83%87%E3%83%BC%E3%82%BF%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E5%9F%BA/

興味を持ったのは以下の差です。
<b>Datatable型：Datatable型.Rows(行番号)(列番号 or "列名")
DataFrame型：DataFrame型.("列名")(行番号) もしくは DataFrame型.("列名")("行名")
</b>

<b>【補足】</b>
UiPathではDatatable型からセルの値をピンポイントでを取得するときは、
<b>Datatable型.Rows(行番号)(列番号 or "列名")</b>で記述します。


## 指定範囲のデータを取得
はい、これで終わり！とするのも良いのですが、これだとオチも面白さも何もないので、試しにデータの範囲を抽出する練習をしてみましょう。
PowerBIのブログで使用したサンプルデータを使います。

 <b>DataFrame型[開始行:終了行]</b>

 試しにdtHeightData[0:3]と書いて実行すると...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/06a775d4-35d7-aa26-278e-9b370c167df0.png)
お、出ましたね。
DataFrame型[0:5]とすると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502614/1ca18639-cdaa-7e33-6f5f-7dce5b5fc896.png)

まずはこの数を変更すれば任意の行の範囲を取得できる事を理解しました。
ああ、早く業務でPythonを使いたい。。。

## まとめ
Datatable型とDataFrame型は似ているようですが、データの取得方法が少し違うということが理解できました。
DataFrame型は行名を設定することができるという点は初めて知れたのでよい機会になりました。
Pythonでのデータ取得の幅が広がりそうです。
これからもPythonで業務に生かせる日が来るよう精進していきます。
最後までお読みいただきありがとうございました。


## 参考URL
【第6回】箱ひげ図
https://note.com/kensty/n/n5e25b873b1d4

【入門】C#技術者の為のPython独学！データフレーム基礎編
https://resanaplaza.com/2021/06/06/%E3%80%90%E5%85%A5%E9%96%80%E3%80%91c%E6%8A%80%E8%A1%93%E8%80%85%E3%81%AE%E7%82%BA%E3%81%AEpython%E7%8B%AC%E5%AD%A6%EF%BC%81%E3%83%87%E3%83%BC%E3%82%BF%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E5%9F%BA/
なんちゃて水Shader

# おはこん
おはこんばんにちはUniyaです．
最近Shaderを勉強しておりまして，友人に水面をARで表現するには計算量がたくさんかかって困るという相談を受けたので，なるべく軽い処理を心掛ける形でなんちゃって水面を表現してみました．
## 波の流れる感じ
UVスクロールを利用して水面のテクスチャを動かしています．

```HLSL
fixed4 frag (v2f i) : SV_Target {
    _XShift = _XShift * _HorizontalSpeed;
    _YShift = _YShift * _VerticalSpeed;
    i.uv.x = i.uv.x +_XShift * _Time;
    i.uv.y = i.uv.y +_YShift * _Time;
    fixed4 col = tex2D(_MainTex, i.uv);
    UNITY_APPLY_FOG(i.fogCoord, col);
    return col;
}
```

## 波の高さ
Wave Parameterをの値を調整して波の高さを表現しています
頂点Shaderの値を時間ごとに変更してsin波，cos波の積で出てくるグラフの形がそのまま波の形になります
delta変数で0~2π間で少しずつ波に変化を与えています
```HLSL
v2f vert (appdata v){
    v2f o;
    float delta = (_SinTime.w + 1.0) / 2.0;
    o.vertex = UnityObjectToClipPos(v.vertex);
    o.vertex.y += ((sin(v.vertex.x + delta))*(cos(v.vertex.z + delta))) * _WaveHeight;
    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    UNITY_TRANSFER_FOG(o,o.vertex);
    return o;
}
```
動画
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">version2 <a href="https://t.co/wQlfEAYKLt">pic.twitter.com/wQlfEAYKLt</a></p>&mdash; ゆにやん (@Uni_yan3) <a href="https://twitter.com/Uni_yan3/status/1606466508565401600?ref_src=twsrc%5Etfw">December 24, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

今度はRaymarchingとか利用して水面(水)を表現してみたいですね．
本記事は以上になります．ご高覧ありがとうございました
全体のコードや実際に手元で利用してみたい方は以下のリンクからお願いします．

[なんちゃって水Shader](https://github.com/keigo194547/LightWaveShader)
参考：https://nn-hokuson.hatenablog.com/entry/2016/10/20/201111
簡単Elixirシリーズ  ~ unquoteを理解しよう ~

# 簡単Elixirシリーズ 
## ~ unquoteを理解しよう ~

この記事は「[Elixir Advent Calendar 2022](https://qiita.com/advent-calendar/2022/elixir)」5日目の記事です
東京にいるけどfukuokaexのYOSUKEです。

簡単 Elixirシリーズでは小ネタをサクッと書いていこう。というコンセプトで作っていきます。

今回は、unquoteって何？ を理解する。という小ネタ（そう、この記事はサクッとがコンセプトW）

以前、quoteについて書いたのですが、

https://qiita.com/Yoosuke/items/f82e80d764b051ab283e

quoteを理解したなら、unquoteも！って事で公式見たら終わりですが、僕なりの表現で書いておこうと思います。

unquoteとは、
* quoteで評価した値を修正することができる
* quoteで評価された内部表現のASTに後付けでコードを注入することができる。

unquoteとは、上記2つの特徴を持つマクロです。

サンプルコードで実際の動作も見てみましょう。

例えば、次のような場合、結果の合計 24 ではなく、 11 + 13 を文字列にしたいとします。
```elixir
num = 13
13
iex()> Macro.to_string(11 + num)                   
"24"
```

そこで、quoteを使って、評価した値を文字列にしようと試みます。

```elixir
iex()> Macro.to_string(quote do: 11 + num)
"11 + num"
```

しかし、numに束縛した変数の値```13```ではなく、```num```がそのまま文字列に表現されています。

そこで、```unquote```を使って、```quote```の中を修正します。

```elixir
Macro.to_string(quote do: 11 + unquote(num))
"11 + 13"
```

すると、意図した結果が表示されるようになりました。

もう1つ例を見てみたいと思います。
numに13を束縛して、quoteで評価してみます。すると以下のようになります。

```elixir
iex()> num = 13
13
iex()> quote do: num              
{:num, [if_undefined: :apply], Elixir}
```

今度は、unquoteを利用して再実行してみます。

```elixir
iex()> quote do: unquote(num)     
13
```
すると、num ではなく、numの束縛された値が評価されて、そのまま自身の値が返ってきました。
今日のElixirSchoolメモ16「カスタムMixタスク」

Elixir Schoolの学習メモです。

https://elixirschool.com/ja/lessons/intermediate/mix_tasks

## セットアップ

```elixir
$ mix new hello
* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/hello.ex
* creating test
* creating test/test_helper.exs
* creating test/hello_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

    cd hello
    mix test

Run "mix help" for more commands.
```

Mixが生成した lib/hello.ex に "Hello, World!"を出力する簡単な関数を作成する。

```elixir
defmodule Hello do
  @doc """
  Outputs `Hello, World!` every time.
  """
  def say do
    IO.puts("Hello, World!")
  end
end
```

## カスタムMixタスク

カスタムのMixタスクを作成する。
新しいディレクトリとファイル、 hello/lib/mix/tasks/hello.ex を作成する。

```elixir
defmodule Mix.Tasks.Hello do
  @moduledoc "The hello mix task: `mix help hello`"
  use Mix.Task

  @shortdoc "Simply calls the Hello.say/0 function."
  def run(_) do
    # calling our Hello.say() function from earlier
    Hello.say()
  end
end
```

## アプリケーションの読み込み

Mixはアプリケーションやその依存関係を自動的に起動しない。
ただ、Ectoを使用してDBとやりする必要がある場合は、Ecto.Repoの起動を確認する必要がある。
処理する方法は2つあり、明示的にアプリを起動する、もしくはプリケーションを起動して他のアプリ達も起動する方法である。

```elixir
defmodule Mix.Tasks.Hello do
  @moduledoc "The hello mix task: `mix help hello`"
  use Mix.Task

  @shortdoc "Simply calls the Hello.say/0 function."
  def run(_) do
    # This will start our application
    Mix.Task.run("app.start")

    Hello.say()
  end
end
```

## Mixタスクの実行

```elixir
$ mix hello
Compiling 1 file (.ex)
Hello, World!
```
データギルドにおけるQCD向上に向けた取り組み

本記事は、[クリスマスに向けデータに関する想いや技術をぶっちゃける Advent Calendar 2022](https://qiita.com/advent-calendar/2022/sinkcapital) 24日目の記事です。

# はじめに

　はじめまして、データギルドを運営しているSinkCapitalの櫻井と申します。
カレンダーの終盤とのことで自分の会社について触れておこうかなと思います。
少し細かい自己紹介は[こちら](https://qiita.com/yuji_sakurai/items/ee815be30e170a102dfe)を参考にしてもらえればと思います。
では以下本編になりますのでよろしくお願いたします！

# なぜQCD向上が必要だったか

　弊社はデータギルドという形式でデータに関する業務の支援をさせていただいており、
ワーカーの多くが副業やフリーランスで構成されています。
必要に応じて副業やフリーランスの人材を活用することで、
必要十分な稼働を短期的に確保することができると言った特徴があります。
　ただ一方特に副業という形態の場合は工数や働き方のばらつきは大きく、
それによって提供価値のQCDは不安定になりがちです。
弊社の規模拡大に合わせて運営側が見れる範囲も限られてきた中、
QCDを下げないために行ってきた取り組みについて書かせていただければと思います。

# ギルド組織におけるQCDの特徴

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198985/f9c550d7-cfdd-ba16-3ba9-cbed126a7f31.png)
＊ 弊社提供価値のイメージ図

　まず取り組みの説明の前にQCDそれぞれの簡単な説明を記載させていただこうと思います。

### Quality :　品質

　これはアウトプットそのものの品質を指しており、
以下のようなものの品質を表しています。

- パイプライン構築　：　設計や開発したシステム
- マート設計　：　dwh上でのマート設計書
- データ分析　：　分析設計やデータ抽出結果
- ...

まさに技術力や経験が必要になってくる箇所であり、
ここが不十分だと例えばSQLや仮説設計のミスが発生してしまいます。
その結果「無駄にデータをこねただけでなんの成果も得られなかった...」
といった状況を招きかねない箇所になります。

### Cost　：　コスト

　次は活動にかかるコストの部分になります。
コストは役割に応じて設定しており無理に調整する取り組みは行ってはいませんが、
元々営業非介在で見積もり時から最適な人員配置を提案することで、
必要十分な分のみのコストが掛かるような仕組みとなっています。
案件推進中であっても稼働内容の変更に応じて体制を変えるため、
初めデータ基板側の人材が多かったところから、
データ分析側の人材に入れ替えていくと言ったことを行う場合もあります。

### Delivery　：　納期

　最後のデリバリーが個人的にギルドで一番困難な点だと考えています。
というのも工数や働き方のばらつきが大きい副業という形態では、
外部要因によって工数が取れるタイミングが変わったり、
想定より取れる工数が少なかったりといった事が起きる可能性が大きいためです。
そのため単純に規模を大きくしていくと、
外部要因によりデリバリーへのリスクが高まります。

# QCDを高めるための取り組み

　ここからはそういった中組織拡大時にQCD低下を防ぐため、
取り組んできた内容について説明させていただこうと思います。

### メンバー加入時の技術テスト

　まずはメンバー加入時に行うテストの導入です。
当然Qualityに関わる技術力の面は図ることができますが、
それと同時に問題の解釈に幅をもたせることで、
期日に対して要件確認をどのように行うかも確認することができます。
一例として問題によっては以下のような基準で採点しており、
回答の正確性以上に事前確認を以下に行えているかを重視していたりします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198985/b37fa70a-ff6d-d9a1-e46a-898d3b182d5e.png)
　実際の業務においては最初から要件が固まりきっていないことも多く、
要件確認の余裕を持って対応を行えるかなどの確認をすることができます。

余談ですがテスト受講用のGoogle Forms送信後に、
Google Apps Scriptが動き権限付与がされた回答用Google Driveができるといった、
少し凝った自動化を行っていたりします。

### 疎結合なタスク管理

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198985/89b86bd4-7897-ab8c-9bbb-411544ab3c10.png)

　次に行ったのがJIRAやBacklogといったツールを用いた疎結合なタスク管理です。
「工数や働き方のばらつき」がある中でPRJを回すためには疎結合にすることが重要で、
それによって例えば朝に稼働する人と夜に稼働する人が同じPRJで稼働できるようになっています。
またツール自体の使い勝手もありますがタスクを渡す側がツールに合わせることで、
副次的に背景やゴールの言語化が進みテキスト上での案件推進が促進されたり、
期日やステータスのモニタリングによってシステム的にデリバリーの担保を行うことができます。

### 全体の管理業務のフロー化

　最後に行ったのがそういったツールを用いた管理フローの型化です。
例えば内部定例の開催頻度や確認内容などを型化することで、
PMにあたる人が変わっても必要な内容が確認できるようにしています。
こちらは現在進んでいるプロジェクトの中で良いものを残しているため、
今後も改善余地が大きく存在する箇所かと思われます。

# １年推進して見た結果

　一番わかりやすく変化したのはタスク管理のところで、
現在ではほぼすべてのプロジェクトにおいてチケット管理が行われ、
期日や稼動内容がひと目で分かる状態が担保されています。
フルリモートでの個人の予定に合わせて時間が組めることは、
副業やフリーランスの方の好む働き方ともマッチしており、
メンバー内でも働きやすいといった声を聞けることが多いです。
　テストや管理業務の型化による効果は感覚値ではで始めてきているため、
目に見える効果が出てき次第また記事にさせていただければと思います。

# 最後に

　今年は会社3期目の年だったのですが、
単なる人の集まりから「組織」へと変革させる準備をしていた１年だと感じています。
まだ組織の体裁を整えている状態ですが、
今後は知見の蓄積などより未来に向けた準備を進めていきますので、
引き続きどうぞよろしくお願いします！
GitHub の Issues を Markdown 形式で出力する

# 背景

私は手元の Markdown ファイルにタスクを書き出すことが多いのですが、その際に GitHub の Issues をタスクとして持ってきたいことがしばしばありました。数が少なければ普通にコピペで十分なのですが、多かったりすると大変です。

ということで楽にできる方法を考えました。

# 手順

1. GitHub の Issues を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1248726/158f1e21-6e5a-8f7c-d81f-04b57b348153.png)
2. 開発者ツールを開き、コンソールで下記コードを実行する
    ```javascript
    console.log(Array.from(document.getElementsByClassName('h4')).reduce((carry, e) => e.href ? carry + '- [' + e.innerText + '](' + e.href + ')\n' : '', ''));
    ```
3. 出力結果をコピペする
    ```markdown
    - [Out of bounds handling for non-US keyboards](https://github.com/vlang/vinix/issues/104)
    - [Vinix kernel panic on pressing the tab key](https://github.com/vlang/vinix/issues/103)
    - [V panic spam when typing 'vim'](https://github.com/vlang/vinix/issues/100)
    - [Add more than one keyboard layout](https://github.com/vlang/vinix/issues/83)
    - [Vinix halts when pressed keys '(' and ')' in vim or nano](https://github.com/vlang/vinix/issues/79)
    - [question: Can a screen reader be built/ported to this system](https://github.com/vlang/vinix/issues/78)
    - [shell: Number of characters per line limited by screen](https://github.com/vlang/vinix/issues/51)
    - [trying to move cursor in nano inserts capital letters](https://github.com/vlang/vinix/issues/41)
    - [building with v creates weird file](https://github.com/vlang/vinix/issues/39)
    - [OsDev Tutorial ](https://github.com/vlang/vinix/issues/16)
    - [Resources & ideas for inspiration](https://github.com/vlang/vinix/issues/5)
    - [Logo suggestion](https://github.com/vlang/vinix/issues/3)
    ```

# 補足

Pull requests でも使えます。
ミュータブルとイミュータブルを理解してみる

# 目的

新卒1年目でレビュー指摘もらった箇所を理解したい。
プルリクのコメントで `mutable` なコーディングを指摘された。

![スクリーンショット_2022-12-20_16_43_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/687433/95e96516-c860-1478-830a-42be4f769cf4.png)

javascript で 配列には `push` メソッドばかり使ってきた私なので `immutable` の意識が欠けていたのでここで整理してみようと思った。

## 英語の意味

- mutable：可変
- immutable：不変

`immutable`　は変化しないということですね。

## mutable, immutable とは？

ミュータブルオブジェクトは、オブジェクトを作成した後に状態を変更できるオブジェクトです。
イミュータブルは、オブジェクトが作成された後は状態を変更できないオブジェクトです。

- mutable = 変更可
- immutable = 変更不可

ということですね。

その中でも、プリミティブ型はイミュータブルです。
また、文字列や数値もイミュータブルです。
それに対して `Array` オブジェクトや `Object` オブジェクト、`Date` オブジェクトなどはミュータブルなオブジェクトです。

## mutable の例

### array

```typescript
const fruits = ['バナナ', 'いちご', 'ぶどう'];
fruits.push('シャインマスカット'); // fruits というオブジェクトが書き換えられてしまう。
cosole.log(fruits); // output => ['バナナ', 'いちご', 'ぶどう', 'シャインマスカット']
```

### object

```typescript
const user = {"id": 1, "name": "Qiita太郎", "age": 23}
user.country = 'Japan'; // user が書き換えられる
console.log(user); // output => {id: 1, name: 'Qiita太郎', age: 23, country: 'Japan'}
```

## immutable の例

例えば、以下の例は `TypeScript` という文字列を `hello world` という文字列を変更しているように見えますが、 `mutableString` という変数に対して、 `hello world TypeScript` という文字列を再代入しているということです。

```typescript
let mutableString = 'hello world';
mutableString = mutableString + 'TypeScript';
console.log(mutableString) // output => 'hello world TypeScript'
```

## なぜ immutable を意識したほうがよいのか？

> もしオブジェクトがイミュータブルであったなら、オブジェクトの複製はオブジェクト全体の複製ではなく、単に参照の複製で済む。参照は通常オブジェクト自体よりもずっと小さいので（典型的にはポインタのサイズのみ）、メモリが節約でき、プログラムの実行速度もよくなる。（wikipedia参照）

`immutable` のオブジェクトは何度生成しても同じものが作成されます。

## JavaScript で immutable を意識してみる

### 結論

　なるべく破壊的メソッドの使用を控える
（禁止しろ！ということではなく、状況によって使い分けようねということです。）

### 破壊メソッド

- `splice()`
- `push()`
- `unshift()`
- `pop()`
- `shift()`
- `sort()`
- `reverse()`
- `fill()`
- `copyWithin()`

### 破壊メソッドの使用をやめてみる

```typescript
// ======
// 前述の例
// ======
const fruits = ['バナナ', 'いちご', 'ぶどう'];
fruits.push('シャインマスカット'); // fruits というオブジェクトが書き換えられてしまう。
cosole.log(fruits); // output => ['バナナ', 'いちご', 'ぶどう', 'シャインマスカット']

// ======
// スプレッド構文で書き換える
// ======
const fruits = ['バナナ', 'いちご', 'ぶどう'];
// 既存の fruits というオブジェクトを書き換えることなく、 値の書き換えに成功！
const immutableFruis = [...fruits, 'シャインマスカット'];
cosole.log(immutableFruis); // output => ['バナナ', 'いちご', 'ぶどう', 'シャインマスカット']
```

## まとめ

いかがでしょうか？
`immutable` を意識しつつ、状況によって柔軟に対応していきましょう！
【UiPath】使用できない文字を置き換える

# はじめに

この投稿は、RPAツールの「UiPath Studio」での「ちょっとしたナレッジ」について、個人的にまとめたものです。

UiPath Advent カレンダーの 11 日目 の記事でもあります。

https://qiita.com/advent-calendar/2022/uipath


# ファイル名・フォルダ名・シート名で使用できない文字

「Windowsフォルダ名／ファイル名／Excelシート名」には「使用できない文字」がありますが、RPA/UiPathで自動化する際に、処理の都合上で、その文字が邪魔になることがあります。

　例）WEBブラウザ上に表示されている名前と同じファイル名で保存したい時

「Windowsフォルダ名／ファイル名／Excelシート名」で使用できない文字は以下になります。

```
ファイルやフォルダー名に使用できない文字（半角）
	\	　円マーク、円記号
	/	　スラッシュ
	:	　コロン
	*	　アスタリスク
	?	　クエスチョンマーク、疑問符
	"	　ダブルクォーテーション　※ Excelシート名なら使用可能
	<>	　不等号　　　　　　　　　※ Excelシート名なら使用可能
　	|	　縦棒　　　　　　　　　　※ Excelシート名なら使用可能

シート名に使用できない文字（半角）
	\	　円マーク、円記号
	/	　スラッシュ
	:	　コロン
	*	　アスタリスク
	?	　クエスチョンマーク、疑問符
	[]	　角括弧　　　※ ファイルやフォルダー名では使用可能
```

使用できない文字を指定すると、以下のようなエラーになります。

| 種類 | 名称エラー画面 |
|:-:|:-:|
| ファイル・フォルダ名  | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/b5e07caa-82bd-86c4-c3a8-029642bcf9cd.png) |
| シート名  | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/9d1cf1e9-635e-6925-adc9-d981c04fc8fd.png)  |


# 使用できない文字を置換する

使用できない文字は「除去する or 置き換える」事になりますが、「代入アクティビティ」と「.Netのlinqメソッド構文」で置き換えるのが一番楽です。

「フォルダ・ファイル名」で使用できない文字は、`Path.GetInvalidFileNameChars()` で配列で取得できます。「エクセルシート名」で使用できない文字は、自分で定義して配列型にします。具体的には`"\/*?:[]".ToCharArray()`で取得できます。

この「使用できない文字列配列」を使って、元の文字列を１文字づつ移動しながら「使用できない文字列配列に含まれている文字なら置き換え」をしていきます。

例）複数代入アクティビティで、ファイルフォルダ名に使用できない文字を「_」に置換
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/955baf5b-fdc6-09d9-8ed8-8f867b748dab.png)

```
<式エディタにセットしている値>
String.Concat(ファイル名にしたい文字列.Select(Function(c) If(Path.GetInvalidFileNameChars().Contains(c), "_", c)))
```

例）複数代入アクティビティで、エクセルシート名使用できない文字を「_」に置換
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/c9106d72-ed12-5696-da23-a5f1d159159c.png)

```
<式エディタにセットしている値>
String.Concat(ファイル名にしたい文字列.Select(Function(c) If("\/*?:[]".ToCharArray().Contains(c), "_", c)))
```

上記の式、少し分かりにくいですが
　１）ファイル名にしたい文字を「.Select」で１文字づつチェックして
　２）「.Contains」で判定して使用できない文字があったら「_」にする
　３）「.Contains」で判定して使用できない文字に無かったら、そのまま使う
　４）上記の結果が配列型になっているので「String.Concat」で文字列結合する
という処理をしています。


# 終わりに

以上、ちょっとしたナレッジでした。
この記事が参考になったら、 いいね をお願いします。閲覧ありがとうございました。
GEOのデータをChAMPで読み込む

[TCGAのデータをChAMPで読み込む](https://qiita.com/Yh_Taguchi/items/a20d293e0ee3d2b45fed)をかいたのでついでにGEOも書いておきます。こっちはとても簡単なのですが。

# GEOからデータをダウンロード
[GSE77965](https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE77965)を例にとります。Supplementary fileからGSE77965_RAW.tarのcustomを選んでファイル名がidat.gzで終わっているファイルを選択してGSE77965_RAW.tarを作成し、ダウンロードしカレントディレクトリに展開して下さい。

# Sample_Sheet.csvの作成
ファイル名は
GSM2062665_7796806124_R01C01_Grn.idat.gz
などとなっているはずなのでそこの7796806124とR01C01の部分を使って

Sample_Name,Sample_Group,Sentrix_ID,Sentrix_Position
T1,Tumor,7796806124,R01C01
T2,Tumor,7796806124,R02C01
T3,Tumor,7796806124,R03C01
T4,Tumor,7796806124,R04C01
T5,Tumor,7796806124,R05C01
T6,Tumor,7796806124,R06C01
N1,Normal,7796806124,R01C02
N2,Normal,7796806124,R02C02
N3,Normal,7796806124,R03C02
N4,Normal,7796806124,R04C02
N5,Normal,7796806124,R05C02
N6,Normal,7796806124,R06C02

という形式のファイルを作成します。

# 読み込み
```
>require(ChAMP)
>myLoad <- champ.load("./",arraytype="450K")
```
で読み込めます。
GitHub Actionsの実行・結果確認をターミナルで完結させるalias

# この記事を読むとできるようになること
git commitしてpushして、ブラウザ開いてactionsタブを開いてワークフロー探して・・・
というちょっと面倒な手間をなくして、`gh-run`とターミナルで叩けばワークフローが実行できるようになります。
```shell
$ gh-run
# my-workflow.ymlをcurrent branchで実行

$ gh-watch
# 実行状況をターミナルに表示

$ gh-view
# 実行結果をターミナルに表示

$ gh-log
# 実行ログをターミナルに表示

```
# aliasを設定します
~/.zshrc等に下記を追記して保存します。
その後、`source ~/.zshrc`の実行もお忘れなく。
```
# gh
# 実行する
alias gh-run='gh workflow run .github/workflows/$workflow --ref $(git branch --show-current)'
# 実行を見守る
alias gh-watch='gh run list --workflow=$workflow | grep $(git branch --show-current) | cut -f 7 | head -n 1 | xargs gh run watch'
# 結果を確認
alias gh-view='gh run list --workflow=$workflow | grep $(git branch --show-current) | cut -f 7 | head -n 1 | xargs gh run view'
# ログを確認
alias gh-log='gh run list --workflow=$workflow | grep $(git branch --show-current) | cut -f 7 | head -n 1 | xargs gh run view --log'
```

# 実際のご利用イメージ
## 準備1: shell変数にファイル名を格納します
今回実行したいワークフローのファイル名は`everyday-holiday.yml`です。
```shell
workflow=everyday-holiday.yml
```
## 準備2: 実行したいブランチに移動して、ワークフローを修正したりしなかったり
my-feature-branchでいい感じの修正を加えたとします。
```shell
$ git branch
* my-feature-branch

$ git commit -m "feat: Happy Holidays"
$ git push origin HEAD
```

# 3. よし、修正したワークフローを実行しよう
`gh-run`を叩くだけで、current branch上にあるワークフローを使ってワークフローが実行できるので、先程の修正を即座にテストできます。
```
$ gh-run
✓ Created workflow_dispatch event for everyday-holiday.yml at my-feature-branch
To see runs for this workflow, try: gh run list --workflow=everyday-holiday.yml

```

# 4. 実行が終わったかどうかをチェックする
`gh-watch`を叩けば、先程実行したワークフローの実行状況がターミナルに表示できます。
実行状況は5秒間隔で実行状況が更新されます。
- <font color="green">**✓**</font> がPassしたjob
- <font color="red">**×**</font> がFailしたjob
- <font color="orange">**\***</font> が実行中のjobです
```
$ gh-watch
Refreshing run status every 3 seconds. Press Ctrl+C to quit.

* my-feature-branch Everyday Holiday #00000 · 1234567890
Triggered via workflow_dispatch less than a minute ago

JOBS
✓ wake-up (ID 12345678901)
× sleep-again (ID 909090909090)
* morning-coffee (ID 23456789012)
```

# 4. 実行結果を確認
`gh-watch`はワークフローが実行中のとき使えるコマンドなので、すべて終わっていたら使えません。
代わりに`gh-view`で確認します。
```
$ gh-view
✓ my-feature-branch Everyday Holiday #00000 · 1234567890
Triggered via workflow_dispatch about 14 minutes ago

JOBS
✓ wake-up (ID 12345678901)
× sleep-again (ID 909090909090)
✓ morning-coffee (ID 23456789012)
```

# 5. 実行ログを確認して失敗理由を調査する
`gh-log`ですべてのログが表示されます。
ターミナルのログは見慣れない形式だったりブラウザで見る場合と情報が違っていたりします。もしブラウザでログを確認したいときは、`-w`オプションを付けて`gh-view -w`を叩くと一発で開けます。（※gh-log -wではないことに注意！）

その他のオプションを追加したい場合は[GitHub CLIの公式ドキュメント](https://cli.github.com/manual/gh_run_view)を参照してください。
```shell
$ gh-log
# ログが出力される
```

# まとめ
ターミナルでGitHub Actionsを実行→結果確認をおこなうことで、修正→動作確認を楽にしていきましょう〜
一発で動くコードが書けたら全然必要ないんですけどね:P

追記）書き忘れましたが、前提条件としてGitHub CLIをインストールしている必要があります。まだインストールしていない方は公式サイトをご確認ください。
https://cli.github.com/
非エンジニアメンバーを巻き込んで少しずつ自動化を進めた話

こんにちは！横断本部わり算グループのしげるです。
9日目は [@kentaro_suzuki](https://qiita.com/kentaro_suzuki) さんで [最近読んだGo言語の本の紹介：100 Go Mistakes and How to Avoid Them](https://qiita.com/kentaro_suzuki/items/c9c31dc81217f237433c) でした。明日で、アドベントカレンダーも最後ですね。

趣味で、社内の自動化をいくつかお手伝いしています。
4日目に、 [Google Apps Script(GAS)を使い倒して、アンケート作成を自動化した話](https://zenn.dev/4geru/books/advent-calendar-2022-day-4/viewer/introduction) もあげているので、興味があれば、読んでください。
今回は自動化の案件を元に、普段意識していること、自動化案件が成功するための秘訣について共有できればと思います。

先に端的に 3行で、伝えたいことをまとめると次の3行になります。
* 自動化した後に、運用するメンバー(カスタマーサポートのTさん)を巻き込む
* 定期的に時間を確保する
* やりたいことの本質を考える

## 案件

今回紹介するのは、[luccafort](https://twitter.com/luccafort) さんとの自動化案件の話が落ち着いた頃に、カスタマーサポートのTさんに自動化案件のヒアリングから始まったプロジェクトです。

マネーフォワード クラウドには20以上のサービスがあります。
[マネーフォワード クラウドガイド](https://biz.moneyforward.com/support/) を提供して、それぞれのサービスの使い方についてサポートしています。クラウドガイドに投稿されている記事は数千を超えています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64677/213835de-bd15-437c-170e-9f3c2dd99c2c.png)

数千の記事を公開していると、サービス側のURL変更や、参考として掲載した外部サイトの掲載終了など、様々な要因でリンク切れが発生します。

リンク切れが発生すると、ユーザーに対して求める情報に辿り着けない不便が発生します。
以前は、人力で全ページ確認するなどの涙ぐましい作業も実施されていましたが、数千ページを人力で全て確認するのはとても大変そうでした。

## 進め方
自分とカスタマーサポートのTさんと一緒に小さく始めました。
一番最初に二人で kick off をして、ゴール・解決方法・進め方をまとめました。
朝のリフレッシュしている時間帯の1時間。頻度は、1週間に一度。難しそうであれば、 skip する方針で進めました。
少しの雑談から始まり、前回の内容を Google ドキュメント から思い出し、TODOの整理、会ごとにペアプロを回していきます。1時間しか時間をとっていないので、少しずつですが、試行錯誤しながら、前に進めることができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64677/cc4e6bd3-7839-5614-239c-485639fff9c3.png)

5月に kick off をはじめ、 11月末にプロジェクトとして完了。途中空白の期間も挟みつつ細く長くのプロジェクトでした。結果として、多くのリンク切れページが発見できることができました。

## 方針について
5月から11月の中で右往左往しつつ最終的には、[muffet](https://github.com/raviqqe/muffet)（Go製のリンク切れ検出ツール）、 [Github Actions](https://github.com/features/actions) を利用して完成させました。その中で、 [AWS Lambda](https://aws.amazon.com/jp/lambda/) なども検討したりしています。

- step1. local で muffet の使い方を調査
- step2. muffet on Docker の使い方を調査
- step3. AWS Lambda で muffet on Docker を調査
    - 週1では AWS を使いこなせず詰まる / 断念
- step4. Github Action で muffet on Docker を調査
    - 動き感動に包まれる
- step5 Github Action で 定期自動実行 & 手動実行の調査
- step6 ドキュメントをまとめて Tさんにお渡し

## プロジェクトを完走して

コロナ禍に入って、他部署の方とコミュニケーションが減った中で、定期的に話せる環境はとてもよかったです。始業前に手と頭を動かすことで、業務にもリフレッシュして取り組めるようになりました。

自動化を進める上で、何をゴールにしたいのか。CSVに出力にしたいのか。Slackに通知が飛ぶようにしたいのか。自動化したいMVP(Minimum Viable Product) はどこなのか、一番工数が掛かっている点に着目し、有志の範囲で挑戦したいとに絞るトレーニングになりました。

途中で挫折した AWS Lambda も含め普段業務で使わない技術に挑戦もできました。

Zoomですべての作業画面を録画していたので、非エンジニアのカスタマーサポート Tさんがコードやクエリの学習にも役立てることができました。オンライン時代ならではのメリットだと思います。

## 最後に
開発完了後、チーム内で運用できる形でサポートチームに仕組みをお渡ししました。
サポートチームでは、まずは現在残っているリンク切れをすべて無くせるよう確認を進めています。
現在あるリンク切れを無くしたあと、定期実行によりリンク切れを自動で通知できる仕組みを整える予定です。

自動化にあたっては、どこまで手動でして、自動化させるかが大切になります。
周りの人を巻き込むことで、1人では続かないことでも続けられ、新しい発見、感動を共有することができます。
技術に自信のない人でも、一歩踏み出して少しずつ積み重ねることで成長することができます。
ぜひチャレンジしていきましょう！！
CodeceptJSのmailSlupメール対応が旨くいってた

# 概要
久々にCodeceptJSを使って自動テストする機会があり、いろいろ触っていると、[以前](https://qiita.com/KazuhiroYoshino/items/d55e570f3b9fb0fd24bc)利用できなかったmaiolslurpのhelperが、使えるようになっていたので、使ってみました。
自動テストにメール認証を含んでいる場合や、受信メールの文面がテスト対象になっている場合に、helperをインストールすれば、簡単に自動テストできます。
# インストール
CodeceptJSの[公式サイト](https://codecept.io/email/#installation)の通りにできました。
```
npm i @codeceptjs/mailslurp-helper --save-dev
```
以前は、インストールでコケていたのですが。
当時のCodeceptJSのバージョンは、3.1.2
今は3.3.7、結構すすんでいました。
# 使い方
以前は、mailslurp-clientインスタンスを起動していましたが、
```
const { MailSlurp } = require("mailslurp-client");
```
現在は、codecept.conf.jsに、
```
helpers: {

  MailSlurp: {
    require: '@codeceptjs/mailslurp-helper',
    apiKey: '<apiKeyFromMailSlurp>'
  },
}
```
を記述しておけば、
受信用のカスタムメソッドを自前で記述することなく、inboxID宛てのメールは、
```
const inboxID = await I.haveNewMailbox();
const mailAddress = inboxID.emailAddress;
```
でCodeceptJSのメソッドのように使えるので、テストコードの見通しが良くなりました。
進化を続けているフレームワークを使うメリットは、大きいですね。
上記の事例では、emailAddressメソッドでメールアドレスを取得していますが、他にもhelperから使える検証メソッドがあって、詳しくは[こちら](https://codecept.io/email/#assertions)を参照下さい。
# 総括
mailslurpで用意されているAPIを利用すれば、CodeceptJS以外の自動テストツール（MagicPod等）にメール受信を含む検証がローコードで容易に作成することができます。
Node.jsのテストコードを少しだけ記述する必要はありますが、CodeceptJSのhelperを利用して自動テストが構築できますので、なんとなく何をしているのか読めるテストコードを記述してテスト自動化を検討してみても良いかもしれません。
wordpressでテーマを作る時に必要なファイル達

## はじめに
wordpressでテーマを作ろうと思ったけど、何のファイルを作れば良いかわからない。
調べても見つからなかったので、自作してみました。

## リスト
- [x] function.php
- [x] footer.php
- [x] sidebar.php（サイドバーがないデザインには不要）
- [x] header.php
- [x] 404.php
- [x] search.php
- [x] archive.php
- [x] date.php
- [x] author.php
- [x] tag.php
- [x] category.php
- [x] page.php
- [x] single.php
- [x] home.php
- [x] comments.php（コメント機能がないデザインには不要）
- [x] index.php
- [x] style.css

### function.php
関数を入れるファイルです。

#### テンプレート
```php
<?php
/*
 * Template Name: functions.php
 */

/* style.cssを読み込む。 */
function register_style_file() {
    wp_enqueue_style( 'style-name', get_template_directory_uri() . '/style.css');
}
add_action( 'wp_enqueue_scripts', 'register_style_file' );
```

### footer.php
テーマのフッターを記入します。
```<?php wp_footer(); ?>```で呼び出すことができます。

### sidebar.php
サイドバーを表示できます。
```<?php get_sidebar();?>```で呼び出すことができます。

### header.php
テーマのヘッダーを記入します。
```<?php wp_header();?>```で呼び出すことができます。

### 404.php
404ページのデザインを記入します。

### search.php
検索結果を表示するページです。

### archive.php
投稿アーカイブや、カテゴリーアーカイブを表示します。

### date.php
日時でのアーカイブテンプレートです。


<後で追記します。>
【ルール説明・basic】deprecated-local-action

こちらの記事は [Ansible lint Advent Calendar 2022 カレンダー2](https://qiita.com/advent-calendar/2022/ansible-lint) 4日目の記事になります。

今回はルール [deprecated-local-action](https://ansible-lint.readthedocs.io/rules/deprecated-local-action/) について説明します。

### deprecated-local-action

[deprecated-local-action](https://ansible-lint.readthedocs.io/rules/deprecated-local-action/) はキー`local_action`が利用されている時に`delegate_to: localhost`に変更するように警告を出力します。

#### 問題のあるコード

```yaml
---
- name: Task example
  local_action: # <-- 非推奨の記述方法
    module: boto3_facts
```

#### 修正されたコード

```yaml
- name: Task example
    boto3_facts:
  delegate_to: localhost # <-- ローカルホストで処理を実行する際の標準的な記述方法
```

### 参考サイト

* [deprecated-local-action — Ansible Lint Documentation](https://ansible-lint.readthedocs.io/rules/deprecated-local-action/)
Nx速度競争 def vs defn

[この記事](https://qiita.com/GeekMasahiro/items/a15d2b0a96c6e96c1d57)で、@zacky1972 さんから、defnには最適化高速化の効果もある。とコメントいただきました。
[kino_benchee](https://qiita.com/RyoWakabayashi/items/afbd4d2187368346d5a9)も使ってみたかったので、勉強も兼ねてやってみます。

# 速度比較結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532235/3d18bc27-fc23-f3ec-52b8-2b3bed399816.png)

defn、compiler指定無し（青色）でも速くなってます。
`Nx.Defn.jit(dot_fn, compiler: EXLA)`でjitコンパイルした場合（オレンジ色）は飛びぬけて速い！

`default_defn_options`に`compiler: EXLA`を指定しておけば、デフォルトのcompileがEXLAになります。
defnで記述するだけで、この効果が得られます。
compiler: EXLAをつけましょう！効果は絶大です

```Elixir
import Config
config :nx, :default_backend, EXLA.Backend
config :nx, :default_defn_options, compiler: EXLA
```
この例は、jitでコンパイルしましたが、defnで記述した場合も同じ効果が得られるとおもいます。
そういえば、Axonのコードを実行する場合、この記述を付ける事でかなり速くなってました。この働きですね。

以下は、測定した時のlivebookです

# 速度比較のlivemd

```elixir
Mix.install(
  [
    {:nx, "~> 0.3.0"},
    {:exla, "~> 0.3.0"},
    {:kino, github: "livebook-dev/kino", branch: :main, override: true},
    {:kino_benchee, "~> 0.1", github: "livebook-dev/kino_benchee", branch: "main"}
  ],
  config: [
    nx: [
      default_backend: EXLA.Backend
      # default_defn_options: [compiler: EXLA] #比較kのためデフォルトでは無効にする
    ]
  ],
  system_env: [
    XLA_TARGET: "cuda111"
  ],
  # XLA_TARGETの変更で、exlaを再コンパイルしたい時はtrueにする
  force: true
)
```

## 速度比較

```elixir
dot_fn = fn ->
  a = Nx.random_uniform({100, 100})
  b = Nx.random_uniform({100, 100})
  Nx.dot(a, b)
end

dot_jit = Nx.Defn.jit(dot_fn)
dot_jit_exla = Nx.Defn.jit(dot_fn, compiler: EXLA)

Benchee.run(
  %{
    "def" => dot_fn,
    "Nx.Defn.jit" => dot_jit,
    "Nx.Defn.jit_exla" => dot_jit_exla
  },
  time: 10,
  memory_time: 2
)
```

参考
https://qiita.com/zacky1972/items/c8deaf2413efa726ea79
https://qiita.com/RyoWakabayashi/items/afbd4d2187368346d5a9
composer installでSQLSTATE[HY000] [2002] Connection refused　

## 環境 ##
OS : mac
仮想環境　：　docker (Linux, apache(debian), mysql, php )

## 背景 ##
docker環境を使って複数サイトをローカルで見れるようにしたい
`docker-compose exec サービス名 bash`
でdockerコンテナ内に入りgithubからpullしてきたプロジェクトのディレクトリで
`composer install`したところ
以下エラーが出てしまった

```
In Connection.php line 664:

  SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_s
  chema.tables where table_schema = XXX and table_name = ABC)


In PDOConnection.php line 31:

  SQLSTATE[HY000] [2002] Connection refused


In PDOConnection.php line 27:

  SQLSTATE[HY000] [2002] Connection refused
```


## 試したこと ##
　いろいろと検索していたら.envのファイルのdb_host の記述が誤っていたらしい。
「DB_HOST 127.0.0.1」とそれまで記載していた。
どうやらdockerを使う場合は.envのdb_hostにはコンテナ名にしないといけない模様。

![スクリーンショット 2022-12-24 10.09.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462069/a7077782-1bdf-7738-2fd5-b50d22e7811e.png)

以下のように設定。
```.env
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=test
DB_USERNAME=root
・
・

```

そしてまた
`composer install`　を実行
これまで出ていたエラーは無くなった

今度は次のエラーが出たが、、、
これは単純に.envで記載したDBがmysql上にないのだろう。。

```
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi

In Connection.php line 664:

  SQLSTATE[HY000] [1049] Unknown database 'test' (SQL: select * from inf
  ormation_schema.tables where table_schema = XXX and table_name = ABC)


In PDOConnection.php line 31:

  SQLSTATE[HY000] [1049] Unknown database 'test'


In PDOConnection.php line 27:

  SQLSTATE[HY000] [1049] Unknown database 'test'
```

`docker-compose exec db bash`　でmysqlのコンテナに入って
データベースを作成。

`exit`でコンテナから出て、また`docker-compose exec サービス名 bash`で
サービス用のコンテナに入り、
`composer install`　を実行

以下で表示され、無事composerのインストールが完了しました！！

```
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover --ansi
Discovered Package: aws/aws-sdk-php-laravel
Discovered Package: barryvdh/laravel-dompdf
Discovered Package: barryvdh/laravel-snappy
Discovered Package: beyondcode/laravel-dump-server
Discovered Package: chumper/zipper
Discovered Package: fideloper/proxy
Discovered Package: jenssegers/agent
Discovered Package: kris/laravel-form-builder
Discovered Package: laravel-notification-channels/apn
Discovered Package: laravel-notification-channels/fcm
Discovered Package: laravel/nexmo-notification-channel
Discovered Package: laravel/passport
Discovered Package: laravel/slack-notification-channel
Discovered Package: laravel/tinker
Discovered Package: laravelcollective/html
Discovered Package: nesbot/carbon
Discovered Package: nunomaduro/collision
Discovered Package: xethron/migrations-generator
Package manifest generated successfully.
```
【フロントエンドエンジニア】これ、必要ですか？という勇気を持って欲しい

## はじめに

フロントエンドエンジニアってどういう役割をになっていると思いますか？

UIやUIにまつわる機能を作る人。でしょうか？
それだけだと意識が足りないと思います。

僕曰く、**ユーザーに提供するサービスの最終防衛ライン**です。

## ユーザーに提供するサービスの最終防衛ラインとは？

**サービスや新機能などをリリースする際、開発フェーズにおいて、最後に携わる人**
ということです。

僕らが、作ってリリースしてしまえば、それは世の中に出てしまいます。

企画者が企画し、デザイナーがデザインをしてくれる。バックエンドエンジニアは抽象化された要件をAPIという形で提供してくれます。

それらを全て吸収し、実際の形に仕上げるのがフロントエンドエンジニアです。
**作られたものの全責任はフロントエンドエンジニアにある**ぐらいに思った方がいいかなと思います。

## フロントエンドエンジニアが意識すること

開発の最終ラインにいるわけですから、僕らが言われた通りのものを作ると実際のユーザーにその機能やサービスが提供されてしまいます。

だから僕はフロントエンドエンジニアこそ

- 「**これ、必要ですか？**」
- 「**これ、こうした方がよくないですか？**」

という勇気を持って欲しい。

### 他の職種の人のこと信頼してないの？

それは違う。信頼している。
企画者はユーザーのためを思って企画をしてくれていると思っているし、デザイナーはできる限りUXの高いものを仕上げようと思ってくれていると信じている。

でも、愛社精神がある人たちほど、いつしか**ユーザーのための機能**から**会社のための機能**にすり替わっている時がある。
いわゆる**売上・利益が積めるけど、ユーザビリティが下がるもの**を作ろうとしている時がある。

そして、それは悪ではない。実際、売上・利益が積めるということは、ユーザーに使ってもらえたということで、それが結果としてユーザーの利益になっている場合もある。

でも、それが最適だとはやっぱりどうしても思えない。
ユーザビリティ高く（ユーザーを騙すことなく）、売上・利益が上がる方法があると思うし、それを模索するのが僕たち運営の役割だと思う。

そして、何度もいうが、フロントエンドエンジニアはそれらをまとめ上げ、機能として完成させる人である。なので、最終の防衛ラインが何も言わなくていいわけがない。

### でも、もうほとんどの機能は出来上がってるし、今からひっくり返すのは？

むしろ今ひっくり返せてラッキーではないだろうか？
一度、ユーザーに提供してしまったら信頼が下がる。失った信頼を取り戻すのは1から作るより難しい。

それが嫌なら、企画の段階から口を出す必要がある。
企画MTGに招待してくれ。といって最初のフェーズで意見を言えるようにしておくんだ。

## そして、何よりも重要なのは信頼関係を作り上げておくこと

まとめの代わりとして、「**信頼関係**」についても触れておこうと思います。

企画者やデザイナーからすると、正直いい気がしないと思います。
自分達が頑張って作ったアイデアやデザインを後からひっくり返されるわけですから。
否定されたような気持ちになると思います。

今回の記事の主旨はそれを土返しにしてでも、ユーザーのために動くべきである。という記事ですが、彼らの気持ちを蔑ろにしているわけではありません。

誰しもが盲目になるんです。
だからこそ客観的に機能を見つめれるフロントエンドエンジニアが代表していう必要がある。

ということです。
嫌われ役みたいですね。

嫌われ役にならないためには、「信頼関係」がポイントになってくると思います。
普段からきちんとコミュニケーションをとり、相手のことをリスペクトしていることを伝える。

相手は自分のことをちゃんと評価してくれている。と思えるからこそ相手の意見を素直に聞くことができるんです。
だから、実は何よりも重要なのは普段から信頼関係を作りましょうね

ということかもしれません。
同一 PC 内で Azure CLI の複数バージョンを利用するアイデア

## 背景と目的

Azure CLI をバージョンアップしていくと、昔書いた Azure CLI のコードが動かなくなるケースがあります。これは、Azure CLI のリリースノートで「破壊的変更」と書かれたコマンドがあり、そのバージョンからは以前の仕様で動作しなくなる事を意味します。ところが、Azure CLI は同一 PC 内に複数のバージョンをインストールする事ができません。しかしながら、少しの工夫で異なるバージョンの Azure CLI を実行する事が可能なので実際やってみました。

## Python を使って複数バージョンの Azure CLI をインストール＆実行

```bash:bash
$ python3 --version
Python 3.10.8

$ python3 -m venv azcli236

$ . azcli236/bin/activate

$ pip install azure-cli==2.36.0

$ az version
{
  "azure-cli": "2.36.0",
  "azure-cli-core": "2.36.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {}
}

$ deactivate

$ python3 -m venv azcli237

$ . azcli237/bin/activate

$ pip install azure-cli==2.37.0

$ az version
{
  "azure-cli": "2.37.0",
  "azure-cli-core": "2.37.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {}
}

$ deactivate
```

## Docker を使って複数バージョンの Azure CLI を実行

```bash:bash
$ docker --version
Docker version 20.10.21, build baeda1f

$ docker run --name azcli236 -it mcr.microsoft.com/azure-cli:2.36.0

bash-5.1# az version
{
  "azure-cli": "2.36.0",
  "azure-cli-core": "2.36.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {}
}

bash-5.1# exit

$ docker rm azcli236

$ docker run --name azcli237 -it mcr.microsoft.com/azure-cli:2.37.0

bash-5.1# az version
{
  "azure-cli": "2.37.0",
  "azure-cli-core": "2.37.0",
  "azure-cli-telemetry": "1.0.6",
  "extensions": {}
}

bash-5.1# exit

$ docker rm azcli237
```

## 参考

https://learn.microsoft.com/ja-jp/cli/azure/release-notes-azure-cli?toc=%2Fcli%2Fazure%2Ftoc.json&bc=%2Fcli%2Fazure%2Fbreadcrumb%2Ftoc.json#role-1

https://learn.microsoft.com/ja-jp/cli/azure/microsoft-graph-migration#breaking-changes

https://learn.microsoft.com/ja-jp/cli/azure/run-azure-cli-docker
ruby 練習問題42　（アウトプット用）

問題
ユーザーが数字を2つ渡すと、それらを掛け算した結果を返すプログラムを作ってください。

定義する変数
2つの数字を、それぞれnum1, num2という変数にgetsメソッドを利用して定義してください。
という問題。
下記、実行結果の例。
```
#デスクトップに移動
$cd Desktop
#Rubyファイルを実行
$ruby argument_test.rb
最初の数字を入力してください
5
2番目の数字を入力してください
6
5と6をかけた答えは30です！
```
以下、模範解答
```ruby
def multiplication(num1, num2)
  puts "#{num1}と#{num2}をかけた答えは#{num1 * num2}です！"
end

puts "最初の数字を入力してください"

num1 = gets.to_i

puts "2番目の数字を入力してください"

num2 = gets.to_i

multiplication(num1, num2)
```
以下、解説
今回は基本的なdefメソッドとgetsメソッドの使い方の復習問題のようだがポイント引数の使い方であるらしい。
引数の受け取り側の名前は何でも良いということは、メソッドの呼び出し側と同じでも構わないということで、不自然に違う名前にするくらいなら、同じ名前にした方がわかりやすいことも多々ある。

メソッドには、複数の引数を渡すこともできます。複数の引数を渡した場合、引数の受取側はメソッドの呼び出し側での引数の順番で代入される値を決めています。今回はnum1, num2といった順番で引数を渡したため、メソッド側でもそれぞれnum1とnum2にそのままの順番で値が代入されています。
RailsチュートリアルでSass::SyntaxError: File to import not found or unreadable: bootstrap-sprockets.が出たので解決策を探ってみた。

<h1>問題</h1>
<h4>・RailsチュートリアルにあるBootstrapが導入できない。</h4>

<h1>結論</h1>
<h4>・custom.scssから@import "bootstrap-sprockets";を削除する。</h4>

```Scss:custom.scss
@import "bootstrap-sprockets"; ←この行を削除する
@import "bootstrap";
```
[bootstrap3から4への移行方法について　(Rails5)
](http://binbo-roku.com/bootstrap/programming/study/bootstrap)によると、@import "bootstrap-sprockets";という記述はbootstrap4からは必要がなくなっているようだ。

おそらく、rails-tutorialで想定しているのはbootstrap3でコードもそれを想定したものになっていたのかと。なんらかの理由でbootstrap4以上のバージョンが使用されていたため、(原因はよくわかっていません。)この記述があると、bootstrapがうまく起動しなかったのかなと思います。

<h1>解決するまでに行ったこと</h1>
<h4>・gem 'bootstrap-sass'を削除する。</h4>
<h4>・application.jsを作成して中身を書く。</h4>

```javascript:sample_app/app/assets/stylesheets/application.js
//= require jquery3
//= require popper
//= require bootstrap
```
<h4>・gem 'jquery-rails'を入れる。</h4>

```Ruby:Gemfile
gem 'jquery-rails', '4.5.1'
```

<h1>今回のエラーで感じたこと</h1>
bootstrapについては知識が全くなくて、なんとなく動くようになっただけで今回は終わってしまった感じがしています。なので、cssやjavascriptの学習とbootstrapの公式ページの確認をこれからやれるといいのかなと思いました。

<h1>参考記事</h1>

[bootstrap3から4への移行方法について　(Rails5)
](http://binbo-roku.com/bootstrap/programming/study/bootstrap)
Falling back to ALSA for audio output. PulseAudio is not available or could not be initialized.[WARNING:audio_manager_linux.cc(60)]

```bash
$ google-chrome-stable --headless --single-process --disable-gpu --disable-dev-shm-usage --dump-dom https://domains.google.com/checkip
[1224/005541.808998:WARNING:audio_manager_linux.cc(60)] Falling back to ALSA for audio output. PulseAudio is not available or could not be initialized.
[1224/005541.811767:WARNING:bluez_dbus_manager.cc(247)] Floss manager not present, cannot set Floss enable/disable.
<html><head></head><body>35.229.216.43</body></html>
```

# `--disable-audio-output`で警告を抑制できます

```bash
$ google-chrome-stable --headless --single-process --disable-gpu --disable-dev-shm-usage --disable-audio-output --dump-dom https://domains.google.com/checkip
[1224/005555.058735:WARNING:bluez_dbus_manager.cc(247)] Floss manager not present, cannot set Floss enable/disable.
<html><head></head><body>35.229.216.43</body></html>
```

# 参考

https://peter.sh/experiments/chromium-command-line-switches/#disable-audio-output