OmniAICreator/Qiita-1.07M huggingface dataset:
ECRにあるDockerイメージをTrivyでスキャンするツールを作ってみた

# 前置き
AWS ECSでDockerを本番運用する際に脆弱性チェックするためのツールを作りました！
そのツールの内容と使い方を説明していきます。リポジトリは[こちら](https://github.com/homoluctus/ecranner)。

# ツール説明
## 開発動機
AWS ECSを本番運用する際に脆弱性を持続的にチェックするツールがなかったので開発しました。
有料であればあるのかもしれませんが、金銭的コストがかかるので自作することにしました。

## 使用言語・ソフトウェア
- Python3.7
- Pipenv
- Docker
- Trivy

### Pythonライブラリ
- requests
- boto3

## 機能
### イメージの取得
ECRからDockerイメージを取得するために[Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ecr.html)を使っています。
ECRへのログインは環境変数に認証データをセットしてあれば自動でログインしてくれます。ログインが成功すれば、指定したAWSアカウントのECRにあるDockerイメージを全て取得します。現段階ではタグによって取得するイメージのバーションを制限できますが、イメージ名では制限できません。
あと、ソースを読んでもらえればわかりますが所々でコマンドを使っています。これはおいおいSDKに置き換えて行きたいと思っています。

### 脆弱性スキャン
脆弱性スキャンにはタイトル通り、[Trivy](https://github.com/aquasecurity/trivy)を使わせていただきました。
Trivyといえば、先日aquasecurityに買収されたニュースがありましたね。個人で開発したOSSが買収されるなんて夢がありますよね:grin:

### Slack通知
Dockerイメージを脆弱性スキャンした結果をSlackへ通知します。今回はSlack APIではなく、[Requests](https://github.com/psf/requests)を使ってSlackへPOSTしています。また、メッセージのレイアウトには[Blocks](https://api.slack.com/reference/messaging/blocks)を採用しました。色をつけるために従来のattachmentsも使っていますが・・・
Slack通知の内容は、イメージ名・パッケージ（ソフトウェア）名・脆弱性の説明・深刻度・ID・参考リンクとなっています。
見た目はこんな感じです⬇️

![slack_ui.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/173064/bdf803f8-39fc-83d3-f92d-18112c08bad8.png)



Referenceで変な感じに改行されていますが、これはSlackに表示される時にこんな感じになってしまいました。<-原因がわからん:thinking:

# 使い方
このツールはDockerイメージを用意しているのでDockerがインストールされている環境であれば簡単に試すことができます。
GitHub AcitonsとCLIで実行する方法を説明します。

## GitHub Actions
GitHub Actionsで毎日9時に定期実行する例を紹介します。

```..github/workflows/scan.yml
on:
  schedule:
    - cron: '0 9 * * *'
name: Scan Docker Image
jobs:
  scan:
    name: Scan
    runs-on: ubuntu-18.04
    steps:
      - name: scan images
        uses: docker://iscream/ecranner
        env:
          AWS_ACCOUNT_ID: ${{ secrets.AWS_ACCOUNT_ID }}
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: 'ap-northeast-1'
          SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
          SLACK_CHANNEL: '#random'

      # jobの成否を通知
      - name: slack notification
        uses: homoluctus/slatify@master
        if: always()
        with:
           type: ${{ job.status }}
           channel: '#random'
           job_name: ':trivy: *Scan Image*'
        env:
           SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
```

## CLI
### .envファイルの作成
値は自身の環境に合わせて変更してください。

```..env
TZ=Asia/Tokyo
AWS_ACCOUNT_ID=xxxxxx
AWS_ACCESS_KEY_ID=xxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxx
AWS_DEFAULT_REGION=ap-northeast-1
SLACK_WEBHOOK=xxxxxx
SLACK_CHANNEL=#random
```

### 実行

```
docker pull iscream/ecranner
docker run --rm --env-file ./.env --privileged iscream/ecranner
```

# おわりに
ECSに限らずDockerを本番運用する際にはセキュリティには十分に気をつけたいものですよね。Trivyの他にもOSSでは[Dockle](https://github.com/goodwithtech/dockle)というDockerfileのベストプラクティスに沿っているかチェックするツールもあります。様々なツールを駆使してセキュリティを確保していきましょう。

あとツールに関してですが、今回はPythonで書きましたがGoで書き直そうかと思います。ついでにコマンドを実行しているところもSDKで置き換えていくつもりです。
それでは:wave_tone2:
[VBA]為替情報をスクレイピング

FXにハマっていた時期がありまして、何とか値動きをつかもうと模索していました。
その中の



為替のサイトの[リンク](https://fx.minkabu.jp/pair/USDJPY)
マクロを起動すると以下の画像のようにデータが溜まっていき、SLOPE関数とINTERCEPT関数で
値動きの傾向を探ろうとしたわけです。
![為替の入力システム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361605/46239b34-e987-c7f6-bb08-054a2a8c679a.png)

まあ結果は何の役にも立ちませんでしたけど。

コード乗っけます。

VBAでweb操作をしたかったら四角で囲まれた部分にチェックを入れてね
![webスクレイピング参照設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/361605/790b4e64-ff01-d203-6926-80cfdd34cb91.png)


```vb


#If VBA7 Then
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal ms As LongPtr)
#Else
Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
#End If

Sub dlleGet()

    Dim ie As InternetExplorer
    Set ie = CreateObject("Internetexplorer.Application")
    
    ie.Visible = True
    ie.navigate "https://fx.minkabu.jp/pair/USDJPY"
    
    Do While ie.Busy Or ie.readyState <> READYSTATE_COMPLETE
        DoEvents
    Loop
    
    Dim maxRow As Long
    Dim change As Double
    
    For i = 1 To 5
        maxRow = Cells(Rows.Count, 1).End(xlUp).Row + 1
        Cells(maxRow, 1) = maxRow - 1
        Cells(maxRow, 2) = Now
        Cells(maxRow, 3) = ie.document.getElementsByClassName("pair-box-rate")(0).innerText
        On Error GoTo err
        Cells(maxRow, 4) = Cells(maxRow, 3) - Cells(maxRow - 1, 3)
err:
        Sleep 1000
    Next
    ie.Quit
    
End Sub

```

果たして需要はあるのやら・・・
Vuexのモジュール作成を自動化する

# TL;DR
以下のようなファイルを自動生成できます。
<img width="301" alt=" 2019-08-31 22.19.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198781/c914685c-a7b8-e2c7-31f1-748fb380a1e4.png">

## はじめに
Vuexを使っている場合、ほとんどの割合でモジュールを使用すると思いますが
モジュールを作成するときの作業って面倒ですよね。
そんなときにうってつけのジェネレータをご紹介します。

GitHub : https://github.com/lyonlai/generator-vuex

このジェネレータを使用したプロジェクトのサンプルはGitHubに置いています。
(カウントのインクリメントとリセットをストアで管理するアプリ)
<img width="257" alt=" 2019-08-31 22.56.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198781/1101b7a1-cc94-49a6-28e7-53be3be4ab28.png">

## 使い方

READMEにも説明を書いてくれてますが、一応こちらでも使い方を説明しておきます。
### yeomanをインストール
yeomanを使用するので、yeomanをインストールします。

```
npm install -g yo
```

###  ジェネレータをインストール

```
npm install -g generator-vuex
```

## 実行

最初に一度のみ使用するストア生成コマンドと、
モジュールを生成するコマンドの２種類が用意されています。

### ストア生成
ストアを生成する場合、[vuex-module-configuration-composer](https://github.com/lyonlai/vuex-module-configuration-composer)を追加する必要がありま
す。

```
npm install vuex-module-configuration-composer
```
インストールできたらyeomanのコマンドを実行します。

```
yo vuex
```

<img width="567" alt=" 2019-08-31 22.07.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198781/92f8bc88-df1a-9497-27af-85770236d4ee.png">

2つ質問されますが、何も入力せずエンターで大丈夫です。
終了するとsrc/storeにファイルが生成されます。

- modules(空のフォルダ)
- actions.js
- getters.js
- index.js
- mutation-types.js
- mutations.js
- state.js

こちらのindex.jsがVuexのインスタンスを生成するため、プロジェクトに組み込みます。

### モジュール生成

package.jsonと同じディレクトリでyeomanのコマンドを実行します。

```
yo vuex:modules
```
<img width="1095" alt=" 2019-08-31 22.27.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/198781/bca27342-5ce9-b446-dce0-f91b9991c446.png">

質問に対してモジュール名を入力します。(画像のモジュール名はlogin)

使用方法の説明は以上です。

## モジュール追加後
生成されたモジュールにはresetStateというアクションのみ用意されています。
このアクションを呼び出すと該当のモジュールのstateを初期化することができます。


これで手作業でファイルをコピーして書き直すような作業からは開放されましたね！

---

yeomanは割と古いので、他に使っているツールがあれば、コメントいただけるとうれしいです:bow:
PostgreSQL（Windows）インストール時に『an error occured executing the microsoft vc++ runtime installer』が発生

## はじめに
PostgreSQLのv9.1とかの頃によく見て、最近は発生していなかったのですが、ちょうどさっきv9.6の最新をWindows10（1903）に入れようとした際に出たので、自分の備忘録に残します。

## インストール方法
普通に実行ファイル（.exe）をクリックしても「an error occured executing the microsoft vc++ runtime installer」とメッセージが表示されるので、以下の手順でインストールを実行します。

```terminal
C:\> cd [exeの存在するフォルダ（※ここではC:\tmp）]
C:\tmp> postgresql-9.6.x.x-windows.exe --install_runtimes 0
```

## 最後に
最初から入っているからか、それとも上位のバージョンがすでに入っているからなのか、原因を調べきっていませんが、とりあえず無事インストールできました。
insertCaption

# 概要
powershellでwordを動かす話の続きで今日は図表番号

#表番号の挿入
けっこう試行錯誤したんでup,
基本的な話は前書いたので省略

## selectionの使い方
どうも、rangeとselectionの使い方がよくわからなかった。

簡単に言えば、selectionは操作者が選択している部分でrangeはそれと関係ない選択範囲。

っで、xx.range.select()
という操作により
$wd.selectionが変更されるという動きになっている。

wordの中の図(innershaps)のデータで$doc.innerShapes[n].select()
とすると、無事その図が選択されていることが、見える($wd.visible=$trueにしている場合）

#insertCaption
要は、メニューでいうところの参考資料→図表番号の挿入の機能を使うということなんだが、これは

```:powershell
selection.insertCaption(-2, #表=-2,図=-1
                     "タイトル",
                     "",
                     0 #上0、下1
                    $false) #表という文字を入れる
```

ということになっているようだ。最初の-2の部分をずーっと"表”とやっていて動かなかった。

word.interopを読めばいいということがわかった。

https://docs.microsoft.com/ja-jp/dotnet/api/microsoft.office.interop.word.wdcaptionlabelid?view=word-pia

成程、成程
[VB.net] SQLiteを読み込んでデータグリッドビューに表示するクラス

SQLite専用の読み込みクラスを作りました。
引数には以下の文を指定して下さい。

まずはNuGetパッケージから、Sqlite.Dataをインストールして下さい。

path　＝　SQLiteデータベースファイルのパス
table ＝  対象のテーブル
insertSQL ＝SQL文
datagrid ＝ Datagridviewオブジェクト
fillStr ＝ フィルターを書けるワード

以下コードです。

```vb

Imports System.Data.SQLite

Public Class SQLiteClass
    Public Sub SQL_Execution(path As String, table As String, insertSQL As String, datagrid As DataGridView)

        'SQL文の実行メソッド

        Debug.Print(insertSQL)

        'Try
        Using con As New SQLiteConnection("Data Source=" & path)

                con.Open()

                Using SqlCommand As SQLiteCommand = con.CreateCommand()
                    SqlCommand.CommandText = insertSQL
                    SqlCommand.ExecuteNonQuery()
                End Using

            End Using

        'Fast_data_show(path, table, datagrid)

        'Catch ex As Exception
        '    MsgBox("エラー", vbAbort)
        'End Try

    End Sub


    Public Sub Fast_data_show(path As String, table As String, datagrid As DataGridView)

        'データグリッドビューにデータを表示

        ' Try

        datagrid.Columns.Clear()

            Using con As New SQLiteConnection("Data Source=" & path)
                Dim ds As New DataSet
                Dim da As New SQLiteDataAdapter("SELECT * FROM " & table, con)
                da.Fill(ds, table)

                datagrid.DataSource = ds.Tables(table)
                con.Close()
                con.Dispose()

            End Using

        'Catch ex As Exception
        '    MsgBox("エラー", vbAbort)
        'End Try

    End Sub


    Public Sub DataGridViewFilter(fillStr As String, datagrid As DataGridView, sqlStr As String)

        'データグリッドビューにフィルターをかける

        Dim objBind As BindingSource
        Dim objData As DataTable

        ' DataGridViewにバインドしたデータをDataTableとして取得する
        objData = CType(datagrid.DataSource, DataTable)

        ' データが存在する場合
        If IsNothing(objData) = False Then
            objBind = New BindingSource
            ' バインドするデータソースにDataTableをセット
            objBind.DataSource = objData
            ' データソースにフィルターをセット
            objBind.Filter = sqlStr
        End If

    End Sub
End Class

```
pythonの仮想環境構築(windows10)

#仮想環境構築#
以下のコマンドを,自分が作業するディレクトリで入力する.
`name`の所は自分で名前を決める.

```
C:作業したいディレクトリ> python -m venv name
```

#仮想環境実行#
以下のコマンドを入力

```
C:作業したいディレクトリ> name\Scripts\activate
```

#仮想環境を閉じる#

```
(name) PS C:作業したいディレクトリ> deactivate
```

#参考#
- [Django Girls Djangoのインストール](https://tutorial.djangogirls.org/ja/django_installation/)
- [VSCodeでPythonをvenvで仮想化環境として使えるようにする](https://qiita.com/drumer2/items/7968be3398d3af7353f0)
[VBA]図形のアドレスを取得し、図形があるセルの内容を取得する

アクティブシート上にある図形の中で四角形の図形のみ、図形があるセルの内容を取得します。



```vb
Dim shapeR As Range

For Each i In ActiveSheet.Shapes
    If i.AutoShapeType = msoShapeRectangle Then 
        MsgBox i.TopLeftCell.Value
    End if
Next
【Python】 Python3エンジニア認定基礎試験　受験記録

#### はじめに
表題の通り、「Python3エンジニア認定基礎試験」を受けてきました、というエントリです。
私の学習方法・学習量など記載しますが、私自身、先人が残してきたエントリを参考に対策したので、目新しい内容はないと思います。

#### Python3について
私は金融系SIerで勤務しており、業務でPython3を扱うことはありません。
しかし、転職活動を行なっているコトもあり、業務で扱っている分野・言語以外のところにも関心や学習意欲がありますよ、というアピールの一助になれば、という程度の動機で受験しました。

#### 結果
合格ライン700点(1問25点、40問中28問正解)に対し、得点は750点。合格でした。

#### 学習方法、学習量
私の場合、学習方法は大きく以下の3つでした。
#####1.Web講座
これは試験対策というより、Python3での基本的なプログラミングを学ぶためのものです。
どちらかというと、この講座で基礎を学んだからこそ「何か学習の証拠となるような資格認定はないかな」と思ってエンジニア認定基礎試験の受験を考えた、という順番でした。
内容的には、`print("Hello World.")`に始まり、変数の宣言・データ型や繰り返し処理、例外処理など、ホントに基礎的な部分を学習しました。(ちなみにpaizaの講座です)
#####2.模擬試験
DIVE INTO EXAMというサイトで模擬試験ができるので、何も見ずにスラスラ解いて満点取れるようになるまで、ひたすら繰り返しました。
特に「以下のコードの実行結果として正しいものを〜」といった問題は、実際にローカルに環境を作って実行結果を確認して（さらには少しずつ改変した結果を見たりして）、なぜそうなるのかを確認するようにしました。

<img width="1186" alt="Screen Shot 2019-08-31 at 22.21.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/fb1a4455-1cd7-f308-58f4-23cbc818f86b.png">
※30日に0点があるのは、始めた直後に急用ができて時間切れになったせいですね・・・

#####3.Pythonチュートリアル
試験対策本というより、「出題範囲」そのものの本。
一応手元にあったんですが、正直ほとんど読みませんでした。
「●●の説明として正しいものを〜」といった出題の内容を確認するために、たまに逆引きした程度です。

####受験の感想
DIVE INTO CODEの模擬試験よりはかなり難しかったです。
（前日の模擬試験で満点取ってるのに、本番で割と合格点ギリギリなトコから察してください。）
私個人としては、「コードいっぱい書いてればもっと簡単に解けただろうなぁ」という問題が多かったです。
初めて見るコードはどうしても実行結果のイメージが湧きにくいというか・・・。
「例外になるのは分かるけど、どんなエラーメッセージが出るんだっけ？」とか。

とはいえ、模試で連続満点取れる程度に理解が深まっていれば、合格ラインの28問は正解に自信持てるくらい解けるんじゃないかなぁ、と思います。（実際、私は「多分ギリギリの合格だろうなぁ」と思いつつも、28問正解は自信あったので時間半分も使わず終了しました。）
たしか、データ分析試験の方もベータ版(?)が始まってたかと思いますが、こちらも先人たちのノウハウが集まってきたトコロでチャレンジしてみます。
urllib HTTPDigestAuthHandler でPOSTが難解だったのでメモ

認証系によくあることだけど、何か不具合があると調べるのに困る。 requestsは素敵だがデバッグしにくい。 urllibのrequestも requestsがいらないくらいに素敵だが認証系がよくわからない。

HTTPDigestAuthHandler をつかって、リクエスト内容を細かく設定・調べたりできるようになったのでこにメモしておく。

```python

import urllib

# 使うRealmはよくわからないけど、 curl で試してみて通るコマンドラインがあるのなら curlに -vオプションつければ見れる
auth_handler.add_password('使うRealm', 'http://hogehogeとかドメイン部分.com/, 'ユーザ名はここ', 'パスワードはここ'] )
opener = urllib.request.build_opener(auth_handler)

data = urllib.parse.urlencode({'hoge': 'fuga'}).encode()
request = urllib.request.Request('リクエスト先のフルURL', method='POST', data=data)
# ここで何が送られるのか確認できる

res = opener.open(request)
if res.status != 200:
    ....

```
[VBA]SQLite For Excel でSQL実行モジュール

仕事でSQLiteをよく使うようになり、使いまわし出来るモジュールを作りました。
SQLiteForExcel-0.9.zipを[こちら](https://archive.codeplex.com/?p=sqliteforexcel)からダウンロードして解凍し、
同じディレクトリにデータベース[data.db]を作成します。


引数SQLStrにSQL文を入れ実行します。

以下備忘録のコードです。

```vb
'引数 SQLStr に任意のSQL文を入れてください。
Public Sub SQLiteExecution(SQLStr As String)
    
    #If Win64 Then
    Dim myDbHandle As LongPtr
    Dim myStmtHandle As LongPtr
    #Else
    Dim myDbHandle As Long
    Dim myStmtHandle As Long
    #End If
    Dim RetVal As Long
    Dim recordsAffected As Long
    
    Dim stepMsg As String
    Dim TestFile as String

    TestFile = ThisWorkbook.Path & "\data.db" 
    Debug.Print "----- SQL_Start -----"
    
    RetVal = SQLite3Open(TestFile, myDbHandle)
    Debug.Print "SQLite3Open returned " & RetVal
    

    RetVal = SQLite3PrepareV2(myDbHandle, SQLStr, myStmtHandle)
    Debug.Print "SQLite3PrepareV2 returned " & RetVal

    RetVal = SQLite3Step(myStmtHandle)
    
    If RetVal = SQLITE_DONE Then
        Debug.Print "SQLite3Step Done"
    Else
        Debug.Print "SQLite3Step returned " & RetVal
    End If
    

    RetVal = SQLite3Finalize(myStmtHandle)
    Debug.Print "SQLite3Finalize returned " & RetVal

    RetVal = SQLite3Close(myDbHandle)

    Debug.Print "----- SQL_End -----"
　　Call SQLite3Free

End Sub
```
Javaのリフレクションについて学んだことをまとる

# モチベーション
Javaにはオブジェクトの型情報を取得するためにリフレクションという機能が用意されています。いままで名前と概要は知っていたのですが、きちんと知っておきたいと考えたのでまとめます。

# リフレクションとは
Javaでは実行時に動的に型の情報を取得し、操作することができます。
そのように、プログラムの実行過程でプログラム自身の構造を読み取ったり、書き換えたりする技術のことを情報工学ではリフレクションと呼びます。
Javaのリフレクションではおもに以下のような機能を提供します。

* クラスやインターフェースの型や名前の取得
* フィールドの値の読み書きメソッドの読み出し
* プロキシクラスによる処理の差し込み

フレーワークやなどではこのリフレクションを利用してフィールドへのアクセスやメソッドの呼び出しを可能としています。

## Javaリフレクションの仕組み
Javaのリフレクションの仕組みは以下の2つのクラスと機能を活用することで可能となります。

* `java.lang.Class`
* クラスローダー

### java.lang.Class
Javaにはクラスを表す`java.lang.Class`というクラスが用意されています。ソースコード内で扱うクラスやインターフェースにはそれぞれ対応するClassオブジェクトが存在します。これは、例えばStringであれば`Class<String>`のように表現されます。
このクラスは特殊で`new`などを使ってインスタンス化ができません。代わりにクラスをロードする際にJVMによって生成されるか、クラスローダーのdefineClassメソッドの呼び出しによって自動的に構築されます。
Javaでは生成されたClassオブジェクトから型情報を取得することが可能となっています。 

### クラスローダー
クラスローダーとは文字通りクラスをロードする役割をもつオブジェクトになります。
ソースコードからClassオブジェクトを取得する際は内部的にこのクラスローダーから取得することになります。


# リフレクションを活用してクラス情報にアクセスしてみる。
せっかくなんで簡単にですがリフレクションを使ってみたいと思います。
まずは以下のような簡単なクラスを用意します。

```java
public class Foo {
	
	Foo(String name){
		this.name = name;
	}
	
	private String name;
	
	public void greet(){
		System.out.println("Hello, " + name);
	}
}
```

#### メソッドを呼び出してみる。
上記の`Foo.class`クラスに対してリフレクションを利用して`Foo#greet()`を呼び出してみます。

```java
import java.lang.reflect.Method;

public class ReflectionSample {

	public static void main(String[] args) {

		Class<Foo> fooClazz1 = Foo.class;
		Foo foo = new Foo("taro");

		try {
			Method greetMethod = fooClazz1.getMethod("greet");
			greetMethod.invoke(foo);
		} catch (ReflectiveOperationException e) {
			e.printStackTrace();
		}
	}
}

```

あるクラスのメソッド呼び出しは`java.lang.reflect.Method#invoke`を使って行います。
`Method`クラスは`Class#getMethod`から取得することができます。その際の引数には呼び出したいメソッド名を指定します。
今回の`Foo#greet()`は引数なしですが、第二引数以降に、呼び出すメソッドの引数を渡すことができます。

実行結果

```
Hello, taro
```

# 感想
普段、業務アプリ書くときに使うことは少ないかもしれませんが、フレームワークのコードリーディングする際にはこの辺の知識がいるのではないかと思いました。

# 参考書籍 & サイト
* [改訂2版　パーフェクトJava ](https://www.amazon.co.jp/dp/B00V2WMQNE/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
* [Javadoc(Class)](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Class.html)
* [Javadoc(ClassLoader)](https://docs.oracle.com/javase/jp/7/api/java/lang/ClassLoader.html)
Unityで画面外に移動してしまったウインドウの位置をリセットする

# はじめに

UnityでHierarchyやConsoleウインドウを何かの拍子で画面外に移動してしまう事があります。このウインドウはUnityが独自に管理しているのでOSに準じた方法で移動する事ができないので何とかリセットする方法を調べました。

# Windowsの場合

1. Unityを終了します。
1. レジストリエディタで`HKEY_CURRENT_USER\Software\Unity Technologies\Unity Editor 5.x`を開きそれらしいキーを探します。
1. たとえばConsoleウインドウの場合はスクショのように座標とサイズの4つのキーがあるので`UnityEditor.ConsoleWindowx_h3505357846`と`UnityEditor.ConsoleWindowy_h3505357847`を開いてすべての値を0で上書きします。
キー自体を削除したり桁数が異なると反映されないので注意してください。
1. Unityを開くと画面の左上にウインドウが表示されます。

キー名末尾の`_h3505357847`はハッシュ値なのでキー名を探す時は無視しても問題ありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8995/d3809f56-4665-e522-da54-d0980d77e25d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8995/3f9965ac-bf14-1dd7-5448-ba4caa1710c2.png)

余談ですが、自分の環境は4KディスプレイとフルHDディスプレイを混在していて4K側にUnityを配置してフルHD側に何かのウインドウを配置した際に画面外に移動してしまうことがありました。その時にフルHD側にUnityを移動してレイアウトをリセット後にUnityを再起動すると画面外に移動したウインドウの位置がリセットされました。

# macOSの場合

`~/Library/Preferences/com.unity3d.UnityEditor5.x.plist`にWindowsと同様の設定が保存されていますが変更しても反映されませんでした…
プロキシ環境で vue add electron-builder がこける

よっしゃー ` vue-cli-plugin-electron-builder` で Electron アプリ開発したるでー！ と意気込んで `vue add electron-builder` を叩いたら `Error: connect ECONNREFUSED` などと怒られて困った。

## 結論

```
npm config https-proxy http://<user>:<pass>@<host>:<port>
```

こういうときはやっぱりプロキシのせいでした。あれ？ でも npm のプロキシ設定なんてとっくの昔に済ませていたような……

## 原因

同じ箇所でハマっておられる先人がいらっしゃって助かりました。

[npm config -g でプロキシの設定をしているのに electron-quick-start や electron-prebuilt でコケる](https://aquasoftware.net/blog/?p=927) によると…


>electron-prebuilt のコードを見てみると、 どうやら electron-download というパッケージを使って electron のビルド済zip をダウンロードしているらしい。

>では、その electron-download の中身はというと…

>おや？ なんか rc モジュール使って、 npm config の proxy, https-proxy 設定取得しているっぽいぞ？

> `–global` オプションの保存先の `%APPDATA%\npm\etc\npmrc` や `%ALLUSERSPROFILE%\npm\etc\npmrc` が読み込まれていねぇじゃねぇか！

というわけで、こと Electron の取得に関してはグローバルなプロキシ設定は効かないようです。ローカルな設定を追加してあげるとすんなり通りました。マジかおまえ。

## 参考リンク

* [プロキシ環境下でElectron開発環境の初期セットアップをするときに困ったこと](https://qiita.com/ota-meshi/items/69ed2333ed2ba0768178)
IntelliJ IDEA(JetBrains製品)の基本ショートカットキー・Tipsなど　その１

# はじめに
vscodeをしばらく使っていると
「あれ、PyCharmだと、このショートカットどうやるんだっけ？」
となりがちだったので、知見をまとめておきたい次第。

ショートカットキーのみならず、その他Tipsも含めて書いていこうと思います。
（こちら、その１ですが、多分,その3or４くらいまでは行くつもり・・・）

# Chrome Extension
## JetBrains Toolbox Extension
拡張へのリンクはこちら：
https://chrome.google.com/webstore/detail/jetbrains-toolbox-extensi/offnedcbhjldheanlbojaefbfbllddna?hl=ja 

GitHubから直接JetBrains製品を開けるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241481/0e97ceb3-83b1-bce5-08ff-4dd4127526cc.png)

こんな感じ。

## JetBrains IDE Support
拡張へのリンクはこちら：
https://chrome.google.com/webstore/detail/jetbrains-ide-support/hmhgeddbohgjknpmjagkdomcpobmllji
ライブ編集がはかどります。
IDE側のカーソルに合わせて、ブラウザ側もどこを選択しているのかが一発でわかるのも良い感じです。

![jetbrains01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241481/7aca0265-e954-b26b-cd02-c6b276ca8724.gif)
※開いているファイルで「^⇧D」で、ライブ編集ウィンドウが立ち上がります。

# JetBrains Toolbox App
ダウンロードは以下より。
https://www.jetbrains.com/toolbox/app/

また、以下は公式ブログから引用。
（ https://blog.jetbrains.com/jp/2018/10/09/1294 ） 

>ToolBox Appを使うと、お使いのJetBrains  IDE製品の新バージョンが利用可能になるとToolBox内でToolsタブ内で通知され、UpdateボタンまたはUpdate allリンクのワンクリックでバージョンアップが可能になります。リリースノート(What’s new)へのリンクも提供されるので、新バージョンの内容を確認してからバージョンアップということもできます。

ピンクで囲った箇所をクリックすると以下画像みたくなります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241481/2d1d5874-aa09-5e90-068f-45b76872555e.png" width="50%" />
とってもアップデートしやすいです。
他にも便利機能がありますが、公式ブログの記事を確認してみるのがよいかと。

# ショートカットキー
## 文字入力の基本操作
| 操作       |       キー |
|-----------------|---------------- |
| 取り消し          |           ⌘Z　　　|
| やりなおし        |            ⌘⇧Z　 |
| 検索            |           ⌘F 　　|
| 置換            |              ⌘R |
| 選択範囲の複製    |             ⌘D |
| プロジェクト内検索  |           ⌘⇧F |
| プロジェクト内置換  |           ⌘⇧R |

vscodeと比較で考えるとすると、
⌘Dの挙動が違うことで、よくミスっているなあ、という感じ。
これ、私だけでしょうか・・・？


# インテンション・アクション
ショートカットキー：⌥ + EnerKey 

ヘルプはこちら。
https://pleiades.io/help/idea/intention-actions.html

何かととってもスグレモノです。
例えば、HTML書いているときであれば、
classの箇所でインテンション・アクションすると、CSSのセレクタを作成できたり。
![jetbrains02.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241481/a8318d88-8dae-19f9-b3b5-73c47ddd50e1.gif)

JavaScript書いているときであれば、
使用していない変数の箇所でインテンション・アクションすると、（未使用変数だから）消すかを問われたり。
![jetbrains03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/241481/63f4e28d-2ffa-0c15-f6e9-069ab094c29a.gif)


# Postfix Completion
「後置補完」です。公式はこちら。
https://pleiades.io/help/idea/settings-postfix-completion.html

Preference→Editor→General→Postfix Completionから設定を確認できます。
※後置補完はいろいろあるので全ての説明はできないですね。
手を実際に動かしてみてみるのがよろしかと、、、。

# Rename Refactorings
ショートカットキー：⇧+F6
公式はこちら：
https://pleiades.io/help/idea/rename-refactorings.html

変数にカーソルをあわせた状態でショートカットキーを押下し、変更後の名称を入力すればOK。
ファイルをまたいだ状態でも、ちゃんとリネームされます。
limits.confに書いたのに、oracleユーザのulimit -nの結果が変わらないときは

## 症状

ulimitの値を増やそうとしています。`/etc/security/limits.conf`に以下を追加して、

```
oracle   soft   nofile    4096
oracle   hard   nofile   16384
```

再起動しました。しかし、ulimitコマンドの実行結果は以下のようになったままです。

```
$ ulimit -n
1024
$ ulimit -Hn
65536
```

## 原因

`/etc/security/limits.d/`ディレクトリに、`oracle-rdbms-server-12cR1-preinstall.conf`(12cR1の場合)などというファイルが存在します。これは、Oracle Databaseインストール前に`oracle-rdbms-server-12cR1-preinstall`などの事前構成RPMパッケージをインストールした時に作成されたものです。

このファイルの中身に、以下のように書かれています。

```
# oracle-rdbms-server-12cR1-preinstall setting for nofile soft limit is 1024
oracle soft nofile 1024

# oracle-rdbms-server-12cR1-preinstall setting for nofile hard limit is 65536
oracle hard nofile 65536
```

oracleユーザがログインすると、`limits.conf`に書いたほうではなく、上記の値のほうが有効になります。

## 対処

`oracle-rdbms-server-12cR1-preinstall.conf`などのファイルのほうの値を変更しましょう。
Golangのinterfaceのポインタ配列

## やりたかったこと

interfaceのpointerの配列を作りたかった。

## やったこと
1. interfaceのポインタ配列を作る。
1. interfaceを実装した構造体を作る。
1. その構造体のポインタをinterfaceのポインタ配列に入れる。

作成したサンプルコードは下記の通り。

```vehicle.go
package main

import "fmt"

type Vehicle interface {
	Name() string
}

type Car struct {
	name string
}

type Train struct {
	name string
}

func (c *Car) Name() string {
	return c.name
}

func (t *Train) Name() string {
	return t.name
}

func main() {
	vs := make([]*Vehicle, 2)
	var car Car
	var train Train
	car.name = "car"
	train.name = "train"
	vs[0] = &car
	vs[1] = &train
	for i := range vs {
		fmt.Println("vs[i] is " + vs[i].Name())
	}
}
```

上のコードを作成して実行してみると、

```console
cannot use &car (type *Car) as type *Vehicle in assignment:
	*Vehicle is pointer to interface, not interfacego
```

と出る。 調べると
[stackoverflow](https://stackoverflow.com/questions/40823315/x-does-not-implement-y-method-has-a-pointer-receiver) で

```
An interface can store either a struct directly or a pointer to a struct.
```

と書いてあった。

なので、下記のようにすれば解決。

```
vs := make([]Vehicle, 2)
```
memoiseによる1行変更するだけのShinyApp高速化

Shiny App を高速化したいときに比較的簡単に試せるのが`memoise`を使ったデータのキャッシュ化です。それについて紹介します

## memoise とは？

私がこのパッケージを初めて知ったのは、Shiny高速化を調べてる際に`promises`のドキュメントを読んでたときでした

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69266/af8c6892-eb23-0e43-30bd-233769f6f1b0.png)

参考 : [Case study: converting a Shiny app to async](https://rstudio.github.io/promises/articles/casestudy.html)

`memoise`がどう役立つかというと、**ある関数を同じインプットで何度も呼び出すなら、はじめて呼び出したときにデータをキャッシュ化して、2度目以降の呼び出しはそのキャッシュ化されたデータを返してあげよう** というところです

キャッシュ先としては、なんらかのファイルシステム（例えば、 tmpfs） やクラウドストレージ（例えば、S3)を使うことができます

**2019-10-21追記** また、キャッシュ先としてRedisを使うことも、次のPR通りにreduxパッケージを使ってやれば実装することができそうです : https://github.com/r-lib/memoise/pull/67

とくに`memoise`と相性が良いのが、Shiny Serverの上で、あるShiny Appを複数人が使用している場合です。よくあるパターンで、別のデータベースで毎日夜にデータが更新され、Shiny Appの閲覧時に独自関数を使ってそのデータをロードする処理が発生することを考えます

最初にそのShiny Appにアクセスしたときは、そのデータベースからデータをロードしますが、その処理を`memoise`でかぶせておけば、データがキャッシュ化されます。その結果、2度目以降にアクセスした人は、そのキャッシュ先からデータをロードすることができるので、高速に呼び出すことができます

では試してみましょう

## 公式ドキュメント
* Github : https://github.com/r-lib/memoise

## やるべきたった1つのこと

**キャッシュ化したい関数に`memoise`をかぶせる** だけです。まず適当にデータを読み込む関数を用意してみます

```R
library(memoise)
set.seed(42)

load_data <- function(start_date, end_date){
  
  # Preprocess　- ここにホントはデータベースへの接続やデータのクレンジング入っている
  Sys.sleep(5)
    
  # return data
  data <- rnorm(end_date - start_date, mean = 0, sd = 1)
  data
}
```

これのパフォーマンスをチェックしておくと、`Sys.slepp`をしたとおりデータのロードに5秒かかりました

```R
> t <- proc.time()
> data <- load_data(as.Date("2019-08-01"), as.Date("2019-08-31"))
> (proc.time() - t)["elapsed"]
elapsed 
  5.008
```

これをmemoiseでかぶせてみます。キャッシュさせる先のファイルシステムは今回はホームディレクトリで適当に切っておきます

```R
m_load_data <- memoise(load_data, cache = cache_filesystem("~/tmp"))
```

まず一回目の実行をしてみます。とくに実行時間は変わらないですね

(キャッシュ先にデータを書き出すということは、ストレージIOがボトルネックになることがあるので、適切な場所を選ばないと、遅くなる可能性はあります）

```R
> t <- proc.time()
> data <- m_load_data(as.Date("2019-08-01"), as.Date("2019-08-31"))
> (proc.time() - t)["elapsed"]
elapsed 
  5.019 
```

しかし、2回目を実行してみると、ちゃんと爆速になりました（完）

```R
> t <- proc.time()
> data <- m_load_data(as.Date("2019-08-01"), as.Date("2019-08-31"))
> (proc.time() - t)["elapsed"]
elapsed 
    0.148 
```

## 補足

https://github.com/r-lib/memoise/blob/master/R/memoise.R

のコードを読めばどうやって実現してるかの雰囲気はわかります。`memoise`用の`new.env`を作ってその中でハッシュデータをもたせて覚えてる？みたいですね。ファイルシステムへの書き出しは`RDS`フォーマットのようです

実際自分が運用して複数人に提供しているShiny Appだと、別のホストのデータベースから複数の集計済みデータを日付指定でロードする必要があり、`memoise`を使うことでかなり改善されました。一度試してみるのをおすすめします

（さらにいうと、1回目のアクセスを自動的に別のプロセスで定期的にアクセスさせる処理を書いておけば、より良いと思います）
AZ-900 Microsoft Azure Fundamentals受験記録

AZ-900 Microsoft Azure Fundamentalsの試験に合格しました。
開始されて日が浅く、純粋な技術の人が受ける必要のある試験でもないので、情報が少なく準備に多少苦労しました。自分の例を簡単にまとめておきます。よかったら参考にしてください。

### なぜ受験したか
仕事で一部Azureを使い始めることになり、恐々触っているうちに興味がわいてきた。一番簡単な資格を取って概要を把握したかった。

### 本人のレベル
技術系の資格は基本情報だけ。日頃も非技術系の仕事してます。

### 事前勉強
公式の[Azure の基礎](https://docs.microsoft.com/ja-jp/learn/paths/azure-fundamentals/)だけ。手を動かすパートもスキップせず愚直に一周しました。
Webで検索すると大量に出てくる怪しげな日本語のサードパーティの試験対策講座は気になりましたが、結局受講しませんでした（そこまで難しい試験ではなかったので、結果的には受講しなくて正解でした）。

### 試験内容
[公式](https://www.microsoft.com/ja-jp/learning/exam-AZ-900.aspx)で言及されている通りの出題範囲です。

試験は日本語で受験しました。用語は英語画面で慣れていたこともあり、英語で受験することも考えましたが、試験端末側で一時的に日本語 -> 英語に切り替えするボタンがあり、日本語で受験して正解でした。

### 感想
- Azureを使ったプロジェクトにかかわる非技術者に特に役立つ資格と感じました。費用や構成、保証範囲について最低限の土台を持った上で実際に開発する人と会話ができるようになります。
- [Azure の基礎](https://docs.microsoft.com/ja-jp/learn/paths/azure-fundamentals/)を一通り勉強する動機としてちょうどいい資格でした。
- LinkedinやFacebookに貼れる認定証がもらえるのが地味にうれしい。
Adminerで楽々DB管理

##Adminerとは

phpMyAdminのようにブラウザからデータベースを管理できるツールです。
知名度はphpMyAdminやphpPgAdminなどより下かもしれませんが、
これらを基にして後発で作られた故にか、取り回しはずっと楽になっています。

![adminer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482202/d4495ef4-ebce-cec9-f1f9-6c07534d391e.png)

##メリット

・導入が楽
・1ファイルで本体が小さくサーバー容量を圧迫しない
(adminer-4.7.3.phpは473KB)
・動作が軽い
・複数種のDBに対応
(MySQL, PostgreSQL, SQLite, MS SQL, Oracle, Firebird, SimpleDB, Elasticsearch, MongoDB)


##導入
公式サイトの Download（Downloads）から、Adminer X.X.X (.php, XXX kB)
をDLしてサーバにアップロードするだけで利用できます。

![adminerDL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482202/76cc914f-1155-72d6-9a9d-b3b26da8fc95.png)

公式：https://www.adminer.org/en/

2019/8/31時点では最新ver.は4.7.3


##セキュリティ対策

公開ディレクトリに本体を置くと、URL入力でアクセスできてしまいます。
ルートディレクトリにそのまま置いた場合ならこんな感じ↓
http://sample.com/adminer-4.7.3php

よって、ローカル環境以外ではアクセス制限をつけます。
adminer本体を非公開のディレクトリに置きに置き、アクセス制御用の別のPHPファイルから呼び出すと
安全です。こちらはIP制御の例。

```
adminer_ext.php
<?php
$acl = [//↓アクセスを許可するIPを指定
    '::1',  //localhost
    'xxx.xxx.xxx.xxx',
];

if(!in_array($_SERVER['REMOTE_ADDR'], $acl)){
    header("HTTP/1.0 404 Not Found");
    exit;
}

require '../adminer-4.7.3.php';
```


参考：
https://qiita.com/danishi/items/7b4aa105844c015cd429


おまけ

見た目をカスタマイズすることもできます。
公式にもいくつか紹介されているので、必要に応じて使ってみてください。

![CSS.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482202/339de664-a817-9620-2484-5ade416b8437.png)


ＣＳＳをリンクからＤＬ，本体と同ディレクトリに上記のadminer.cssのファイルを設置するだけです。
【エンジニアでもわかる】キャリアアップのためのブランディングのしかた に参加しました

#実施要項
[8/29(木) 19:30～＠サポーターズcolab](https://supporterzcolab.com/event/919/)
講師：さのし さん
参加者：4人…とアットホームでした。12人申し込んでいたハズですが。

#０．冒頭の注意事項
☆この場で伝えること
・成長の仕方
　・マーケティング
　・ブランディング
　・情報収集術
　・マインドセット
⇒「好きなこと」でもいいので、キャリアを描く上での軸を考える/作る契機になる話をする。
☆この場で伝えないこと
・マーケティングの深い話
・ブランディングの深い話
・自己分析や面接のやり方(対策)
・「これさえやれば！」といった、特効薬的な話


#１．背景
・終身雇用難しい問題…一度入れば問題なし、という時代ではない。
・「個」の時代…フリーランスのように「会社名で勝負をしない人」も増えている


#２．エンジニアにも分かるマーケティング/ブランディング
☆3C…競合(Competitor)/市場・顧客(Customer)/会社(Company) の視点を持とう

##2-1 競合
・エンジニアとしてあこがれる人はいるか？
　⇒いれば、その人を「競合相手」と仮定して比較する

☆「競合」のポイント
・自分がエンジニア市場の商品であると理解する
・あこがれの人・身近な人も商品
・いくつかの指標を設定して競合と比べよう
　⇒何でもいいので、比較して自分の強みはなにか考える
・自分の技術力を棚卸してみよう
・競合を何人か比較してみよう

##2-2 市場・顧客
☆企業を知ることが大事
・自分も頑張らなければ、利益が増えない以上はお金も増えない
　⇒会社を知る方法はなにか
　⇒例えば財務状況はトータルの結果であり、そもそも公開してないケースも

☆「市場・顧客」のポイント
・マクロ×ミクロ のアプローチを仕掛ける。

###マクロ：以下の順番でトレンドや動向を追う
世界のIT市場→日本のIT市場→ベンチャー立ち上げ→資金調達・新規部署設立→エンジニアの採用　※ベンチャー：スタートアップ＋中小企業
・勉強会時点では、Fintech・C2C・AI・IoTなどがアツいか。

☆今後、ITが台頭してくる場面を考える
・「不便/非効率な産業or業界の効率化」
　※以下の例は、参加者から挙がった意見です
現時点で不便/非効率な産業or業界を考える：教育や介護
場所に着目する：シェアリング/コワーキングスペースや人と人を結ぶサービス、個人支援の類
氾濫している情報を管理する(自動的にフィルタリングする) サービス

###ミクロ：企業のフェーズにより求められる人材を知る
☆状態は千差万別なため、企業のサイトやサービスを直接見る
・SNSやyenta等のビジネスマッチを使う
・転職サービス(Wantedly,Green,MIIDAS,GLIT,scouty…)を活用する
・エンジニアに会いに行く
・話を聞く(勉強会：commpass,TECH PLAY, facebook,meetup/カジュアル面談)

☆自社の求人条件(特に歓迎要件)を見てみると、企業側のニーズが案外分かるかもしれない。

##2-3 企業
☆「会社＝自分」という意識
・自分も会社を動かしている一員である、という当事者意識を持っているか？

☆「自分がエンジニアリングを事業としている」と認識する
・コードを書いて生計を立てている
・「給与」をもらうことが当たり前、という認識は捨てるべき
・製品/サービス × 売り方 の組み合わせで自分のキャリアを考える
　⇒製品・サービス：能力、強み
　⇒売り方：売りたい相手は誰で、どうアプローチするべきか？

##2-4 マーケティングを行う必要性
☆製品・サービスが分からないからマーケティングできるものなんてないのでは？
・一人前になるまでの過程をSNSで発信することだってできる。
　⇒要は、やり方次第であるし何もしない言い訳を作る前にやってみれば良い。
☆自分のブランドをどうするか考える
・どうなりたいか？
・どの層に、どう見せたいか？
☆見せ方の手段(チャネル)を検討する
・SNS、ブログ、カンファレンス、youtube…
　⇒いずれの手段でも、ある程度の時間と一貫性というコストは想定しておこう


##2-5 ブランド
☆ブランドとは何か？
・製品やサービスについて思い浮かぶ一連の期待
☆ブランドを構成する4要素
・メッセージ：訴求する内容
・ビジュアル：ブランド/メッセージ連想させるアイコン
・一貫性　　：一定のメッセージを実践しているか？
・反復　　　：繰り返し実践することでユーザーとの機会を増やしてブランドとして定着する
☆「肩書き」の意味
・ブランドを表現するためのメッセージ
　⇒キャッチフレーズ、エレベーターピッチを決めよう。
☆メッセージに加えて考えるポイント
・ニッチさも大事になってくる。
　⇒ターゲットを狭めて、「その層にとって価値あること」を提供する
☆決めたら発信しよう。とにかく反復と検証を。
・勉強会/meetupに参加しよう、もっと言えば登壇しよう

#３．所感
・平日の夜(急な残業も考えられる)とはいえ、ドタキャンの多さに申込者の意識が垣間見えた。
　「来る」というアクションすら起こせない人が果たして変われるのか…？
・勉強会に参加した話は、引き続き発信していきたい。
　欲を言えば、というより時間はまだ必要だが言語を学んだらここに整理も兼ねて書いていく。
　こうして足跡を残すこともまた、ブランド構築の一助になると信じて。
・勉強会も含めて、外に出て人と会う中でも自分の立ち位置は考えられるはずだ。
windowsで急にnpmが使えなくなったら

なんか知らんけど急にwindowsでnpmが使えんくなった。

``` 
C:\Users> npm -v
internal/modules/cjs/loader.js:582
    throw err;
    ^
Error: Cannot find module 'C:\Program Files (x86)\Nodist\npmv\6.4.1\bin\npm-cli.js' 
```

どうやらnodistをバージョンアップさせたことが問題らしい。

解決方法
1. Nodist/npmvの中にある6.4.1という名前の空のフォルダを削除
2. Nodist/lib/npm.jsというファイルを開き、そこにある

``` npm.js
return 'https://codeload.github.com/npm/npm/tar.gz/vVERSION'
```
という記述を

``` npm.js
return 'https://codeload.github.com/npm/cli/tar.gz/vVERSION'
```

という記述に変更
ターミナルとかで

```
nodist npm match
```
ってやる。そのあとに

```
npm -v
```
とか打って問題なくバージョンが表示されれば終わり。
Docker に立てた Cloud9 で共同編集する方法

## TL;DR

Cloud9 の引数に `--collab` をつけて実行し、共同編集するブラウザに ID となる Cookie を登録するんだ！

## 環境

ホストOS: CentOS Linux release 7.6.1810 (Core)
ゲストOS: alpine Linux 3.7
Cloud9: 2018/07/26 Github.com コミット分
Docker: 1.13.1, build b2f74b2/1.13.1

### 動作確認ブラウザ

#### Windows10

OS ver: 1903
Chrome: 76.0.3809.132（Official Build） （64 ビット）
Microsoft Edge: 44.18362.329.0 
Internet Explorer: 11.0.140

#### Android

OS ver: 8.0.0
Chrome: 76.0.3809.132

#### iOS

ハード: iPad Pro 10.5 inch
OS ver: 12.4.1
Chrome: 76.0.3809.123

## 手順

1. Cloud9のコンテナを作成
2. 共同編集するブラウザの数だけコードを用意
3. 共同編集するそれぞれブラウザから各々のコードを実行

### Cloud9 のコンテナを作成

下記 `docker-compose.yml` の内容を同じファイル名でコピペして、`docker-compose` コマンドを実行して Cloud9 のコンテナを作成します。
version が古いのは大目に見てください…

```yml:docker-compose.yml
version: '2'

services:
    cloud9:
        container_name: c9
        image: sshinya/alpine-cloud9
        volumes:
            - ./workspace:/workspace  # あらかじめ mkdir ./workspace しておく
        ports:
            - "8080:8080"
        entrypoint: >
            /usr/bin/node /c9/server.js 
            -l 0.0.0.0 
            -p 8080
            -w /workspace 
            -a user:password 
            --collab
```

```sh:実行するコマンド
$ mkdir workspace        # データ保存先のディレクトリをあらかじめ作っておく
$ ls                     # 確認をしているだけ、このコマンドは実行不要
docker-compose.yml  workspace
$ docker-compose up -d   # コンテナの作成
Creating c9 ... done
```

### 共同編集するブラウザの数だけ ID を用意

共同編集のための Cookie をブラウザに食わせます。
以下のブックマークレットの`id:` の値を変えたものを、共同編集する画面分用意しておきます。
共同編集したい各々のブラウザのアドレスバーから実行します。

```javascript:例
javascript:(function(){javascript:document.cookie='__c9_uid='+escape(JSON.stringify({id:1}))+';Domain=.com;Max-Age=315360000'})()
```

### 共同編集するブラウザからそれぞれの ID を登録

各ブラウザで `http://localhost:8080` へアクセスし、Cloud9 を開きます。IDE 画面に切り替わったらアドレスバーより上記ブックマークレットをを実行します。
`localhost` は適宜接続先 IP アドレスやドメインに読み替えてください。

1度実行すれば、ウィンドウを閉じても効果は続きます。共同編集できなくなったら再度 Cookie を登録するコードをコンソールから実行してください。

## 参考にした投稿

[How to run with multiple users? #241 のコメント 284794640 - c9/core](https://github.com/c9/core/issues/241#issuecomment-284794640)
【Rails】戻るボタンの実装方法【複数ページ戻ることも可能】

こんにちは！
ねこじょーかー（[@nekojoker1234](https://twitter.com/nekojoker1234)）と申します。

前のページに戻るボタン、付けたいと思ったことはありませんか？

「rails　戻るボタン」とかで調べると出てくるのが、以下の処理です。

```slim
= link_to '戻る', :back
```

これは、1ページだけ戻る場合は上記で問題ないのですが、**複数ページ戻る場合、ループしてしまう問題があります。**

たとえば、以下の操作を見てみましょう。


1. 投稿一覧を見る
2. Aさんの投稿の詳細を見る
3. Aさんのプロフィールを見る

上記の操作をしたあと、「1. 投稿一覧を見る」に戻りたいとします。

戻るボタンを押すと、「2. Aさんの投稿の詳細を見る」まで戻ることができるのですが、もう一度戻るボタンを押すと、「3. Aさんのプロフィールを見る」に戻ってしまいます。

**つまり、`= link_to '戻る', :back`というのは、「一つ前に表示していた画面に戻る」という機能でしかありません。**

したがって、複数ページ前に戻ろうとしても、２つのページをぐるぐるループしてしまうようになります。
（３→２→３→２→・・・）

ではどうすればいいのかというと、以下のように書きます。

```slim
= link_to '戻る', 'javascript:history.back()'
```

上記の処理を書くことで、複数ページ前に戻ることが可能になります。
このボタンを先ほどの１〜３のページに置いておけば、「３→２→１」のように戻るようになるので、ぜひお試しください！

##まとめ
- １ページ戻るだけでいいなら`= link_to '戻る', :back`を使う
- 複数ページ戻るような画面設計なら`= link_to '戻る', 'javascript:history.back()'`を使う

## あわせて読みたい

[HTMLもわからない初心者が、独学で「投稿型SNSサービス」を作ったって本当？【193日間の死闘】](https://qiita.com/nekojoker/items/2497b4f81ffd1cd7025c)

運営している PlayFab 専用ブログ
https://playfab-master.com
AWS のポリシーを楽に作成する方法（ポリシージェネレーター）

##概要

AWSでサービスへのアクセス許可を設定するポリシーを楽に作成するにはポリシージェネレーターを使うとよい。
書き方覚えた方がいいんだろうけど、最初はどう書いたらいいかわからないし、まずはこれで。

[ポリシージェネレーターはこちら](https://awspolicygen.s3.amazonaws.com/policygen.html)

##手順

### Step 1: Select Policy Type

このジェネレータではS3の他にはSQS,VPC,IAM,SNSのポリシーが作成できます。
今回作成するポリシーはS3バケットのポリシーにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265708/9202e1d0-f1de-c88f-72ca-8ed0d840af0c.png)

### Step 2: Add Statement(s)

各項目は以下のようなものです。

Effect → アクセスを許可かするか、拒否するか
Principal → 許可対象
AWS Service → どのサービスに対して、という意味だが、S3の場合はS3のみしか選択できない
Actions → どのアクションを対象にするか
Amazon Resource Name (ARN)　→ リソース名

今回はS3に対して、以下の設定でポリシーを作成してみます。

- ユーザ
 - udon (IAMで作成済み. ARN→arn:aws:iam::123456789012:user/udon)

- バケット (バケットは全てのkeyにアクセスできるように * とする)
 - test.bucket (ARN→arn:aws:s3:::test.bucket/*)

- アクション
 - 読み取り(GET)、アップロード(PUT)のみ許可する

ポリシージェネレーターでは以下のように設定する。
Actionsはリストで選択するので画像では見えませんが、GetObject と PutObjectのみオンにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265708/f9e7c428-2cfe-8947-df4a-02b8f7c5eb3c.png)

設定が終わったら Add Statement を押します。
押すと、ボタンの下に詳細が表示されます。
いくつか同時にポリシーを設定できるので、他にも設定したい場合は、再度入力し、Add Statementを押すと、このエリアに表示されていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265708/451b8681-bbf8-953e-d412-f5601ad84545.png)


### Step 3: Generate Policy

最後に Generate Policy ボタンを押すと、ポリシーが表示されます。
このポリシーをS3のポリシー設定に貼り付ければOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265708/b678ecb0-1148-25b4-f4dc-cc5c0fd0f608.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/265708/7b8b55be-7dd5-8252-95ae-26224ba39cd9.png)


以上、ポリシージェネレーターによるポリシー作成でした。
jQuery学習メモ




####jQuery読み込み設定


読み込み


```html:例.html（htmlにjQueryを読み込む）
<body>
<div id="box"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="例.js"></script>
</body>
```

```javascript:例.js
$("#box").text("Hello jQuery!");
```


onloadイベントハンドラ使った例


```html:例.html（htmlにjQueryを読み込む）
<head>
<meta charset="utf-8">
<title>Title Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<script src="例.js"></script>
</head>
```


```javascript:例.js（onloadイベントハンドラ）
window.onload = function() {
  $("セレクタ").text("テキスト");
}
```




####ready()


大量のデータが読み込まれる際にDOMの読み込みが終わった時点で操作できるようになる


```javascript:例.js
$(document).ready(function() {    // DOMの読み込みが完了したらここが実行される
  $("セレクタ").text("テキスト");
});
```


ready()を省略して書ける　※こっちの方が一般的


```javascript:例.js
$(function() {    // DOMの読み込みが完了したらここが実行される
  $("セレクタ").text("テキスト");
});
```


####DOMの操作


```javascript
$(セレクタ).操作();
```

操作を繋げることも可能


```javascript
$(セレクタ).操作1().操作2();
```




####子要素、子孫要素の指定


子要素だけ指定したい場合


```javascript
$("#上の要素名 > div").上の要素("子要素");
```


子孫要素を指定したい場合


```javascript
$("#上の要素名 div").上の要素("子孫要素");
```
CognitoをAWS SDK for JavaScriptから使ったらドハマリした

# やりたかったこと

EC2をブラウザから起動・停止したかった。

Cognitoでアクセス権限を生成し、AWS SDK for JavaScriptを使ってできると思っていた。

# 実際にやったこと

公式ドキュメントにあった、[ブラウザから非認証ユーザーでPollyを使うチュートリアル](https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/getting-started-browser.html)を行った。

その後Pollyにアクセスする部分をEC2に変えてとりあえずdescribeInstancesを実行してみた。

# 起こったこと（ハマったこと）

UnauthorizedOperationが発生。

```
"UnauthorizedOperation: You are not authorized to perform this operation.
```

権限を過大に付けても駄目。

実行に権限が不要なsts:getCallerIdentityを実行するもこちらは普通に動作。

チュートリアルのPollyに変えてみても普通に動作。この状態でPollyの権限を外すともちろんエラー。

訳が分からず小一時間ほど格闘…。

# 原因

[公式ドキュメント(日本語版は訳がわかりにくいので英語版)](https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html)のアクセスポリシーの項目に次のようにありました。


> In other words, this policy allows an identity using these credentials with access to only the following services:

> AWS AppSync
Amazon Comprehend
GameLift
Amazon Lex
Amazon Polly
Amazon SimpleDB
Amazon Transcribe
CloudWatch
DynamoDB
AWS IoT	
Amazon Machine Learning
Amazon Rekognition
Amazon SES
Amazon Translate
Amazon Cognito Identity
Amazon Kinesis Data Firehose
AWS KMS	Amazon Mobile Analytics	
Amazon Sumerian
Amazon SNS
Amazon Cognito Sync
Amazon Kinesis Data Streams
AWS Lambda
Amazon Pinpoint
Amazon S3
Amazon SQS

さらにこうあります。

> If you need access to something other than these services for your unauthenticated users, you must use the basic authentication flow. If you are getting NotAuthorizedException and you have enabled access to the service in your unauthenticated role policy, this is likely the reason.



…つまり上記以外のサービスにアクセスしたい時は未認証ユーザーではなく何かで認証しないといけないとのこと。

ゆくゆくは認証処理も入れようと思っていましたが、開発中だしとりあえず未認証のまま進めようとしたばっかりにドハマリしてしまった。
XCrySDenことはじめ

# XCrySDen
第一原理計算アプリPWscf, WIEN2k, Gaussian, FHI98MDのインプットファイルを読み込んで、原子配置、結晶構造の可視化が出来る。実空間格子から、対応する第一Brilloun域での対称性の高い点の座標を逆格子ベクトルで表現した際の係数を算出してくれる機能がある
他にも、電荷密度を描いたり、Fermi面を描画する機能もある(らしい)。
[XCrySDen - (X-Window) Crystalline Structures and Densities](http://www.xcrysden.org/)

# インストール
ダウンロードのページ ( http://www.xcrysden.org/Download.html ) からソースを落としてきて、インストールする。
いくつかのLinuxに入れてみた経験としては、xcrysden-1.5.60、Linux_x86_64のsemisharedを入れるのが最も簡単。
tar.gzを解凍して出来るディレクトリ下の`xcrysden`を実行すれば、立ち上がる。
(Kubuntu 19.04ではこれで動作確認済み。ただし、何かしら事前に入れたライブラリに依存しているかもしれない)

# 使い方
(後で書く)
MySQLでデータ実体のディレクトリがどこか分からない時に見つけるためのコマンド

### 目的
自分が構築したわけではない未知の環境で、MySQLのデータの（ディレクトリコピーでの）バックアップしたり、データの実サイズとか知りたい時に場所を知りたくなることがあります。


### コマンド
MySQL の root ユーザで入れる前提だと以下のようになります。

```shell
$ mysql -uroot -p -e "show variables" | grep data | grep dir
datadir	/var/lib/mysql/
```

show variables で全変数とって、grep で絞り込んでます。
show variable さえ覚えていれば、多分設定で `dir` （directoryのdir）がついているだろうとか、`data` がついているだろう、という辺りからレファレンスで正確な設定名を知らなくても設定を探せるので応用が効きやすいです。
Windows Server の DNS のデバッグログについて

Windows Server 2012 で DNS デバッグログの場所と読み方の自分用備忘録です。

[DNS サーバーのデバッグ ログ オプションを選択および有効にするには][ms_dns]

# デフォルトの出力先

デバッグログ出力先を特に指定しない場合、以下の場所に出力されます。

C:\Windows\System32\dns\dns.log

# 読み方

ログファイルの先頭に各フィールドの一応意味が書いてありますが、一部 DNS に詳しくないとわからないものがあります。以下のリンク先の記事を読むとある程度わかるようになります。それにしてもドキュメントが見つからないので苦労します。
[DNSプロトコルのヘッダセクションのフォーマット][dns_header]
__以下の解説っぽいのは想像を含みますので、信頼度は低いです。__

```
fields):
	Field #  Information         Values
	-------  -----------         ------
	   1     Date
	   2     Time
	   3     Thread ID
	   4     Context
	   5     Internal packet identifier
	   6     UDP/TCP indicator
	   7     Send/Receive indicator
	   8     Remote IP
	   9     Xid (hex)
	  10     Query/Response      R = Response
	                             blank = Query
	  11     Opcode              Q = Standard Query
	                             N = Notify
	                             U = Update
	                             ? = Unknown
	  12     [ Flags (hex)
	  13     Flags (char codes)  A = Authoritative Answer
	                             T = Truncated Response
	                             D = Recursion Desired
	                             R = Recursion Available
	  14     ResponseCode ]
	  15     Question Type
	  16     Question Name

2019/08/20 11:48:27 0BE4 PACKET  000000149B80B390 UDP Rcv 8.8.8.8 
  ccfb R Q [0581   D   REFUSED] A      (6)google(3)com(0)
```

6の「UDP/TCP indicator」は UDP か TCP がセットされると思いますが、UDP しか見たことがないです。DNS の仕様だと UDP のサイズには制限があり、応答でそのサイズを超える場合は、TCP を使うようです。サイズは時代とともに増やされ今はサーバー毎バラバラらしいです。

7の「Send/Receive indicator」は Send の場合「Snd」、Receive の場合は「Rcv」になります。

12と13の「Flags」は16bitのフラグを4つの10進数で表現したのが12でそれを文字で表すと13になると思われます。

14の「ResponseCode」には「NOERROR」や「REFUSED」「NXDOMAIN」など[DNS Update Message Flags][dns_upd_msg_flg]の名称がセットされます。

15の「Question Type」は「A」や「CN」などを意味します。

16の「Question Name」は問い合わせをしたドメイン名です。カッコ内の数字はその後に続く文字列の文字数です。

# 感想

DNS は古い技術ですがいろいろ調べると面白いかもしれません。（調べるとは言っていない）

[ms_dns]:https://msdn.microsoft.com/ja-jp/windows/desktop/cc759581?f=255&MSPPError=-2147217396
[dns_header]:https://yoshida-eth0.hatenablog.com/entry/20110203/1296675571
[dns_upd_msg_flg]:https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2003/cc772774(v=ws.10)#dns-update-message-flags
React-Staticの基本ルーティング設定


#はじめに


プログラミング歴2ヶ月の素人が書いています。（間違っていたらご指摘ください）

「React-Staticのルーティングを設定する」ための学習メモです。

* React-Staticのルーティング

* 


上記についてまとめます。


👇React-Static公式👇
https://github.com/react-static/react-static


#今回の目的

React-Staticで生成したブログに、ページを追加します。



#基本のルーティング

```react:static.config.js
export default {
  getRoutes: async ({ dev }) => [
    // A simple route
    {
      path: 'about',
      template: 'src/containers/About',
    },
```


* path: URLに入力される文字列。ルート移行を記述します。

* template: コンポーネントまでのパス

この２点のみで基本のルーティングは動きます。



データを渡すルーティング

```react
//static.config.js
import axios from 'axios'

export default {
  getRoutes: async () => {
    const { data: posts } = await axios.get(
      'https://damp-thicket-88898.herokuapp.com/posts'
    )
    return [
      {
        path: 'foo',
        template: 'src/containers/Foo',
        getData: async () => ({
        posts,
      }),
  }
}

//---ここから別ファイル---
//src/containers/Foo.js

import React from 'react'
import { useRouteData } from 'react-static'

export default function Testes() {
  const { posts } = useRouteData()//渡したデータを受け取る
  return (
  <p>{posts[0]['title']}</p>//データの利用
  )
}

```

ルート先のコンポーネントにデータを渡す場合は、`getData: async ()`関数を利用します。

ルート先のコンポーネントで、`const { object } = useRouteData()`の形で受け取ることができます。



#動的にルートを変更する場合

```react:static.config.js
export default { //エクスポート
  getRoutes: async () => { //ブログエントリを取得し'posts'にJSONを格納
    const { data: posts } = await axios.get(
      'https://damp-thicket-88898.herokuapp.com/posts'
    )

    return [ // 各blogポストへのパスの配列を返す
      {
        path: '/blog',
        getData: () => ({
          posts, //Blogコンポーネントで使用できるようデータを渡す
        }),
        children: posts.map(post => ({ //Postsコンポーネント
          path: `/post/${post.id}`, // '/blog/post/1'みたいな各ポストへのパス
          template: 'src/containers/Post', //Postコンポーネントを元にレンダリング
          getData: () => ({
            post,// Postsコンポーネントで使用できるようデータを渡す
          }),
        })),
      },
    ]
  },
```

配列に合わせて、動的にルーティングを設定します。
配列内に含まれるIDを利用します。

また、その子コンポーネントで利用できるようデータを`getData: async ()`関数を利用して渡します。
mysqlのバージョンを8にしたらphpmyadminがログインできなくなった

## 環境
mysql 8.0.17 
docker 19.03.1
 
## 状況
mysqlのバージョンが5.7の時は問題なくログインできたが、バージョンを8にしたら、
phpmyadminが急にログインできなくなった

dockerで環境構築を行なっています。
localhostでのphpはちゃんと表示されている。
mysqlのコンテナの中に入ってmysqlの接続はできる。しかし。phpファイルからmysql接続と
phpmyadminからの接続ができないという状況でした。

ググったら、バージョン8.0からセキュリティが厳しくなったらしい
https://qiita.com/RayDoe/items/baf53818ec8e44d4d148

バージョン8から認証プラグインが「caching_sha2_password」になったらしい。

色々ググったら認証方法を前のバージョンの時と同じにすればいいということはわかったが、
なぜかうまく行かなかった

## 解決策

まず、認証に関するテーブルの中身を見る

```
mysql> SELECT user, host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| root             | %         | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
```

認証方法を変更(今回はパスワードをsecretにしました)

```
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'secret';
ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'secret';
```

どうなったか確認してみた

```
mysql> SELECT user, host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| user             | host      | plugin                |
+------------------+-----------+-----------------------+
| root             | %         | mysql_native_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | mysql_native_password |
+------------------+-----------+-----------------------+
```

これでうまくいった。
【Vimium】Vimiumで不要なキーはPatterns Keysから無効化できる。

## 便利だけど、たまにそうじゃねえよと。
とっても便利なクロームの拡張機能[Vimium](https://chrome.google.com/webstore/detail/vimium/dbepggeogbaibhgnhhndojpepiihcmeb?hl=ja)ですが、便利すぎていらない機能がある事も。

・間違ってoを押すと検索が邪魔。
・tで別タブに変わって面倒。
・~~タイピングゲームしたいのに出来ない。~~

なのでキーを無効化する方法をご紹介します。

## 簡単、10秒で出来る。

方法は簡単。タブ上のVimiumのアイコンをクリック。
Patternsにルールを適用するURLを入力。
＊がワイルドカードになるので全ページで無効化したい場合
**https?**にしましょう。

Keysに無効化するキーを入力するだけ。
とても簡単ですね。
gifを撮りました。こんな感じです。

Add Ruleで複数のキーに対して適用できます。
最後はSave Changesです。
![2019-08-31 20.00.18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/431639/22f04df8-817d-5564-0b13-4004dd226afd.gif)

## 最後に
mapping を帰るのもとても簡単なので一度[公式リポジトリ](https://github.com/philc/vimium)に目を通すといいかも。
AWS認定ビッグデータ - 専門知識 勉強記

AWS認定ビッグデータ - 専門知識を一度受験したものの,不合格になっているため勉強記録を Qiita につけていく.

この記事は試験概要と各勉強の記録のインデックスページである.

# 試験概要
[AWS 認定ビッグデータ – 専門知識](https://aws.amazon.com/jp/certification/certified-big-data-specialty/)

* 試験の形態 : 選択式
* 試験時間 : 170 分
* 受験料金 : 30,000 円（税別）

## 試験のガイド

[試験ガイド](https://d1.awsstatic.com/training-and-certification/docs-bigdata-spec/AWS%20Certified%20Big%20Data%20-%20Specialty%20Exam%20Guide%20000%20v1.2%20JPN.pdf)

## 模擬試験
[模擬試験](https://d1.awsstatic.com/training-and-certification/docs-bigdata-spec/BD-S%20Sample%20Questions%20for%20Web.pdf)

# 勉強記録のインデックス
* [AWS認定ビッグデータ - 専門知識 勉強記~RedShift~](https://qiita.com/tada_infra/items/b82d69c5baa35ba153b4)
* [AWS認定ビッグデータ - 専門知識 勉強記~Kinesis Streams&Kinesis Firehose~](https://qiita.com/tada_infra/items/beff4dd30198e24c91c2)


# 勉強で参考にさせていただいた記事
* [AWS認定Big Data勉強記 - 1](https://qiita.com/ieiringoo/items/f191d1679d7db6e5047c)
* [AWS認定ビッグデータ専門知識(BDS)を、１ヶ月の準備期間で取得した試験準備やったことまとめ](https://qiita.com/go_sougen/items/bfdf5e5d1c6c57ca6141)
* [AWS認定ビッグデータ - 専門知識 受験レポート](https://qiita.com/nakazax/items/757d4c7c46618e2193be)
【Rails】画像を表示したいのに画像のURLが表示されてしまう

# はじめに
すごくしょうもないミスをしてしまったので、備忘のため残しておきます。。。

# やりたいこと
画面上に画像を表示したい

## 問題
以下の通り画像を表示したいのに、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389470/33abaa43-f80d-5c8f-fa10-e6f5bdd106db.png)


URLが表示されてしまう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/389470/d00022fc-cec4-9dbc-1745-cc8c8fcd6594.png)

コードは以下の通り。
userテーブルに保存されている画像を表示しようとしています。

```before.
.contents-image
  = @user.image
```

## 対処法
以下のようにimage_tagにしてあげればいいだけでした。

```before.
.contents-image
  = @user.image
```

```after.
.contents-image
  = image_tag @user.image, alt: 'user-icon', class: 'user-image'
```

## 最後に
しょうもないミスですが、少しハマってしまったので戒めのため。。。。