OmniAICreator/Qiita-1.07M huggingface dataset:
SpringBoot ✕ jQuery✕ DataTables・DataTables-pluginsの導入

#はじめに
SpringBootのRESTで検索機能を実装した際に、`Gradle`プロジェクトでの**DatTables**と**DataTables-plugins**の導入方法が見つからず、時間をロスしたので、同じように悩んでいる人などに向け備忘録として書いておきます。

#build.gradle
結論、参考文献に書いてあるようにすればいいだけですので、非常に簡単です。

```java
dependencies {
    implementation 'org.webjars:datatables:1.10.21'
	runtimeOnly 'org.webjars:datatables-plugins:1.10.21'
}
```

上記2行追加するだけでライブラリの導入は完了です。
お役経てば幸いです。

#参考文献
> [MavenRepository](https://mvnrepository.com/artifact/org.webjars/datatables-plugins/1.10.12)
複数ファイルのドラッグでファイルの中身を確認しようとしてハマったこと

# これは何
Reactのリハビリ+ついでに触ったことのないnext.jsを触ってみようといろいろ遊んでました。D&Dでドロップされてきたファイルの中身を読み取る処理を書いていたのですが、ファイル読み込み部分で若干ハマったので備忘録として残します。

## やりたかったこと
1. Finderから複数のmp3ファイルをブラウザにD&Dでドロップする
1. mp3ファイルのメタデータを読み込む
1. 読み取ったメタデータをリストに表示する

## だめだったコード
最初は以下のようにドラッグイベントから`items`を引っ張ってきて、そのアイテムを全て回して取得しようとしました。1つ目のファイルは読み取れましたが、それ以降のファイルの `type` を読んだ時に中身がなくなっていて読み取れない現象が発生してました。

```react
  const handleDrop = async (e: DragEvent) => {
    const items = e.dataTransfer?.items;

    if (items) {
      const newList = [...data];
      for (const el of Array.from(items)) {
        if (el.type === "audio/mpeg") {
          const audioFile = el.getAsFile();

          if (audioFile) {
            // ファイルのメタデータを読み取る処理
            const audioFileBuffer = await audioFile.arrayBuffer();
            const tags = await mm.parseBuffer(Buffer.from(audioFileBuffer));
            newList.push({
              id: newList.length + 1,
              title: tags.common.title ?? audioFile.name,
              artist: tags.common.artist ?? "",
            });
          }
        }
      }

      setData(newList);
    }
  }
```


## 読み取りできたコード
以下のようにforを回す前に `getAsFile()` までやってしまう形で実装したところ、うまく全ファイルの内容を取得することができました。

forループの中でawaitとかしているので、その処理の間にDragEventから情報が取れなくなってしまうんですかね。このへん公式ドキュメントからその辺の情報を拾おうとしたのですが、まだ見つけられてないですね。。。逆に `getAsFile()` ってなんか名前的に重そうですけど Promise じゃないんですね。

```react
  const handleDrop = async (e: DragEvent) => {
    const items = e.dataTransfer?.items;

    if (items) {
      const newList = [...data];
      const files = Array.from(items)
        .filter((el) => el.type === "audio/mpeg")
        .map((el) => el.getAsFile());

      for (const audioFile of files) {
        if (audioFile) {
          // ファイルのメタデータを読み取る処理
          const audioFileBuffer = await audioFile.arrayBuffer();
          const tags = await mm.parseBuffer(Buffer.from(audioFileBuffer));
          newList.push({
            id: newList.length + 1,
            title: tags.common.title ?? audioFile.name,
            artist: tags.common.artist ?? "",
          });
        }
      }

      setData(newList);
    }
  }
```
【css】リスト(li)を横並び、かつ中央寄せにする方法！

リストに使う、「ul」や「li」を横並びで中央に寄せようとするとうまくいかなかったため、これならできたぁってのを載せておきます！

簡易的なリスト↓

```html:list.html
<ul>
 <li>リスト１</li>
 <li>リスト2</li>
 <li>リスト3</li>
</ul>
```

これさえあれば、横並び中央にできる↓

```css:list.css
ul {
 text-align: center;
}

li {
 display: inline;
}
```

これだけだと、余白だったりが気になるので、
**li**部分に**margin**を仕込むといいですよ！

ちなみに、**float**を使うとうまくいかんかった(T-T)
正直、**float**使うと、「・」を取るコードが必要なんやけど、**display: inline;**使うと勝手に無くなってくれるのでコードの短縮にもつながる！
【WinSrv2016】リモートデスクトップサービスのプロファイル【固定プロファイル】【RDS】


# RDSクライアントに固定ユーザープロファイルを読み込ませる場合の話

`Windows Server 2016`では、ドメインユーザーのプロパティの「リモートデスクトップサービスのプロファイル」タブがRD接続時に読み込まれない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651121/0f6750cd-9407-0552-a6f5-32a7774c1238.png)


このタブでは、`RDセッションホスト`にRD接続でログインする際に読み込むプロファイルを指定する。

しかし、タブのプロファイルパスに「NTUSER.MANがあるフォルダのパス」を指定するだけでは固定プロファイルにならない。Windows Server 2016ではここでの設定が無視される。

---

解決策は２つ。
一つは、このタブでの設定を諦めてGPOで固定ユーザープロファイルの設定を構成すること。「RDセッションホストサーバー上の固定プロファイルを使用する」を有効にして、「リモートデスクトップサービス移動ユーザープロファイルのパスを指定する」にパスを指定すれば良い。

二つ目の解決策は、RDSHサーバー側で次のいずれかのレジストリ値を作成すること。
`HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Terminal Services\fQueryUserConfFromDC`
`HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\fQueryUserConfFromDC`
種類は「Reg_Dword」、数値は「1」とする。これを設定すると、ドメインユーザーがRD接続した際に、リモート接続マネージャー(RCM)というものが「リモートデスクトップサービスのプロファイル」タブを参照するようになるらしい。

ちなみに、二つの「fQueryUserConfigFromDC」の優先度は「SOFTWARE\Policies\」の方が高い。PoliciesキーはGPOが反映される場所なので、優先度が高くなるのだろう。二箇所で値を作成しても、「\SYSTEM\CurrentControlSet\」での設定は意味がなくなる。

https://docs.microsoft.com/ja-jp/troubleshoot/windows-server/remote/remote-connection-manager-changes
【Swift】クリップボードに文字列や画像をコピーする

SwiftでiOSアプリを開発する際に、クリップボードに文字列をコピーするコード。

## クリップボードに文字列をコピー

文字列をコピーする時のコードは以下の通り。

```swift
let str = "コピーしたい文字列"
UIPasteboard.general.string = str
```

## クリップボードに画像をコピー

画像も同様にコピー可能です。

```swift
//１枚の画像をコピー
let img = UIImage(named: "sample")
UIPasteboard.general.image = img

//複数の画像をコピー
let img1 = UIImage(named: "sample1")
let img2 = UIImage(named: "sample2")
UIPasteboard.general.images = [img1!,img2!]
```

## 他にコピーできる種類

文字列や画像以外もURLや色のコピー可能です。

> var url: URL?
The URL object of the first pasteboard item.

> var urls: [URL]?
An array of URL objects in all pasteboard items.

> var color: UIColor?
The color object of the first pasteboard item.

> var colors: [UIColor]?
An array of color objects in all pasteboard items.

> https://developer.apple.com/documentation/uikit/uipasteboard

## 参考
https://exgyaruo.com/programming/swift/copy-to-clipboard

https://developer.apple.com/documentation/uikit/uipasteboard

## おすすめ情報

https://wagtechblog.com/programing/swift-iphone-application-school

https://wagtechblog.com/programing/swift-textbook.html
UnityEngine.Localizationをスクリプトから呼ぶ

[プロ必見！最新ローカライズ機能徹底解説 - Unityステーション](https://youtu.be/CRQuiltI06o)
という動画をみて、Unity謹製の便利なローカライズツールのことを知りました。
ツールでできることは[大変多岐にわたっていて](https://docs.unity3d.com/Packages/com.unity.localization@1.0/manual/index.html)、言語ごとにSpriteやAudioClipの切り替え等もできるようです。
動画中の拡張例は[こちら](https://qiita.com/yuji_yasuhara/items/694c8a32e86fda871dd5)の記事で紹介されています。


現在、ちょうど十数カ国のローカライズに対応したタイトルに関わっているので、早速これを使ってみようということになったのですが、一点だけ、スクリプトから呼ぶことができるのかについて不明だったので調べてみました。

```C#:LocaleStringTest.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class LocaleStringTest : MonoBehaviour
{
    [SerializeField] TMPro.TMP_Text m_text = null;
    [SerializeField] UnityEngine.Localization.Components.LocalizeStringEvent m_stringEvent = null;
#if UNITY_EDITOR
    [SerializeField] UnityEditor.Localization.StringTableCollection m_collection = null;
#endif
    private void Awake()
    {
        m_stringEvent.OnUpdateString.AddListener(onUpdate);
    }

    // Start is called before the first frame update
    void Start()
    {
#if UNITY_EDITOR
        for (int i=0;i< m_collection.StringTables.Count; ++i)
        {
            Debug.Log("Table=" + m_collection.Tables[i].asset.name);
            
            IEnumerator<UnityEngine.Localization.Tables.StringTableEntry> values = m_collection.StringTables[i].Values.GetEnumerator();
            while (values.MoveNext())
            {
                string str0 = values.Current.Key;
                Debug.Log("Key,Value=" + values.Current.Key + "," + values.Current.Value);
            }
        }
#endif
        string str = m_stringEvent.StringReference.GetLocalizedString();
        Debug.Log("LocalisedString=" + str);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    void onUpdate(string _str)
    {
        m_text.text = string.Format(_str, "World") +"!!";
    }
}
```

m_stringEvent はTextMeshProにアタッチしたローカライズ用スクリプト、
m_collection はローカライズ用に作成したテーブルとなります。
ローカライズ用スクリプトやテーブルの作成方法については上記動画を参考にしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/51118d71-99b8-f284-afd3-2324e7dd6b1d.png)

実行した結果がこちらです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/aba256ad-4c41-9e21-d838-3883c5d60b33.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/cb0b2724-bd13-8b91-597f-29e07622a127.png)

テーブルからKey,Valueが取得でき、ローカライズ文字列への変更(OnUpdate())も動的に追加できるのを確認しました。ひとまず最低限これができれば安心して開発に組み込めそうです。

**~~[追記] テーブルからKey,Valueが取得できるのはUnityEditorのみでした。~~ソースプログラムも更新しています**
アップデートによりテーブルからKey,Valueが取得できるようになっていました。[こちら](https://qiita.com/ELIXIR/items/0fbca9a6e64e101a44ea)で記事にしています。

ちなみにビルマ語（ミャンマー語）が表示されていないのは、Unityエディターのフォントがこれらの言語に対応していないためです。
Preferencesなどからもフォント変更はできないようなので、対応していない言語の国のUnityユーザーはどうしているんでしょうね？
経験上、こういう国の人たちは母国語以外に英語等の第二言語がペラペラだったりするので問題ないのかもしれません。
APIとは


最近学習しているAPIについて改めて復習したいと思います。

# APIとは

> アプリケーションプログラミングインターフェースの略。
サーバが提供している機能やデータを、httpで通信して利用するための機能の一つ。
データの形式は最近はJSONで返される。

## APIで出来ること

仕様例
・Google Maps API (住所を地図で表示させる)
・楽天商品検索API（キーワードから楽天市場の商品を検索することができる）
・Twitter API（コードを書けば、Twitterを開かずに特定のツイートにリツイーやリプライができる）

## RailsをAPIモードで実行するには

rails newの際に `--api` を入力する。

```
rails new myapp --api
```

## APIモードとのファイル差分

ざっくり言うと、ビューファイルやUI関連のgem等が省かれて生成される。

https://qiita.com/61503891/items/d4eda649a10a3494830c

次回はpostmanを使ってログイン認証したいと思います。
kintoneで時間表記の入力チェック

# kintoneの欠点
kintone上で時間表記で記録をしたい場合、何時何分から何時何分、という表記であれば時間入力のフォーマットを使えば済むのだが、経過時間を記録したい場合は、この時間表記というのは都合が悪い。しかも秒まで記載できない。従って、選択肢は単一行入力のSINGLE_LINE_TEXTしかないのだが、全員が全員書式通りに入れてくれるわけでもない、ということで、書式チェックのやり方。

# 前提
moment.jsを使うので読み込んでおく。

## サンプル説明
日報に通話合計時間を「時分秒」の形式で入力させたい場合のチェック。kintoneの画面から入力された値を取得してきて、moment.jsでフォーマット、「isValid()」の形式でチェックして、falseであれば、メッセージを表示させる。

## サンプル
```javascript:sample.js
    // 通話時間の妥当性チェック
    if(record['通話時間']['value'] !== undefined){
      var telTime = moment(record['通話時間']['value'],'HH:mm:ss');
      if(!telTime.isValid()){
        swal({
          title: "入力不備（通話時間）",
          text: "HH:mm:ssの形式で入力してください。",
          icon: "error",
          button: "OK",
        });
        
        return false;
      }
    }

```

## （追記）そもそもHH:MM:SSで入力してくれない
実運用を続けているうちに、そもそも、moment.jsでフォーマット出来る値なのかを先にチェックするべき、という判断に至った。性善説に頼りすぎると良くない。「：」（全角コロン）区切りとかでもisValid()は通ってしまう。

```javascript:sample.js
    if(!isTime(record['通話時間']['value'])){
      swal({
        title: "入力不備（通話時間）",
        text: "HH:mm:ssの形式で入力してください。（全て半角入力）",
        icon: "error",
        button: "OK",
      });
      return false;
    }

```

```javascript:sample.js
  // 時刻のフォーマットチェック
  function isTime(str){
    return str.match(/^([01]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$/) !== null;
  }

```



## エラーメッセージの表示について
エラーメッセージの表示はsweetAlertを使用。別記事参照のこと。
Rust OpenCV Canny法によるエッジ検出の閾値を自動計算する

Rust OpenCVを使ってエッジ検出をしたいとき、ありますよね。
そんなときは`opencv::imgproc::canny`を使います。

https://docs.rs/opencv/0.8.0/opencv/imgproc/fn.canny.html

## 発生した問題

しかし、何やらパラメータの中に`閾値`とやらを設定しなければいけないようです。

とりあえずベタ書きでいい感じの数値を入れちゃいましょう。

```Rust
fn main() {
    let src_img = imread("path/to/image.png", IMREAD_GRAYSCALE).unwrap();
    let mut edge_img = src_img.clone();
    let result_find_edge = canny(&src_img, &mut edge_img, 100.0, 100.0, 3, false);
    match result_find_edge {
        Ok(_) => imwrite("path/to/result.png", &edge_img, &Vector::new()).ok(),
        Err(code) => {
            panic!("code: {:?}", code);
        }
    };
}
```

### 元画像
![元画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518222/52cff1d6-ca8a-5ec7-ab1c-2e536174ac1a.png)

### エッジ検出後の画像
![エッジ検出後の画像](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/518222/95cd024e-ba6d-10c3-bf64-8f2ae2c30378.png)

しかしこれだと画像ごとにいちいち閾値を設定しなくてはいけないですね。このままでは使い物にならないですね。

## 実現したいこと
入力画像からいい感じの閾値を算出して、その値をもとにエッジ検出を行う

## 結論
大津の２値化を使っていい感じの閾値を取得する

```rust
fn main() {
    let max_thresh_val = threshold(&src_img, &mut Mat::default(), 0.0, 255.0, THRESH_OTSU).unwrap();
    let min_thresh_val = max_thresh_val * 0.5;

    let mut edge_img = src_img.clone();
    let result_find_edge = canny(&src_img, &mut edge_img, min_thresh_val, max_thresh_val, 3, false);
    match result_find_edge {
        Ok(_) => imwrite("path/to/result.png", &edge_img, &Vector::new()).ok(),
        Err(code) => {
            panic!("code: {:?}", code);
        }
    };
}
```

これで画像入力画像からいい感じの閾値を算出してくれるようになりました。

## バージョン情報

```toml
# Cargo.toml

[dependencies]
opencv = "0.53.1"
```

```shell
$ cargo --version
cargo 1.54.0 (5ae8d74b3 2021-06-22)

$ rustc -V                                                                                                                                                                 
rustc 1.54.0 (a178d0322 2021-07-26)

$ rustup -V                                                                                                                                                                
rustup 1.24.3 (ce5817a94 2021-05-31)
```

## 参考記事
https://qiita.com/Takarasawa_/items/1556bf8e0513dca34a19

https://stackoverflow.com/questions/4292249/automatic-calculation-of-low-and-high-thresholds-for-the-canny-operation-in-open

## ソースコード
ここに載せてあります。

https://github.com/kazup1125/tilt-correction/blob/7086f2c73cbd2d169d925559848558e31681de79/src/main.rs#L30-L42
リモートデスクトップが真っ黒のまま。

#調べてみたときによくでてくる対処法。
Ctr+end　→　キャンセルで復旧する。
それを繰り返す
#実際にうまくいった方法
Ctr+end で右下の電源ボタンから再起動。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2176811/da4babc5-40bf-bd21-eb5c-9e26b382dc4b.png)
bondingについて調べてみる

## 勉強前イメージ

active/standbyとかactive/activeとか・・・

## 調査

### そもそもbondingとは

linuxでSWのLAGのようなことが出来るのですが、それをbondingと呼びます。
bondingとは複数のNIXを束ねて、一つのものとして運用します。
負荷分散や帯域・耐障害性の向上を図る技術になります。

### bondingの名称

- スレーブインタフェース

bondingを行う物理インタフェースを指します。

- マスターインタフェース

bondingを行う論理インタフェースを指します。

図にすると以下のようになります

![12021-11-07 # bondingについて調べてみる - diagrams.net - Goo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/4c396cf1-fa1e-b977-e678-726a9528fa0c.png)


### bondingの種類

bondingの種類は全部で7つあります。
それぞれ確認していきます。

- mode=0 : balance-rr

ラウンドロビンによる負荷分散になります。
bondingを行っているすべてのインタフェースで受信が可能

- mode=1 : active-backup

active/backupの方式で、1つのスレーブインタフェースで送信を行う
activeポートが使用できなくなると、backupポートがactiveポートになる

- mode=2 : balance-xor

送信元/宛先情報を元に負荷分散を行う
情報はxmit_hash_policyによって設定可能
bondingを行っているすべてのインタフェースで受信が可能

- mode=3 : broadcast

すべてのスレーブインタフェースから同じパケットを送信する
bondingを行っているすべてのインタフェースで受信が可能

- mode=4 : 802.3ad

LACP(Link Aggregation Control Protocol:リンクアグリゲーションの接続を確立させるプロトコル)を使用する
情報はxmit_hash_policyによって設定可能
送信元/宛先情報を元に負荷分散を行い、受信はLACPでネゴシエーションが取れたインタフェースであれば可能

- mode=5 : balance-tlb

スレーブインタフェースの負荷によって負荷分散され、送信する
bondingを行っているすべてのインタフェースで受信が可能

- mode=6 : balance-alb

スレーブインタフェースの負荷によって負荷分散され、送信する
受信は負荷に応じて変更

### xmit_hash_policy とは？

mode=2,4で使用する、送信の負荷分散の方式でパラメータで決めることができます。
デフォルトは `xmit_hash_policy=0`

## 勉強後イメージ

それぞれ送信と受信があるってことか・・・
mode=0だったらフレーム到達の順序が逆になるってのもあるみたい
特に5,6がちょっとイメージつかないなぁ
active/backupはわかりやすい


## 参考

- [Linux(CentOS8/RHEL8)のBondingのmodeと設定確認方法,スイッチのLink Aggregation設定との組合せ](https://milestone-of-se.nesuke.com/nw-basic/link-aggregation/linux-bonding-and-switch-config/)
- [Linuxのネットワークチーミング(Bonding)の設定【RHEL 6/CentOS 6】](https://tech-mmmm.blogspot.com/2016/05/linuxbonding.html)
Vapor Docs Leaf Getting Started (和訳)

自分用です。誤訳は大目に見ていただけると...🙏

# Leaf

Leaf は Swift の言語構文にインスパイアされた力強いテンプレート言語です。フロントエンドウェブサイトの動的 HTML ページの生成や API から送信するリッチメールの生成をすることができます。

## パッケージ

Leaf を使うための最初の一歩はプロジェクト内の SPM パッケージマニフェストファイルに依存としてそれを追加することです。

```swift
// swift-tools-version:5.2
import PackageDescription

let package = Package(
    name: "MyApp",
    platforms: [
       .macOS(.v10_15)
    ],
    dependencies: [
        // 他の依存
        .package(url: "https://github.com/vapor/leaf.git", from: "4.0.0"),
    ],
    targets: [
        .target(name: "App", dependencies: [
            .product(name: "Leaf", package: "leaf"),
            // 他の依存
        ]),
        // 他のターゲット
    ]
)
```

## 設定

1度プロジェクトにパッケージを追加すると Vapor でそれを使うために設定することができます。これは通常 `configure.swift` で行います。

```swift
import Leaf

app.views.use(.leaf)
```

これは Vapor にコード内で `req.view` を呼び出した際に、 `LeafRenderer` を使うようにさせます。

> **注釈:** Leaf はページをレンダリングするための内部キャッシュを持ちます。アプリケーションの環境が `.development` に設定されている時、このキャッシュは無効化されます。そのため直ちにテンプレートに加えられた変更は影響します。 `.production` やその他全ての環境ではキャッシュが既定で有効になっています。テンプレートに加えられた変更はアプリケーションが再起動するまで影響しません。

!!! 警告 Leaf がテンプレートを Xcode での実行時に見つけられるようにするには、 Xcode ワークスペースの [custom working directory](https://docs.vapor.codes/4.0/xcode/#custom-working-directory) を設定する必要があります。

## フォルダ構成

1度でも Leaf を設定したら、 `.leaf` ファイルを保存するための `Views` フォルダがあることを保証する必要があります。既定では Leaf はビューのフォルダがプロジェクトルートから相対的に `./Resources/Views` にあると期待します。

`/Public` から JavaScript と CSS などのファイル提供するために、 Vapor の `FileMiddleware` を有効にしたいとも思うでしょう。
<pre>
VaporApp
├── Package.swift
├── Resources
│   ├── Views
│   │   └── hello.leaf
├── Public
│   ├── images (images resources)
│   ├── styles (css resources)
└── Sources
    └── ...
</pre>

## ビューの描画

最初のテンプレートを描画しましょう。 `Resources/Views` フォルダ内に以下の内容で `hello.leaf` と言う新しいファイルを作りましょう。

```leaf
Hello, #(name)!
```

そして、ビューを描画するためにルーターへ登録します。 (通常は `routes.swift` かコントローラーで行います)

```swift
app.get("hello") { req -> EventLoopFuture<View> in
    return req.view.render("hello", ["name": "Leaf"])
}

// または

app.get("hello") { req async throws -> View in
    return try await req.view.render("hello", ["name": "Leaf"])
}
```

これは Leaf を直接呼ばずに `Request` の一般的な `view` プロパティを使います。これはテスト内で異なるレンダラーに切り替えることを可能にします。

ブラウザを開いて `/hello` にアクセスすると、 `Hello, Leaf!` と表示されるはずです。おめでとうございます。はじめての Leaf ビューの描画です。
Visual Studio Professional 2015 「セットアップパッケージが欠落しているか、破損しています。」


#はじめに
会社のプロジェクトで使ってるのが「**VisualStudio2015Professional**」
だから最新のバージョン代わりにを入れて済ませるとかできなかったしこれ解決するのに結構時間かかった。。
エラーは以下の通り。
カスタムしているのは案件に合わせるため。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2176811/2752ce39-668b-98b7-4dd4-894a2f83b04c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2176811/e861f406-5de0-64ac-cea6-fa203cf47df0.png)
ちなみに、カスタムしないで「既定」を選んでも同じ結果。
その場しのぎに「パッケージをスキップする」をしても途中でボタンが不活性になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2176811/7850db12-5e03-bbc1-9435-6d8d9bd10014.png)
##解決法模索１
同じエラーについて語っているサイトがある。しかも2021年版で。
それがこちら。↓

https://ameblo.jp/mizuhokuzuhara/entry-12660286277.html

ただこれ**Windows7に**Visual Studio 2015をインストールするやり方で自分とは合わないかもという思いで一応やってみるがだめだった。
そもそもPC2台用意して会社のPCをいったんオフラインにしてっていうやり方はリモートデスクトップ接続をして仕事をしている私には至難。
##解決法模索２
次に参考にしたのはこのサイト。

http://aqurex.jp/windows-10-%E3%81%A7-visual-studio-2015-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E6%89%8B%E9%A0%86/

**ただこのサイトすでにisoファイルをゲットしていることを前提として話が始まっている**
なにが言いたいのかというと、


https://visualstudio.microsoft.com/ja/vs/older-downloads/

公式のサイトから**Visual Studio Professional 2015**を探しても見つからない。。
2017とかならあるんだけど。。
じゃあ私はどこからインストーラーを手に入れたのかというと会社のbacklogにあったファイルをダウンロードさせてもらった。
それは「**ja_visual_studio_professional_2015_with_update_3_x86_x64_web_installer_8922975.exe**」
っていファイル名だった。**のちのちこれは更新プログラムだったことがわかる**。
つまりすでにVisual Studio Professional 2015がインストールされていないとだめってこと。

##解決法模索3
会社の情シス部に聞く。
もはや自分にしか参考にならないことをここに書くのはどうかと思うが、散々苦戦した挙句、結局会社から**「isoファイル」をゲットする。**
もしVisual Studio Professional 2015を使う案件にアサインされたとき、会社にisoファイルの場所を聞くのがいいと思う。
だって公式サイトにはないのだから。
ゲットしたファイル名はこれ
**「ja_visual_studio_professional_2015_with_update_3_x86_x64_dvd_8923241.iso」**
これをマウントすると
「**vs_professional.exe**」があるからそれを実行。
**するとセットアップが順調に進むが。。。。**
#苦難は続く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2176811/e1f49c76-720b-559a-4c63-778eab662dbd.png)
セットアップは完了したが、しかしパッケージの実行の失敗＆インストーラーの失敗。。
しかしこのエラーに関する対処は公式サイトに書かれている。

https://visualstudio.microsoft.com/ja/vs/support/vs2015/this-update-requires-visual-studio-2015-update-3-to-be-installed/

https://docs.microsoft.com/en-us/previous-versions/mt752379(v=vs.140)

いろいろ書かれているが要するに**Visual Studio 2015 Update3**を別にインストールするといい。

それでもまだこういうエラーが出てくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2176811/b1d732a3-a31d-4109-2c49-ae66814c19df.png)

でもこの段階でなんの更新プログラムがインストールしてあるのかを見てみると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2176811/0fb48c18-96e1-91be-b762-d0b0a95dfe86.png)

これで
**Visual Studio Professional 2015** 
および
**Visual Studio 2015 Update 3**
の導入が完了。
今のところ案件作業はうまくいってます。
#終わりに
更新プログラムの名前がインストーラーっぽいのが罠。。。
Laravel 処理速度向上の為にwhereHasをwhereInに書き換える

# はじめに
whereHasの処理が遅いと言われていますが、詳しくは下記の記事を見て下さい。
whereHasが必ず悪いというわけではなく、状況次第ではwhereHasを使っても問題ありませんが、無難にwhereInへ書き換える方法を超ざっくり解説します。
https://qiita.com/mpyw/items/0761a5e44836c9bebcd5

こちらでは結局どう書けばいいのか分からない初心者に超ざっくり説明するだけの記事です。

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [whereHasの処理](#whereHasの処理)
2. [whereInで同様の処理を書く](#whereInで同様の処理を書く)
3. [参考文献](#reference)

<!-- 各チャプター -->
# whereHasの処理
そもそもwhereHasとはリレーション先のテーブルからwhere等で絞り込んだ状態でデータを取得したい時に使います。
例えば、id=1のユーザーの投稿（posts)から公開中だけのものを絞り込みたい時は以下のように使います。

```
// ユーザーid=1の人を絞り込む
$user = User::where('id', 1);

// usersテーブルのリレーション先であるpostsテーブルを指定し、クロージャの中でデータを絞り込む
$published_post = $user->whereHas('posts',function($query){
  $query->where('is_published', true);
})->get();

```

# whereInで同様の処理を書く
上で紹介したwhereHasをwhereInに書き換えてみます。
<font color="blue">これでwhereHasを使用した時と同じデータが取得できます。</font>

```
// ユーザーid=1の人を絞り込む
$user = User::where('id', 1);

// whereInの中にリレーション先のモデルインスタンスを記述し、絞りこんでデータを取得する。
$published_post = $user->whereIn('id', Post::select('user_id')
                       ->where('is_published', true))
                       ->get();
```


<a id="#reference"></a>
# 参考文献
- [【Laravel】 Eloquent の has() や whereHas() が遅い？なら速くしてやるぜ](https://qiita.com/mpyw/items/0761a5e44836c9bebcd5)
CGRectを中心とサイズ指定で簡単に生成できるようにする

##やりたいこと

Viewの配置場所指定などで頻繁に使用する、おなじみのCGRect。

CGRectの生成方法は

```swift
CGRect(origin: CGPoint, size: CGSize)
```

　または

```swift
CGRect(x: CGFloat, y: CGFloat, width: CGFloat, height: CGFloat)
```
という感じで、
　四角形の左上の座標指定 ＋　幅・高さ指定
で生成します。



なのですが、実際には
 中心の座標指定 ＋ 幅・高さ指定
からCGRectを生成したいシーンはよくあるかと思います。

毎度毎度、これらの値からoriginを計算してCGRect生成するのはめんどくさいので、
　中心の座標　＋　幅・高さ
で一発でCGRectを生成できるようにしてしまいたいですね。


##解決方法

CGRectを 中心座標 + サイズ の情報で生成でいるイニシャライザを、
CGRectのExtensionとして実装してしまえば良いです。

```swift:CGRectExtension.swift
import UIKit

extension CGRect {
    init(center: CGPoint, size: CGSize) {
        let originX = center.x - size.width / 2.0
        let originY = center.y - size.height / 2.0
        self.init(x: originX, y: originY, width: size.width, height: size.height)
    }
}
```

これで、中心座標とサイズから一発でCGRectを生成できます。
Playgroundで実行した結果が下記。

![CGRectExtensionSample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1117570/39de49a0-8f6a-a792-55c6-72e4dee382f0.png)


##動作確認環境

Xcode: 13.1
iOS: 15.1
Swiftバージョン: Swift 5.5.1


以上
Blender(ver 2.83LTS)で3Dビューの背景色を変更する方法

# 方法を調べたきっかけ
Blender(ver 2.83LTS)の3Dビュー上に表示した3Dモデルのスクショを撮ろうとしたところ…
![blender1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590483/a77f9a89-e959-1dda-e0c7-a6c2643add40.png)
見えなくはないけど、3Dモデルの色が暗めで何となく見づらい状態に。
そこで3Dビューの背景色を変えようと思ったのですが、Blenderに不慣れすぎて苦戦。調べてみても意外と方法が載っているサイトが少なかったので、記録として解決方法を書き記しておきます。

# 背景色の変更方法
以下の流れで設定を行います。（言語は英語です）

1. 「Edit」の「Preferences」を開く
2. 左側の項目一覧から、「Themes」を選択
3. 「3D Viewport」を選択し、「Theme Space」を開く
4. 「Gradient Colors」の「Gradient High/Off」の色を変更（色のリセットは右上の「Reset」でできます）


実際に色をいじってみます。
##### デフォルト
![blender2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590483/a09b5c4d-94c4-771c-d3e5-58f6d5cfcd61.png)
##### 変更後
![blender3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1590483/5864277a-f0f0-1890-ab58-582c0aea34e4.png)
かなり見やすくなりました！

# おわり
正直わざわざ3Dビューのスクショを撮る必要は無い気もするのですが、別の理由で背景色を変更したいけどやり方がわからないという方がいらっしゃいましたら、参考程度に見ていただけると幸いです。

# 参考サイト
https://www.youtube.com/watch?v=yKQzMfhzsks
エンジニアとして副業をしてわかったこと

エンジニアとして副業をしてわかったことを端的にお話ししたいと思います。

ますは私の自己紹介から
私は、大学時代に初めてプログラミングに触れました。最初は、ドベの一人であり全く自分には向いていないと思っていましたが、どこかでそのかっこよさや奥深さ、可能性を見いだしていました。
転機となったのは、日本の大学代表で（そもそも目的は全然違いましたが）シリコンバレーに１週間ほど行ったことでITの最先端に触れ自分のなかで何かが変わりました。日本に帰国し再度独学でHTML・CSSを勉強し始めサイトを作れるように（ちゃっちいものでしたが）なってうきうきになりました。大学でもUnityやグラフィックデザイン系のプログラミング講義、サイバーセキュリティプログラミングなどを受講するようになりました。第二の転機は、大学で行っていた紛争の研究手法の妥当性というかもっと具体的な研究をしたいと思い、実際にコンピューターでシミュレーションできれば面白いのではと思い、プログラミングの勉強にさらに力を入れるようになりました。その時期に、さらに実践面でも経験を積みたいと思いSEをやり始めました。そこから、「自分はITのプロフェッショナル」になると心に近い、外資の大手起業にIT起業に新卒就職し現在もまだいます。それと同時にサイバーセキュリティ関連の勉強を行っています。

■どこで副業の仕事を見つけるか

仕事を見つける方法は大きく3つあるかと思います。
1つ目：知り合いから仕事を受ける（一番有効的というかホワイトで気軽です）
→では、この知り合いを見つけるにはどうすればいいのか。
さまざまですが、TokyoEliteClub（かなりよいサービスかなと思います）
https://www.tokyoeliteclub.com/
ここでいろんな人と出会えて人脈構築できます。エンジニアの仕事だけでなく将来的にかなり使えるのかなと思いますのでぜひ活用してみてください。

２つ目：Crowd Worksで仕事みつける
→かなり案件が多く自分にあった仕事を見つけやすいです。
ただし、嘘の案件も少しあるので気をつけましょう

３つ目：あまりおすすめしないのですが、副業サイトに登録して仕事を見つけてもらう
→あまりおすすめはできません。なぜなら社員みたいな立場で自由にできる（自分の要領でできない）
仕事はないと思っています。

副業ってやっぱ自由に自分の要領でやることが醍醐味かと思っていますので１番目にあげたサイトなどを活用して知り合いやメンターを見つけるのが一番です。

ぜひ実践してみてください！！
シートをシート内の一番左に移動

GASでは、
「このシートをここに移動」というメソッドは存在しない
↓
「アクティブなシートをここに移動」のメソッドを利用

以下の2ステップで実施
① 移動対象のシートをアクティブにする（setActiveSheetメソッド）
② アクティブなシートを1番目に移動する（moveActiveSheetメソッド）

```GAS.js
SpreadsheetApp.setActiveSheet(tarSheet);
SpreadsheetApp.getActiveSpreadsheet.moveActiveSheet(1);
// 呼び出し元の関数がこのシートを操作できるよう「これが新しいシートです」と返す
return tarSheet;
```


>参考

https://mag.sweeep.ai/topic/78286/
Amazon Linux 2 で Python3 の環境構築

#はじめに
EC2でPythonの動作環境を作るための手順です。

#環境構築
```bash:Pythonインストール前のもろもろ
#!/bin/bash
sudo yum update -y
sudo cp /usr/share/zoneinfo/Japan /etc/localtime
```

---
(python3はインストール済みなら空振り)

```bash:python3のインストール
sudo yum install python3 -y
```

```bash:requestsのインストール
sudo pip3 install requests
```

```bash:boto3のインストール
sudo pip3 install boto3
```

```bash:pandasのインストール
sudo pip3 install pandas pandas-datareader
```

#おわりに
何かあれば追加していきます。

```bash:全部入りインストールスクリプト
#!/bin/bash
sudo yum update -y
sudo cp /usr/share/zoneinfo/Japan /etc/localtime
sudo yum install python3 -y
sudo pip3 install requests
sudo pip3 install boto3
sudo pip3 install pandas pandas-datareader
```


#参考文献

https://qiita.com/hiren/items/17984191da2ab8955174
javascript演習　〜１7日目/３０日

覚えたこと

localstorageに保存するには文字列に一旦変換する必要がある。
データを取得するには、取得した文字列データをJSON形式に戻す。

```javascript
localStorage.setItem('items', JSON.stringify(items))

const items = JSON.parse(localStorage.getItem('items')) || [];
```



クリックした要素がinputなら除外する。

```javascript
itemsList.addEventListener('click', (e) => {
  if(!e.target.matches('input')) return;

})
```



ES6 Destructuring


```javascript
itemsList.addEventListener('mousemove', (e) => {
  let { offsetX: x, offsetY: y } = e;

})
```


hover要素が子要素に当たった時に、mousemoveのoffsetが子要素の数値に変わってしまうのを修正


```javascript
itemsList.addEventListener('mousemove', (e) => {
  let { offsetX: x, offsetY: y } = e;

  if(this !== e.target){
    x = x + e.target.offsetLeft;
    y = y + e.target.offsetTop;
  }
})
```



正規表現とreplaceで冠詞を取り除く

```javascript
function strip(bandName) {
  return bandName.replace(/^(a |the |an )/i, '').trim();
}
```
配列内の要素を自動集計するメソッド

 ## 開発環境
`ruby 2.6.5`
`Ruby on Rails 5.2.5`



["京都府", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "広島県", "東京都", "東京都", "東京都", "東京都", "島根県", "東京都", "東京都", "茨城県", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "広島県", "広島県", "東京都", "東京都", "東京都", "東京都", "東京都", "広島県", "広島県", "広島県", " 島根県", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "京都府", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "千葉県", "東京都", "東京都", "東京都", "東京都", "広島県", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "広島県", "東京都", "広島県", "東京都", "京都府", "東京都", "広島県", "東京都", "東京都", "島根県", "東京都", "東京都", "東京都", "広島県", "東京都", "東京都", "東京都", "東京都", "東京都", "広島県", "東京都", "東京都", "島根県", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "京都府", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "北海道", "京都府", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "茨城県", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "広島県", "京都府", "東京都", "東京都", "山梨県", "京都府", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "山梨県", "東京都", "東京都", "広島県", "東京都", "広島県", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "山梨県", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "茨城県", "東京都", "広島県", "茨城県", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "東京都", "山梨県", "東京都", "島根県", "京都府", "東京都", "北海道"]

上のみたいな配列があって要素毎に集計したい

___
https://techacademy.jp/magazine/19771

こんなメソッドがあった

```
a = @mapping_worship.group_by(&:itself)
b = a.map do |key,value|
  [key, value.count]
end
```
こんなふうにしてやると

 [["京都府", 8], ["東京都", 161], ["広島県", 16], ["島根県", 5], ["茨城県", 4], ["千葉県", 1], ["北海道", 2], ["山梨県", 4]]

こうなる
CloudBuildのglobalで使用されるリージョンはどこか？

```
steps:
  - name: gcr.io/cloud-builders/curl
    args:
      [
        "-sS",
        "-H",
        "Metadata-Flavor: Google",
        "http://metadata.google.internal/computeMetadata/v1/instance/zone",
      ]
```

上記を使って半日ほど試したところすべて`us-central1-f`でした。
geochart 日本地図が描画出来ない

## 開発環境
`ruby 2.6.5`
`Ruby on Rails 5.2.5`

## 前提
`slim` で書いている

## 本題

https://developers-dot-devsite-v2-prod.appspot.com/chart/interactive/docs/gallery

上のを参考に日本地図を描画する

ゆくゆくは変数を渡したいけど今回の目標は素の日本地図を描画すること

`js` ファイルを記事を参考にセットアップ。しかし描画されず

コンソールでは

```
Uncaught ReferenceError: google is not defined
```

読み込みエラー

___

読み込み位置が悪かった

```
= javascript_include_tag 'application'
script src="https://www.gstatic.com/charts/loader.js"  
```

ってなってたけど正しくは

```
script src="https://www.gstatic.com/charts/loader.js"  
= javascript_include_tag 'application'
```

地図をロードする前にマニフェストファイルを読み込もうとしていた

[![Image from Gyazo](https://i.gyazo.com/7836fe4e7fa1efa9ceb76b32d918bbae.png)](https://gyazo.com/7836fe4e7fa1efa9ceb76b32d918bbae)
Lottieアニメーションをすぐ使えるように

#今回の内容

<img width="150" alt="E0FF5A40-FB6C-487E-A213-E51CF49AC396_4_5005_c.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/f54542fa-62e1-6959-0a46-6ec6cebdf619.jpeg">

* 半透明な`View`の上に`Lottie`をアニメーションさせます。

#コードと簡単解説

* 今回は`UIButton`に`extension`してます。
* `showContent:String`でアニメーションさせるデータを指定
* `animationTime:Double`でアニメーションさせる時間を指定

```Swift:
extension UIButton{
    
    func showAnimation(showContent:String?,animationTime:Double?,targetView:UIView,completion: @escaping (Bool) -> Void){
        
        guard let content = showContent else { completion(false); return }
        guard let time = animationTime else { completion(false); return }
        
        let underView = UIView(frame: CGRect(x: targetView.frame.maxX / 4, y: targetView.frame.maxY * 0.25, width: targetView.frame.width / 2, height: targetView.frame.width / 2))
        underView.layer.cornerRadius = 15.0
        underView.backgroundColor = .darkGray
        underView.alpha = 0.7
        targetView.addSubview(underView)
        
        let animationView = AnimationView()
        animationView.frame = CGRect(x: targetView.frame.maxX / 4, y: targetView.frame.maxY * 0.25, width: targetView.frame.width / 2, height: targetView.frame.width / 2)
        animationView.layer.cornerRadius = 15.0
        animationView.backgroundColor = .clear
        animationView.animation = Animation.named(content)
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .loop
        animationView.play(completion: nil)
        targetView.addSubview(animationView)
  
        DispatchQueue.main.asyncAfter(deadline: .now() + time) {
            
            completion(true)
            animationView.stop()
            animationView.removeFromSuperview()
            underView.removeFromSuperview()
        }
    }
    
}
```

##実際に使用


```Swift:
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let button = UIButton(frame: CGRect(x: view.frame.maxX / 4, y: view.frame.maxY * 0.7, width: view.frame.width / 2, height: view.frame.height / 15))
        button.backgroundColor = .systemTeal
        button.setTitle("ShowAnimation", for: .normal)
        button.titleLabel?.textColor = .white
        button.addTarget(self, action: #selector(showAnimation), for: .touchDown)
        view.addSubview(button)
    }
    
    @objc func showAnimation(button:UIButton){
        
        button.showAnimation(showContent: "5", animationTime: 10, targetView: self.view) { result in

            if result == false{

                return
            }

            print("終わり")
        }
    }
```

# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。
railsチュートリアル第１１章 editアクションで有効化

###editアクションで有効化
####アカウントを有効化するeditアクション
app/controllers/account_activations_controller.rb

```rb
class AccountActivationsController < ApplicationController

  def edit
    user = User.find_by(email: params[:email])
    # paramsハッシュで渡されたメールアドレスに対応するユーザーを認証します
    if user && !user.activated? && user.authenticated?(:activation, params[:id])
    # 攻撃者がユーザーの有効化リンクを後から盗みだしてクリックするだけで、
    #   本当のユーザーとしてログインできてしまいます。
    
      user.update_attribute(:activated,    true)
      user.update_attribute(:activated_at, Time.zone.now)
      # ユーザーを認証するには、ユーザーを認証してから
      #   activated_atタイムスタンプを更新する必要
      log_in user
      flash[:success] = "Account activated!"
      redirect_to user
    else
      flash[:danger] = "Invalid activation link"
      redirect_to root_url
      # トークンが無効になるようなことは実際にはめったにありませんが、
      #   もしそうなった場合はルートURLにリダイレクトされる仕組み
    end
  end
end
```
####有効でないユーザーがログインすることのないようにする
app/controllers/sessions_controller.rb

```rb

class SessionsController < ApplicationController
.
.
. 
  def create
    @user = User.find_by(email: params[:session][:email].downcase)
    # 送信されたメアドを使ってデータベースから取り出す。
    #emailを小文字にする
    if @user &.authenticate(params[:session][:password])
    # user  取得したユーザーが有効かどうか？
    # その後にデータベース上にパスワードがあるか？
    # ユーザーログイン後にユーザー情報のページにリダイレクトする
    # &.は省略型
      if user.activated?
      # ユーザーが有効か？
        log_in user
        params[:session][:remember_me] == '1' ? remember(user) : forget(user)
        # 1の場合はremmber(user)
        # それ以外はforget(user)
        redirect_back_or user
      else
        message  = "Account not activated. "
        message += "Check your email for the activation link."
        flash[:warning] = message
        # メッセージを表示
        redirect_to root_url
        # ホーム画面に送る
      end
    else
      flash.now[:danger] = 'Invalid email/password combination'
      # flash.nowでリクエストが発生後メッセージを消滅する
      # エラーメッセージを作成する
        render 'new'
        # newアクションのビューを表示
    end
  end
.
.
.
end
```
###演習
1.
コンソールから、11.2.4で生成したメールに含まれているURLを調べてみてください。URL内のどこに有効化トークンが含まれているでしょうか?

```
https://*******5.vfs.cloud9.ap-northeast-1.amazonaws.com/account_activations/OGHN0ebW8H-S6dqER1u-bQ/edit?email=ghi%40jkl.com
```

有効かトークン```OGHN0ebW8H-S6dqER1u-b ```

2.
先ほど見つけたURLをブラウザに貼り付けて、そのユーザーの認証に成功し、有効化できることを確認してみましょう。また、有効化ステータスがtrueになっていることをコンソールから確認してみてください。
確認
有効化ステータスがtrueになっていることをコンソールから確認できなかった。
railsチュートリアル第１１章 ユーザーのcreateアクションを更新

###ユーザーのcreateアクションを更新
####ユーザー登録にアカウント有効化を追加する
app/controllers/users_controller.rb

```rb
lass UsersController < ApplicationController
  .
  .
  .
  def create
    @user = User.new(user_params)
    if @user.save
      UserMailer.account_activation(@user).deliver_now
      flash[:info] = "Please check your email to activate your account."
      redirect_to root_url
    else
      render 'new'
    end
  end
  .
  .
  .
end
```
####失敗するテストを一時的にコメントアウトする
test/integration/users_signup_test.rb

```rb
require 'test_helper'

class UsersSignupTest < ActionDispatch::IntegrationTest

  test "invalid signup information" do
    get signup_path
    assert_no_difference 'User.count' do
      post users_path, params: { user: { name:  "",
                                         email: "user@invalid",
                                         password:              "foo",
                                         password_confirmation: "bar" } }
    end
    assert_template 'users/new'
    assert_select 'div#error_explanation'
    assert_select 'div.field_with_errors'
  end

  test "valid signup information" do
    get signup_path
    assert_difference 'User.count', 1 do
      post users_path, params: { user: { name:  "Example User",
                                         email: "user@example.com",
                                         password:              "password",
                                         password_confirmation: "password" } }
    end
    follow_redirect!
    # assert_template 'users/show'
    # assert is_logged_in?
  end
end
```

###演習
1.
新しいユーザーを登録したとき、リダイレクト先が適切なURLに変わったことを確認してみましょう。その後、Railsサーバーのログから送信メールの内容を確認してみてください。有効化トークンの値はどうなっていますか?

```
https://*******5.vfs.cloud9.ap-northeast-1.amazonaws.com/account_activations/OGHN0ebW8H-S6dqER1u-bQ/edit?email=ghi%40jkl.com
```

2.
コンソールを開き、データベース上にユーザーが作成されたことを確認してみましょう。また、このユーザーはデータベース上にはいますが、有効化のステータスがfalseのままになっていることを確認してください。

```
>> User.last
   (1.7ms)  SELECT sqlite_version(*)
  User Load (1.1ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" DESC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 101, name: "c", email: "ghi@jkl.com", created_at: "2021-10-18 05:24:37", updated_at: "2021-10-18 05:24:37", password_digest: [FILTERED], remember_digest: nil, admin: false, activation_digest: "$2a$12$PS8VhZg/p4.1H/faHMtKae1LUk/HIUZLCAB.8KB3zlm...", activated: false, activated_at: nil>
```
どれが有効なステータスなのかわからない。
Geocoder seed データの反映でコールバックが発生しない

## 開発環境
`ruby 2.6.5`
`Ruby on Rails 5.2.5`

## 前提
神社テーブルがあり、その住所カラムに `geocoder` をコールバックさせている
`seed_fu` をつかって `seed` データを作成している
説明上関係ないカラムは無視してください

## 本題

神社の `CSV` ファイルの `seed` データを反映する。

そのタイミングで住所カラムにコールバックさせて緯度と経度を登録したかった

モデルには以下のように定義

```
class Shinto < ApplicationRecord
  geocoded_by :address
  after_validation :geocode
end
```
`seed` データには以下

```
import_read('test_shinto.csv') do |line, idx|
  Shinto.seed do |s|
    s.id      = idx
    s.name = line[0]
    s.image = line[1]
    s.address = line[2]
    s.origin_shrine = line[3]
    s.original_url = line[4]
    s.kamisama = line[5]
    s.origin_term = line[6]
    s.origin_history = line[7]
  end
end
```

で `seed`f を反映させる
すると

[![Image from Gyazo](https://i.gyazo.com/60dcf361955b0adb4d898b04d5db13c9.png)](https://gyazo.com/60dcf361955b0adb4d898b04d5db13c9)

`latitude` と `longitude` が反映されてない
___

`seed` ファイルを以下のようにした

```
import_read('test_shinto.csv') do |line, idx|
  Shinto.create do |s|
    s.id      = idx
    s.name = line[0]
    s.image = line[1]
    s.address = line[2]
    s.origin_shrine = line[3]
    s.original_url = line[4]
    s.kamisama = line[5]
    s.origin_term = line[6]
    s.origin_history = line[7]
  end
end
```

`seed_fu` をつかっていたので最初は `seed` メソッドで反映したんだけど
`create` メソッドに変えてみた。

で、また反映
すると

[![Image from Gyazo](https://i.gyazo.com/e661e36a50f01e1bb80d1cee5a9043a4.png)](https://gyazo.com/e661e36a50f01e1bb80d1cee5a9043a4)


反映された。
どうやら `seed` メソッドではコールバックは走らないっぽい


#### 追記

最初は `after_validation` が悪いと思って `after_create` に変えてみた。
結果的にはそれでもだめだった

ただそのおかげでコールバックの細かい挙動の違いが発見できた。


`seed` ではなくコンソール上でコールバックが走るのか確認したかったので

[![Image from Gyazo](https://i.gyazo.com/d8ccf16d0003e18d663d543334ac61c4.png)](https://gyazo.com/d8ccf16d0003e18d663d543334ac61c4)

こんなふうに実在する住所のみをいれて登録すると
コールバックが走って緯度経度が入る

これ自体は想定内。

しかし

[![Image from Gyazo](https://i.gyazo.com/d819f23b3bbd8991c9b339e82d4cd4d9.png)](https://gyazo.com/d819f23b3bbd8991c9b339e82d4cd4d9)

再度確認すると消えている。

これはコールバックのタイミングが `after_create` なので
 API を叩いてもその後保存するっていう処理が走らないため

`after_validation` だと `create` の前にコールバックが走るのでちゃんと保存される
circle ciでYour requirements could not be resolved to an installable set of packagesというエラーが出た時の解決策

###やろうとしたこと
circleciでpackageをインストールしようとした。
###コード
```
version: 2.1
jobs:
  build:
    docker:
      - image: circleci/php:7.3-node-browsers
    steps:
      - checkout
      - run: sudo composer self-update --1
      - run: composer install -n --prefer-dist
      - run: npm ci
      - run: npm run dev
      - run:
          name: php test
          command: vendor/bin/phpunit

```
###エラーメッセージ
![スクリーンショット 2021-11-06 23.00.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/712442/eb06be4b-2ed7-da3a-dc0b-6a5dbdd8bfd2.png)

###原因と対策
翻訳してみるとどうやらphpのバージョンが古かったらしい。そのため、dockerのphpのimageを8.0にすると解決できた。

```
version: 2.1
jobs:
  build:
    docker:
      - image: circleci/php:8.0-node-browsers
    steps:
      - checkout
      - run: sudo composer self-update --1
      - run: composer install -n --prefer-dist
      - run: npm ci
      - run: npm run dev
      - run:
          name: php test
          command: vendor/bin/phpunit
```
ELBのSSL Termination とは

## 勉強前イメージ

ELBでSSLの設定できるのは知ってるけど、それのこと？
それともまた別のことなのかな？

## 調査

### ELBのSSL Termination とは

ELBの機能で、ロードバランサー側でSSL認証を行ってくれる機能があります。
基本的にはクライアントから443番ポートでアクセスされると、ELBはSSL証明書の確認を行い
ELB配下のサーバへ80番おポートでアクセスを行います。

### 構成

よくある構成としては以下になります。

1. ACMで証明書の作成
2. ELBを作成し、ACMの証明書を紐付ける
3. EC2を作成し、ELB配下に設置

こちらを行うことで、EC2に証明書の設定をせずとも暗号化通信が行われます。
ELB配下のEC2が複数台になったとしても、ELB側の変更を行うだけで暗号化通信を設定できるので
証明書更新の手間が省けます。

![12021-11-04 # ELBのSSL Termination とは - diagrams.net.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/29afd89d-5c23-055c-67b4-4091d01b8558.png)

### 設定方法

詳細な設定方法は [こちら](https://qiita.com/miyuki_samitani/items/1734dc13c6b7af601bd9) に記載しておりますが、
ELBのリスナーをhttpsにし、セキュリティの設定で作成した証明書を指定することで
簡単に設定することができます。
また証明書をACMで設定したDNS認証の証明書にすると
基本的には証明書は自動更新なので、証明書の期限を毎年確認し更新するという作業を省くことができます。
※ワイルドカードでの証明書を使用すると、DNS認証でも自動更新できないので注意してください

## 勉強後イメージ

ELBでSSLの設定することをSSL Terminationっていうのか・・・
あまりちゃんとみたことなかったなー
ただみんなよく使う機能なので気をつけないといけない

## 参考

- [ELBでSSL Termination後の内部通信を暗号化する](https://dev.classmethod.jp/articles/elb-ssl-termination/)
応用情報技術者試験を受験した

先日、2021年10月10日(日)に応用情報技術者試験を受験したので受験記録をメモしておきます。

# 応用情報技術者試験の概要
- 応用情報技術者試験とは、IPA 独立行政法人 情報処理推進機構が実施している資格試験のひとつ。
- 英語表記はApplied Information Technology Engineer Examinationで、APと略される。（受験票には試験区分が英字二字の略称で記されていた。）
- 春期試験と秋期試験の年二回の試験がある。春期試験は4月、秋期試験は10月に行われる。
- 応用情報技術者試験の範囲は[公式が出しているシラバス](https://www.jitec.ipa.go.jp/1_04hanni_sukiru/_index_hanni_skill.html#syllabus)に記載されている通りで、以下のようになっている。
    - テクノロジ系（いわゆるコンピュータサイエンスの科目で扱われる分野）
        - 基礎理論
            - 基礎理論
            - アルゴリズムとプログラミング
        - コンピュータシステム
            - コンピュータ構成要素
            - システム構成要素
            - ソフトウェア
            - ハードウェア
        - 技術要素
            - ヒューマンインタフェース
            - マルチメディア
            - データベース 
            - ネットワーク
            - セキュリティ
        - 開発技術
            - システム開発技術
            - ソフトウェア開発管理技術
    - マネジメント系（プロジェクトやサービスの開発・運営に関わる事柄）
        - プロジェクトマネジメント
            - プロジェクトマネジメント
        - サービスマネジメント
            - サービスマネジメント
            - システム監査
    - ストラテジ系（いわゆる経営に関する事柄）
        - システム戦略
            - システム戦略
            - システム企画
        - 経営戦略
            - 経営戦略マネジメント
            - 技術戦略マネジメント
            - ビジネスインダストリ
        - 企業と法務
            - 企業活動
            - 法務
- 応用情報技術者試験は午前試験と午後試験から成っている。午前試験と午後試験を両方とも合格すると応用情報技術者試験の合格が認定される。
    - 午前試験
        - 4択問題でマークシート形式
        - 100点満点
        - 上記の試験範囲の中から80問が出題される。1問あたり1.25点。
        - 基準点は60点。すなわち80問中の6割（48問）以上を正解すると午前試験は合格となる。
        - 試験時間は9時30分から12時00分までの150分間。
    - 午後試験
        - セキュリティ+10個の大問から自由選択4問。大問1つの配点は20点である。
        - 基準点は60点。
        - 試験時間は13時00分から15時30分までの150分間。

# 勉強方法
　まともに勉強を始めたのは試験当日の二週間前（9月25日前後）からでした。遅いと思います。
　参考書には技術評論社から出ている[『応用情報技術者 合格教本』](https://gihyo.jp/book/2020/978-4-297-11799-3)を使いました。キーワードとその説明をひたすら紙に書き続けながら、とりあえず教本を1周しました。キーワードを空で説明できるようになれば、そのキーワードは理解したものと判定して進みます。
　過去問は[応用情報技術者過去問道場](https://www.ap-siken.com/apkakomon.php)を1周しました。ネットワークやデータベースといった、個人的に重要だと思う科目は2周目も解きました。過去問を解いて、抜けている知識があったら教本を読んで補填するを繰り返しました。
　面倒だったのでやりませんでしたが、午後問題は解答する大問セットを決め、時間を計って本番と同じように解いてみるべきだと思います。本番では問題文の読み間違えや誤解を防ぐためにゆっくり解いていたせいか、時間がなくて焦りました。
# 結果と感想
　[IPAの公式解答](https://www.jitec.ipa.go.jp/1_04hanni_sukiru/mondai_kaitou_2021r03.html)によれば午前試験は80問中59問正解でした。
　午後試験は筆記が半分近くを占めているため何とも言えませんが、[TACが出している解答例](https://www.tac-school.co.jp/kaitousokuhou/downloads/9_R3F_AP%E8%A7%A3%E7%AD%94%E4%BE%8B.pdf)を見る限り、おそらく少なくとも7割程度を得点できたと思います。
　受験した感想としては、「広く浅くCSの語彙を学べる点で、中高生や大学一年生が応用情報取得のために勉強することは勧められるかもしれない。一方でプログラマの知識や技能の指標としてはほとんど役に立たない」といった感触です。
　全体的に、多くの問題がキーワードの表面的な理解で解けてしまう上、過去問からの使い回しが多く、合格教本で一通りキーワードを押さえる+過去問を回すだけでかなり点が取れるようになっています。
　加えて、とにかく6割という基準点が低くて、特に午前試験は常識問題や国語・算数の問題がそこそこの割合を占めているため、それらを得点して残り30問程度を正解すれば午前の基準点を通過できてしまいます。午後試験もアルゴリズムやシステム開発がほとんど勉強なしに点を稼げる科目となっていて、専門知識や技能を問うようにはなっていないように感じます。
　学部でCSを学んだ方、CSを自習できている方にはかなり自明な試験だと思います。とはいえ、大学ではあまり学ばないマネジメントやストラテジ系の知識を（強制的に）入れることができる点は良いのかもしれません。
ransack 検索前と検索後のアクションを１つにする

## 開発環境
`ruby 2.6.5`
`Ruby on Rails 5.2.5`

## 前提
`ransack` を導入している

## 本題

`ransack` を導入するにあたって色々調べた。

どこの記事も検索前の画面と検索後の画面でアクションを分けている。
理由はないんだけど、なんとなくあんまりアクションを増やしたくなかった。

うまいこと１つにできないかなと。
そしたらなんとかできたので。

実際の画面は

[![Image from Gyazo](https://i.gyazo.com/65eccff0969e1dc7f361285b17028caf.png)](https://gyazo.com/65eccff0969e1dc7f361285b17028caf)

こうやって検索したら

[![Image from Gyazo](https://i.gyazo.com/f357bea8dcbddca66ae8d7bd302ea45d.png)](https://gyazo.com/f357bea8dcbddca66ae8d7bd302ea45d)

こうやって同じアクションに再び送られて条件分岐で画面遷移する

コードは以下

```:controller
 def index
   @q = Shinto.ransack(params[:q])
     unless params[:q].blank?
       @shintos = @q.result(distinct: true)
     else
       @shintos = nil
     end
  end
```

```:view
= search_form_for @q do |f|
  = f.label :name, "神社を検索する"
  = f.search_field :name_or_address_or_kamisama_cont
  = f.submit "検索"

- unless @shintos == nil
  table
    thead
      tr
        th = sort_link(@q, :name, "神社名", hide_indicator: true)
        th = sort_link(@q, :address, "住所", hide_indicator: true)
        th 詳細
        th お気に入り

    tbody
      - @shintos.each do |shinto|
        tr
          td = shinto.name 
          td = shinto.address
          td = link_to 'Show', shinto, class: "btn btn-primary"
          td
            - if current_user.favorite_shintos.find_by(shinto_id: shinto.id).present?
              = link_to "お気に入りを解除する", favorite_shinto_path(shinto.favorite_shintos[0].id), method: :delete, class: "btn btn-danger"
            - else 
              = link_to "お気に入りする", favorite_shintos_path(shinto_id: shinto.id), method: :post, class: "btn btn-danger"
  br
```

どうやら `ransack` のフォームは 検索したいモデルから
`ransack` メソッドっていうのでビルドした変数を受け取る必要があるみたい。

なので上みたいなコードになる

他にも良い書き方あるかもだけど
laravel Eloquent  updateOrCreate()メソッドの使用

## 目的

- laravelのEloquentの`updateOrCreate()`メソッドを使ってみたら非常に使いやすかったので簡単にまとめる

## `updateOrCreate()`メソッドって？？

- 公式ドキュメントだと下記に記載されている。
    - [https://readouble.com/laravel/6.x/ja/eloquent.html](https://readouble.com/laravel/6.x/ja/eloquent.html)

        ![Eloquent：利用の開始_6_x_Laravel.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/a1e9f505-bdf6-38da-a71a-f2025cd13020.png)

- 当該のモデルに紐づくテーブルを探索してくれて、指定した値が指定したカラムに格納されているレコードがヒットすればupdate、ヒットしなかった場合はcreateを実行する。
- このメソッド一個でsaveまで行ってくれる。

## 使用方法

- 下記のように記載する。

    ```php
    updateOrCreate(['探索カラム名' => 条件となる値], ['値を格納するカラム名' => 値],);
    ```

- 例えばhogeテーブルが存在したとする。
    - `id`カラムが4のレコードを探索してレコードが
        - 存在していた場合、`name`カラムに「name_string」を格納してupdateを行う。
        - 存在していなかった場合、`name`カラムに「name_string」を格納してcreate（新しいレコードの作成）を行う。
- 上記の処理を`updateOrCreate（）`メソッドで記載する場合、下記の様に記載する。（Hogeモデルクラスはすでにuse宣言されているものとする。）

    ```php
    Hoge::updateOrCreate(['id' => 4], ['name' => 'name_string'],);
    ```

- エラー`Add [カラム名] to fillable property to allow mass assignment on [モデル名]`が出る場合は下記の記事をご確認いただきたい。
    - [laravel 「Add [カラム名] to fillable property to allow mass assignment on [モデル名]」エラーの解決
](https://qiita.com/miriwo/items/9ae2500bfc3f26e83e3a)
    - どうやらMass Assignmentというものが安全のためにブロックしたようで、`updateOrCreate()`メソッドを使って更新するカラムをホワイトリストに登録して上げる必要があるらしい。
        - 参考リンク
            - [https://laravel.com/docs/6.x/eloquent#mass-assignment](https://laravel.com/docs/6.x/eloquent#mass-assignment)
            - [https://qiita.com/yyy752/items/820260163d4883efb132](https://qiita.com/yyy752/items/820260163d4883efb132)

## 具体的な使用例（かなり不親切な記載ですすみません。）

- ※依存注入とかをしている（`__construct()`メソッドとかに色々書いてる）ので若干分かりにくいかもしれません。わからなかったらスルーでOK
- 下記は本当に一部分の処理のみ記載する。詳細は下記のリンク先のGithubのリポジトリを参照いただきたい。
    - [https://github.com/miriwo0104/laravel8_easy_crud](https://github.com/miriwo0104/laravel8_easy_crud)
- 下記のようなスキーマのcontentsテーブルがあったとする。

    ```
    +--------------+------------------+------+-----+---------+----------------+
    | Field        | Type             | Null | Key | Default | Extra          |
    +--------------+------------------+------+-----+---------+----------------+
    | id           | bigint unsigned  | NO   | PRI | NULL    | auto_increment |
    | content      | text             | NO   |     | NULL    |                |
    | deleted_flag | tinyint unsigned | NO   |     | 0       |                |
    | created_at   | timestamp        | YES  |     | NULL    |                |
    | updated_at   | timestamp        | YES  |     | NULL    |                |
    +--------------+------------------+------+-----+---------+----------------+
    ```

- contentsテーブルのidの値を探索して
    - ヒットしたら当該レコードのcontentsの内容を更新（update）する。
    - ヒットしなかったらcontentsにpostされた値を格納してレコードを作成（create）する。

    ```php
    public function save($post_data)
    {
        return $this->content->updateOrCreate(
            ['id' => $post_data->id],
            ['content' => $post_data->content],
        );
    }
    ```