OmniAICreator/Qiita-1.07M huggingface dataset:
Railsで多言語化対応する！

今[自分が開発しているwebアプリ](https://www.code-sell.net/)を英語に対応しようとしたときにやったことを書いていきます。

[詳しくは>](https://qiita.com/UTOG/items/40baefaf9a4a668d39cc)

##インストール

```ruby:Gemfile
gem 'rails-i18n'
```
インストール

```
bundle
```

##config/application.rbに設定

```ruby:config/application.rb
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}').to_s]

    # 対応する言語。今回は日本語(ja)と英語(en)だけ
    config.i18n.available_locales = %i(ja en)

    # 上記の対応言語以外の言語が指定された場合、エラーとするかの設定
    config.i18n.enforce_available_locales = true

    # デフォルトの言語
    config.i18n.default_locale = :ja
```

##controller
```ruby:controller/application_controller.rb
    before_action :set_locale

    def set_locale
        I18n.locale = locale
    end

    def locale
        @locale ||= params[:locale] ||= I18n.default_locale
    end

    def default_url_options(options={})
        options.merge(locale: locale)
    end
```

##routes.rb
```ruby:routes.rb
  scope '(:locale)', locale: /#{I18n.available_locales.map(&:to_s).join('|')}/ do
    root "posts#index"
    resources :posts
  end
```

scopeで囲んだ部分が多言語対応するページです。

##多言語化
en.ymlとja.ymlを作ります。
多言語化したい文に

```erb:views
<%= t(:hello) %>
```
と書きます。helloのところは自由に変えてください

```yml:ja.yml
  ja:
    hello: こんにちは
      # モデルは全て activerecord を起点にする。
      # これにより、User.model_name.human / User.human_attribute_name({attr_name})でアクセス可能。
    activerecord:
      models:
        user: 'ユーザー情報'
      attributes:
        user:
          name: '名前'
          mail: 'メールアドレス'
          url:  'ウェブページ'
```

```yml:en.yml
  en:
     hello: "hello"
    # モデルは全て activerecord を起点にする。
      # これにより、User.model_name.human / User.human_attribute_name({attr_name})でアクセス可能。
    activerecord:
      models:
        user: 'User'
      attributes:
        user:
          name: 'Name'
          mail: 'Email'
          url:  'URL'
```

こんな感じでやっていきます。

参考
http://alfa.hatenablog.jp/entry/2013/12/03/221308
直近でTreasure Workflowではまったこと



# bqオペレーターがUSリージョン以外は使えない

digdagの[issue](https://github.com/treasure-data/digdag/issues/1088)としてはあがっているが。2019年の4月にあがったままなので対応されないのかもしれない...
issue内にshオペレーターを使ってbqコマンドを叩くワークアラウンドの記載があるが、Treasure workflowでは使えないので回避策なし。

# TreasureData → BQのエクスポートでUS以外の場合はlocationの指定が必要

US以外の場合、以下のような形でlocationの指定が必要

```yaml:sample.dig
+td2bq:
  td>: queries/xxx.sql
  result_connection: (connection_name)
  result_settings:
    project: gcp_project_name
    dataset: dataset_name
    table: tablename
    location: asia-northeast1
    mode: append
    max_bad_records: 0
    ignore_unknown_values: true
    allow_quoted_newlines: true
```

TDからBQへエクスポートする際の `result_settings` で設定可能なオプションは下記リンク。ただし、 `location` が書いていない...
https://github.com/treasure-data/treasure-boxes/tree/master/td/bigquery#supplemental

# BQエクスポート時にmode:replaceの場合にauto_create_tableとschema_fileが必要

以下のようにreplaceを使う場合、auto_create_tableをtrueにしてschema_fileも設定する必要がある

```yaml
+td2bq:
  td>: queries/xxx.sql
  result_connection: (connection_name)
  result_settings:
    project: gcp_project_name
    dataset: dataset_name
    table: tablename
    location: asia-northeast1
    mode: replace
    auto_create_table: true # appendでは必要はないがreplaceの場合は必要
    schema_file: '[{"name":....}]' # appendでは必要はないがreplaceの場合は必要
    max_bad_records: 0
    ignore_unknown_values: true
    allow_quoted_newlines: true
```

# 変数を入れ子で使えない

やりたかったことは、td_for_eachオペレーターを使って取得した値（以下サンプルでいうとaccountid）をsubタスクに変数として渡して、subタスク側で利用する。

```yaml:main.dig
+for_each:
  td_for_each>: queries/xxxx.sql
  engine: presto
  _do:
    +task1:
      _export:
        accountid: ${td.each.accountid}
      +task2:
        call>: sub.dig
```

```yaml:sub.dig
td>: queries/xxxx.sql
result_connection: xxxxx
result_settings:
  xxxxx: ${accountid}
```

sub.dig内の `xxxxx: ${accountid}`  が変数の入れ子になるので値を渡すことができない。
取得した値を利用するには、`xxxxx: ${td.each.accountid}` とするしかない。

本当はsub.digを切り出すことで、別のところからも再利用したかったのに。

# 参考

- [digdag: td_for_each](https://docs.digdag.io/operators/td_for_each.html)
ローカルで動作をさせるまでに必要なコマンド

#環境
この記事ではmacOS Catalina10.15.6にインストールしたRuby 2.6.5を使っています。

#目的
git cloneしてから、ローカルで動作をさせるまでに必要なコマンドを入力します。

# 結論
以下のコマンドを入力することで、クローンしたアプリを使用できるようになります。
※リモートリポジトリのURLとアプリケーションのディレクトリを確認してから行ってみてください。

```
% git clone <リモートリポジトリのURL>
% cd アプリケーションのディレクトリ
% bundle install
% yarn install
% rails db:create
% rails db:migrate
% rails s
```

# 最後に
最後までお読みいただきありがとうございます！
GitHubを使用している方のお役に立てれば幸いです！
Chromeリモートデスクトップで人のPCを遠隔操作する

Chromeのリモートデスクトップ拡張機能を使えば、なぜかChromeを超えて相手のPCにフルアクセスできる。
Mac→Windowsでリモートデスクトップしたいときにおすすめ。

## ユースケース
テレワーク環境でPCサポートなどがしづらいときに運用担当者が使うときなど

## 手順
### 操られる側🎎
- 以下の『他のユーザーとパソコンを共有する』に従ってアクセスキーの発行を行う。
https://support.google.com/chrome/answer/1649523?co=GENIE.Platform%3DDesktop&hl=ja
- 払い出したアクセスキーを操ってほしい人に送る。 

### 操る側👨🏽💻‍
- 以下の『パソコンでリモート アクセスを設定する』に従ってプラグインをChromeに追加する
https://support.google.com/chrome/answer/1649523?co=GENIE.Platform%3DDesktop&hl=ja
- Chromeリモートデスクトップを開き、操られる側から送られたアクセスキーを入力してリモートデスクトップする。
ノードを追加・置換・削除

前回の
[属性値やテキストの取得](https://qiita.com/TaHiroki/items/5e6b818e13e927f8a2ef)
の続き


あるHTMLのdivタグの文章を変えたいとなると

 - 要素ノードを取得
   - 直接取得
   - 文書ツリー間の行き来
   - イベントドリブンモデル
 - 属性値やテキストを取得・設定
   - 取得・設定
   - フォームタグ
 - ノードを追加・置換・削除

の、最後、ノードを追加・置換・削除の部分となります。

##ノードを追加・置換・削除

HTMLの編集には「innerHTML」を使うことができたが、これはセキュリティなどの観点からも使うタイミングを考えたいといけなかった。今回のアプローチはノードを作成して任意のノードにくっ付けると言う操作についてまとめる。
これで、要素・属性とテキストを区別できるので、ユーザーからの入力によってスクリプトが混入する危険が回避されやすくなる。反面、コードは冗長になりやすいため、
　　シンプルなコンテンツの編集　→　innerHTMLプロパティ
　　複雑なコンテンツの編集　　　→　今回のアプローチ
と使い分けると良い。

###ノードの作成
まず、必要なタイプのノードを作成する。イメージはパズルのピースを作る感じ。
作成するにはcreateXxxxxと言う、ノードに応じて様々な種類がある。
主なcreateXxxxxメソッド

| メソッド| 生成するノード|
|:--|:--|
| createElement（要素名）| 要素ノード|
| createAttribute(属性名)| 属性ノード|
| createTextNode(テキスト)| テキストノード　※プレーンなテキストなのでHTMLがあってもテキスト扱いとなる。|
| createCDATASection(テキスト)| CDATAセクション|
| createComment(テキスト)| コメントノード|
| createEntityReference(実体名)| 実体参照ノード|
| createProcessingInstruction(ターゲット名、データ)| 処理命令ノード|
| createDocumentFragment()| ドキュメントの断片|

###ノード同士の組み立て・追加
ノード同士を組み立てる。ピースを一つの塊にする。

appendChild/insertBeforeメソッドを使う。

| メソッド| 概要|
|:--|:--|
| elem.appendChild(node)| elem:要素オブジェクト　の最後の子要素として、node:追加ノード　を追加する|
| elem.insertBefore(node, desNode)| elem:要素オブジェクト　の子要素　desNode:指定箇所のノード　の後ろに node:追加ノード　を追加する |

###属性ノードの追加
属性ノードの設定は、属性と同名のプロパティを設定するだけ。または、createAttributeメソッドを使用する。

```java
let anchor = document.createElement('a');
// anchor.href = "http://~~~";
let href = document.createAttribute('href');
href.value = "http://~~~";
anchor.setAttributeNode(href);
```

・DocumentFragment()について
appendChildで追加するたび、コンテンツが再描写される。そのため、forなどで繰り返して追加するとパフォーマンスが低下する。そのため、DocumentFragment()オブジェクト上でノードの塊を作成してから、一括で追加する。


###ノードの置換・削除
####ノードの置換　replaceChildメソッド

```javascript
 elem.replaceChild(after, before)
```

elem:要素オブジェクト　after:置き換え後のノード　before:置き換え対象のノード

####ノードの削除　removeChildメソッド, removeAttributeメソッド

```javascript
 elem.removeChild(node)
 elem.removeAttribute(属性名)
```

elem;属性オブジェクト　node:削除対象のノード


これで、追加・置換・削除ができるようになった。
結構、一つの物を変更するだけでも手間がかかるんですね…
いい勉強になりました！

→　完
→　と思いきやおまけ　[スタイルシートの操作](https://qiita.com/TaHiroki/items/9fc01a3ee9bb06e67d1c)
【Obsidian】Preview機能の使い方

# １．はじめに

ObsidianのPreviewk機能の紹介。Obsidianがインストールしてあることを前提に、実際に確認してもらう内容になっています。

## 「Obsidianって何？」という方へ
こちらのページを参考にしてください。
https://qiita.com/koKekkou/items/f1f684f0d7dadb658d02

# ２．Preview

対象のメモを切り替えることなしに、リンク先のメモの内容の一部が参照できる機能。
編集モードではCtrlを推しながらマウスをリンクに動かすと表示される。

## 設定

- プラグイン/```Page preview```

## メモ（３つ）

### refTest
```
# メモの構造に合わせたインデント
- [[refTestChild]]
	- [[refTestChild#投稿サイト一覧]]
		- [[refTestChild#Qiita]]
			- [[refTestChild#^4c806a]]
			- [[refTestChild#^4c806a|内容説明１]]
		- [[refTestChild#Medium]]
			- [[refTestChild#^821026]]
			- [[refTestChild#^821026|内容説明２]]

# 文章の途中でリンクを入れる
Cygwinの構築手順やツールの使い方については[[refTestChild#^4c806a|Qiita]]にメモを残しておく。その他のことは、 [[refTestChild#^821026|Medium]] に記事を書いていく。 [[refTestChild#^821026|内容説明２]]は考え事を整理して言葉にすることが目的になっている。
```

### refTestChild
```
#  投稿サイト一覧

## Qiita

技術者向け記事投稿サイト。記事にマークダウン記法が利用できる。 ^4c806a

##  Medium

ブログ記事投稿サイト。Twiiterの人が立ち上げたサイトで、長文用Twitterのようなものを目指している。 ^821026
```

### refTestParent
```
# リンクのネストでPreviewの見え方。
[[refTest]]
```

## 見た目

refTestParentからrefTestを参照し、表示されたプレビューから更にrefTestChildを参照。
![2020-10-28 ObsidianPreview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/665190/f7593dad-757e-6fea-bdc3-f2b4ff5fac3a.png)
- refTestChildの行末にあるブロックIDは、refTestからブロックID指定でリンクを作った時にObsidianが作成する。
- 自分で直接ブロックIDを記入することも可能。行末に、半角スペースを挟んで```^英数```と書く。

# 雑感
編集するメモ（note）を変えることなく、ちょこっと見られるって結構便利だと思います。

# 以上
【Cloudflare】ファイアーウォールの適用順

Cloudflareのファイアーウォールタブには複数の種類のFWが存在する。
これら複数種類のFWがどういった順序で適用されていくかを記載する。

## 全体の処理順
![b187593b-ed77-40bd-9284-fb1c92281a73-1920x1031r.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282929/75d7dfc5-2105-cb06-3fa1-09fbcaa7ae77.png)

IPアクセスルール・ファイアーウォール ルール・ゾーンロックダウンなどのそれぞれがアクションを設定できる。
そのアクションで許可/ブロックがなされると、後続のルールはスキップされる。

## Firewall Ruleの「許可(Allow)」について
ファイアーウォール ルールのアクション「許可(allow)」は、『他のファイアーウォール ルール』を許可するだけで、WAFやRate limitまでは許可しない。

後続のルールをスキップしたいときは、アクション「スキップ(bypass)」を選択する。
Laravel モデル

## Model
### php artisan make:model Test
Test.phpモデルのファイルが作成されます。
### php artisan make:model Models/Test
Modelディレクトリの下にTest.phpファイルが作成されます。
### php artisan make:model Models/Test -mc
-mcをつける事によってマイグレーションファイルとコントローラーを作成する事ができます。
### php artisan migrate
このコマンドでデータベースにテーブルを作成できます。
![スクリーンショット 2020-10-28 16.13.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/663122/ee8ff00f-3473-b4cc-1990-0de10e8e2930.png)
gazebo起動時にエラー（Error: BadAccess (attempt to access private resource denied) 10）


gazebo起動時にエラー（Error: BadAccess (attempt to access private resource denied) 10）

```
$ gazebo
X Error: BadAccess (attempt to access private resource denied) 10
  Extension:    130 (MIT-SHM)
  Minor opcode: 1 (X_ShmAttach)
  Resource id:  0x2400004
X Error: BadShmSeg (invalid shared segment parameter) 128
  Extension:    130 (MIT-SHM)
  Minor opcode: 5 (X_ShmCreatePixmap)
  Resource id:  0x1a9
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x240000d
X Error: BadDrawable (invalid Pixmap or Window parameter) 9
  Major opcode: 62 (X_CopyArea)
  Resource id:  0x240000d
X Error: BadAccess (attempt to access private resource denied) 10
  Extension:    130 (MIT-SHM)
  Minor opcode: 1 (X_ShmAttach)
  Resource id:  0x141
X Error: BadShmSeg (invalid shared segment parameter) 128
  Extension:    130 (MIT-SHM)
  Minor opcode: 5 (X_ShmCreatePixmap)
  Resource id:  0x1a9
...
```

以下を実行すると解決した

```
export QT_X11_NO_MITSHM=1
```

# 参考
[DockerでGUIのアプリ動かすためのメモ](https://qiita.com/tnarihi/items/275c009e9dec1306893f)
[https://github.com/P0cL4bs/WiFi-Pumpkin-deprecated/issues/53](https://github.com/P0cL4bs/WiFi-Pumpkin-deprecated/issues/53)
でかいファイルを分割＆結合するコマンド

test.tar.gzという名前の、でかいファイルを2GBづつに分割

```
split -b 2000m -a 2 test.tar.gz test_p_
```

結合

```
cat test_p_* > test2.tar.gz
```

でかいログファイルをUSBメモリに保存する時などに使う

# 参考
[【UNIX】ディレクトリをtar.gzにして分割する](https://www.mtioutput.com/entry/2019/01/16/174929)
UnityからのWebSocket接続時にハンドシェイクでエラーが出た際の対処法

### websocket-sharpを使ってWebSocketに接続
[websocket-sharp](https://github.com/sta/websocket-sharp)はUnityで使えるWebSocket接続用のライブラリ。
基本的な使い方は以下の通りで、WebSocketインスタンスを作ってURLを引数として渡し、Connectメソッドで接続するだけと非常にお手軽。

```C#:WebSocketController.cs
using System;
using UnityEngine;
using WebSocketSharp;

public class WebSocketController : MonoBahaviour
{
    private WebSocket webSocket;

    // wssから始まるWebSocketの接続先URL。
    private string baseURL = "wss://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

    // WebSocketインスタンスを作成し、接続先URLを渡す。
    webSocket = new WebSocket(baseURL);

    // WebSocketへ接続。非同期で行いたい場合はwebSocket.ConnectAsync()を使う。
    webSocket.Connect();
}
```

### An error has occurred during a TLS handshake. 
接続をしようとすると上記のエラーメッセージが出た。
URLがwssから始まるセキュア通信用のプロトコルだったため、webSocketインスタンスをセキュア通信ができるように弄ってあげる必要があるみたい。
そこで以下のようにコードを修正。

```C#:WebSocketController.cs
using System;
using UnityEngine;
using WebSocketSharp;

public class WebSocketController : MonoBahaviour
{
    private WebSocket webSocket;

    private string baseURL = "wss://XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";

    webSocket = new WebSocket(baseURL);
  
    // この一文を追加する。
    webSocket.SslConfiguration.EnabledSslProtocols = System.Security.Authentication.SslProtocols.Tls12;

    webSocket.Connect();
}
```
webSocket.SslConfigurationはセキュアな通信を確立するために使われるクラスで、その中のEnabledSslProtocolsというプロパティが認証用のプロトコル（[SslProtocols 列挙型](https://docs.microsoft.com/ja-jp/dotnet/api/system.security.authentication.sslprotocols?view=netcore-3.1)）を格納するプロパティとなっている。

そこへSslProtocolsの「Tls12」をセットしてあげることで、セキュアな通信ができるようになる。

あとは通常時と同じくConnectメソッドで接続してあげればエラーは解消された。
ubuntuにpyqt5をインストールする

ubuntuにpyqt5をインストールする

以下を実行するとよい

```
$ sudo apt-get install -y python3-pyqt5 python-pyqt5
```

pip3がない場合は以下実行してインストールする

```
$ sudo apt-get install -y python3-pip
```

以下コマンドではないようです

```
$ sudo pip3 install pyqt5
ERROR: Could not find a version that satisfies the requirement pyqt5 (from versions: none)
ERROR: No matching distribution found for pyqt5
```



# 参考
[ModuleNotFoundError: No module named 'PyQt5'](https://github.com/spyder-ide/spyder/issues/7252)
[No matching distribution found for PyQt5](https://stackoverflow.com/questions/59289369/no-matching-distribution-found-for-pyqt5)
[Ubuntu18.04 LTSにQt5をインストールしよう！](https://enjoysoftware.hatenablog.com/entry/2019/12/02/144425)
pip3でnumpyインストールを試みるもエラー

pip3でnumpyインストールを試みるもエラー

```
$ sudo pip3 install numpy
...
ModuleNotFoundError: No module named 'numpy'
```

pip3を更新してnumpyをインストールし直して解決

```
$ pip3 install --upgrade pip
$ sudo pip3 install numpy
```

# 参考
[pip3 install --upgrade pipを実行後、pip3が開けない](https://teratail.com/questions/223914)
Raspberry Pi の Ubuntu にシリアルで接続

こちらでインストールした Ubuntu 20.10 にシリアルで接続しました。
[Raspberry Pi に Ubuntu 20.10 をヘッドレスインストール](https://qiita.com/ekzemplaro/items/3dc7c6ba40b71cd83995)

Ubuntu 20.10 はデフォールトで、/dev/ttyS0 が使えます。

Raspbian から cu で接続しました。

```bash
sudo cu -s 115200 -l /dev/ttyS0
```

ログイン前
![ubuntu_a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/aa3b4689-b629-c22c-3fcc-922ee51d6226.png)

ログイン後
![ubuntu_b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/ba289a27-be56-163c-916f-575794b3fa0e.png)
ubuntuのdockerコンテナ内でpingがないときは、"iputils-ping net-tools"をインストールするとよい

ubuntuのdockerコンテナ内でpingがないとき

```
$ ping
ping: command not found
```

以下をインストール

```
$ sudo apt-get update
$ sudo apt-get install iputils-ping net-tools
```
docker push時のエラー解決メモ"unauthorized: incorrect username or password"

docker push時のエラー解決メモ

```
$ docker push xxx/yyy
The push refers to repository [docker.io/xxx/yyy]
dc63c2755f46: Preparing 
...
644879075e24: Waiting 
unauthorized: incorrect username or password
```

logout/loginをやり直して解決した

```
$ docker logout
$ docker login
```
git : vscodeで扱うgitのあれこれ(個人メモ)

初書：2020/10/28
PC：macOS 10.15.7
git version 2.28.0

# 前書き
個人的メモなので、さほど解説とかはないかも

# 前提
gitの理解

# 拡張機能
・GitLens
・Git Graph

# バージョン確認
ターミナルにて

```zsh
% git --version
```

# gitの開始
ターミナルにて

```zsh
% git init
```

# 名前とメールアドレスの設定
ターミナルにて / git initの後

```zsh
% git config --local user.name xxx
% git config --local user.email xxx@example.com
```
`xxx`と`xxx@example.com`は任意に変更
なお、グローバルで変更する場合は、`--local`を`--global`に


# 終わりに

git自体実はあんまり理解していないので、随時追加していく…かも

# 参考サイト
[君には1時間でGitについて知ってもらう(with VSCode) - Qiita](https://qiita.com/jesus_isao/items/63557eba36819faa4ad9)
[Gitのコミットメッセージの書き方 - Qiita](https://qiita.com/itosho/items/9565c6ad2ffc24c09364)
ssh接続時のエラー解決メモ（Bad owner or permissions ）

ssh接続時の以下のようなエラー解決メモです

```
$ ssh **
Bad owner or permissions 
```

以下のように所有権を適切に更新して解決

```
$ chmod 600 ~/.ssh/config
```

さらに以下のように、Load key "xxx/.ssh/[keyname]": Permission deniedとなった場合も

```
$ ssh [hostname]
Load key "xxx/.ssh/[keyname]": Permission denied
xxx@xxx.xxx.xxx.xxx: Permission denied (publickey).
```

以下のように所有権を適切に更新して解決

```
$ sudo chown xxx:xxx ~/.ssh/[keyname]
```
[PHP/symfony1.4]外部キー未設定のテーブルをDoctrineでJOINしたい

symfony(1.4)のDoctrineを使って、外部キーが登録されていないテーブル同士をJOINさせるのに躓いた時のメモ。

## 元のプログラム

```php5
$q = StoreTable::getInstance()
      ->createQuery('s')
      ->setHydrationMode(Doctrine_Core::HYDRATE_SCALAR)
      ->select('s.*')
      ->leftJoin('s.StoreItem si')
      ->leftJoin('si.Item i')
      ...(略)
      ->execute();
```
StoreItemテーブルには、store_idカラムが存在してるけれど、訳あって外部キーが設定されていない。このテーブルを結合しないと他のテーブルと結合できる方法がない状態だった。

この状態でクエリを実行すると、

```
Oct 28 12:23:48 symfony [err] {Doctrine_Table_Exception} Unknown relation alias StoreItem
```
とエラーが出てしまう。

## 解決策

Doctrineの実行前に、bindを使ってリレーションを一時的に定義する。


## 修正したプログラム

途方に暮れていたら、無理やり結合させている他の人のコードを見つけた。笑
ドキュメントで見つけられなかったけど下のような書き方をして、リレーションを一時的に？定義できるみたい。

```php5
StoreTable::getInstance()
      ->bind(array('StoreItem as StoreItem', array(
        'local'   => 'store_id',
        'foreign' => 'id',
      )),
        Doctrine_Relation::ONE
      );

$q = StoreTable::getInstance()
      ->createQuery('s')
      ->setHydrationMode(Doctrine_Core::HYDRATE_SCALAR)
      ->select('s.*')
      ->leftJoin('s.StoreItem si')
      ->leftJoin('si.Item i')
      ...(略)
      ->execute();
```
G検定の勉強法、試験、結果について(2020#2)

#なぜG検定を受験したのか
<p>
G検定を受験した理由は私が通所しているリワークにてスタッフと月1回の面談した際に「仮に転職するならどんな職業につきたいか？」と質問があり、私が「プログラムの研究職に就きたい。できれば人工知能の関係で」と答えました。<br>
元々私自身はG検定の存在は知っていましたが、面談を受けてスタッフがG検定を知り、費用が半額な事もあり受験を勧められました。<br>
当初はジェネラリスト向けの検定という事を知っていたので、個人的にはあまりエンジニアとしての経験にはつながらないと考えていました。
</p>
#G検定の勉強法
<p>
今回は基本的には以下の本を5月末から以下の期間で読み始めました。
</p>
## 読んだ本
<p>
深層学習教科書 ディープラーニング G検定（ジェネラリスト） 公式テキスト：5月31日〜6月6日<br>
人工知能プログラミングのための数学がわかる本：6月7日〜6月13日<br>
AI白書 2020：6月14日〜6月27日<br>
G検定 ～最短合格指南書～：7月3日〜7月4日
</p>
## 問題集
徹底攻略 ディープラーニングG検定 ジェネラリスト 問題集 徹底攻略シリーズ：6月28日〜7月2日
##勉強法
<p>
基本的には読んだ本については1日1時間を目安に一週間で読み切る事を心がけて初めから終わりまで一度読みました。<br>
AI白書については量が膨大だったため二週間時間を取っています。<br>
また書籍は全てKindleで販売されている電子書籍をiPadやiPhoneで読んでいました。<br>
公式テキストとAI白書については読み進めるうちに面白さを感じる部分が多く、楽しく読む事ができました。<br>
逆に数学の本に関しては当初読めば理解できると踏んでいましたが、微分と行列と確率については読んだ本では中々難しく、一朝一夜に身に付く知識ではない様に感じました。<br>
『G検定〜最短合格指南書〜』についてはKindle Unlimitedで無料だった事もあり、資料として軽く目を通した程度になります。
</p>
<p>
問題集については2日で総仕上げ問題以外を一度何も見ないで解きました。<br>
その後試験時間を考慮して総仕上げ問題以外を、実際の試験同様に参考書籍やインターネットでの検索を活用して、100分で解く事をしました。<br>
最後に試験同様に参考書籍やインターネットの検索を活用して120分で総仕上げ問題を解く事を行っています。<br>
総仕上げ問題は1回しか通しで解いていませんが、この時は85%弱の正解率でした。
</p>
## 使用した書籍
深層学習教科書 ディープラーニング G検定（ジェネラリスト） 公式テキスト
https://www.amazon.co.jp/exec/obidos/ASIN/B07H2ZR6M2/hatena-blog-22/

人工知能プログラミングのための数学がわかる本
https://www.amazon.co.jp/exec/obidos/ASIN/B079TLRZ8K/hatena-blog-22/

ＡＩ白書　２０２０
https://www.amazon.co.jp/exec/obidos/ASIN/B085RKWNPB/hatena-blog-22/

G検定 ～最短合格指南書～ Kindle版
https://www.amazon.co.jp/exec/obidos/ASIN/B07ZN2G8C1/hatena-blog-22/

徹底攻略 ディープラーニングG検定 ジェネラリスト 問題集 徹底攻略シリーズ
https://www.amazon.co.jp/exec/obidos/ASIN/B07NDVCN99/hatena-blog-22/

#G検定の試験について
<p>
2020年7月4日にG検定の方を受験しました。<br>
結果としては以前のブログにも登場しますが、著作権や自動運転の基準、また兵器としての使用などに関する法律や倫理の問題が60問近く出題されました。<br>
またディーブラーニングについてもCNNやRNNについて自体の問題はなく、その応用であるFCNやRNNでの自然言語解析に関する問題が多かった様に感じています。<br>
そして問題の順番が法律や倫理に関する問題が前半に固まっていました。
</p>
<p>
今回の私の受験の失敗としては、法律や倫理に関する問題についてインターネットで調べる事に時間を使いすぎてしまい、後半のディープラーニングの問題についてあまり調べる時間がありませんでした。<br>
その為、後半に関してはとりあえず埋めるだけで問題を進めましたが、それを振り返る時間がなく試験が終了しました。<br>
試験の自己採点はしていませんが、受験後の感覚としては5割から6割程度当たっていれば良い方だと感じ、今までの合格基準から考えると非常に合格は厳しいと感じました。
</p>
#G検定の結果について
<p>
G検定の結果については7月16日の午後にメールにて合格との内容をいただきました。<br>
正直結果があまり良くないと思っていたので意外でしたが、合格できたことは嬉しかったです。
</p>

#G検定受験の感想
<p>
G検定を受験する過程で色々知り、考えている以上に人工知能の奥深さを知ることができ、人工知能を使うことの必要性も知れました。<br>
また人工知能の人材不足についてと教育についても知ることができた為、今後人工知能の人材育成を社内外で行うことがかなり必要になりそうだと感じます。<br>
色々と知ることができ、有意義な試験勉強をすることができたと感じました。
</p>
[aftereffects] effect("スライダー制御")("スライダー") で起こる多言語トラブルの原因

```
※記事に関しましてご注意下さい
こちらでは「対処法そのもの」よりも「そもそも何故その問題がおこるのか」を探るべく調査した内容になります。
実際の現場では具体的な解決策として様々な手段がとられますが、その根源は実は同じであることも多く、
そこを知っておくことでこれから未来に起こるトラブルも防ぎたい、心の準備をしておきたい、というメモになります。
あくまでも個人調査のメモです。間違い・勘違いが含まれている可能性もありますので予めご了承ください。
```

～ デフォルト名を参照した expression の怪 ～
起こる場面：
　スライダー制御を expression で参照した場合など

## 調査のきっかけ
aftereffects で起こるトラブルの中に
`作成時と異なる言語（英語・日本語）でファイルを開くと expression エラーが出る`
というものがあります。

これについてはいろんなサイトにいろんな対応が書かれてあり、

```Javascript
thisComp.layer("A").effect("スライダー制御")("スライダー") // aftereffects 日本語
thisComp.layer("A").effect("Slider Control")("Slider") // aftereffects 英語
```
のように言語による記述の違いがあること、また

```Javascript
thisComp.layer("A").effect("ADBE Slider Control")(1)
```
のようにして共通化の書き方をするといいかも、などの情報があります。

今回はこの原因を潜って調べたメモです。 

## 調査の結果
実はこれは根本に１つの仕様というか問題が潜んでいて、それは

```
「デフォルト名で作成した場合、言語によってその内容が変わってしまう」
　※ デフォルト名で作成、とはユーザーがあえて名前を付けなかった場合
```
というもののようです。

### 問題が起こることを確認する方法
1) 日本語モードで起動し、「スライダー制御」でエフェクトを作成し保存
2) 英語モードで起動し、1) のデータを開き直す
3) "Slider Control" に変わっている
### 問題が起こらないことを確認する方法
1) 日本語モードで起動し、「スライダー制御 1」でエフェクトを作成し保存
2) 英語モードで起動し、1) のデータを開き直す
3) "スライダー制御 1" で残っている

## 運用上どう対処するべきか

```Javascript
thisComp.layer("A").effect("スライダー制御")("スライダー")
```
例としてこの ↑ 場面では
　１．エフェクト名：effect("スライダー制御")
　２．プロパティ名：("スライダー")
がそれぞれ名前を持っており、
　１ はデフォルト名から変更が可能（「スライダー制御 1」や「横調整スライダー」など）
　２ はリネーム不可（UI 的にも）なのでデフォルト名以外にはならない
となっています。

これを前提に実験してみたところ、

はじめから 「スライダー制御 1」のように名前を変更してあった場合

```Javascript
thisComp.layer("A").effect("スライダー制御 1")
```
までは英語モードでも問題なく動作しました。
ただ、２は変更不可のため同じこと（リネーム）ができません。
この場合はエクスプレッション制御がどれもパラメータを１つしか持たないことを踏まえて
　("スライダー") と書かずに (1)
と書くことで名前のトラブルを回避できました。

### 対処法１

上の条件を組み合わせると

```Javascript
thisComp.layer("A").effect("スライダー制御 1")(1)
```
という`デフォルト名を避けた書き方`であれば実は起動言語に依存せずに動作しました。


## 共通の書式（ADBE ～）ではだめなのか
いやいやそれよりも

```Javascript
thisComp.layer("A").effect("ADBE Slider Control")(1)
```
と書けばよいのでは、、、という方もいらっしゃると思います。（状況によっては可）

実はこの記述では避けられないパターンがあり、
`エフェクト項目にスライダー制御を「複数」組み合わせた場合`
に対応できないです。（その状況が無いフローの場合は問題がでない）

また、もし複数スライダー制御があった場合には

```Javascript
thisComp.layer("A").effect("ADBE Slider Control")
```
の記述では必ず最初のエフェクトにヒットしてしまうようです。
この場合も

```Javascript
thisComp.layer("A").effect("スライダー制御 1")(1)
thisComp.layer("A").effect("スライダー制御 2")(1)
```
であればそのまま動作します。

追記：
もちろん、aftereffects 内で敢えて同じエフェクト名にリネームした場合、つまり

```
スライダー制御 1
スライダー制御 1
スライダー制御 2
```
が同じレイヤーのエフェクトとして重複している場合、
最初のエフェクトにヒットしてしまい、場合によって想定外の動作になります。
※ここまでいってしまうとどの手段も同じで index 番号指定になってしまいそうです。

つづく。
Railsのフォームで過去の日付を入力させない方法

# はじめに
カレンダーから日付を入力してもらう際に、過去の日付を選択できないようにしたい。
保存するモデルのカラムはDate型を使用。
ビューでのフォーム作成にはform_withを使用。
# 開発環境
ruby 2.6.5
Rails 6.0.3.3
# 
# 方法
※余計な記述は省いています
私の場合はorderモデルのstart_date（Date型）に保存するためのフォーム

```ruby:index.html.erb

<%= form_with model: @order, url: item_order_path, local: true do |f|%>
   <%= f.date_field :start_date, class:"order-date-form %>
<% end %>
```
カレンダー表示ができて、日付を選択できるようになってます。



<img src="https://i.gyazo.com/45d7496a4febd7db15e3efa788e9944a.png" width="200px">

しかし、現状では過去の日付も選択できてしまいます。

これを解消するために記述を追加します。

```ruby:index.html.erb

<%= form_with model: @order, url: item_order_path, local: true do |f|%>
   <%= f.date_field :start_date, class:"order-date-form, min: Date.current %>
<% end %>
```
同じようにカレンダーは表示されますが、過去の日付は選択できないようになりました。
<img src="https://i.gyazo.com/51f2a775540b86a5924e78145c6d2c17.png" width="200px">

"Date"についてはActive_supportが用意してくれているもので、デフォルトで使えるようです。
"Date.today"ではなく"Date.current"が推奨されています。

詳しくはこちら [Railsガイド](https://railsguides.jp/active_support_core_extensions.html#date%E3%81%AE%E6%8B%A1%E5%BC%B5 "Railsガイド")


# さいごに

バリデーションやコントローラーで防ぐのは各々で追加してみてください。
Webサーバー 'IIS Express' に接続できませんでした。が出たときの対応

## 結論
1. Visual Studioを閉じる
2. ソリューションフォルダ内の`.vs`フォルダを削除する
3. Visual Studioを起動してデバッグ実行する

## 理由とか
`.vs`の中にある `config/applicationhost.config` のポートの整合性が合わなくなっているのか…詳しいことはあまり調べていませんが。
一度削除して再度起動すればフォルダごと再作成されるので、デバッグはできるようになります。


## 参考
https://developercommunity.visualstudio.com/content/problem/720271/unable-to-start-iisexpress.html
AWS Security JAM 2020に参加して（2020年10月参加）

本日はAWSが実施したイベント「[AWS Security JAM 2020](https://pages.awscloud.com/JAPAN-event-OE-Security-Jam-20201028-reg-event-LP.html)」に参加しました。
AWSの運営の方から「問題の内容に触れない範囲での感想はOK」との話がありましたので、問題内容は一切記載せずにイベント内容と感想についてアップしておこうと思います。
私としては、なかなか良いイベントであり、参加する意義があったと思っています！

#イベントの位置付け
まず、今回のイベントは「[AWS Security Roadshow](https://aws.amazon.com/jp/about-aws/events/2020/securityroadshow2020/)」の一環で開催されました。
「AWS Security Roadshow」は以下のようなイベントです。

>お客様が抱える様々なセキュリティに対する課題とその対応方法、実際のお客様のAWSのセキュリティサービス活用事例、今後必要となるセキュリティ対策、AWSのセキュリティの方向性などを包括的にご説明する予定です。企業・組織の中で、セキュリティやコンプライアンスに課題をお持ちの皆様（営業、マーケティング、開発や運用など）、セキュリティに関する意思決定に関わる管理職や役員の方、公共機関や金融機関のセキュリティ担当者など、AWSセキュリティの最新情報を知りたい方は是非ご参加ください。

そして、「AWS Security JAM」は以下の通りです。

>AWS Security JAM は、権限管理、自動化、インシデントレスポンスなどに関連するサービスを利用して、参加者が各課題ごとに AWS 環境を適切に修正するゲーミング形式のイベントです。 参加者はオンライン上で提示されたセキュリティ上の課題に対して、実際の AWS マネジメントコンソールを利用し、ご自身の知識、経験を活用し、必要に応じて学習をしながら課題解決に取り組みます。 （提示される課題は re:Invent2019や過去にAWSのイベント（例： AWS Professional Services が実施したイベント）で出題された課題を含みます）

ゲーミング形式というのが面白そうだと思い参加することにしました。
開催日は10月28日（水）。
仕事しながらは無理…と判断し、「有給休暇」カードを切って自宅から参加することとしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561572/7dd0b58a-8f4d-aea4-2d9a-a16a3a59b3cf.png)

#参加方法
参加方法は「[AWS Security JAM 2020](https://pages.awscloud.com/JAPAN-event-OE-Security-Jam-20201028-reg-event-LP.html)」で申請するだけです。

後日案内のメールが届きます。
事前に実施しておく必要があるのは「[AWS Jam](https://jam.awsevents.com/)」への登録のみ。
あとは開始前に接続する為のWebinarにアクセスするのみです。
WebinerでAWS JAMのセキュリティコードを教えてもらえるので、それを入力することで当日のイベント環境に接続します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561572/461e802b-064d-cc03-2fe2-4ce24875f029.png)
#内　容
内容は以下の通りです。

>13:00-13:30 Security JAMご紹介
13:30-16:00 Security JAM演習
16:00-16:30 クロージング

**＜ルール＞**
・個人単位で9問の問題を解く速さを競う。
・ヒントが1問につき3つまで取得できるが、ヒントを空けるたびに減点される。
  ※なので、ヒントを空けずに回答すると高得点となる。

ルールは上記の通りシンプルで、2時間30分の制限時間内で他の参加者と競うイベントなのです。以下のマップから問題を選択して1問ずつ解いていきます。問題は好きな問題から開始できます。それぞれの問題でAWSコンソール環境が準備されているので、その環境に対してセキュリティ対策を実施して、問題が解決したら完了となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561572/41500d57-599f-01d2-1375-fe72ab734eac.png)
問題内容については詳細は記載できませんが、基本的な内容から、最近開始されたサービスまで幅広くセキュリティ機能の知識が問われます。最初の方の問題は皆が解けますが、あとになるほど難易度が上がっていくわけです。
私は9問中4問くらいまではなんとか解けましたが、5問目くらいからヒント3つとも空けないと全然歯が立たなくなり…自分の実力が分かって勉強になりました（3つ目はほぼ答え・・・）。ヒント3つでも解けない場合はAWSの方に質問することも可能です。1問解らなくなり質問したのですが、親切に支援してもらって乗り切りました！

もちろん、上位者は最終問題まで完了しており、すごいなぁと感嘆しました。
どれだけ実務経験を積んだら、この境地に至るのかなぁ・・・

|問題NO |参加数　|完了数| 
|:------|:------|:------|
|1|76|72|
|2|69|59|
|3|58|42|
|4|52|25|
|5|37|21|
|6|54|18|
|7|33|25|
|8|27|10|
|9|21|02|

#感想
時間制限ありで実力を競う形で面白いイベントだと思いました。
参加料無料ですし、問題も練られていて勉強になります。
そして他の方との実力差も感じることができて、また学習意欲が高まります。
こんな楽しいイベントを企画して頂いた運営の方々には感謝の気持ちでいっぱいです。
年休を取得して参加した甲斐がありました。

毎年実施しているようなので、来年度もぜひ参加して、
自分の実力を試す機会にしたいと思いました。

この記事を参照された方も、興味があれば次回参加することをお勧めします！
【Vue.js】Async/awaitとaxiosによる非同期処理

methodsに記述したaxiosによるHTTP通信の完了を待ってから残りの処理をしたい必要があったのですが、少し詰まったので記録として残しておきます。
※Async/awaitやaxiosについての説明記事ではありませんのでご了承ください

```javascript:
  mounted: {
    this.settingXxx();
  },
  methods: {
    fetchSample: async function(){
      let ret = null
      // 非同期処理を記述
      await axios.get('(url)', {
        .then((response) => {
          ret = response
        })
        .catch((error) => {
          this.errorMsg = 'Error! Could not reach the API. ' + error
          console.log(this.errorMsg)
        })
      return ret
    },
    settingXxx: async function(){
      // this.fetchSample()の実行が完了するまで待機
      let result = await this.fetchSample()
      console.log(result) //待機後の残りの処理を記述
    },
  }
```

fetchSample();によりPromiseオブジェクトが返され,
Promiseの状態が確定しその結果が返されるまで、JavaScriptを待機させます。

## 参考にさせていただいた記事
- [非同期処理ってどういうこと？JavaScriptで一から学ぶ](https://qiita.com/kiyodori/items/da434d169755cbb20447 "非同期処理ってどういうこと？JavaScriptで一から学ぶ")
- [async/await、promise・・これが最後の「JavaScriptの非同期処理完全に理解した」](https://qiita.com/_takeshi_24/items/1403727efb3fd86f0bcd "async/await、promise・・これが最後の「JavaScriptの非同期処理完全に理解した」")
- [async await の使い方](https://qiita.com/niusounds/items/37c1f9b021b62194e077 "async await の使い方")
CodePipelineのアーティファクトで悩んだ時のメモ

# はじめに
初めてCodePipelineでパイプラインを作っていて、Buildステージのアーティファクトがよくわからなくて悩んだ時のでメモです

# メモ
## CodePipelineのアーティファクトストア(S3)のある場所
アーティファクトストアはアーティファクトがあるS3バケットのことです

- パイプライン作成時
高度な設定 → カスタムロケーション で指定する事ができます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/de35038a-4544-893c-800f-6f72dda49420.png)
---

- デフォルトのロケーションの場合
パイプライン → 設定 → アーティファクトストア を見ると場所があります
(ここでは codepipeline-us-west-1-999999999999 になります)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/7c0ff7eb-87bc-7b0a-79a7-146048dc470e.png)

## アーティファクトストアの中
デフォルトのロケーションをみると codepipeline-(リージョン)-(アカウントID)になるので、この中には複数のアーティファクトが置かれます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/384971d0-41cf-867d-3343-d60aa7e0f9ff.png)

このように今作った SamplePipelineLS3 と以前作った hellow-world があります

## アーティファクトの場所
Sourceステージでは SourceArtifact
Buildステージでは BuildArtifact
上記の2つで指定されたアーティファクトはそれぞれ
codepipeline-(リージョン)-(アカウントID)/(パイプライン名)/ 配下にあります
( ここでは codepipeline-us-west-1-999999999999/SamplePipelineLS3/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/83f3f708-836c-dc41-393a-006a96844a9d.png)

名前が短かくなっていますが、調べてないのでちょっとわかりません
BuildArtif/
SourceArti/

### 名前の変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/244bcd91-5030-2783-0159-27cb84bed71a.png) ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/384c44ab-9288-91c3-1d28-0061dfb6e47f.png)
アーティファクト名を Soruceステージで ohayou、Buildステージで oyasumi に変更するとそれぞれ合わせて出来ます
古いアーティファクトは消えません
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/b723f70e-f7b6-3b0a-5b6d-1dcf11d2145d.png)
それぞれこの中にあるzipファイルをダウンロードして解凍すると、中にSourceステージやBuildステージでファイルが入っています

### 数を増やす
BUildステージの出力アーティファクトの数を2つに増やします
oyasumi と nemurenai です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/4dc760d6-2031-499f-8cdb-fb366710589e.png)
この時は buildspec.yml も修正します
<details><summary>ここ</summary><div>

```buildspec.yml
version: 0.2
phases:
  build:
    commands:
      - echo Build started on `date`
      - sam package --template-file template.yml --s3-bucket $S3_ARTIFACT_BUCKET --output-template-file packaged.yml

artifacts:
  secondary-artifacts:
    nemurenai:
      files:
        - "**/template.yml"
    oyasumi:
      files:
        - '**/packaged.yml'

```

元は下記です。secondary-artifacts を追加しています。

```
(略)
artifacts:
  files:
    - '**/packaged.yml'
```

</div>
</details>

下記のように3つのフォルダができます。(古いのは削除しました)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/b5c0b8ea-267f-6f61-651d-a5b47205d68b.png)

それぞれzipファイルをダウンロードして中を見ると下記が入っています
nemurenai → template.yml
oyasumi → packaged.yml
ohayo → template.yml と buildspec.yml 等

buildspec.yml を指定していなかったり、ミスっているとビルドがエラーになりフェーズ詳細で下記のメッセージが表示されます

```
CLIENT_ERROR: no definition for secondary artifact usimitu in buildspec
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128663/962c0266-4c29-4c78-ac78-f3ddfa79475a.png)

---

とりあえず以上になります

残課題
- ビルドプロジェクトで追加したアーティファクトの扱い
UnityでAndroidのプラグインのクラスが見つからなくて(ClassNotFoundException)何故か使えないときに怪しむべきProGuard、Minify

# Androidのプラグイン何故か使えない
俺は完璧に設定しているのにビルドして実行するとClassNotFoundExceptionでAndroidプラグインが使えないことがあって時間を費やしたのですが、いろいろ調べた結果ProGuardのMinifyという処理が原因でした。ClassNotFoundExceptionの原因調べててProGuardまでたどり着かなくね？という懸念があったので共有します。
自分がたどり着いたのは[これ](https://forum.unity.com/threads/native-share-for-android-ios-open-source.519865/page-11)にProGuradの記述があったからです。。。

## リリースビルドはMinifyが有効になっている
デフォルトの状態でリリースビルドするとProGuardによるMinify処理が行われるようになっているみたいです。
チェックが入っていてMinifyを切るとプラグインの機能が使えるようになりました。
![スクリーンショット 2020-10-28 16.45.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57778/f2d49b4f-e8cc-e74f-bb8a-0603c85c1c63.png)



## ProGuardって何？
ProGuardはアプリのアプリの圧縮、難読化、最適化の機能みたいですね。
[アプリの圧縮、難読化、最適化](https://developer.android.com/studio/build/shrink-code?hl=ja)
この処理によってプラグインで使っている機能まで取り去られるみたいなことが起きているみたいです。

## ProGuardの設定
ProGuardの設定ファイルを作成することで勝手に処理されない部分を指定できるようになっているようです。Minifyを切ってしまうとこの機能の恩恵が受けられなくなるのでこの方法で対処するのがベターなのではないでしょうか。

![スクリーンショット 2020-10-28 16.46.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57778/36d27e27-4868-9a02-5d08-59f7518f282b.png)

この Custom Proguard File というチェックをつけるとproguard-user.txtが作成されるのでそれを編集することで設定できます。

```proguard-user.txt
-keep class android.support.v4.content.** {
    *;
}
```

例えばandroid.support.v4.contentでClassNotFoundExceptionが出ていた場合はこんなふうに指定する感じです。この状態でビルドするとMinify対象外になる感じですかね。別の書き方もあるようですので、リンクを参考してください。

## まとめ
- 何故かClassNotFoundExceptionが出たときはMinifyを疑ってみよう。
- ProGuardの設定で対処しよう。
- これわかりづらいから何とかならんのか。。。

## 参考
[Unity に Admob 実装した時、Proguard や Minify を無効にせずに Releaseビルドする方法](https://www.hirohomme.com/2019/05/25/unity-に-admob-実装した時、proguard-や-minify-を無効にせずに-releaseビルド/)
[Unity Android ビルドの Minify オプションの罠](https://monry.hatenablog.com/entry/2019/03/12/163447)
gatsby（react）にNoto Sans JPを入れてMaterial-UIのthemeでfont-familyを上書き指定する

メモです。

参考：
https://www.npmjs.com/package/fontsource-noto-sans-jp
https://mrtry.hatenablog.jp/entry/2018/05/07/193920

#インストール
`npm install fontsource-noto-sans-jp`
もしくは
`yarn add fontsource-noto-sans-jp`

でNoto Sans JPをインストールする。

#インポート

`gatsby-browser.js`で

```react
import { ThemeProvider } from 'styled-components'
import { MuiThemeProvider } from '@material-ui/core/styles'
import { theme } from './src/utility/theme'
import "fontsource-noto-sans-jp"
import "fontsource-noto-sans-jp/500.css"
import "fontsource-noto-sans-jp/900-normal.css"
```
などする。

#Material-UIのthemeのfont-familyを上書き指定

```react
import { createMuiTheme } from '@material-ui/core/styles'

// fontFamilyを上書き
export const theme = createMuiTheme({
  typography: {
    fontFamily: ['Noto Sans JP', 'sans-serif'].join(','),
  },
})

```
CKFinderでアップロードファイルサイズの設定を変更しようとしたらハマった話

お客さん：CKFinderでちょっと大きめのファイルもアップロードできるようにしたい！！
僕：よっしゃconfig変えるだけでいけるな。余裕や！！
一時間後...
僕：あれconfig変えたのにアップロードできない。。オワタ。。

ということが発生したので忘れないようにメモメモ。実は単純な話でした。

# まずDocumentを確認
https://ckeditor.com/docs/ckfinder/ckfinder3-php/configuration.html
![スクリーンショット 2020-10-28 17.18.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/402204/f87a34e1-6af2-ab67-5e72-d6c90bbe03a8.png)
どうやらfileSizeに20Mとか2Gとか設定すればいいみたいだ(ここまでは余裕モードでした)

# アップロードできない。なんか設定効いてないっぽい。。
色々設定を変えてみてもある一定までは効くけど、それ以上はアップロードできない状態になってました(ここら辺から暗雲が立ち込める)
しょうがないのでCKFinderのソースを確認してみることに。

```ckfinder/core/connector/php/vendor/cksource/ckfinder/src/CKSource/CKFinder/Command/Init.php
$resourceTypeObject = array(
  'name'              => $resourceTypeName,
  'allowedExtensions' => implode(",", $resourceType->getAllowedExtensions()),
  'deniedExtensions'  => implode(",", $resourceType->getDeniedExtensions()),
  'hash'              => $resourceType->getHash(),
  'acl'               => $aclMask,
  'maxSize'           => $resourceType->getMaxSize() ? min($resourceType->getMaxSize(), $phpMaxSize) : $phpMaxSize
)
```
ソースを追っていてふと気づく。`$resourceType->getMaxSize()`と`$phpMaxSize`の最小値を設定してる？

```ckfinder/core/connector/php/vendor/cksource/ckfinder/src/CKSource/CKFinder/Command/Init.php
$phpMaxSize = 0;

$maxUpload = Utils::returnBytes(ini_get('upload_max_filesize'));
if ($maxUpload) {
  $phpMaxSize = $maxUpload;
}

$maxPost = Utils::returnBytes(ini_get('post_max_size'));
if ($maxPost) {
  $phpMaxSize = $phpMaxSize ? min($phpMaxSize, $maxPost) : $maxPost;
}

//ini_get('memory_limit') only works if compiled with "--enable-memory-limit"
$memoryLimit = Utils::returnBytes(@ini_get('memory_limit'));
if ($memoryLimit && $memoryLimit != -1) {
  $phpMaxSize = $phpMaxSize ? min($phpMaxSize, $memoryLimit) : $memoryLimit;
}

```
さらに追っていくと。
あ、やはり`upload_max_filesize`とか`post_max_size `を超えないようにしている！！
まあ冷静に考えてみればそりゃそうですよね。。

# 解決
ということでCKFinderのconfigの設定と合わせて、phpの`upload_max_filesize`も合わせて許容値までに上限をあげて解決しました。
毎日更新されるGoogleスプレッドシートの値を定期的に別シートにコピーする方法

余命三ヶ月で作成したプログラムが別プログラムに差し替わる事が決定して、資産が消失するのでメモ。

##背景
従業員のシフト管理をスプレッドシートで管理していて、
Webサイト上に従業員の出勤有無を出力する事となった。

従業員数が多く、二ヶ月先までシフトが組んであり
サイトに出力するのは直近5日のみ。

前回以下の記事でコケた事もあり。
[GoogleAppsScript(GAS)でスプレッドシートの値を取得した時にハマったこと](https://qiita.com/Kis3_/items/41e2e60b6a6bdde473f8)
必要なデータを毎日別シートに抽出して、抽出結果をjsonp形式で配信する設計とした。
配信は前回記事にある処理を流用。Webサイトに出力する処理はJavaScriptでゴリゴリ書いた。
本記事はデータを毎日別シートに抽出する処理のみを記載。

##処理イメージ
毎日特定の条件でシートからデータを抽出し、別シートにコピーする。
![FireShot Capture 086 - 無題のスプレッドシート - Google スプレッドシート - docs.google.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90415/b222c423-5ab8-6751-1c33-b7cbe3f8ee8a.png)

##必要最低限の機能
・同じ名前のシートが存在しなければ作成。
　→誰かの手によってコピー先シートが削除されても問題ない様にする。

・現在日付から5日後まで抽出を対象とする。

##抽出処理
```javascript
function weekCp() {
  //コピー先シート存在確認
  var sheet = set_sheet("直近5日");
  //コピー先シートクリア
  sheet.clearContents();
  //コピー元シートのデータを二次元配列で一括取得
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var original = spreadsheet.getSheetByName('シート1');
  var var1 = original.getDataRange().getValues();
  
  //現在日付を取得
  var date = new Date();
  var date_D = new Date(date.getFullYear(),date.getMonth(),date.getDate(),0,0,0);
  
  //5日後の日付を取得
  var date_range = new Date(date.getFullYear(),date.getMonth(),date.getDate(),0,0,0);
  date_range.setDate(date_range.getDate() + 4);
  
  //フィルタ後の配列を初期化　ヘッダー情報は固定なため、ベタ
  var data = [
    ["日付", "時間", "場所", "状況", "担当者"]
  ];
  
  for(var i=1; i < var1.length; i++){
    //当日以前のデータは対象外なため最初に落とす
    if(var1[i][0] >= date_D) {
      //それが5日の範囲内か
      if(var1[i][0] <= date_range) {
        data.push(var1[i]);
      }
    }
  }

  //データの書き込み
  //横(行)
  var lastColumn = data[1].length
  //縦(列)
  var lastRow = data.length
  //開始行　開始列　終了行　終了列
  sheet.getRange(1, 1, lastRow, lastColumn).setValues(data)
}


//同じ名前のシートがなければ作成
function set_sheet(name) {
  var sheet = SpreadsheetApp.getActive().getSheetByName(name)
  if(sheet)
    return sheet

  sheet = SpreadsheetApp.getActiveSpreadsheet().insertSheet();
  sheet.setName(name);
  return sheet;
}
```

##トリガー
毎日0時に起動する様にする。

★[編集]　→　[現在のプロジェクトのトリガー]を選択
![sss.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90415/0e07a648-ff6a-e8a8-1352-119ffe07eeef.png)

★トリガーを追加
![FireShot Capture 093 - weekCp - プロジェクトのトリガー - Apps Script - script.google.com.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/90415/afcf5796-f38e-7bd9-cdac-6b552d94a225.png)
以上で毎日0時以降に勝手に起動してくれる。

##おわりに
余命三ヶ月って悲しいですね。
is演算子のキャストと早期returnの組み合わせの際の注意点

## この記事で述べていること
- is演算子でのキャストは結果がtrueになる際のみ行われます。ですが、**結果に関係なくキャスト後の変数の宣言はなされます(falseの場合中身は未初期化になる)**
- また、ifステートメントの条件式内でis演算子を用いてキャストすると、**キャスト後の変数のスコープはそのifを囲むブロック内となります。**
- この性質のせいで、早期returnで弾くと同時にキャストし、キャスト後の変数をその後使おうとすると怒られます。
- そういう時はasとnullチェックを使いましょう。
  
## 説明
is演算子を使ってifステートメントの条件式内でキャストを行った場合、**キャスト後の変数のスコープはそのifを囲むブロック内となります。**  
また、is演算子でのキャストはインスタンスの型が一致した場合のみ行われます。一致しない場合**変数は宣言されますが、中身は未初期化になります(nullが入るわけでもありません)**  
この性質のせいで、早期returnでインスタンスの型が一致しない場合を弾いた後、キャスト後の変数を後々の処理に使おうとするとちょっと問題が生じます。


  ```c#:インスタンスの型チェックと早期return
public void hoge(Object obj){
    //こうしてobjのインスタンスの型が任意の型でない場合を弾いた後
    if((obj is int x) == false) return;

    //後々の処理にxを使おうとすると
    //未初期化の可能性があると言われ怒られる
    Console.WriteLine(x);

    //同名変数の再宣言も不可で怒られる
    int x = 1;
}
  ``` 

コンパイラから見たらintじゃない場合最初のifで弾かれてるからifの外で使っても大丈夫なんてわからないので、怒られます。   
かといって変数が死んでいるわけではないので、同名変数の再宣言も不可です。怒られます。  
考えてみれば当たり前の話で馬鹿らしいですが、私はこれで数十分無駄にしました。

## 解決策
ではどうするか。as演算子とnullチェックを組み合わせましょう。
  
```c#:as演算子との組み合わせ
public void hoge(Object obj){
    int x = obj as int;
    if(x == null) return;

    //怒られずにnullチェック済みのxを使って処理が可能
    Console.WriteLine(x);
}
```

これで解決ですね。

## 最後に
マサカリお待ちしてます。

## 参考サイト
- is、switch の拡張 (型スイッチ)  
https://ufcpp.net/study/csharp/datatype/typeswitch/
- [雑記] 識別子のスコープとオブジェクトの寿命  
https://ufcpp.net/study/csharp/start/st_scope/?p=3#declaration-expressions
【Android】switch/caseでR.id.XXXXを書いたら警告が出た

# 事の発端

アクションバーの戻るボタン実装方法を調べていて、
以下の書き方の記事がよく見かけたので、

```java
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    int id = item.getItemId();
    switch (id) {
        case R.id.home:
            // ...
            break;
        default:
            break;
    }
    return super.onOptionsItemSelected(item);
}
```
その通りに実装したら、こういう警告がでてしまいました。
> Resource IDs will be non-final in Android Gradle Plugin version 5.0, avoid using them in switch case statement.

# if-else文のほうが良いらしい

[AndroidStudioのガイド](
http://tools.android.com/tips/non-constant-fields)では、
`R.id.XX`は、ビルドするまでfinal staticではないから、らしい。

なので、if-else文で判定するようにしたら警告は消えました。

```java
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
    int id = item.getItemId();
    if (id == R.id.home) {
      // ...
    } else {
      
    }
    return super.onOptionsItemSelected(item);
}
```

# どうしてもswitch/caseを書きたい場合

gradle(モジュール)のLintを無効にすれば良いようです。

```
android {
    
    lintOptions {
        disable 'NonConstantResourceId'
    }
}
```

### 環境
* Android Studio 
  * 4.1
* Android Gradleプラグインバージョン 
  * 4.1.0
* Gradleバージョン 
  * 6.5
AWS Lambda Layers作成から紐付けまでさらっと解説

## はじめに
Pythonを扱う前提の記事です。

## Layers(レイヤー)とは
ガイドによると
>レイヤーは、ライブラリ、カスタムランタイム、またはその他の依存関係を含む ZIP アーカイブです。レイヤーを使用することで、関数のライブラリを使用することができます。

ライブラリのような共通で使用するモジュールをLayerにすることで、デプロイパッケージにライブラリを含める必要がなくなります。
つまり、Lambdaでサードパーティ製のライブラリやモジュールを使用する際に、Layerに格納して各Lambda関数から呼び出して使用するというような使い方ができます。

## 注記
・Lambdaで一度に利用できるLayerは5つまで
・解凍後のデプロイパッケージのサイズ制限 250 MB

## ディレクトリ構成
Lambda実行環境のパスは /opt ディレクトリとなるので、
Layerのディレクトリ構成としては /opt/python/Layer となります。

レイヤー自体のパッケージ構成はこんな感じ。

```
python
├ layer.py (共通処理などコードも入れられます。common的に扱える)
├ Crypto (外部ライブラリその1)
├ psycopg2 (外部ライブラリその2)
├ sqlalchemy (外部ライブラリその3)
…etc
```

## Layerの作成
ローカルで作成してみます。

ライブラリを場所指定でpip installする。

```
$ pip install pycryptodome -t .
```

そしてzip

```
$ zip -r  ../python .
```

AWS上でLayerの作成を行います

![スクリーンショット 2020-10-28 16.57.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392337/9ca204e4-d054-803b-27df-f6c80c322c2c.png)

上から順に
・名前(必須)
・説明(なくても可)
・アップロード(先ほど作成したzipを選択)
・互換性のあるランタイム - オプション(忘れがちになるので注意)
・ライセンス - オプション(なくても可)

「作成」をクリックしLayerを作成します。


## Lambda関数に紐付け

今度はLambda関数にLayerを紐付けます。

Layerを紐付けたいLambda関数から「デザイナー」を選択し、
「レイヤーの追加」を選択。

![スクリーンショット 2020-10-28 16.55.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392337/9efdd6b3-27c0-1ea1-56d1-8d647dd77c63.png)

「レイヤーの選択」から「カスタムレイヤー」をクリックし作成したLayerを選びます。
その後「バージョン」を設定し、「追加」をクリックして完了です。

Lambdaから呼び出すときはimportして呼び出します。

```Python
import layer
```

## よくあるミス
・LambdaはAmazon Linux上で動作するので、
pip installした環境によっては実行エラーとなるライブラリもあります。

・AWSにアップロードしたLayerはバージョンごとにダウンロードすることも出来ます。
そしてLayerが増えてくるとディレクトリで、こんな感じで管理することもあるかと思います。

```
test_layer
├ python
    ├ layer.py 
    ├ Crypto 
```

この場合、そのまま解凍し修正してzipしがちですが、
そのままzipすると親ディレクトリも圧縮してしまいアップロード後の展開時にディレクトリ階層とマッチしなくなるので
作成した時と同じく中身をzipしましょう。

```
$ zip -r  ../python .
```

## まとめ
Layerは上手く使えばLambda間でのコード共有など非常に便利です。
上手く活用していきましょう。

## 参考
https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/configuration-layers.html

https://stackoverflow.com/questions/54467095/module-initialization-error-cannot-load-native-module-crypto-cipher-raw-ecb
【Rails】遷移前のURLのパス名を取得してリンク先を変更する

#### 環境
*rails* 6.0.3


## 説明
遷移前のページの`URL`内の**パス名**によって、ページに表示するリンク先を分岐させる方法。

```ruby:該当のviewファイル
<% if URI(request.referer.to_s).path == 'パス名' %>
  #前のページが指定したパスだった場合のリンク先
<% else %>
  #その他のリンク先
<% end %>
```

1. `request.referer`は文字列を返す。  
※ `URL`に数値（`integer`）がある状態でリクエストされた際にエラーにならないように`to_s`で文字列に変換しておく必要がある。
2. `Ruby`の`URIモジュール`を使用して、`request.referer`をラップすると、パスだけを要求することができる。


## 参考記事
URLすべてを取得して、ページに表示するリンク先を分岐させる方法
https://qiita.com/taka_571/items/9b1c82d8fcc602df8a1a
【RSpec】NameError: uninitialized constant FactoryBotというエラーが出た話

こんにちは、あおい（https://twitter.com/aoi_engineer ）です
今回は、RSpecにてテストコードを書いているときにNameError: uninitialized constant FactoryBotというエラーが出てしまった話をしていきたいと思います。

<h2>環境</h2>
rails：6.0.3.4


<h2>エラー内容</h2>

FactoryBotを導入後に

```
% bin/rspec      
```

を実行すると以下のようなエラーが出る。


```
An error occurred while loading ./spec/models/user_spec.rb.
Failure/Error: config.include FactoryBot::Syntax::Methods

NameError:
  uninitialized constant FactoryBot
```

<h2>原因</h2>
おそらくRSpecのFactoryBotがうまく反映されていない。

<h2>解決策</h2>

もう一度Gemfileを確認する。

```ruby
group :development do
 #省略
 gem 'factory_bot_rails'
end
```

あ、、、記述する箇所を間違えていた。
正解は以下の「test」という記述のあるdevelopmentでしたね。

```ruby
group :development, :test do
 #省略
 gem 'factory_bot_rails'
end
```

<h2>最後に</h2>
かなり初歩的なエラーでしたが、ハマる人は多いと思うので、ぜひ参考にしてください。
うまく動かない Xcode Command Line Tool を諦めて再インストールする前に確認すること

## 実行環境と現象
- Mac Pro (Late 2013)
- macOS Catalina ver. 10.15.7
- Xcode ver. 12.1 (12A7403)

```xcodebuild``` したかったけど、動かなかった。

```
$ xcodebuild -version
xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance
```


## インストールされてるか
homebrew が動いてりゃインストールされてるんでしょうが、一応以下にあるので、確認。

```
/Library/Developer/CommandLineTools
```

## Location は設定されているか

Xcode > Preference > Locations で確認
![Screen Shot 2020-10-28 at 15.47.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245908/e321563c-578d-0a60-5a91-8b2c4f5e3da0.png)

私のは、ここが入ってませんでした。勝手に入らないの？homebrew, xcode の順に入れたから？

兎に角、動いた。

```
$ xcodebuild -version
Xcode 12.1
Build version 12A7403
```


## ダメなら再インストール

```
xcode-select --install
```

または、

```
rm -rf /Library/Developer/CommandLineTools
xcode-select --install
```

または、[More Downloads for Apple Developers](https://developer.apple.com/download/more/) からダウンロードしてインストール。
魔王「この世の全てを曇り空にしてくれるわッ！！」【Photoshop 2021】

#このままでは世界は暗黒の曇り空になってしまう
![maou.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/3c74e9c2-2811-44c1-83a0-eff66dd8c025.gif)**魔王曇天**「クックック・・・きたか勇者よ・・・お足元が悪い中、ご苦労なことだ。お前がこうしている間にも、この世は曇り空になっていっておるぞ！！」
![bf00.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/ba5a4c3d-4893-93d4-2ee3-954ca3736979.jpeg)

![yusha.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/32a99982-67fd-a6a7-645c-c9251aa86e07.gif)
**勇者フォトショ**「そうはさせないぞ・・・魔王曇天！」


**魔王**「しかし、お前に何ができるというのだ？？」
**魔王**「お前が**従来のペンツールや選択範囲を駆使して、曇り空を青空に置き換えている時間よりも、私がこの世を曇りに変える魔力のほうが上**なのだ！！ハッハッハ！！！！」

##──勇者は何かを唱え始めた

**魔王**「無駄なことを・・・！！」

**魔王**「いくらフォトショップ**AIが進化して自動選択の精度が上がった**所で、**空だけを抽出することなど不可能**なのだ！！」

**魔王**「クライアントから**地獄のような曇天素材を85枚**提供され、**『チャチャッと青空にしておいてくださぁ～い。』**と言われた**ワシの苦しみを、この世のデザイナー共にに知らしめてやるのだ！！！！**」


**勇者フォトショ**「黙れ！！」
**勇者フォトショ**「負の遺産を後世に残すことしか考えず、技術の進歩から目を反らしたお前にデザイナーを語る資格はないッ！！」

##勇者フォトショ「編集＞空を置き換え！！」

──　まばゆい光があたりを照らす


**魔王**「ば、ばかな・・・！！！！」
![set03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/fce944ef-11ae-77cc-223d-de8da3d53007.jpeg)
![set02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/dfa62be1-eb13-523d-2643-e25adeabd486.jpeg)



**魔王**「空が一瞬で・・・！！！！」



##精霊AIアドビのご加護

**勇者フォトショ**「精霊AIアドビのご加護により、**編集メニューから「空を置き換え」**でAIによって自動で空と建物や電線を自動で検出できるようになった。機械学習の得意とするところ・・・」
**勇者フォトショ**「**青空の他にも虹を出したり、夕方にすること**や、お前の好きな曇天にすることも可能な危険な魔法だ。」
![sora02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/7580bc80-d78a-fc5b-05b2-5789e748f414.png)

**勇者フォトショ**「・・・魔王よ、これを見てくれないか・・？」

──　勇者は一枚の写真を取り出した

**魔王**「・・・？」

![soramain.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587632/fff382e8-1586-a36a-66f1-20449c539978.jpeg)


**魔王**「これは・・！！」

**勇者フォトショ**「そう、空だけの写真だ。**ここまでくるともう原型がわからない。**
クライアントが『**電線だけ残してこの空を夕方にしてくれませんか？』**とか**意味不明なことを言いだしても、**できる時代になったんだ。」

**魔王**「・・・俺はもう・・・」
**魔王**「クライアントの理不尽な要求に屈しなくてもよいのか・・・？」

**勇者フォトショ**「そうだ、精霊アドビのご加護により、俺たちは救われたんだ。」


###こうして世界に平和は訪れた。
CentOS7 VirtualBOX yumが使えない

yumが使えない。

```
#yum list installed

Could not retrieve mirrorlist...
14:curl#6 - "Could not resolve host:mirrorlist.centos.org; Unknown error"
......
```

エラー名で検索し下記の記事を拝見

https://qiita.com/taro0219/items/5bde092868b5ac817977

名前解決が出来ていないときのエラーみたいです。
記事に従い設定を行います。

```
#ip a
2:enp0s3
3:enp0s8

#nmcli c modify enp0s3 ipv4.dns 8.8.8.8
Error: unknown connection 'enp0s9'.
```

コネクションが設定されていないみたいです。
確認して設定します。

```
#nmcli device
DEVICE TYPE     STATE        CONNECTION
enp0s3 ethernet disconnected --
enp0s8 ethernet disconnected --

#nmcli connection show enp0s3 | grep connection
connection.autoconnect no

#nmcli connection modify enp0s3 connection.autoconnect yes

#nmcli device
DEVICE TYPE     STATE        CONNECTION
enp0s3 ethernet connected    enp0s3
enp0s8 ethernet disconnected --
```
デバイスとコネクションの設定完了
もう一度行います

```
#yum list installed

Could not retrieve mirrorlist...
14:curl#6 - "Could not resolve host:mirrorlist.centos.org; Unknown error"
......
```

同じエラーです。
「yum 使えない」で検索してヒットしたものを確認します

https://qiita.com/Nether_2046/items/bd897fdf16616ec90b67

DNSの設定がされていない場合があるそうです。
早速確認します。

```resolv.conf
nameserver 8.8.8.8

```

設定されていなかったため「8.8.8.8」を設定
もう一度実行

```
#yum list installed

.
.
.
.
.

```

実行できました。
yum list installedもインターネット接続が出来ないと行えないみたいです。
DNSの設定はきっとホストPCに依存するのかな、、、
今度検証します。