OmniAICreator/Qiita-1.07M huggingface dataset:
画像取得WEBAPI PixabayAPIお試し

Pixabay公式

https://pixabay.com/api/docs/

アカウント作ってAPIキーを取得する。特に障壁なし。

https://paiza.hatenablog.com/entry/2017/11/30/120%E4%B8%87%E6%9E%9A%E8%B6%85%E3%81%88%E3%81%AE%E7%94%BB%E5%83%8F%E3%82%92JavaScript%E3%81%8B%E3%82%89%E7%84%A1%E6%96%99%E3%81%A7%E4%BD%BF%E3%81%88%E3%82%8B%E3%80%8CPixabay_API%E3%80%8D%E3%81%A7%E7%94%BB

per_pageで取得画像枚数を設定できる。3枚が最低限

サンプル Codepen

```HTML:index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Pixabay API サンプルデモ</title>
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    
    <form name="search">
      <input name="key" type="text" placeholder="文字を入力してください">
      <input name="btn" type="submit" value="ボタン">
    </form>

    <div id="result"></div>
    
    
    <script src="app.js"></script>

  </body>
</html>
```

```CSS:Css
form {
  margin: 25px 0;
  text-align: center;
}
form input[type="text"] {
  width: 80%;
  border: none;
  outline: none;
  padding: 5px 0;
  font-size: 18px;
  font-weight: bold;
  border-bottom: 1px solid #aaa;
}
form input[type="submit"] {
  padding: 5px 10px;
  border: 1px solid #aaa;
  outline: none;
  color: #000;
  background-color: #fff;
}
form input[type="submit"]:hover {
  color: #fff;
  background-color: #aaa;
  cursor: pointer;
}

img:hover {
  opacity: 0.5;
}

#result {
  width: 90%;
  margin: auto;
  padding: 30px;
  
}
```

```Javascript:JS
(function() {
  
'use strict';
  
  
//フォームのボタンがクリックされたら、またはエンターキーが押されたら
document.search.btn.addEventListener('click', function(e) {
  e.preventDefault();  //画面更新をキャンセル
  
  
  fetch( createURL(document.search.key.value) )
  .then( function( data ) {
    return data.json();  //JSONデータとして取得する
  })
  .then( function( json ) {
    
    createImage( json );
    
  })
})

  
  
//リクエスト用のURLを生成する
function createURL( value ) {
  var API_KEY = '*******';
  var baseUrl = 'https://pixabay.com/api/?key=' + API_KEY;
  var keyword = '&q=' + encodeURIComponent( value );
  var option = '&orientation=horizontal&per_page=3';
  var URL = baseUrl + keyword + option;
  
  return URL;
}
 
  
//画像のJSONデータを画面に表示する
function createImage( json ) {
  var result = document.getElementById('result');

  result.innerHTML = '';  //検索するごとに画面をリセットする

  //該当する画像があれば
  if( json.totalHits > 0 ) {
    json.hits.forEach( function( value ) {
      var img = document.createElement('img');
      var a = document.createElement('a');

      a.href = value.pageURL;  //ダウンロード用のサイトURL
      a.target = '_blank';
      img.src = value.previewURL;  //プレビュー用の画像URL
      
      a.appendChild( img );
      result.appendChild( a );
    })
  }
  else {
    alert('該当する写真がありません');
  }
}
  
})();
```
【あいまい回避】技術力とかいうよくわからんワードを分解する

# 0.はじめに

お酒の場だったとおもう。
フリーランスになって多く製品を経験しながら、自分のプロダクトを持ちたいという夢を語ったところ、

「お前の技術力なんて、オレ以下だ…（長いので省略…）」

と、激励をいただいた。
まぁ、怒っているか？と言われてもなるほど？わからん・・・
ってなったので、”技術力”などという曖昧な言葉を分解しようと思った。

別に優劣つけるとかそういうわけでもないので、
相手が、技術力といったときにどれの文脈で言ったのか考えるたしになればと思う。

# 1. 前提

まずは、技術力という言葉の定義を次のようなモノであると定義する。

**ある問題領域をテクノロジーで解決して、世の中に使える形でリリースをする力**

広義すぎると思われる方がいらっしゃるかもしれない。
技術力とは、それぐらい曖昧な言葉なのではないかと思う。

# 2.分解

まず、製品をリリースするにあたって、必要な要素を考えてみた。

- 世の中のシーズ・ニーズ・ウォンツを読む
- 製品リリースを勝ち取る
- 顧客の要求を予測する（もしくは、読み取る）
- 技術調査をする。
- 技術選定をする。
- 技術に最適な、設計を考える。
- 技術・設計を利用し、実装する。
- 実装をテストし、品質をあげる。
- 流通に乗せて出荷する（もしくは、Webなどの媒体でリリースする）

製品ローンチまでに行うことはこれで、漏れがないと思う。
さらに細かくしようと思うと、細かくはできるかもしれないが、
一旦の粒度は、隣り合う分野で使う技能が違うと自分が考えた結果を書いた。

## 2-1.社会分析能力

世の中のシーズ・ニーズ・ウォンツを読む能力とする。
社会と大きな言葉で言っているのは、自社開発であることを考慮したためである。

会社組織にいる場合は、上司や役員のシーズ・ニーズ・ウォンツからくることもある。

また、ここで製品を思いつくことになるので、一般的にいわれる発想力はこの分野である。
ただ、個人的には社会分析をした結果でてくるモノなので、分析の分野にいれた。

## 2-2.承認力

製品をリリースするための、承認を得る能力とする。

承認とは、会社組織は、上司や役員・もしくは取引先からリリースOKをもらうこと。
起業の場合は、VCや銀行やスポンサー・株主からリリースするための資金が調達できること。

## 2-3.要求定義力

顧客（社会・他社）の要求を予測する能力とする

顧客はだいたい、自分の要求をわかっていないことが多い。
というか、自分もだいたい、したいことわからない。

最終的に、何がしたいのかを予測する能力とする。
おそらく、これが一番むずかしい…

ヘンリー・フォードの言葉
**『もし私がお客さんに何が欲しいかとたずねたら、彼らは、もっと早く走れる馬をと、と答えていただろう。』**

要求する側も社会通念以上のことを考えがたいという証拠である。
※もちろん、要求側がイノベーションしてくることもある。

## 2-4. 技術調査力

要求を実現するための能力を探す。
もしくは、普段から、技術を蓄える能力とする。

実現する引き出しの多さは、ここに起因する。
発想力もこのあたりを強めることで、強くはなっていく。

## 2-5. 技術選定力

技術選定をする能力を指す。

ここで、大きくいいたいのがコスト感なのである。
最良を決めるコスト感覚が重要である。

世の中の問題はだいたい、「金」か「時間」が解決する
しかし、プロジェクトは終わりが決まっていることもある（時間が固定されている）
もしくは、予算が決まっているプロジェクトもある（お金が固定さている）
それとも、両方とも決まっているプロジェクトもあるだろう…

なので、このコスト内で選べる最大効率の技術を選定する能力と思っている。

このあたりすべて度外視で選べるなら、一番いい装備で挑めばいいのだ。

## 2-6. 技術利用能力

- 技術に最適な、設計を考える。
- 技術・設計を利用し、実装する。

この2つに対応していく能力を指す。
選定した技術に対して、それを適切に利用する能力だ。
設計力と実装力をわけようかと考えたのだが、技術利用という意味では同じなので一つにした。

OSSを使うなら、OSSの関数の意図を汲み取って利用したり、
必要であれば、OSSに対してIssueをあげたりもする。

設計であれば、その言語に一番適した設計をするというのが利用力であると考える。
おそらくはできるのだろうがHaskellでオブジェクト指向をしようとしたりは、あまりいい打ちてではないのだろうか？
※もちろんどういうシーンで…とかもあるので間違いはない。

多くの人が技術力技術力って言ってるのはここを指してるのではないかと思っている。

## 2-7. 品質向上力

技術でつくったモノの品質を向上させる能力を指す。
テスト　→　修正　の流れで、品質をあげていく能力を指す。

リファクタリング能力もここに含まれるだろう。
※そもそも、リファクタリングは単体自動テストが存在するはずだ。
※最初からきれいに書く能力は、技術利用能力に含めたいと考える。

## 2-8. デプロイ・ローンチ力

製品出荷についての能力を指す。
デプロイフローや、はたまた、CI/CDを考える能力
顧客に先にデリバリーする流通まで考えられたらさらにいいのかもしれない。

運用をしていくソフトウェアなら、ここに、製品戦略も交えないといけない可能性もある。

# 3. まとめ

技術力と一言でいわれても、これくらい多岐にわたっていると考えている。
安易に、技術力と呼称するのも、なんかちょっと違うような気がしている。
逆に、なんだろうか、技術利用能力だけで語るのも、狭すぎるかもしれない。

結論を書いておくと、技術力という言葉は非常に曖昧で分野でみて、能力評価をしたほうがいいのだと思う。
なんとなく、技術力が高そうというだけでは、やはり評価として曖昧になるのではないだろうか？

細分化をしたほうが、具体的な能力向上の解決策もでると考える。

以上、技術力についてでした。

もし、こんなのも技術力じゃないか？とかあればコメントを貰えると嬉しいです。
【Swift】UIButtonをsetTitleしたときのちらつきをなくす

#はじめに
以下のように、UIButtonをsetTitleした時に一瞬ちらついてしまいます。これをスムーズに入れ替える方法を紹介します。

ちらつきあり
![ezgif.com-gif-maker (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/d36a1b2d-aca6-f77c-9089-9dceb19e4034.gif)

ちらつきなし
![ezgif.com-gif-maker (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954451/c3f4b054-e155-59a0-f75b-f736d840943c.gif)


#実装
まず、ちらつきをなくす前のコードがこちらです。　

```Swift
enum ButtonType {
    case a
    case b
    var text: String {
        switch self {
            case .a: return "AAAAA"
            case .b: return "BBBBB"
        }
    }
    mutating func change() {
        switch self {
            case .a: self = .b
            case .b: self = .a
        }
    }
}

final class ViewController: UIViewController {
    
    @IBOutlet private weak var button: UIButton!
    private var buttonType: ButtonType = .b
    
    @IBAction private func buttonDidTapped(_ sender: Any) {
        button.setTitle(buttonType.text, for: .normal)
        buttonType.change()
    }
    
}
```

そして、ちらつきをなくしたコードがこちらです。

```swift
enum ButtonType {
    case a
    case b
    var text: String {
        switch self {
            case .a: return "AAAAA"
            case .b: return "BBBBB"
        }
    }
    mutating func change() {
        switch self {
            case .a: self = .b
            case .b: self = .a
        }
    }
}

final class ViewController: UIViewController {
    
    @IBOutlet private weak var button: UIButton!
    private var buttonType: ButtonType = .b
    
    @IBAction private func buttonDidTapped(_ sender: Any) {
        UIView.setAnimationsEnabled(false)
        button.setTitle(buttonType.text, for: .normal)
        buttonType.change()
        button.layoutIfNeeded()
        UIView.setAnimationsEnabled(true)
    }
    
}
```

ポイントは以下ですね。
ボタンのタイトルを変更する前にアニメーションを止めて、ちらつきを無くします。そして、ボタンに対して`layoutIfNeeded`をしてあげることで、ちらつきがなくなります。（これを書かないと、ちらついてしまう）そして、最後にアニメーションを再開します。

```swift
UIView.setAnimationsEnabled(false)
button.setTitle(buttonType.text, for: .normal)
buttonType.change()
button.layoutIfNeeded()
UIView.setAnimationsEnabled(true)
```


#おわりに
おわりです。
[Python]Seleniumを利用したWebページのPDF保存方法 メモ

* Python + Seleniumを利用して複数のWebページにアクセスし、それらのページをPDF保存する方法をメモする。
  * Windows環境でGoogle Chromeを利用して実施する。

## 事前準備

* **[こちら](https://qiita.com/KWS_0901/items/7191b5f5d129aba6315c)**の手順でSelenium,Chromeドライバーをインストールしておく。

## 処理フロー

0. 以下のような対象WebページのURL一覧(`urls.txt`)を用意する。

   ```
   https://hogehoge.com/hoge.html
   https://fugafuga.com/fuga.html
   ...
   ```

1. 上記ファイルに記載のURLにアクセスする。
2. アクセスしたURLをPDF保存する。
3. １，２を繰り返す。

## コード

* ※有料ジャーナルなどを対象に実行しないこと。

```python
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from pathlib import Path
import time
import json

# 保存対象URL一覧取得
urls = []
with open('urls.txt', mode='rt', encoding='utf-8') as f:
    urls = f.readlines()

# Chrome の印刷機能でPDFとして保存
options = webdriver.ChromeOptions()
# PDF印刷設定
appState = {
    "recentDestinations": [
        {
            "id": "Save as PDF",
            "origin": "local",
            "account": ""
        }
    ],
    "selectedDestinationId": "Save as PDF",
    "version": 2,
    "pageSize": 'A4'
}
# ドライバへのPDF印刷設定の適用
options.add_experimental_option("prefs", {
    "printing.print_preview_sticky_settings.appState":
    json.dumps(appState),
    "download.default_directory": '~/Downloads'
})
options.add_argument('--kiosk-printing')

with webdriver.Chrome("./chromedriver.exe", options=options) as driver:
    # 任意のHTMLの要素が特定の状態になるまで待つ
    wait = WebDriverWait(driver, 15)
    for url in urls:
        driver.implicitly_wait(10)
        driver.get(url)
        # ページ上のすべての要素が読み込まれるまで待機
        wait.until(EC.presence_of_all_elements_located)
        # PDFとして印刷
        driver.execute_script('window.print()')
        # 待機
        time.sleep(10)
    driver.quit()

```

* ダウンロードフォルダにPDFファイルが保存される。

## 参考情報

* [PythonのSeleniumでログインありのwebページをPDF保存する](https://qiita.com/kuro227/items/838b9bab231902e280d4)
* [SeleniumとPythonを用いて複数のウェブサイトをPDF保存](https://qiita.com/cozy16/items/9448203691e206072558#rpapy)
* [PythonのSeleniumでhtmlをpdfにするときの設定メモ](https://salamann.com/python_selenium_html_pdf_automation)
VBA　問題１－１新規bookを立ち上げる

もとのエクセルに上書きされたくない！！
その解決法は、VBAで最初に新規BOOKをもう1つ開くことです。

では、どのように書けばあよいのか？


workbooks.add

になります。



https://www.youtube.com/channel/UCWKCTqspSJnq_6M4nHcX_ug
[Ruby]メソッドの引数の値渡し、参照渡しと破壊的メソッドについて

## はじめに
Rubyを勉強していて、値渡しと参照渡し、破壊的メソッドの関係について学んだのでメモ

## 学んだこと
以下のようなコードを書いていて想定していた動きと違ったので深掘りしてみた。

```
def remove_same_word(array , element)
    array.delete(element)
    array
end

words = ['hoge','hige']
word = 'hige'

p words 
p remove_same_word(words , word)
p words
```

```
=> ["hoge", "hige"] 　# 元のwords
=> ["hoge"]         　# remove_same_wordの実行結果
=> ["hoge"]         　# remove_same_word後のwords
```

上記は第一引数の配列wordsから第二引数のwordと同じ名前の要素を取り除きその結果を変えすメソッドです。
メソッドに渡したwordsの値が変わらないと思っていたのですがそうではありませんでした。
なぜこうなったか、結論からいうと**破壊的メソッド**を使っていたからでした。

私の今までの認識では破壊的メソッドは「!」がつくと勘違いしており、引数に入れたオブジェクトの値は変わらないと思っていました。
今回の例で言うと**remove_same_word**メソッドの中で使っている**remove**がそれにあたり元の値までもが変更されていました。

## 参考

https://qiita.com/hogucc/items/39c89c25a39d15b41f4e
herokuにError ID: mfa_required でログインできないとき

# herokuにログインができない
herokuにログインができずハマったので、備忘録として残します。

# Error ID: mfa_required
herokuにログインする。

```bash
$ heroku -login -i
```


メールアドレスとパスワードを入力。
(メールアドレスは最初から入力されてる)

```bash
heroku: Enter your login credentials
Email [******@gmail.com]: 
Password: ************
```

以下のエラーでログインできないと言われた。

```bash
Error: Your account has MFA enabled; API requests using basic authentication with
›   email and password are not supported. Please generate an authorization token for
›   API access.
›
›   Error ID: mfa_required
```

どうやら通常のメールアドレスとパスワードではログインができないらしい。

# 通常のログインパスワードの代わりにAPI Keyを入力することで解決。

API Keyはブラウザでherokuにログインをして、設定から取得可能。Revealをクリックすると表示される。

改めてheroku login -iで、パスワードにAPI Keyを入力。

```bash
heroku: Enter your login credentials
Email [******@gmail.com]: 
Password: ************************************
```

ログインできました。

```bash
Logged in as ******@gmail.com
```


# 参考サイト
https://community.gitpod.io/t/heroku-login-fails-error-forbidden/1867
RSpec 実行時に `Failure/Error: require File.expand_path` のエラーが出た

`bundle exec rspec` 実行時に `Failure/Error:`なるエラーが出ました。

エラーメッセージの詳細はこちらです。

```console
An error occurred while loading ./spec/requests/todo_spec.rb.
Failure/Error: require File.expand_path('../config/environment', __dir__)

FrozenError:
  can't modify frozen Array: ["/usr/src/app/app/channels", "/usr/src/app/app/controllers", "/usr/src/app/app/controllers/concerns", "/usr/src/app/app/jobs", "/usr/src/app/app/mailers", "/usr/src/app/app/models", "/usr/src/app/app/models/concerns", "/usr/local/bundle/gems/actiontext-6.1.3.2/app/helpers", "/usr/local/bundle/gems/actiontext-6.1.3.2/app/models", "/usr/local/bundle/gems/actionmailbox-6.1.3.2/app/controllers", "/usr/local/bundle/gems/actionmailbox-6.1.3.2/app/jobs", "/usr/local/bundle/gems/actionmailbox-6.1.3.2/app/models", "/usr/local/bundle/gems/activestorage-6.1.3.2/app/controllers", "/usr/local/bundle/gems/activestorage-6.1.3.2/app/controllers/concerns", "/usr/local/bundle/gems/activestorage-6.1.3.2/app/jobs", "/usr/local/bundle/gems/activestorage-6.1.3.2/app/models"]
```

[Rails : RuntimeError - can't modify frozen Array when running rspec in rails](https://stackoverflow.com/questions/47320772/rails-runtimeerror-cant-modify-frozen-array-when-running-rspec-in-rails)


色々と検索しても、エラーの原因にピンポイントで当たる可能性は低いと思います。
少なくとも自分の場合は検索したどの記事も問題の解決にはつながりませんでした。

## 環境を見直す

### Dockerがちゃんと上げてるか？

データベースコンテナを上げ忘れていないか確認します。

自分はDockerコンテナが上がってなかったので立ち上げました。

```console
$ docker-compose up
```

### テーブルがちゃんと作られているか？

test環境用のテーブルが作られているか？

FactoryBot に問題はないか？
自分の場合は`spec/factories`以下の書き方に問題があったので直しました。

```console
# bin/rails db:migrate RAILS_ENV=test
rails aborted!
NoMethodError: undefined method 'done' in 'item' factory
Did you mean? 'done { false }'
```

ここまで確認したら`bundle exec rspec`自体は動くようになりました。

### config 以下のファイルに変な修正を入れてないか？

検索して出てくる記事では config/application.rb などに変な修正を入れて挙動がおかしくなった人が多いようでした。

デフォルトのファイルから何かおかしな修正を入れていないか。
インストールした Gem に不備はないか、などの設定・定義周りを確認するのがいいと思います。

環境か設定に原因がある可能性が高いはずです。
VScode で M5Stack開発時のメモ

#はじめに
ArduinoIDEを使用してM5Stackをいじってきたが、先日VSCodeを使ってみようと導入してみた(2021/05)
とりあえず導入して、以前自分が作成したプログラムを書き込めるところまでは確認。

ただ、ちょっと使いにくい、わからない、理解できていないところもあるので、いろいろメモしておく。

##c_cpp_properties.json の作成
インテリセンスを使用するために必要なファイル。
インクルードしたいファイルの指定などをここに記述する必要がある。

各プロジェクトのフォルダに[.vscode]というフォルダが作られ、その中に自動で作られる。

ただし、新規作成したり、既存プロジェクトのフォルダを開いただけでは自動で作成されないみたい。

コマンドパレットに[Rebuild IntelliSense Configuration]があるが、ファイルがないと押しても何も起きない。c_cpp_properties.jsonのことではないらしい。

###ベリファイで作成
ソースファイルが空っぽでもベリファイを実行すれば、c_cpp_properties.jsonは作成される。
ボード情報のフォルダと、ライブラリ（スケッチの保存先指定してあるフォルダ）から関連するヘッダファイルがある場所を自動で取得、追加してくれるみたいだ。

\#include でヘッダファイルを追加した場合、一度ベリファイすればc_cpp_properties.jsonに自動で追加され、インテリセンスが働くようになる。
すぐにインテリセンスを使いたければ、自分でc_cpp_properties.jsonのincludePathにヘッダファイルの場所を追加する。

エラーメッセージはbrowse.Pathにないとでるが includePathで問題ないらしい。
browse.Pathを省略すると、includePathが使われる仕様らしい。

c_cpp_properties.jsonを編集したら保存しないと反映されない。

###電球マークから追加

c_cpp_properties.jsonが無くてインクルードにエラーが出てる場合は、カーソルを重ねたときに電球マークが出る。これを押すと、「"browse.path"設定の編集」というボタンがさらに出て、これを押すと、c_cpp_properties.jsonが作成される。

ただし中身は空っぽ。
結局、インクルードするファイルはフォルダ場所を指定してあげないといけない。
だったらベリファイして作った方が早い。

c_cpp_properties.jsonは各プロジェクトごとに作成される。
編集できるが、それはそのプロジェクトのみに有効となるようだ。
大元のファイルがあって、それを変更できればよさそうだが、見つからず。

c_cpp_properties.jsonについては、どのタイミングでどのような方法で作成するのかセオリーなのかよくわからず。

とりあえず今回はここまで。
docker-composeでSeleniumを使ったRspecでinvalid session idエラーの解決方法

## 概要
docker環境でchromeでのブラウザテストを実行した際に今まで通っていたテストが
"invalid session id"のエラー発生したので解消方法を記載します。

```:エラー内容
Selenium::WebDriver::Error::InvalidSessionIdError:
 invalid session id
```

## 原因と解決方法

【原因】
どうやらメモリ不足が原因みたいでした。

【解決方法】
chromeコンテナのメモリを増やすように設定を行う。

 → docker-compose.ymlを修正してコンテナで使用するメモリを設定します。

```yml:docker-compose.yml
  chrome:
    image: selenium/standalone-chrome:latest
    shm_size: 256m　　#　←　追加
    ports:
      - 4444:4444
```

shmサイズは、Chromeがコンテンツをダウンロードした際の一時ファイル領域のことです。
デフォルトは64mらしいので、多めに設定してみます。

設定後テストが通るようになりました。
Teams から Azure VM を起動・停止する

Azure 上の仮想マシンを teams から まとめて起動・停止させたので備忘録としてまとめます。

#背景
Azure 上に検証環境として複数の仮想マシンを立てています。
これは検証時（週に数回）だけ使いたいのですが、10台近くあるので Azure Portal 上でポチポチ起動・停止するのがめんどくさくなりました。
スクリプトで実行すればいいだけの話ですが、なんとなくスタイリッシュ？に実行したかったので Teams 連携させてみました。

#方法の検討
Azure 仮想マシンを起動・停止させるなら Azure Automation (以下 Automation) の Start/Stop VMs during off-hours という方法があります。
調べたところ、これはスケジュール実行するもので今回のニーズに合わない（検証は不定期で行われる）ので候補から削除しました。

https://docs.microsoft.com/ja-jp/azure/automation/automation-solution-vm-management

ただこの Automation には
・スケジュール実行
・手動実行
・他のプログラムからの呼び出し
・webhook
といった実行方法があり、今回は webhook と Teams を連携させてみました。

#Azure 側の設定
まずは Automation を使うために Automation Account をデプロイします。
少し話がそれますが、このAutomation は Log Analytics と連携させることで使うことができる機能（Start/Stop VMs during off-hours など）があります。
連携させるためには予め決められたリージョンである必要があるので、デプロイする際にリージョンを確認しておくと今後 そのような機能を使いたくなった時に便利かもしれません。（今回は気にしなくて結構です）

https://docs.microsoft.com/ja-jp/azure/automation/how-to/region-mappings

（追記）
Automation Account に Managed ID と呼ばれる ID を振って、Azure 仮想マシンの起動・停止ができる権限を与えたいと思います。
Automation の Managed ID は 2021/6/5 ではプレビューの機能です。

https://docs.microsoft.com/ja-jp/azure/automation/enable-managed-identity-for-automation

この Managed ID に対して、適切な スコープ（サブスクリプションやリソースグループなど）で適切な役割を与えます。
例）スコープ：リソースグループ、役割：仮想マシン共同作成者

（追記ここまで）

Automation Account が準備できたら、スクリプトの準備をします。
Azure のモジュールをインストールする必要があるので
**Automation Account > モジュール ギャラリー**
から必要なモジュールをインストールします。今回は以下の2つが最低限あれば動きます。

* Az.Accounts
* Az.Compute

以下のように検証環境ごとにいくつか仮想マシンが存在しているため、並列処理で仮想マシンの実行を早くしたいと思います。

* 検証環境 1 -> VM01, VM02, VM03, VM04,...
* 検証環境 2 -> VM11, VM12, VM13, VM14,... 

PowerShell で並列処理をしたい場合は ワークフローの中で ForEach -Parallel を使えばいいらしいので

**Automation Account > Runbook > Runbook の作成**
で *PowerShell ワークフロー* を選択し、実行内容を記載します。

スクリプトの内容はこちらに記載しています。
※Runbook 名とワークフロー名を同じにする必要があります。

https://github.com/NakayamaKento/Azure-VM

今回は引数で検証環境を指定できるようにしてみました。これを保存し、発行します。


続いて webhook で使うための設定を行います。
対象の Runbook の画面から **Webhook の追加** を選択します。
名前と引数をここで入力しておきます。

注意点として、**URL はこのタイミングでしか確認ができないので** 忘れないようにメモしておきます。

無事に発行が完了すれば Azure 側の設定は以上です。

#Teams 側の設定
Teams のあるチームのチャネルからメンションしてメッセージを送ると webhook が実行されるように設定します。
以下の公式ドキュメントの手順を参考にして簡単に設定ができました。

>適切なチームを選択し 、[チーム の管理] ([•••] ドロップダウン メニューから [チームの管理] を選択します。
>ナビゲーション バーから [アプリ] タブを選択します。
>ウィンドウの右下隅で、[送信 Webhook を作成する] を選択します。
>表示されたポップアップ ウィンドウの必要なフィールドへの入力を行います。

https://docs.microsoft.com/ja-jp/microsoftteams/platform/webhooks-and-connectors/how-to/add-outgoing-webhook#create-an-outgoing-webhook

#まとめ
無事に Teams から Azure 仮想マシンの起動・停止ができるようになりました。
Automation の ワークフロー、Teams で webhook の登録は初めて試したんですが 何とかできて良かったです。

※Managed ID に関する設定が漏れていたので追記しました、
M5Stack UnitV2をmacOSで試す

# やりたいこと

以下の環境でM5Stack UnitV2と繋いでAIカメラで遊ぶまで。特にドライバはインストールしていない。

- M5Stack UnitV2
- MacBook Pro
- macOS Big Sur
- Chromeブラウザ

## まずは接続

Type-CのケーブルでMacとM5Stack UnitV2を接続する。LEDが点灯してファンが回り出すのを確認する。その後、TerminalでM5Stack UnitV2を探す。

```shell
$ ifconfig
```

多分こんなのがM5Stack UnitV2だと思う。enの数字は環境によって違うかもしれない。わかりやすいのはM5Stack UnitV2をUSBで繋がない状態でifconfigしてみた結果と繋いだ状態のifconfigの差分がM5Stack UnitV2なので、見つからなかったら抜き差しして差分を調べると良い。

```shell
en7: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
	options=6467<RXCSUM,TXCSUM,VLAN_MTU,TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZE
```

以下のコマンドでネットワークを有効にしてあげるとM5Stack UnitV2とのコネクションが確立する。

```shell
$ sudo ifconfig en7 down
$ sudo ifconfig en7 up
```

## AIカメラで遊ぶ

繋がったらChromeブラウザで http://10.254.239.1/ を叩いてみる。M5Stack UnitV2と接続されていればObject TrackingやFace Trackingなどのサンプルが試せるページが開くはず。
色々試してみたけれど、ファンがついてるものの、ちょくちょくオーバーヒートする。
テキストファイルを「メモ帳」で開く（powershell スクリプト）



こんにちは。
テキストファイルを「メモ帳[^1]」（notepad) で開く powershell スクリプトを作りました。
txt や ps1 ファイルを指定できます。既存ではないファイル名を指定した場合には新規作成します。

[^1]: txt や ps1 ファイルは、「メモ帳」があらかじめ関連付けられたアプリケーションとなっています。

```powershell
PS> .\edit-text-file.ps1 test.txt
```

```edit-text-file.ps1
# Encoding::Shift-JIS
Param($file, $string)
if (-Not(test-path $file)) {New-Item $file -ItemType "file"}
Write-Output $string | Out-File -FilePath $file -append  # ファイルへ指定した文字列を書き加える
Invoke-Item $file
```
オレオレ証明書の作り方(OpenSSL)

Webアプリ開発してると

+ 証明書の発行って、認証局に署名してもらったりとかめんどそう。
+ とりあえずWebサーバーをSSL化して動作確認したいだけなのに
+ 3分でできないかな。

ってこと頻繁にありますよね。

この章では、自分で証明書を作成し、自分で認証を行う方法について解説します。

はじめに断っておきますが、この手順は、俺が「オレだ！」という証明書を作ってその証明書を俺が「本物だ！」とハンコを押すようなもので、何の証明にもなっていないということは念頭に置いてくださいｗ

この証明書を使ってブラウザからアクセスするといわゆる「このサイトは信頼できません」というメッセージが出ていわゆる「危険を承知で続行」を押す羽目になりますｗ



##SSL化の目的

WebサーバーのSSL化と言っても、目的はいくつかあると思います
てことでまず目的レベルの確認

+ 通信を暗号化したい(Level1)
+ 偽物のサイトではないことを証明したい(Level2)
+ なりすましのユーザーからのアクセスを防ぎたい(Level3)

Level1はいわゆる「鍵」ってやつです。暗号化するだけが目的ならこれで十分です。
鍵生成ツールだけでセットアップできるのでopensslも要らず楽です。

Level2がいわゆる「証明書」ってやつです。信頼できる（とされている）期間に頼んで「私は〇〇です」ってのを署名してもらったやつですね。印鑑証明みたいなもんでしょうか。
一般的にはこのレベルかと思います。

Level3がいわゆる「クライアント認証」ってやつです。クライアント証明書っていうのをサーバーが発行し、それを持っている人だけがアクセスできるっていうアレです。
最上級レベルですね。

で、Level1が簡単ではあるのですが、サイトを公開するとかなるとLevel2の知識が必要になりますし、opensslさえインストールすれば証明書は簡単に作成できるので今回はLevel2で行きます。

てことで、opesslをインストールしといてくださいね～

## 鍵(Key)の作成

とりあえずディレクトリが散らからないよう、certディレクトリ作ってその中で作業します

```
$ mkdir cert
$ cd cert
```

鍵ファイル「oreore.key」をこうやって作ります

```
$ openssl genrsa -out oreore.key
Generating RSA private key, 2048 bit long modulus
........................+++
..........+++
e is 65537 (0x10001)
```
## 証明書(Certificate)の作成

適当に入力して「oreore.csr」という証明書を作成。
これは正確には「証明書署名要求(certificate signing request)」と呼ばれます。
まだ署名されてない証明書ということですかね。

```
$ openssl req -new -key oreore.key -out oreore.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:OR
State or Province Name (full name) []:Ore Ore
Locality Name (eg, city) [Default City]:Ore
Organization Name (eg, company) [Default Company Ltd]:Ore
Organizational Unit Name (eg, section) []:Ore
Common Name (eg, your name or your server's hostname) []:Ore
Email Address []:oreore@oreore.ore

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
```

これで「oreore.csr」という証明書署名要求ファイルを作成。

これをベリサインなどの認証局(CA)に提出して本人だと署名してもらうわけですね。


##署名(Sign)する

本来的には、オレオレ認証局を立ててそこで署名するっていう手順を踏むのが正当で、技術的理解も深まるかと思われますが、ちょっと長くなってしまうのでｗ、opensslの自己署名コマンドを使っちゃいますｗ[^1]

真面目な方は「プライベート認証局」でググってくださいｗ

てことで、次のようにして署名します。

```
$ openssl x509 -req -days 90 -in oreore.csr -signkey oreore.key -out oreore.crt
Signature ok
subject=/C=OR/ST=Ore Ore/L=Ore/O=Ore/OU=Ore/CN=Ore/emailAddress=oreore@oreore.ore
Getting Private key
```

オレオレ感ハンパないですｗ

これで「oreore.crt」という「正真正銘僕ちゃんですよ！」というファイルができましたので、これと鍵をWebサーバーに設定することになります。

[完]

[^1]: 実は署名要求を生成する際にいきなり自己署名してしまう -x509 というオプションもありますが、説明の都合上使いませんでした
fromから送ったデータがうまくDBに入らない

#fromから送ったデータがうまくDBに入らない原因
bladeファイル

```
<form action="{{ route('posts.add') }}" method="POST">
   <table>
     @csrf
     <tr>
       <th>タイトル</th>
       <td>
          <input type="text" name="title">
       </td>
     </tr>
       <tr>
       <th>人数</th>
       <td>
　　　　　　//数字だけの入力にしたかったのでtype="number"を指定
          <input type="number" name="member">
       </td>
      </tr>
  <table>
</form>
```

コントローラー

```
public function add(Request $request){
   $param =[
      'title' => $request->title,
      'member' => $request->member,
   ];
   DB::table('posts')->insert($param);
   return redirect('/posts/index');
}
```

データを送ろうとしたら下記のエラーが出た

```
SQLSTATE [23502]: Non-null violation
```
翻訳すると「データがnullだから違反してるよ」的な感じだった。
多分....。
なぜNULLで送られる？

原因はDBにあった。

```
 public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->id();
            $table->integer('member');
        });
    }
```
memberカラムをintegerとしていたためエラーが起きた。

なのでbladeファイルのinputのtypeをtext変更

```
 //numberからtextに変更
 <input type="text" name="member">
```

するとうまくデータが送れた。
原因はまだわからないので明日調べる。
もっとDBを勉強するべきだな...
今日はここまで！
Flutterの状態管理パッケージ触ってみた(GetX)

Flutterでは数多くの状態管理方法があるのですが、今回は「GetX」というパッケージを触ってみようと思います！

https://pub.dev/packages/get

##### 追記:
こちらのパッケージ、現在では主流となっているRiverpodを同じくらいのLike数があるのですが、過去に色々あって古参Flutterエンジニアからは敬遠されている節があるようです
ただ多くのバージョンアップを繰り返してクオリティも上がっているようなので、状態管理の選定で一考の余地はあるのかなと思います

##GetXとは

公式では以下のように説明されています。
>GetX is an extra-light and powerful solution for Flutter. It combines high-performance state management, intelligent dependency injection, and route management quickly and practically.

DIや状態管理、ルートの管理を行うためのパッケージということみたいです。

###やってみる
では実際にコードに組み込んでいきましょう


今回使用しているバージョンは以下です。
・Flutter: stable, 2.0.6
・GetX: 4.1.4

###GetMaterialApp

GetXでRouteNavigationの管理を行うには、最初に``GetMaterialApp(home: Widget())``で囲ってあげる必要があるようです。

```dart
void main() {
  runApp(
    GetMaterialApp(
      home: MyApp(),
    ),
  );
}
```

ただ上記で使用した``GetMaterialApp``は、状態管理やDIを行うだけならば必要がないもののようです。
基本的には画面遷移などもGetXパッケージで管理した方がいいと思うのでとりあえずこちらで囲んでおけば問題ないかと思います。


###GetxController

次に状態管理やロジックを書くためのコントローラークラスを作成します。
コントローラーを作るためには``GetxController``を継承します。

```dart
class Controller extends GetxController{
  // state
  var count = 0.obs;

  // logic
  increment() => count++;
}
```

``0.obs``という見慣れないものが出てきました。
公式の文章を引用したものがこちら
>You can make any variable observable using a simple ".obs".

どうやら値を簡単にObservableなものにしてくれるもののようです。
基本的にステートの情報はリアルタイムでUIに反映させたいと思うので、GetXで状態管理をするならば**.obs**を多用することになりそうです。

###UI
では次にUI部分を作成していきます。

GetXではStatelessWidgetの中に組み込んでいけるようです(この辺はRiverpodなどと同じですね)

一通り出来上がったのがこちらです

```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final Controller c = Get.put(Controller());

    return MaterialApp(
      title: 'Flutter Demo',
      home: Scaffold(
        body: Center(
          child: Obx(
            () => Text(
              '${c.count}',
            ),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: c.increment,
          child: Icon(Icons.add),
        ), // This trailing comma makes auto-formatting nicer for build methods.
      ),
    );
  }
}
```

では一つずつ説明します。

###Get

まずこちら

```dart
final Controller c = Get.put(Controller());
```

作成したコントローラーを使用するには``Get.put(Controller());``とする必要があります。
GetXでは``Get.~~()``というものが複数存在します。例を挙げると

```dart
Get.to(NextScreen()); // 画面遷移を行う

Get.back(); // 前の画面に戻る

Get.off(NextScreen()); // 前の画面に戻ることのない遷移(Splashやログイン画面)

Get.offAll(NextScreen()); // 以前の画面を全てキャンセル
```

他にもRouteNameを利用した画面遷移などの方法もあるので、詳しくは[こちら](https://github.com/jonataslaw/getx/blob/master/documentation/en_US/route_management.md#navigation-with-named-routes)を確認してみてください。

### Obx()


次にControllerで定義したStateを表示している部分の説明をします。

```dart
Obx(
  () => Text(
    '${c.count}',
  ),
),
```

**.obs**でObservable化した値をリアルタイムでUIに反映させるには``Obx(() => Widget())``で囲んであげる必要があります。
そうすることで

```dart
onPressed: c.increment,
```

こちらで発火した関数でインクリメントされた値がリアルタイムで反映されます。

実際の画面はこんな感じです
<img width="300" alt="getx.gif" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249334/77ce8dd5-8ab8-3c01-a358-49ff89ca7ce4.gif">

###終わり
とまぁざっと触ってみたんですが、既存で広く利用されているRiverpodやProviderなどよりはずっとシンプルに書けるのかなーといった印象です。
ただ今回の記事は公式ページを軽く翻訳した程度のものなので、もっと詳細が気になる方は公式情報を見てみてください！
SpringBoot 2.4以降で環境ごとの定義ファイルと共通定義ファイルを読み込む（includeが使えなくなった）

# 概要

SpringBoot 2.4以降で、従来できていたapplication.yml関連の複数に分けている設定ファイルのincludeができなくなり、別の方法で分割したyamlファイルを読み込むようにしないといけないようです。
https://spring.io/blog/2020/08/14/config-file-processing-in-spring-boot-2-4

色々調べながら実装したのですが、理解するのに時間がかかったので、備忘のために記録として残します。

# yamlファイルの構成

以下4つのYAMLファイルを用意しています。
`application-common`は環境に依存しない共通の設定を管理し、`***-local`と`***-staging`は環境に依存した設定を管理しているYAMLファイルです。（local＝ローカル開発環境、staging＝ステージング環境）

```
.
├── application.yml
├── application-common.yml
├── application-local.yml
├── application-staging.yml
```

# spring.profiles.groupを使って複数に分かれているyamlを読み込む設定をする

application.ymlの定義として以下のように定義します。

```yaml:application.yml
spring:
  profiles:
    group:
      local:
        - common
        - local
      staging:
        - common
        - staging
```

個人的にわかりづらい点として、

- どのファイルをグループ化するにしても、「application-」という名前の定義ファイルを用意すること。
- 「application-」と名前をつけたファイルの、「common」「local」「staging」だけを列挙して指定すること。

というのが、見ててわかりづらいなと思いました。
別に以下のように記述したっていいじゃないかと。

```yaml
spring:
  profiles:
    group:
      local:
        - application-common
        - application-local
      staging:
        - application-common
        - application-staging
```

とりあえず、上記設定をした状態で、私のローカル開発環境の場合は、Eclipseの実行の構成から、
`プログラムの引数`に`--spring.profiles.active=local`と設定して実行することで、環境ごとの定義情報をロードしてSpringBootを起動することができました。
【Rails】Herokuデプロイ後のstatus 143エラー

# 目的
Herokuデプロイ後に出たエラー`「status 143」`を解決する。

# 開発環境
macOS: *Big Sur*
Rubyバージョン: *2.6.5*
Railsバージョン: *6.0.0*

# 問題

アプリをデプロイして本番環境での確認をしたところ、
`We're sorry, but something went wrong.`とエラーが出ました。

# 対策

とりあえず原因を探るべくエラーログを確認。

```:ターミナル
heroku logs --tail --app アプリ名
```

確認すると、`「status 143」`というエラー文が出ていました。

これについて調べたところ、何らかの影響で処理が止まっているとのこと。
Herokuの再起動をすれば直る可能性があるとの記事を発見したので、さっそく再起動をかけました。

```:ターミナル
heroku restart
```

しかし、何も変化せず。
エラーログをもう一度よく確認すると、ビューファイルの〜行目で止まってるとの記述がありました。

ビューファイルを確認してみると、アプリ内に置いてある画像を表示させている記述でした。
他にも画像表示させている箇所はあるため、この画像がおかしいと予測し、詳しく見てみるとこの画像のみ拡張子が「jpeg」でした。

調べてみると、どうやらHerokuで`「jpeg」`は使用できないようで、
拡張子を`「jpg」`に変換しデプロイしたところ、エラー解決しました!

JPEGの拡張子は「jpg」や「jpeg」があるようですが、今回使用した画像は「.jpeg」でした。
ちなみにどちらも同じファイル形式であり、あまり違いは無いようです。

# 最後に

ローカル環境では発生しなかったエラーだったので、最初混乱しましたが、
エラーログをよく見れば解決できる問題であり、いい勉強になりました。
同じ境遇の方の参考になれば幸いです。
では。
DBのカラム削除方法　Laravel

#使わないカラム名があったので消した。
消し方
まずマイグレーションを作る

```
$php artisan make:migration drop_column_テーブル名_column --table=テーブル名  
```

出来上がったマイグレーションに消したいカラム名を記載

```
   public function up()
   {
        Schema::table('posts', function (Blueprint $table) {
            //postsテーブルのカラム削除
            $table->dropColumn('カラム名');
        });
    }
```

マイグレーション実行

```
$php artisan migrate    
```

これで消せた！
RailsでもRubyのStringクラスに翻訳機能をつけてしまった（Rails 7でも対応）

# 何ができるようになった？


```ruby
'Maybe I should just write articles on Qiita in English and translate them in Rails console using ActiveTranslateSelf'.translate_to_ja
#  "英語でQiitaの記事を書いて、ActiveTranslateSelfを使ってRailsのコンソールで翻訳すればいいのかもしれません。"
```

[![asciicast](https://asciinema.org/a/418440.svg)](https://asciinema.org/a/418440)

Rubyの文字列をRailsのコンソールの中で訳せるようになっています！
基本的にRailsの中であればどこでも使えます！Callback設置して、Sidekiqで翻訳のジョブ設置してもよし、翻訳ファイルの更新スクリプトの中で使ってもよし！

# Rails Engineとは？

Railsの中にあるRailsのアプリ、ということで言えばいいでしょうか。
今回はRailsのConfigとLoadHookを使いたかったので、Engineとして作りました。
コマンドはいかです

```sh
$ rails plugin new ActiveTranslateSelf --mountable
```

`mountable`というオプションがないとRailtieになります。

# ハマったところ

Engineのコンフィグレーションについていろいろ読んでいて、
何回試してもうまくいかない・・・ということでしたが、
今回はDeepLの設定をInitializerを読み込んでから読み込まないといけないというところで積んでいました。

あとでActiveRecordにもちょっとした機能いれようかと思っているため

```ruby
ActiveSupport.on_load(:active_record) do
end
```

で行きました。このあたりはちゃんとRailsの実装を見て勉強しないといけないと思っています。

# Rails 7対応かどうか確認しよう！

RailsのEdgeだとすでにRails 7のAlphaが使えます！
これを以下のようにGemfileに記載すれば、今でも試せます

```ruby
gem 'rails', github: 'rails/rails', branch: 'main'
```
さすがはブランチ名もMainになっていますね。
個人的にすごいといころは、ActiveRecord::Encryptionがすでに使えるということかと思います。
Railsエンジニアの憧れとしてもEdgeで走っているプロジェクト、というのはあるかと思います。
（Github, Shopifyはそれを実践しています）

Github　Actionsで簡単にいろんなRailsのバージョンに対してテストも走らせて、すごく便利です。
ただしRails 5.2はRuby 3.0非対応なため、そこはもう5.2テスト対象として落とすべきか悩ましいところです。

```yml
strategy:
      matrix:
        ruby: [2.7]
        bundler: [default]
        gemfile:
          - rails_5.2
          - rails_6.0
          - rails_6.1
          - rails_master
```

このようにStrategyを指定するとテストもラクチンです！

今回のGem
https://rubygems.org/gems/active_translate_self

ソース
https://github.com/sampokuokkanen/ActiveTranslateSelf/
新卒研修で役に立った学生時代に勉強した技術

# はじめに
今年の4月から新卒エンジニアになり、約2ヶ月の技術研修が終わったので、その時に役に立った技術を述べようと思います。

# Git / Github
<img src="https://cdn.svgporn.com/logos/github-octocat.svg" alt="git"/>
まず一つ目はWeb開発では定番ツールのGit/Githubです。
基本的に研修で作成した成果物は、Githubで上げて先輩にコードレビューしてもらう形で、Gitの使い方の研修はなかったので、学生時代に慣れておいてよかったです。

習熟度は、プルリクエストベースでの開発ができる程度であれば大丈夫な感じでした。

# Docker
 <img src="https://qiita-user-contents.imgix.net/https%3A%2F%2Fcdn.svgporn.com%2Flogos%2Fdocker.svg?ixlib=rb-4.0.0&auto=format&gif-q=60&q=75&w=1400&fit=max&s=ffe3655310819d25c8e8258087ba4f63" alt="docker">

次もWeb開発ではお馴染みとなっているDockerです。
これも研修はなく、バックエンド研修で普通に使うことになっていたので、学生時代に慣れておいて良かったです。

習熟度は、Dockerの基本的なコマンドとdocker-composeでのコンテナ連携ができるくらいのレベルが必要でした。

# クリーンアーキテクチャ
![https___qiita-image-store.s3.amazonaws.com_0_293368_7ce1fb10-504e-16e0-8930-278b8a7f942d.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533652/c8c575c8-e127-cef2-3677-714e0006f0c3.jpeg)

3つ目は、クリーンアーキテクチャの知識です。
この知識は、生のPHPでインスタ風のアプリケーションを作るという研修で役に立ちました。
この研修では、ORMなどのツールも極力利用しないことになっていたので、普通のMVCパターンではなくRepositoryパターンや責務分離についての知見がないと、良い感じにコードを書けないので、クリーンアーキテクチャの知識がとても役に立ちました。

# SQL
最後は、SQLの知識です。
これは生のPHPでアプリケーションを作る時と、自社のWebサービスのDBから知りたいデータを抽出する際に役に立ちました。

習熟度は、基本的な構文の`SELECT`や`WHERE`、`JOIN`が理解できていれば、とりあえず大丈夫でした。

# さいごに
今回紹介した役に立った知識は、自分の働いている会社での話のため、ぜひ、今年入社した新卒エンジニアの方は、この記事のコメント欄に「自分の会社ではこんな知識が役に立った」などを教えてくれると嬉しいです！
今日PostgreSQLにデータを入れようとしたらエラーが出た

#その前に軽くPostgreSQLの操作確認
```
//postgre起動
$sudo brew services start postgresql

//データベース一覧
$psql -l

//データベース接続
$psql データベース名

//テーブル一覧
mydb=# \dt;

//テーブル接続
mydb=# psql テーブル名

//テーブルの中身確認
mydb=# \d テーブル名
```

#ここからが問題
formで受け取ったデータをDBに入れようとしたらエラーが起きた。

###SampleController 

```
public function add(Request $request){

  $param =[
    'title' => $request->title,
    'member' => $request->member,
    'grade' => $request->grade,
    'message' => $request->message,
    'comment' => $request->comment,
   ];

　//テーブル名を指定してinsert（）でテーブルに値を格納
  DB::table('posts')->insert($param);

  //リダイレクトでパスを指定
  return redirect('/posts/index');	
```

すると
Class 'App\Http\Controllers\DB' not found
というエラーが出た

ただ下記の書き忘れだった...。

```
use Illuminate\Support\Facades\DB
```
次から気をつけよう。
JavaScriptのthisとbindについて

#はじめに
jsの勉強をしているので備忘録として残しておきます。
間違っていたらすみません...

#jsのthisとは？
JavaScriptのthisとはオブジェクトを参照するキーワードのこと

```
const obj = {
  first_name: '山田',
  last_name: '太郎',
  putFullname: function() {
　　　　　　　　//thisを用いる場合
    console.log(this.last_name);

　　　　　　　　//thisを用いない場合
　　　　　　　　console.log(obj.last_name);
  }
}

//両方とも出力結果は太郎になる
obj.putFullname();
```
オブジェクト内にthisを用いる時、上のコードの場合だとthisはオブジェクトであるobjを指している。


#thisをクラス内で用いる場合
クラスを作成しただけではオブジェクトは生成されていないので、下記の場合のthisは何も参照していない。

```
class Obj {
  constructor() {
    this.first_name = '山田';
    this.last_name = '太郎';
  }

  putFullname() {
    console.log('hello');
  }
}
```
なのでクラス外でオブジェクトを生成することで初めて、thisがオブジェクトを参照することができる。

```
class Obj {
  constructor() {
    this.first_name = '山田';
    this.last_name = '太郎';
  }

  putFullname() {
    console.log(this.last_name);
  }
}

//ここでオブジェクトを生成。この場合thisが参照するオブジェクトはobj2となる。
const obj2 = new Obj();

//出力結果は太郎になる
obj2.putFullname();
```
#オブジェクトが階層になっている場合
オブジェクトが階層になっている場合、thisは階層を上がって行った時に最初に見つかるオブジェクトを参照する。

```
const obj = {
  first_name: '山田',
  last_name: '太郎',
  putFullname: function() {
　　　　　　　　//この場合のthisはobjを参照する
    console.log(this.last_name);

　　　　　　　　window.setTimeout(function() {
        //この場合のthisはwindowを参照する
        console.log(this);
    })
  }
}


obj.putFullname();
```

#bindについて
下記のwindowオブジェクトの中でwindowではなく、objを参照したい場合はどうすれば良いのか？
そんな時に用いるのがbindである。
bindの第一引数に与えられたものをオブジェクトとすることができる。

```
const obj = {
  first_name: '山田',
  last_name: '太郎',
  putFullname: function() {
　　　　　　　　//この場合のthisはobjを参照する
    console.log(this);

　　　　　　　　window.setTimeout(function() {
        //この場合のthisはobjを参照する
        console.log(this);
    }.bind(this));
    //bindの第一引数のthisがobjを参照しているので、上記のwindowオブジェクト内のthisもobjを参照している。
  }
}


obj.putFullname();
//出力結果は下記がコンソールに２つ出力される
{first_name: "kkk", last_name: "太郎", setFullname: ƒ}
first_name: "kkk"
last_name: "太郎"
setFullname: ƒ ()
__proto__: Object
```

***
まだまだ勉強中なので編集すると思います。
Effective Java(第3版) 項目11 equalsをオーバーライドするときは、常にhashCodeをオーバーライドする

equalsに続き、hashCodeをオーバーライドする場合に守るべき内容について、かなり詳細に記載しています。

# 記載内容
## hashCodeの一般契約
まず、equalsをオーバーライドしているすべてのクラスで、hashCodeをオーバーライドしなければならない。
そうしないと、一般契約を破ることになる。
(一般契約についての説明は[Object.hashCode()](https://docs.oracle.com/javase/jp/8/docs/api/java/lang/Object.html#hashCode--)の通りなのでここでは割愛)

equalsをオーバーライドして、hashCodeをオーバーライドしていない場合、以下の一般契約を破ることになる。
> equals(Object)メソッドに従って2つのオブジェクトが等しい場合は、
> 2つの各オブジェクトに対するhashCodeメソッドの呼出しによって同じ整数の結果が生成される必要があります。

このようなオブジェクトを、HashMapのキーに使用すると、意図せぬ動作になることがある。

## 実装方法
基本的なhashCodeの実装は以下の様になる。
(PhoneNumberはshortのareaCode、prefix、lineNumをメンバーに持つ)

```Java:PhoneNumber.java
@Override
public boolean hashCode() {
  int result = Short.hashCode(areaCode);
  result = 31 * result + Short.hashCode(prefix);
  result = 31 * result + Short.hashCode(lineNum);
  return result;
}
```

パフォーマンスが重要でない状況であれば、以下の実装でも良い。

```Java:PhoneNumber.java
@Override
public boolean hashCode() {
  return Objects.hash(lineNum, prefix, areaCode);
}
```

ただし、この書き方では、可変長引数のための配列生成、基本データ型が含まれる場合はボクシングとアンボクシングが発生するため、
パフォーマンスは良くない。

もし、クラスが不変で、ハッシュコードを計算するコストが高い場合、以下の様にキャッシュすることが出来る。
(スレッドセーフであるように実装する必要が有る)

```java
private int hashCode;

@Override
public boolean hashCode() {
  int result = hashcode;
  if (result == 0) {
    result = Short.hashCode(areaCode);
    result = 31 * result + Short.hashCode(prefix);
    result = 31 * result + Short.hashCode(lineNum);
    hashCode = result;
  }
  return result;
}
```

上記のコードは、ハッシュコードの計算結果とhashCodeフィールドの初期値(上記の場合0)が一致する可能性が低いことが前提になっている。

## 注意点
### ハッシュコードの計算に使用するフィールド
パフォーマンスを向上するために、ハッシュコードの計算から意味のあるフィールドを除外してはならない。
その結果、hashcodeメソッドは速くなるかもしれないが、ハッシュ値の品質がハッシュテーブルで使用できないほど
下がるかもしれない。

例として、Java2より前のStringのhashcodeは、先頭16文字だけを1文字おきに使用してハッシュ値を計算していたため、
URLの様に階層化された大きな文字列をキーにした場合、ハッシュテーブルの検索速度がO(n^2)になっていた

### hashCodeが返す値をドキュメント化しない
hashCodeｋが返す値の詳細な仕様に関するドキュメントを提供するべきではない。
記載した場合、クライアントはその値に依存した処理を記載する可能性がある。

ドキュメントを提供しなければ、値の変更に対する柔軟性を得ることが出来る。

# 考察
equalsに続いて長い項目ですが、こちらも記載されている内容はhashCodeに関する基本的な内容であり、
特に一般契約については理解しておく必要が有ります。

## 実装方法による性能の差異
3つの実装方針が記載されていますが、特に気になるのは、
自分で計算するものと、Objects.hashを使用したものとの性能差だと思います。
そこで、以下のクラスA、BのhashCodeをそれぞれの実装方法で実装し、A.hashCodeの速度を比較してみました。

```java
class A {
    int n;
    String s;
    B object;
}

class B {
    int n;
    String s;
}
```

結果は、4倍程度の性能差はありましたが、
100万回実行して14ミリ秒と50ミリ秒という数値(CPUは3.5GHz)でしたので、微妙な感はあります。

実処理に組み込んだ場合にGCにどの程度影響するのか等も考慮すると、
それなりに影響するのかもしれませんが、コードの読みやすさとの天秤を考えると悩ましいです。

このレベルの性能差が気になるのであれば、3番目のキャッシュする方式の方が良さそうに思います。
(同じオブジェクトに繰り返しhashCodeを呼ぶ場合に限りますが)


## 実装方針
equalsでも触れましたが、IntelliJ、Eclipse等のIDEで、equalsメソッドとhashcodeメソッドをセットで生成してくれますので、
これに従うのが良いと思いますし、
もし、何らかの理由で特殊な比較を行う場合は、その旨をコメントで記載するべきです。

やはりRecordの正式導入が待ち遠しいです。
Laravel5.8 環境変数はconfig経由で！


Laravelで環境変数を扱う際の注意点を学んだので記事として残しておきます。

要は、タイトルの通り、`.env`に格納した内容はconfig経由で使いましょうという話です。

今回は、ポートフォリオでGoogleMapsAPIを使用する機会があったので、APIキーの扱い方を例とします。

<h2>.envにAPIキーを格納</h2>

```project/.env
GOOGLE_MAP_API_KEY=https://maps.googleapis.com/maps/api/js?key=xxxxx
```

<h2>configを経由する</h2>
`.env`に保存した内容をまずconfig/services.phpで取得します。
`env('.envファイルに記述したキー名') `で取得する事ができます。

```config/services.php
    'google-map' => [
        'apikey' => env('GOOGLE_MAP_API_KEY'),
    ],
```

なお、`config/services.php`とは、外部のWebサービスのアカウント情報を設定しておく為に使うファイルだそうです。
その為、APIキーとかAWSのアクセスキーは`config/services.php`を使って取得するようにしましょう。

<h2>BladeファイルでAPIキーを取得する</h2>
GoogleMapsAPIを使う時は、GoogleMapを使いたい画面のBladeファイルでAPIキーを記述する必要があります。`config/services.php`を経由して.envのAPIキーを引き出すには以下のように記述します。

```xxx.blade.php
<script src="{{ config('services.google-map.apikey') }}"></script>
```

これで、

```xxx.blade.php
<script src="https://maps.googleapis.com/maps/api/js?key=xxxxx"></script>
```
が再現できます。

<h2>まとめ</h2>

BladeでAPIキーを使いたい。その為には.envに格納してenv('GOOGLE_MAP_API_KEY')とすれば良いんじゃね？とか思っていましたが、
[こちらの記事](https://hiroto-k.hatenablog.com/entry/2018/03/28/213000)によると、、
>本番環境でconfig:cacheコマンドを実行した際、.envファイルを読み込まないから。

という理由で、直接env()を使用するのはNGだという事を学びました。
私も含めて初学者の方は基礎知識が甘い為、APIキーなどの取扱注意物に関する情報はしっかり調べた上で扱うようにしましょう！！
[Python]Selenium概要およびインストール、基本操作方法 メモ

* Windows環境でのPython + Selenium + Google Chrome利用方法や基本操作()についての備忘録記事。

## Seleniumとは

* Webブラウザ操作を自動化するためのフレームワーク。
* WebDriverと呼ばれるAPI群とプロトコルを利用してWebブラウザ操作を行う。
* 次の用途で利用される。
  * Webアプリケーションの UI テスト
  * Webブラウザ操作タスクの自動化
  * Webサイトのクローリングなど
* サポート言語
  * Java
  * Python
  * C#
  * Ruby
  * JS
  * Kotlin　など

## 事前準備

※Windows環境での例

1.**Seleniumインストール**

   ```shell
   pip install selenium
   ```

   

2.**Google Chrome Webドライバーダウンロード**

   * __[こちら](https://sites.google.com/a/chromium.org/chromedriver/downloads)__のサイトから自環境で利用しているGoogle Chromeと同一バージョンのドライバーをダウンロードする。
   * Zipファイルを解凍し、コードから参照できる場所に`chromedriver.exe`を配置する。



## サンプルコード

* 「`selenium`」をGoogle検索するコード(__[公式](https://www.selenium.dev/documentation/en/)__参考)

  ```python
  from selenium import webdriver
  from selenium.webdriver.common.by import By
  from selenium.webdriver.common.keys import Keys
  from selenium.webdriver.support.ui import WebDriverWait
  from selenium.webdriver.support.expected_conditions import presence_of_element_located
  # Google Chromeを操作するためのWebドライバを読み込む
  with webdriver.Chrome("./chromedriver.exe") as driver:
      # 任意のHTMLの要素が特定の状態になるまで待機するための設定
      wait = WebDriverWait(driver, 10)
      # Googleにアクセス
      driver.get("https://google.com")
      # "selenium"で検索
      driver.find_element(By.NAME, "q").send_keys("selenium" + Keys.RETURN)
      # 1件目の検索結果を取得(描画されるまで待機)
      first_result = wait.until(
          presence_of_element_located((By.CSS_SELECTOR, "h3")))
      print(first_result.get_attribute("textContent"))
  ```



## 参考情報

* [The Selenium Browser Automation Project](https://www.selenium.dev/documentation/en/)
Vimにskk.vimを導入して快適な日本語入力環境を作る

最近WSLのUbuntuでVimの使い方を学習しているLinux初心者です。
Vimの日本語入力に不便を感じていた中で，skk.vimなるものの存在を知り，興味を持ったので使ってみようと思いましたがまとまった情報が少なくやや躓いたので，備忘録も兼ねて記事を書いてみることにしました。
なお，前述した通り筆者はLinux初心者ですので，Vimmerの方々から見れば当たり前のことや，不適切なことを書いている可能性があります。
お気づきの点がございましたらご指摘いただけると幸いです。
また筆者はWSLでUbuntu 20.04を使っていますが，環境によっては以下の説明が当てはまらないこともあるかもしれません。

# SKKとは？
※この箇所を書くに当たって以下のWikipediaの記事を参考にしました。

https://ja.wikipedia.org/wiki/SKK

skk.vimは，SKKというEmacs向けの日本語入力システムをもとにした変換エンジンですので，skk.vimを知るためにはSKKが何なのかを知る必要があります。
SKKは，1987年に，東北大学の佐藤雅彦教授（当時）によって開発された日本語入力システムです。
日本語入力システムであるという点ではMicrosoft IMEなどと同じですが，その機能は非常に独特で，他の日本語入力システムとは大きく異なります。
Wikipediaの表現を借りれば，「__かな漢字変換において形態素解析に基づいた変換を行わないこと__」が特徴です。
どういうことか具体的に見ていきましょう。
## 「ここで履物を脱いでください」と入力するには？
例えば，「__ここで履物を脱いでください__」という有名な文を入力することを考えます。
一般的な日本語入力システムは，「`ここではきものをぬいでください`」と入力されると，例えば「`ここで/履物を/脱いで/ください`」というように，単語や文節の区切りを識別して変換を行います。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1245689/a840c0d7-810a-1f4f-ba43-4ad7e22c601a.png)
しかし，環境によっては「`ここでは/着物を/脱いで/ください`」というような予期せぬ変換結果になるかもしれません。
その場合は，ユーザが自力で単語の区切りを修正する必要があります。
日本語入力システムの精度は向上してきているため，以前と比べるとユーザの負担は軽くなっているようですが，それでもミスをゼロにすることはできません。
## SKKの考え方
一方，SKKは根本的に日本語入力の手法（思想）が異なります。
先ほど述べたように，通常の日本語入力システムでは単語を区切る作業の一部をシステムが自動で行い，不備がある部分のみユーザが手動で修正します。
それに対し，SKKは，「どうせ変換ミスをゼロにはできないのならその作業を全部ユーザに任せればいいじゃないか」という発想です。
## SKKの入力方法
入力方法をざっくり言うと，

* 平仮名を入力→全て小文字で入力する（すぐに確定される）
* 漢字を入力→漢字にしたい単語の最初のローマ字を大文字にする（スペースキーで変換する）
* 送り仮名を入力→送り仮名の最初のローマ字を大文字にする

という風です。
例えば，「ここで履物を脱いでください」と入力するには，「`kokodeHakimono␣woNuI␣dekudasai`」と入力します。
一方，「ここでは着物を脱いでください」と入力するには，「`kokodehaKimono␣woNuI␣dekudasai`」と入力します。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1245689/decf542f-159a-fa17-29d4-5285f4316c47.png)
詳細については後述します。

# skk.vimとは？
SKKはEmacs向けのソフトウェアですが，それをVimで使えるようにVim scriptで再現したのがskk.vimです。Vimで通常の日本語入力システムを使う場合，全角/半角の切り替えなどが煩雑ですが，skk.vimはその特性上その負担を若干軽減することができます。

# 導入の流れ
以下の流れで導入します。
①skk.vimをダウンロードし，プラグインとしてインストールする。
②SKKの辞書ファイルをダウンロードし，適当なディレクトリに配置する。
③`.vimrc`に追記する。

## ①skk.vimのダウンロード・インストール
以下のように行います。
※Vimは初期状態であり，`.vim`フォルダは存在しないという前提の下です。

```bash
~$ git clone https://github.com/tyru/skk.vim
~$ mkdir .vim
~$ cp -r skk.vim/plugin/ .vim
```

## ②SKKの辞書ファイルのダウンロード
SKKの辞書は複数ありますが，ここでは最も標準的なものをダウンロードします。
また，辞書ファイルはホームディレクトリに配置することを想定しています。

```bash
~$ wget http://openlab.jp/skk/dic/SKK-JISYO.L.gz
~$ gzip -d SKK-JISYO.L.gz
```

## ③.vimrcへの追記
WSLのUbuntuではデフォルトで.vimrcが用意されているようです（他の環境は知りません）。
筆者の場合は~~よく分からないので~~デフォルトのものを削除して新規に作成しました。
以下のように記述します。

```vimscript:.vimrc
"SKKの辞書ファイルの場所
let skk_large_jisyo = '~/SKK-JISYO.L'
"ユーザ辞書を自動で保存する（お好みで）
let skk_auto_save_jisyo = 1
```

その他の設定項目については以下のサイトを参照してください。

https://github.com/tyru/skk.vim/blob/master/doc/skk.jax

# 動作確認
以上の操作が完了したら，正しく動作するか確認してみましょう。
通常通りVimを起動し，挿入モードに切り替えたら`Ctrl-j`を押します。
すると，画面下部に「`--挿入(lang)--`」と表示され，日本語入力が可能になります。
通常の挿入モードに戻すにはもう一度`Ctrl-J`を押します。

# 使い方
本稿ではskk.vimの導入を解説することを目的としていること，また筆者がskk.vimをまだ使い慣れていないことから，使い方の説明はごく簡単に記述します。もしかしたら詳細を追記するかもしれません。

* `Ctrl-j`で切り替え
* 小文字入力で平仮名入力
* 漢字にしたい単語の最初は大文字で入力し，以降は小文字で入力→スペースキーで変換
* 送り仮名の最初も大文字で入力し，以降は小文字で入力
* `q`キーで平仮名入力／片仮名入力の切り替え
* 平仮名入力時に片仮名を入力したい場合，単語の最初を大文字で入力し，単語末で`q`キーを押すことで変換可能

以上です。最後まで読んでくださりありがとうございました。
サブディレクトリを含むディレクトリ内のファイルを別のディレクトリにコピー

コピーするファイルの拡張子はcsv限定となっています。
変更する場合はmain関数のtarget_extを変更する必要があります。

コピーしたファイルのファイル名は、指定したコピー元フォルダを起点とした相対パスのパス区切り文字をアンダーバーに変更したものになります。

```python
import os
import re, shutil
import tkinter.filedialog
import pathlib

def name_savefile_dirname(path):
    file_path = path.replace('/', os.sep) #パスの区切り文字を変換
    org_path = pathlib.Path(org_dir)
    sub_path = pathlib.Path(file_path)
    file_name = sub_path.relative_to(org_path)
    return str(file_name).replace("\\","_")

def copy_files():
    file_list = [] #コピーするファイルのリスト
    filepath_list = [] #コピーするファイルパスのリスト
    for dirpath, dirnames, filenames in os.walk(org_dir): #コピー元のディレクトリを基準にtarget_extで指定した拡張子のファイルをリスト化
        for file in filenames:
            m = re.search(re.escape(target_ext), file) #指定した拡張子のファイルを探す
            if m :
                file_list.append(file) #ファイル名をリストに追加
                filepath_list.append(os.path.join(dirpath, file)) #コピー元ファイルのパスをリストに追加

    for i in range(len(file_list)):
        save_file_path = os.path.join(save_dir, name_savefile_dirname(filepath_list[i])) #コピー先ディレクトリ名とコピー元ディレクトリを付けたファイル名を結合
        shutil.copy2(filepath_list[i], save_file_path) #ファイルをコピー
        print(save_file_path)

if __name__ == '__main__':
    target_ext = '.csv' #コピーするファイルの拡張子
    iDir = os.path.abspath(os.path.dirname(__file__)) #ダイアログ表示の初期ディレクトリ
    org_dir = tkinter.filedialog.askdirectory(initialdir=iDir, title='コピー元のディレクトリ') #コピー元のディレクトリのパス
    save_dir = tkinter.filedialog.askdirectory(initialdir=iDir, title='コピー先のディレクトリ') #コピー先のディレクトリのパス

    copy_files() #メイン関数
    print('finished')
```
LabVIEWの関数パレットからワンクリックで任意のダイアグラムを配置する方法

# はじめに
エラーハンドリング用のエラークラスタ＆ケースストラクチャの配置や、ステートマシン用のwhileループ＆ケースストラクチャの配置など、ブロックダイアグラム上にお決まりのパターンを配置する場合が多々あるかと思いますが、その都度、ストラクチャーやループを配置するのは非常に面倒です。

本記事では、その解決策として、関数パレットへ任意のダイアグラムを登録する方法を紹介します。登録されたダイアグラムは、関数パレット上にアイコンとして表示され、クリックすることでブロックダイアグラム上への配置が可能となります。
# 設定手順
設定手順は以下のとおりです。

1.登録したいブロックダイアグラム(SubVI)を作成
2.ユーザーライブラリ(LabVIEW\user.lib)へ保存
3.パレットの設定を変更

SubVI作成後は、規定のフォルダへviを保存し、関数パレットの設定を変更するだけです。
一度覚えてしまえば非常に簡単です。
順番に解説します。

1. 登録したいブロックダイアグラム(SubVI)を作成
まずは、登録したいブロックダイアグラムを配置したSubVIを作成します。
今回は下図のようなエラーハンドリング用のケースストラクチャとエラークラスタを配置した、error_hundling.viという名称のSubVIを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/5680f13b-441c-e595-97dd-73338da7ebd5.png)

1. ユーザーライブラリ(LabVIEW\user.lib)へ保存
作成したviを、C:\Program Files (x86)\National Instruments\LabVIEW XXXX\user.libへ保存します。
\LabVIEW XXXX\の部分は、お使いのLabVIEWのバージョンによって異なります。
私が使用しているLabVIEWは2020なので、下図のフォルダとなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/516353db-472e-d9bd-8452-838d1b52af89.png)
SubVIをuser.libへ放り込んだ後でLabVIEWを起動すると、関数パレット上にerror_hundling.viが表示されるようになります。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/c3c2d2ec-d87b-f286-5e31-3d5b1ddb19f0.png)
まだこの状態では、SubVIとしてブロックダイアグラム上に配置されてしまいます。
あとひと手間必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/01401ab8-e555-359e-fb15-eae44573c0cc.png)
1. パレットの設定を変更
Tools>>Advanced>>Edit Palette Set...をクリックすると、下図のようなウィンドウが表示されます。
FunctionsパレットのUser Librariesをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/9ccd5d7d-e1f4-c196-e701-d020de50320d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/703d1539-3a5c-23d5-58d3-35a8403bc836.png)

error_hundling.vi上で右クリックし、"Place VI Contents"にチェックをいれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/edb23c70-78bc-97be-4d8d-e651a505fc14.png)

Edit Controls and Functions Palette Setウィンドウ上の"Save Changes"ボタンをクリックし、設定を保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/211b0575-ce76-aa38-446f-c36f8821c8b3.png)

以上で設定は完了です。
正常に設定されていれば、関数パレット上のerror_hundling.viをクリックすることで、SubVIではなく、ブロックダイアグラムが配置されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674241/fe468f77-3c5e-64f3-a993-0b94737676af.png)
GitHub Enterprise

#【GitHub Enterprise】

実務でTortoiseSVNしか使ったことがないので、GitHub Enterpriseを簡単に調べました。

##GitHub Enterpriseとは。

企業の導入に適しているGit
超有名企業で数多く導入されており、信頼できる。

Gitに対応したバージョン管理システムであるGitHubと同等の機能を利用可能。
[プルリクエスト](https://qiita.com/uejima_haruki/items/a862c4093126f509a086)、Issueなどの機能とユーザ管理やオンラインバックアップなどの運用をサポートする。

AWSやGCPでの導入も容易である。
もちろん従来のオンプレミスにも対応している。

##1つのプロダクトであり、Webサービスでない。

自社サーバーにインストールすることが可能になるため、社外にソースコードを置くことなく管理できる。
オンプレミスで開発している現場でも使用できる。
　→ セキュリティに厳しい要件に対して、自社内で管理できる。

GitHubと同様に2段階認証や組織・チームのパーミッションの機能を備えている。
　→ GitHubと操作が似ているようなので、直感的に操作できそうだ。

##余談

チーム開発で必須なバージョン管理システムの知識をもっと深めていく。

業務内でのTortoiseSVN、業務外でのGitHub、これらの扱いを通じて、基礎を抑える。
今後、応用が効いてくるところがあればその都度勉強していこうと思う。