OmniAICreator/Qiita-1.07M huggingface dataset:
新卒1年目が1週間でAZ-900(Microsoft Azure Fundamentals)合格

# はじめに
新卒1年目の私が、勉強期間1週間でAZ-900(Microsoft Azure Fundamentals)に合格したため、何を使って学習を進めたのか記載する。
※この記事は個人の経験で語っているため、合格を保証するものではありません。

# 自身のAzure経験
[Microsoft Learn Student Ambassador](https://studentambassadors.microsoft.com/)として2020年7月から活動していたため、Azureを用いた開発経験はある程度（ハッカソンで利用した程度）持っている状態でした。
しかし、使える程度でAzureに関する知識はほとんどありません。

# 勉強方法
参考書と[Udemy](https://www.udemy.com/)を活用して勉強しました。
試験申し込みを先に行い、勉強は1週間前からスタートさせました。

## 参考書
- [合格対策 Microsoft認定 AZ-900:Microsoft Azure Fundamentalsテキスト&問題集](https://www.amazon.co.jp/%E5%90%88%E6%A0%BC%E5%AF%BE%E7%AD%96-Microsoft%E8%AA%8D%E5%AE%9A-AZ-900-Microsoft-Fundamentals%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88/dp/4865942319)
    - 1回全て読む
    - 過去問の章は2周する
        - 正解以外の選択肢に対する解説までしっかりと読み込む

## Udemy
- [これだけで合格！AZ-900: Microsoft Azure Fundamentals模擬試験問題集（7回分430問）](https://www.udemy.com/course/az-900-microsoft-azure-fundamentals4176/)
    - 7回全てで正答率80%を超えるまで繰り返す
    - 正解以外の選択肢に対する解説までしっかりと読み込む

# 試験後の所感
合格することのみが目的であれば、過去問を繰り返し解くのみで合格は可能だと思います。
しかし、それでは実力が身に付かないため、開発経験の少ない方は参考書やUdemy、[Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/)を用いて学習を進めることをお勧めします。
【AWS】Lambdaのスロットリング時の挙動確認

## やりたいこと
- S3のファイルPUTをトリガーとしたLambdaでスロットリングエラーが発生した時の挙動の確認
(スロットリングエラーが発生したときのトリガーイベントが消失するのか…)

## Summary
- Lambdaのスロットリングが発生してもS3 イベントは消失せず、一定間隔でリトライされる。(リトライ間隔は徐々に伸び、最大5分)
- リトライされる期間はイベントの最大有効時間の設定で調整(公式開発者ガイドに記載)

## 前提

https://qiita.com/kei1-dev/items/9321668126c9b84b88a0

## 検証手順
1. Lambdaソースコードの修正
1. Lambda同時実行数、タイムアウト期間の設定
1. 動作確認

### 1. Lambdaソースコードの修正
- Lambda内に70秒の待機を追加し、スロットリングが発生しやすくする。

```javascript:index.js
'use strict';

const aws = require('aws-sdk');
const s3 = new aws.S3();

exports.handler = async (event) => {
    //S3から送られたトリガー内容を確認_
    console.log(event);

    const bucket = event['Records'][0]['s3']['bucket']['name'];
    const key = event['Records'][0]['s3']['object']['key'];
    console.log(bucket);
    console.log(key);

    
    //S3.copyObjectを実施(params内Bucket,CopySource, Keyは必須) 
    const params = {
        Bucket: "copied-bucket-210731", 
        CopySource: bucket+'/'+key, 
        Key: key
    };
    
    //70秒待機
    const sleep = () => new Promise(resolve => {
     setTimeout(() => {
        resolve();
    }, 70000);
    });
    await sleep();
    
	const result = await s3.copyObject(params).promise();
	
	console.log(result);
    
};
```
### 2. Lambda同時実行数、タイムアウト期間の設定
- 同時実行数: Lambdaの設定>同時実行で同時実行の予約=1に設定
![スクリーンショット 2021-08-01 000243.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/0bca0ca9-0838-c4d0-d001-1f6c1419d252.png)

- タイムアウト期間: Lambdaの設定>基本設定でタイムアウト=5分に設定

![スクリーンショット 2021-07-31 225936.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/164c55bb-3ebe-6f76-67ed-70e2e46d867d.png)

### 3. 動作確認
- ファイルを10個用意し、S3バケットに同時にアップロードする。
![スクリーンショット 2021-08-01 054027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/ff4207f4-8de6-6a11-2ad4-08c702575909.png)

- Copiedバケットにすべてのファイルがコピーされていることを確認
    - 概ねリトライ間隔に比例して、コピーされている
![スクリーンショット 2021-08-01 100304.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/1cbb0192-3161-5465-3e4e-11f9f8a3c3e7.png)


- Cloudwatch Metrixよりスロットリングが発生することを確認
    - 投入時に高頻度でスロットリングが発生、リトライ時に処理されることで徐々にスロットリングの値が低下
![スクリーンショット 2021-08-01 100458.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/182a1a71-b000-af99-5626-5b808f803c5f.png)


## 参考

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-async.html

https://dev.classmethod.jp/articles/asynchronous-lambda-error-handling-done-right/

(クラメソさんの記事はやってる最中に見つけて、ほぼやりたいことやってくれてました…ありがとうございます！)
【SAP-C01試験対策】AWS AI ServisesのBlack Belt を文章でまとめてみた

# はじめに
AWSのAIサービスを勉強するためにBlack Belt Online Seminerを視聴したので内容をまとめます。

https://www.youtube.com/watch?v=xvUyKjuv-Z4

# 背景
本記事はAWSソリューションアーキテクトプロフェッショナルに合格するために、[Udemyの模擬試験](https://www.udemy.com/course/aws-53225)を解いて分からなかった部分を勉強してまとめるものです。

試験対策用のため、分からない知識を補足したり試験で問われなさそうなところを省略したりしながらまとめています。
なるべくわかりやすい記載を心がけますが、最終目的は自己学習用であるということをご容赦ください。

# セミナーの内容
* AIサービスは、データを用意するだけでAPIから機械学習を利用できる。(EC2インスタンスを必要としない)
* 利用する機械学習は、AWSによって最適な実装がされている。


## Amazon Recognition
画像・動画の認識サービス。
それぞれAmazon Recognition Image, Amazon Recognition Videoに分かれる。

### 主な機能

* 物体、シーン、アクティビティ検出、
* 顔分析
* 動線の検出
* 顔認識
* 安全でない（不適切な）コンテンツの検出
* 有名人の認識
* 画像中のテキスト認識
* リアルタイム分析

## Amazon Textract
PDF、画像のテキストと構造情報を抽出するマネージドサービス。
テキスト、フォーム、テーブルの抽出が可能。
検出結果はJSON形式で出力される。

## Amazon Polly
テキストを音声に変換する音声認識サービス。

## Amazon Transcribe
音声をテキストに変換する音声認識サービス。

## Amazon Translate
言語間でテキストを翻訳するためのニューラル機械翻訳サービス

## Amazon Comprehend
機械学習を使用してテキストの理解に有用な情報を発見、分析する自然言語処理サービス。
キーフレーズ、感情分析、構文、エンティティ、トピックモデル、言語検出を抽出。

## Amazon Lex
音声やテキストを使用して対話型インターフェース(チャットボット)を構築するサービス。
Alexaと同じ会話エンジンを活用して高性能の音声認識および言語理解が可能。

## Amazon Personalize
ユーザー向けにパーソナライズされたレコメンデーションするための機械学習サービス。

## Amazon Forecast
過去の履歴から将来を予測する時系列データ予測サービス

# まとめ：全体像

| 種類 | サービス | 概要
| :--- | :--- | :--- |
| 静止画・動画認識 | Recognition Image <br> Recognition Video <br> Textract | 画像認識<br>動画認識 <br> テキスト認識
| 音声処理 | Polly <br> Transcribe | テキスト -> 音声 <br> 音声 -> テキスト 
| チャットボット| Lex| 対話型インターフェース | 
|時系列データ予測| Forecast| 過去の履歴から将来を予測 |
| レコメンデーション| Personalize| 機械学習でユーザーごとに<br>レコメンデーションする| 

# おわりに
各サービス概要しか記載していませんが、セミナーでは主な機能やユースケース、システムの構成例も紹介していました。試験対策を進めていくうちに必要であれば記載を充実させていきます。
Progateで作ったWebアプリをDjangoで作ってみる2！ Part7 -DetailView編-

# 目標物の確認

ProgateのNode.jsコースで作ったブログアプリと同じものをDjangoで作ってみます。

Djangoでのアプリ開発の一連の流れを整理するために記していきます。

**完成イメージ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/147877a6-1b3a-25e2-7956-720596125802.png)

#記事画面の作成

個々の記事はDetailViewというViewで表示させます。

まずはHTMLファイル（**article.html**）を作成します。

Part6で作成した**base.html**を継承して（☆1）、``{% block content %}`` ``{% endblock content %}``の中に個別記事を表示するコードを書いていきます（☆2）。

記事が「全員（``object.category == 'all'``）」の場合、コンテンツが表示されるようにします（☆3）。記事が、「会員限定（``object.category == 'limited'``）」の場合、タイトルは表示されるが、コンテンツはログインされている場合（``user.is_authenticated``）は表示されるようにします（☆4）。ログインされていない場合は、コンテンツは表示されず、ログイン画面へのリンクが表示されるようします（☆4）。

```HTML:article.html
{% extends 'blog/base.html' %} <!--☆1-->
{% load static %}

{% block content %} <!--☆2-->
  <main>
    <div class="article">
      {% if object.category == 'all' %} <!--☆3-->
        <h1>{{ object.title }}</h1>
        <p>{{ object.content }}</p>
      {% endif %} <!--☆3-->
      {% if object.category == 'limited' %} <!--☆4-->
        <i>会員限定</i>
        <h1>{{ object.title }}</h1> <!--☆4-->
        {% if user.is_authenticated %} <!--☆4-->
          <p>{{ object.content }}</p> <!--☆4-->
        {% else %} <!--☆4-->
          <div class="article-login">
            <p>今すぐログインしよう！</p>
            <p>記事の続きは<br>ログインすると読むことができます</p>
            <img src="{% static 'blog/login.svg' %}">
            <a class="btn" href="{% url 'blog:login' %}">ログイン</a>
          </div>
        {% endif %} <!--☆4-->
      {% endif %} <!--☆4-->
    </div>
  </main>
  <footer>
    <a class="btn sub" href="{% url 'blog:list' %}">一覧にもどる</a>
  </footer>
{% endblock content %} <!--☆2-->
```

**views.py**ファイルを作成していきます（☆5）。

```python:blogapp/blog/views.py
from blog.models import BlogModel
from django.shortcuts import render, redirect
from django.views.generic import TemplateView, ListView, DetailView # ☆5
from django.contrib.auth.models import User
from django.db import IntegrityError
from django.contrib.auth import authenticate, login, logout
from .models import BlogModel

class BlogTop(TemplateView):...

def signupview(request):...

def loginview(request):...

def logoutview(request):...

class BlogList(ListView):...

class BlogArticle(DetailView): # ☆5
    template_name = 'blog/article.html'
    model = BlogModel
```

**urls.py**ファイルも作成します（☆6）。

``<int:pk>``が、テーブルに入っているデータを具体的に指定する上で使われるコードです（☆6）。

```python:blogapp/blog/urls.py
from django.urls import path
from .views import BlogTop, signupview, loginview, logoutview, BlogList, BlogArticle # ☆6

app_name = 'blog'

urlpatterns = [
    path('', BlogTop.as_view(), name='top'),
    path('signup/', signupview, name='signup'),
    path('login/', loginview, name='login'),
    path('logout/', logoutview, name='logout'),
    path('list/', BlogList.as_view(), name='list'),
    path('article/<int:pk>/', BlogArticle.as_view(), name='article') # ☆6

]
```

ログインの有無でページの表示が変わっています。

成功です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471633/51eb5c2e-1baf-2043-85de-dfd99fc88505.png)
【物体検出】Google ColabでYOLOv5を使ってYouTube動画から物体検出で電車を抽出してみる

#はじめに

YOLOv5でYouTube動画から直接物体検出する方法についてまとめます。
Google Colaboratory上でYOLOv5を使用して、YouTube動画から直接物体検出を試していきます。
YouTube動画から直接物体検出することで、動画内容の分析や情報の把握の自動化への活用が期待されます。
以下ソース

https://github.com/ultralytics/yolov5/pull/2752

#目標(成果物)

![無題のプレゼンテーション (3).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1559455/53fc9285-1608-c38f-6a5c-1e6a3abe96b2.jpeg)

上図のようにYouTube上にある動画に対して物体検出を行なって結果を得ます。
今回は、YOLOv5の自作モデルによりYouTube動画から直接電車の抽出を行います。



#YOLOv5におけるモデル作成

今回試す電車抽出モデルの作成は以前作成したものを使用します。詳細は以下の記事を参照してください。

https://qiita.com/hkwsdgea_ttt2/items/ccac4cec24a3799df8f3


#環境構築

まずはGoogle Colaboratoryを起動して、Yolov5の準備を行います。

```
!git clone https://github.com/ultralytics/yolov5
%cd yolov5/
!pip install -qr requirements.txt
```

これで準備は完了です。

#①学習済みモデルでサクッと試してみる

まずは実際にYouTube動画から物体検出を試してみます。
学習済みモデルを使用するので、誰でもすぐに再現することが可能です。

今回使用する動画は以下のものです。
（ただ電車の通過シーンを撮影した動画です）

https://youtu.be/igh_evKnkFk

この動画に対して物体検出をしていきます。
以下の通り実行します。

```
!python detect.py --source 'https://youtu.be/igh_evKnkFk'
```

しばらくすると結果が以下の場所に結果が保存されます。

`/content/yolov5/runs/detect/exp/`

YouTube動画から物体検出ができました。
学習済みモデルを使用しているので電車以外にも人間などを検出しています。
結果はYouTubeに動画としてアップしていますので、興味のある方は記事最後のリンクよりご確認ください。

#②自作モデルで試してみる

先程の動画に対して、以前作成したモデルで再度検証を行います。
学習モデルはあらかじめ以下の場所にアップしておきます。

`/content/yolov5/`

以下の通り実行します。
引数` weights `で、モデルを指定することができます。

```
!python detect.py --source 'https://youtu.be/igh_evKnkFk' --weights /content/yolov5/best.pt
```

しばらくすると以下の場所に結果が保存されます。

`/content/yolov5/runs/detect/exp2/`

実際にYouTube動画から電車の検出ができました。

#結果
①と②の抽出結果を以下の通り動画にまとめましたので、興味のある方はご覧下さい。


https://youtu.be/G0dTb6sqD5I


#まとめ
YOLOv5でYouTube動画から直接物体検出する手順をまとめました。

https://tt-tsukumochi.com/archives/tag/yolov5
Reactで画像を表示する方法

Reactで画像を表示する方法

今回、Reactで画像を表示させる際、3つの方法を試してみました。
①JSXのみに書き込む方法
②画像ファイル、JSXの両方に画像のパスを書き込む方法
③画像ファイルのパスをインポートし、コンポーネントに表示させる方法

結果
①失敗

```
import React from 'react';

export const ImageTest {
  return <img src="images/logo/PNG" alt="picture" />
}

```

②失敗

```
import React from 'react';
import pic from "images/logo.PNG"

export const ImageTest {
  return <img src="images/logo/PNG" alt="picture" />
}
```


③成功！！!

```
import React from 'react';
import pic from "images/logo.PNG"

export const ImageTest {
  return <img src={pic} alt="picture" />
}
```

結果は③の③画像ファイルのパスをインポートし、コンポーネントに表示させる方法でのみ成功しました！
僕のLinuxコマンド集

#LINUXコマンド集（やりたいこと→コマンド）
逐一更新予定

####ディレクトリ移動
#####cd
```
cd [ディレクトリ]
```

####ディレクトリの内容を表示
#####cd
```
ls
```

####ファイル・フォルダを移動
#####mv
```
mv [移動元ファイル] [移動先ファイル]
```

###ファイル・フォルダコピー
####cp
```
cp [移動元ファイル] [移動先ファイル]
```

####画面をリセット
#####clear
```
clear
```

####フォルダ作成
#####mkdir
```
mkdir [フォルダ名]
```

####フォルダ削除
#####rmdir
```
rmdir [フォルダ名]
```

####ファイル・フォルダ削除
#####rm
```
rm [ファイル名]
```

####現在のディレクトリを表示
#####pwd
```
pwd
```

####cat
#####ファイル内容を表示
```
cat ファイル名
```

####pushd
#####スタックに現在のディレクトリを積んで指定されたディレクトリに移動
```
pushd [移動先]
```

####popd
#####スタックからポップされたディレクトリに移動
```
popd
```

####検索対象に一致する列を取得
#####grep
```
grep [検索正規表現] [検索対象ファイル]
```

###ファイル編集
####vi
```
vi [ファイル名]
```

####コマンド定期実行設定
#####crontab
```
crontab [cron.conf]
  定義実行設定ファイル編集（「分 時 日 月 曜日 実行したいコマンド」をファイ
ルに）
crontab -e
[JS]mutableとimmutableでの配列操作について

## はじめに
自身のおさらいも含め、初学者の方に向けて、JavaScriptでの配列操作についてまとめていきたいと思います。

**[対象読者]** 
JavaScript / React初学者
**[記事のテーマ]** 
mutable / immutableとは？
フロントエンド開発における、非破壊的な配列操作について 

Reactでアプリケーションを作っていく際は、**副作用のない純粋な関数**を使用することが推奨されます。純粋な関数であるためには、以下の条件が必要です。

・最低１つの引数を持つ
・１つの値、もしくは１つの関数を返す
・引数を変化させてはいけない (**immutable**) ← 今回の記事のテーマ

## mutable, immutableとは？

JSの配列操作等のキーワードで検索をかけると、**mutable(破壊的なメソッド)**と**immutable(非破壊的なメソッド)**というキーワードを良く目にするかと思いますが、破壊的なメソッドとは、**対象となる元の配列の値を変えてしまうメソッド**のことを指します。

以下に破壊的なメソッドと非破壊的なメソッドの違いを示します。

#### 破壊的なメソッドは元の配列を直接操作(=破壊)する

```js:破壊的なメソッド
const nums = [1,2,3,4,5];
// 〜何らかの処理〜
nums.push(6);
// 〜何らかの処理〜
console.log(nums);
// 読み手は[1,2,3,4,5]を期待する
```

#### 非破壊的なメソッドは、元の配列のコピーに対して配列操作する

```js:非破壊的なメソッド
const nums = [1,2,3,4,5];
// 〜何らかの処理〜
const newNums = nums.concat(6);
// 〜何らかの処理〜

console.log(nums);
// [1,2,3,4,5] 読み手の期待通り

console.log(newNums)
// [1,2,3,4,5,6] こちらも読み手の期待通り
```

上記のように、破壊的なメソッドを使用して配列操作すると、不要な混乱を招くことになります。JavaScriptには、いくつか破壊的なメソッドが用意されており、以下メソッドを使う時は、注意が必要です。

```js:破壊的なメソッド
splice()
push()
pop()
shift()
unshift()
sort()
reverse()
fill()
copyWithin()
```

破壊的な配列操作をする際も、以下のように、元の配列を変えてしまわないようにスプレッド演算子でコピーを作って操作できないか検討してみましょう。以下は`sort()`を使用する際に、スプレッド演算子を使用して、破壊的な操作を回避した例です。

```js:スプレッド演算子を使用して非破壊的な操作を
const articleIds = [3,5,1,4,2];
const sortedArticleIds = [...articleIds].sort();
console.log(sortedArticleIds);
// [1,2,3,4,5]
```

## ユースケース別の実装例

### 1.配列を加工したい
ES6には複数の便利メソッドが用意されてますが、ここではよく利用されるであろう`map()`を紹介します。

まずは**破壊的**な操作

```js:破壊的な配列加工
let nums = [1, 2, 3];

for (var i = 0; i < nums.length; i++) {
  nums[i] = nums[i] * 2;
}

console.log(nums); // [ 2, 4, 6 ]
```

上記を**非破壊的**な操作に書き換えると以下になります。

```js:mapを使用して非破壊的な配列加工をする
const nums = [1, 2, 3];

const doubled = nums.map((num) => {
  return num * 2;
});

console.log(nums); // [ 1, 2, 3 ]
console.log(doubled); // [ 2, 4, 6 ]
```

### 2.要素を追加したい
`push()` `unshift()`

まずは、**破壊的**なメソッド。

```js:要素を追加したい：破壊的[push、unshift]
// push()
const nums_push = [1,2,3,4,5];
nums_push.push(6);
console.log(nums_push); // [1,2,3,4,5,6]

// unshift()
const nums_unshift = [1,2,3,4,5];
nums_unshift.unshift(0);
console.log(nums_unshift); // [0,1,2,3,4,5]
```

**非破壊的**な操作に書き直します。

```js:要素を追加したい：非破壊的
// popを非破壊的に書き直す
const nums = [1,2,3,4,5];
const newNums = [...nums, 6];
console.log(nums); // 1,2,3,4,5
console.log(newNume); // 1,2,3,4,5,6

// unshiftを非破壊的に書き直す
const nums = [1,2,3,4,5];
const newNums = [0, ...nums];
console.log(nums); // 1,2,3,4,5
console.log(newNume); // 0,1,2,3,4,5
```


### 3.要素を削除したい

`pop()` `shift()`


まずは、**破壊的**なメソッド。

```js:要素を追加したい：破壊的[pop、shift]
// pop()
const nums_pop = [1,2,3,4,5];
nums_pop();
console.log(nums_pop); // [1,2,3,4]

// shift()
const nums_shift = [1,2,3,4,5];
nums_unshift.shift();
console.log(nums_unshift); // [2,3,4,5]
```

**非破壊的**な操作に書き直します。

```js:要素を追加したい：非破壊的
const nums = [1,2,3,4,5];
const newNums = nums.filter(num => num !== 3)
console.log(newNums) // 1,2,4,5
```

## 最後に
以上、駆け足ではありましたが、mutable / immutableな配列操作の違いの解説でした。相互レビューをする際に、不要な破壊的操作を行っているコードは指摘されるポイントになるので、非破壊的な操作は意識しながら開発するのが良いと思います。何故immutableである方が望ましいのかは別記事でもう少し掘り下げようかと思います。
Gatsby で雑にマークダウン形式ブログを作る

「そうだ、自作ブログを作ろう。」
「どうせなら Qiita の記事をそのままブログに載せられるようにしたい。」
「もっというと、マークダウン形式のファイルをそのままブログに突っ込めるようにしたい。」
「でも面倒なことはしたくない。サーバーすら立てたくない」

こんなわがままでもブログが作れてしまいます。
そう、Gatsby ならね。

## 前準備

npm がインストールされている前提で進めます。
まずは Gatsby のプロジェクトを作成しましょう
[公式のチュートリアル](https://www.gatsbyjs.com/docs/tutorial/part-0/#gatsby-cli)を見つつ、コマンドをぽちぽち叩いていきましょう。

```terminal
npm install -g gatsby-cli
gatsby new {任意のプロジェクト名}
```

これで完了です。早い。
生成されたディレクトリに移動し、`npm run develop`を実行することで Gatsby のデフォルトページが閲覧できます。
TypeScript を使いたい場合は`src/pages`ディレクトリ中の`js`ファイルの拡張子を`tsx`に変えましょう。もともと TypeScript での開発も想定されているようで、これだけで機能します。すごい。

## マークダウンファイルのパース

下準備はできたので、早速本題に入りましょう。
マークダウンをパースするためには[gatsby-transformer-remark](https://www.gatsbyjs.com/plugins/gatsby-transformer-remark/)を使います。
`npm install gatsby-transformer-remark`でインストールし、`gatsby-config.js`に設定を加えましょう。

```javascript:gatsby-config.js
  plugins: [
    `gatsby-transformer-remark`,
  ],
```

プラグイン項目に記述を追加するだけで動作してくれます。

次に、実際に読み込みたいマークダウンファイルを追加します。
プロジェクトのルートディレクトリ配下ならどこでもいいのですが、今回は`src/markdown`配下に追加することとします。
適当に記述したマークダウンファイルを配置できたら、再び`gatsby-config.js`に記述を追加しましょう。

```javascript:gatsby-config.js
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `markdown`,
        path: `${__dirname}/src/markdown`,
      },
    },
  ]
```

こちらの設定はマークダウンファイルを Gatsby のエコシステムで認識できるようにするためのものです。

ここまで設定できたら、一度ローカル環境で起動し、`http://localhost:8000/___graphql`にアクセスしてみましょう。
Gatsby では GraphQL を採用しており、様々な情報を GraphQL 経由で取得することができます。
今回追加したマークダウンファイルについても同様で、上記の設定を追加することで GraphQL から取得できようになっています。
下記のクエリを投げてみましょう。

```graphql
query MyQuery {
  allMarkdownRemark {
    nodes {
      html
    }
  }
}
```

問題がなければ、先ほど追加したマークダウンファイルが HTML 形式で取得できているはずです。

## Gatsby への追加

では、上記で取得できた HTML を Gatsby に追加していきましょう。
先ほど行った修正により、マークダウンファイルを HTML 形式で GraphQL 経由で取得することができるようになっています。
Gatsby ではこの GraphQL を利用することができます。

```javascript:index.js
import * as React from "react"
import { graphql } from "gatsby"

import Layout from "../components/layout"

export const query = graphql`
  query MyQuery {
    allMarkdownRemark {
      nodes {
        id
        html
      }
    }
  }
`

const IndexPage = ({data}) => (
  <Layout>
    <div dangerouslySetInnerHTML={{__html: data.allMarkdownRemark.nodes[0].html}}></div>
  </Layout>
)

export default IndexPage
```

GraphQL で取得したデータは、引数に`data`を指定することで読み込むことができます。簡単ですね。
HTML 形式で取得しているので、あとはそのまま出力するように突っ込むだけです。

今回利用している`dangerouslySetInnerHTML`は React で提供されている属性です。
わざわざ`dangerously`としているのは XSS の危険性があるためです。詳しいことは[公式のドキュメント](https://ja.reactjs.org/docs/dom-elements.html)を参照してください。

あとは`npm run develop`などで結果を確認するだけです。
うまく設定できていれば、マークダウンファイルの中身がちゃんと表示されているはずです。

## おわりに

というわけで、Gatsby なら簡単にマークダウン形式のブログが作れるよ、という記事でした。
私は上記に加え Github Pages を利用することで、簡単な俺俺ブログにしています。
厳密には Qiita では改行コードがそのまま改行として扱われますが、今回作成したものではちゃんとスペースを2つ並べなければ改行されません。
とはいえあとはほぼそのままで動きますし、改行させるだけなら大した手間ではないでしょう。
Gatsby は便利だなぁ。
Reactでコンポーネントのプロパティーにイベントを渡すときの型を整理

Reactで定義されているイベントの型がわからずエラーメッセージを見ながら調整していくことになるので型を整理
サンプルコードは[material-ui](https://material-ui.com/)で定義されているコンポーネントを呼び出すと仮定しています。

## onChange
テキストフィールドなどのフォームで値の入力値を検知してアクションを実行する時に出てくる

(event: React.ChangeEvent<{}>) => void;

```typescript
interface Props {
  changeTextFieldHandler: (event: React.ChangeEvent<{}>) => void;
}

<TextField
  onChange={changeTextFieldHandler}
/>
```

## onSubmit
formのサブミット

(event: React.FormEvent<HTMLFormElement>) => void;

```typescript
interface Props {
  formSubmitAction: (event: React.FormEvent<HTMLFormElement>) => void;
}

<form onSubmit={formSubmitAction}>
```

## onMouseEnter / onMouseLeave

コンポーネントにマウスオーバーした時、マウスオーバーを解除したときのアクション

React.MouseEventHandler<HTMLButtonElement>;

```typescript
interface Props {
  onMouseEnterAction: React.MouseEventHandler<HTMLButtonElement>;
  onMouseLeaveAction: React.MouseEventHandler<HTMLButtonElement>;
}

<Button
  onMouseEnter={onMouseEnterAction}
  onMouseLeave={onMouseLeaveAction}
/>
```

## onClick
クリックイベント

(event: React.MouseEvent<HTMLButtonElement>) => void;

```typescript
interface Props {
  onClickHandler: (event: React.MouseEvent<HTMLButtonElement>) => void;
}

<Button onClick={onClickHandler}/>
BEM記法とは？Bootstrapとの併用は難しい・・・[初心者]

<h2>初めに</h2>
ポートフォリオ制作でBEM記法を取り入れていきたいと思いましたが...
Bootstrapを導入しているため、出来そうにないということに気づきました。
（BEM記法に触れていないレベルで、Bootstrapとの併用は高度すぎるように感じました）

色々調べて自分なりに理解したことをまとめていきます。

<h2>BEM記法って何？</h2>

CSSの命名規則。BEM記法にのっとり、記述すればココはあそこの記述ね！というのが自分以外の人が見ても、わかりやすい。
ただし、コードが長くなりがち。
```B:Block　```（ブロック）でっかい括り
```E:Element```（エレメント） でっかい括りの中の要素
```M:Modifier```（モディファイアー・修飾語という意味） 上記２つの変化球　とのこと。

この順番でクラス名を決めていくらしい。（block_element--modifireのように）

<h2>実際にどう記述するのか</h2>

```html
<button type="button" class="form__btn">送信</button>
<button type="button" class="form__btn form__btn--disabled">送信</button>
```
```html
<nav class="nav">
  <ul class="nav__list">
    <li class="nav__item"><a href="">menu</a></li>
  </ul>
</nav>
```

<h5>ここで気付く...</h5>
Bootstrapでは、"btn btn-primary"や、"nav navbar"とか書いて、ボタンやら、ナビゲーションバーを表示していました。もしここにBEM記法のクラス名を導入したら...
かなり長くゴチャゴチャになってしまうのでは....?????

<h2>BEM記法とBootstrapは併用できるのか？ </h2>

相性が悪いというのはやはりあるらしい。

<h4>考えたこと</h4>
<h6>Bootstrap使うところは、Bootstrapの命名規則に従って、Bootstap使わないところはBEM記法で書くのはどうだろうか？？</h6>

一つの Web システム内に2つの命名規則が混在してしまうことになる...ややこしい・・・

<h2>こうすれば綺麗に併用できるらしい</h2>

https://tech.recruit-mp.co.jp/front-end/architecture-bootstrap-bem/


正直、今のレベルで...ポートフォリオ制作期限もある中で...自身のポートフォリオでBEM記法とBootstapをうまく併用するのは無理だと感じました。

<h2>BEM記法について　参考にした記事</h2>
https://tech-dig.jp/bem-css-html/

https://qiita.com/Takuan_Oishii/items/0f0d2c5dc33a9b2d9cb1

https://flying-sheep.info/2020/04/04/%E4%BF%AE%E6%AD%A3%E3%80%81%E8%A6%81%E7%B4%A0%E8%BF%BD%E5%8A%A0%E3%81%AB%E5%BC%B7%E3%81%84%E3%82%B3%E3%83%BC%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0%E6%96%B9%E6%B3%95%E3%80%90bem%E8%A8%98%E6%B3%95/

以上です。
リストに格納された複数の narray をバイナリファイル（npz）にまとめて保存・読み込みする方法

# リストに格納された大量のパラメータをファイルに保存したい

機械学習のプログラムを書いていると、リストに格納した大量のモデルパラメータを保存・読み込みしたい場合があります。


## 書き込み

以下のとおり、リストを辞書に変換して ```numpy.savez``` でバイナリファイルに一気に書き込みます。

```python
import numpy as np
import random

M = 1000
N = 5

# サンプルデータを作る（N 次元ベクトルを M 個生成してリストに格納）
mu = [2 * np.random.rand(N, 1) - 1 for _ in range(M)]

# N 次元ベクトルを辞書に格納する
d = {'mu_' + str(i): mu[i] for i in range(M)}

# 保存する
np.savez('./mu_params', **d)  # dict のアンパックが必要
```

## 読み込み

以下のとおり、保存されたパラメータを ```numpy.load``` で辞書として読み込んだ後、リストに復元します。

```python
# 読み込む
d = np.load('./mu_params' + '.npz')  # 拡張子 .npz の指定が必要

# 辞書からリストを復元する
mu = [d['mu_' + str(i)] for i in range(M)]
```
Error: No valid credential sources found for AWS Provider. の対処法

#対象の読者

terraform 超初学者向けの記事となります。当たり前すぎることなのですが、自分はこれにつまずき、半日以上掛かりました。汗


#問題

terraform plan を実行したら以下のエラーが発生しました。

```
Error: No valid credential sources found for AWS Provider.
	Please see https://terraform.io/docs/providers/aws/index.html for more information on
	providing credentials for the AWS Provider
```

#原因

エラー文を読むと、どうやらAWSのクレデンシャル情報が見つからないということです。
じゃあ設定すればいいのかなと。


#解決策

AWSのアクセスキーとシークレットアクセスキーを設定すれば解決します。
環境変数の設定を行いました。

```
export AWS_ACCESS_KEY_ID=***（自分のAWSアクセスキー）
export AWS_SECRET_ACCESS_KEY=***（自分のAWSシークレットアクセスキー）
```

これで terraform plan が実行できました。
【個人開発】Railsエンジニアの技術選定

## はじめに
普段はRubyをメインにサーバーサイド開発をしています。
この度、個人開発で上場企業を比較できるサイトを個人で開発しました。

開発したサイト: [上場企業ランキング](https://company-ranking.net/)

開発に関する技術選定は今後の開発効率を左右する重要課題であるものの、個人開発の場合はを1人で行うためかなり悩みました。
今後個人開発を始める方にとって少しでも参考になることがあれば良いなと思い、本記事では私が技術選定について考えたことや採用した後の感想を記します。

## 基本的なスタンス

まず、今回の個人開発の目的ですが、サービスの成功を重視しています。そのため、新しい技術の習得はそれほど重要視はしておりません。

その上での基本的なスタンスです。

- 業務を通して使い慣れた技術を使う
- 新しい技術は開発効率に寄与する場合のみ採用する
- 管理コストの低いマネージドなサービスを利用する

以下、バックエンドとフロントエンドの両面から解説します。

## バックエンド

### WEBフレームワーク: Rails(APIモード)

- 業務で1年以上利用しているため採用
- ORM(Active Record)やテスティングライブラリ(RSpec)の使いやすさが素晴らしい

Go言語とEcho(かGin)を採用し、OpenAPI定義を生かして、OpenAPI Generatorでサーバー用のコードを自動生成する方法も検討しましましたが、それでも使い慣れたRailsよりは開発効率が落ちてしまうことを懸念し不採用としました。

### インフラ: Heroku

- 定額の利用料のため(現在は、月月$7のHobbyプランを利用中)、利用料金の見通しを立てやすい
- [ymlでコード化](https://devcenter.heroku.com/ja/articles/build-docker-images-heroku-yml)し開発環境に利用しているDockerfileをでイメージをビルドできるので、構築コストが低い

クラウドインフラ学習のためAWSやGCPも検討しましたが、利用料金過多になることを危惧し不採用となりました。

### DB: PostgreSQL

- Heroku との相性が良い

インフラにHerokuを利用することが決まっていたので、相性の良さからDBはPostgreSQL一択でした。

### CI/CD: GitHub Actions

- GitHubの秘匿情報管理の手間がなく安心

使い慣れたCircle CIを利用する場合も検討しましたが、今回の開発ではメリットがなさそうだったので不採用となりました。

## フロントエンド

### JSフレームワーク: Nuxt.js

- 業務でVue.jsを半年以上書いているため学習コストが低いため採用
- ディレクトリ構成の規約や、ルーティングの自動生成によって開発効率がかなり高い
- 設定周りの記述を`nuxt.config.js`だけで完結できて便利

Nuxt.jsほんと素晴らしいですね。今回の開発で初めて利用しましたが、すんなり導入できました。

### CSSフレームワーク: Bootstrap

- モバイルフレンドリーかつフラットデザイン
- ほぼstyleタグを書かなくて済むため、JavaScript、Vue.jsのコーディングに集中できる
- ドキュメントやカスタマイズの情報が多い
- 色をデフォルトから変更するだけで、Bootstrapぽさを軽減できる
- Tree Shakingを使わないとバンドルサイズが肥大化しすぎるので注意

他にもVuetifyやMaterial、TailwindCSSも検討したものの、マテリアルデザインな点やモバイルに対応していない点、情報量の少なさから不採用としました。

### ホスティング: Netlify

- GitHub と連携しデプロイを自動化できる
- ドキュメントやブログ等に情報が多い

Netlifyにホスティングを終えた後に、[Vercel が無料枠で利用できスループットがよい](https://www.suzu6.net/posts/268-blog-server/)ということを知ったので、Netlifyに課題感が出てきたらVercelへの移行を検討します。

## 参考

- [Zenn個人開発の限界に挑んだ話 - devsumi 2021 | YouTube](https://www.youtube.com/watch?v=DTpGfpLybr0)
- [【個人開発】マンガを楽しむWebアプリを支える技術の共有：インフラアーキテクチャおよび技術選定](https://zenn.dev/foxtail88/articles/7ea20168cc597d)

## まとめ

今回の個人開発では、使い慣れた技術(Rails や Heroku)を使いつつも、初めての技術(Nuxt.js や  GitHub Actions)を利用することで、開発効率と技術学習を良いバランスで実現できています。

引き続き、[開発したサイト](https://company-ranking.net/)をグロースしていきたいです。
【Rails】ストロングパラメーターってなに？？？


#対象者

* ストロングパラメーターに関して知りたい方
* ストロングパラメーターの入力方法を知りたい方


#目的

* ストロングパラメーターのメソッド１つ１つの意味を考えながら使うこと

#実際の手順と実例
###1.ストロングパラメーターって？？

結論から言うと、ストロングパラメーターとは、データ送信時に不正なリクエストによって予期しない値に変更されてしまう脆弱性（マスアサインメント脆弱性）を防ぐ仕組みです。

私個人的に不正アクセスを防ぐ仕組みくらいに考えています。


###2.書き方

#####1.基本構文

````
private
def user_params
  params.require(:キー(モデル名)).permit(:カラム名１,：カラム名２,・・・).marge(カラム名: 入力データ)
end
````

以下は例になります

`````user_controller.rb

  def edit
   @user = User.find(params[:id])
  end

  def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      redirect_to user_path(@user), notice: "You have updated user successfully."
    else
      render "edit"
    end
  end

  private

  def user_params
    params.require(:user).permit(:name, :introduction, :profile_image)
  end



````

#####2.private

privateは一種の境界線のようなもので、
「ここから下はControllerの中でしか呼び出せません」という意味を持ちます。

#####3.requireメソッド

引数にしたいキーを指定する場所
例では,(:user)に当たります。

キーの値に対するデータを抽出したい場合上記例のように書きます。

#####4.permitメソッド

許可された値のみを取得することができます。
permitに記載のないカラムは、保存や更新が実行されません。


#####5.ストロングパラメーターの呼び出し

```user_controller.rb
 def update
    @user = User.find(params[:id])
    if @user.update(user_params)
      redirect_to user_path(@user), notice: "You have updated user successfully."
    else
      render "edit"
    end
  end

````

上記例のUpdateアクション抜粋です。
if文の（user_params）の部分でストロングパラメーターを呼び出しています。この他にもcreate,new等でこのように記述する場合が多いです。


#参照

>[Rails4 | 新規・変更機能 | マスアサインメント機能と脆弱性とStrong Parameters](https://qiita.com/tbpgr/items/63028f5e19a2d1617e40)


####投稿者コメント

先日ストロングパラメーターに記載がないことが理由で作業が前に進まなかったので、このように記事にして改めて認識をまとめてみることにしました。

構文こぴぺして使っていただけると嬉しいです。

####My Profile
プログラミング学習歴３ヶ月目のアカウントです！
プログラミングスクールで学んだ内容や自分が躓いた箇所等のアウトプットの為に発信しています。
また、プログラミング初学者の方にわかりやすく、簡潔にまとめて情報共有できればと考えています。
もし、投稿した記事の中に誤り等ございましたら、コメント欄でご教授いただけると幸いです。
【SAP-C01試験対策】プレイスメントグループとインスタンスタイプ

# はじめに
AWSのプレイスメントグループを勉強するために以下のドキュメントおよび教材を参考にしたので内容をまとめます。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/placement-groups.html

https://www.udemy.com/course/aws-associate/



# 背景
本記事はAWSソリューションアーキテクトプロフェッショナルに合格するために、[Udemyの模擬試験](https://www.udemy.com/course/aws-53225)を解いて分からなかった部分を勉強してまとめるものです。

試験対策用のため、分からない知識を補足したり試験で問われなさそうなところを省略したりしながらまとめています。
なるべくわかりやすい記載を心がけますが、最終目的は自己学習用であるということをご容赦ください。

# プレイスメントグループとは
複数インスタンスを論理的にグループ化して、パフォーマンス性能を向上させたり、耐障害性を高める機能。


## クラスタープレイスメントグループ

低いネットワークレイテンシー、高いネットワークスループットが実現できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951272/d619cb47-7394-1698-89e4-2b013fd2c88d.png)

## パーティションプレイスメントグループ

アプリケーションに関連するハードウェア障害の頻度を軽減できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951272/91b4aaea-1e15-5a31-c9c6-726c01136267.png)


## スプレッドプレイスメントグループ

少数の重要なインスタンスが互いに分離して保持される必要があるアプリケーションに推奨される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/951272/876a84fb-cce2-e8b4-33cb-cfcbb8ab4c09.png)

# プレイスメントグループに適用できるインスタンスタイプ

バーストパフォーマンスインスタンス (T2 など) と Mac1 インスタンスを除く現世代のインスタンス。

| タイプ | 種類 | 説明 |
| :--- | :--- | :--- |
| T | 汎用 | バースト可能 |
| M |汎用 | コンピューティング、メモリ、ネットワークの各リソースがバランスよく提供される |
| C | コンピューティング最適化 | 低いコンピューティングあたりの価格率でコスト効率性が高い優れたパフォーマンス |
| R | メモリ最適化 | メモリ負荷の高いアプリケーション向けに最適化 |
| X | メモリ最適化 | 大規模向け (RAM 1 GiB あたりの価格が最も低い) |
| P | 高速コンピューティング | 汎用 GPU コンピューティングアプリケーション用に設計 |
| G | 高速コンピューティング | グラフィック集約型アプリケーション用に最適化 |
| F | 高速コンピューティング | FPGA(集積回路の一種)によるカスタマイズ可能なハードウェアアクセラレーション |
| I | ストレージ最適化 | 低レイテンシー、極めて高いランダム I/O パフォーマンス、優れたシーケンシャルリードスループットのために最適化 |
| D | ストレージ最適化 | ディスクスループットパフォーマンスあたりの価格が EC2 で最小 |
| H | ストレージ最適化 | 高ディスクスループット、およびバランスの取れたコンピューティングとメモリを実現 |


* 汎用 : バランスの取れたコンピューティング、メモリ、ネットワークのリソースを提供
* コンピューティング最適化 : 高パフォーマンスプロセッサの恩恵を受けるアプリケーションに最適
* メモリ最適化 : メモリ内の大きいデータセットを処理するワークロードに対して高速なパフォーマンスを実現
* 高速コンピューティング : 浮動小数点計算、グラフィックス処理、データパターン照合を効率的に実行
* ストレージ最適化 : 数万 IOPS もの低レイテンシーなランダム I/O オペレーションに最適化


# 設定方法
先にプレイスメントグループを構成した上で、その中でインスタンスタイプとインスタンス数を決定する。
DynamoDBのキー検索に関して

##記事作成にあたって
最近DynamoDBを触るようになってRDBと設計思想が違うから、いまいち操作しにくい。それでも騙し騙し実装をしていたが、あれ？これってプライマリーキー検索以外の場合ってできないの？LSIやGSIってのを定義すれば検索できるけど、なんで検索キーを事前に登録しておかないといけないの？って感じたので、一旦立ち止まって、整理することにしました。

##プライマリーキー
DynamoDBではプライマリーキーの指定方法は2通り。
1. パーティションキー
2. パーティションキー＋ソートキー

###パーティションキーって何？
DynamoDBは分散型DB。RDBのようにデータを一箇所に集約するのではなく、複数の場所にデータを格納する。そのため、どの場所にデータを格納するのかを決める必要がある。で、配置場所を決定するのにパーティションキーを使う。RDBを触り続けた人にはなんだこれってなるかも心ないですけど、分散時に利用するキーなのねってくらいの理解でいいと思います。
![スクリーンショット 2021-07-30 17.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/3c92c3e7-809a-e68d-f7f3-9b103a8e7436.png)

##セカンダリインデックス
インデックスって聞くと、データ検索を効率的に検索するための目次のことね。って理解だと痛い目見ます。実際、この理解で結構苦しめられました。。。:cry:
RDBだとWhere句に検索条件を指定すれば、欲しいデータを絞りこむ事ができた。だけどDynamoDBだと、予め検索キーをしておかないと絞り込み検索できないのです。何もしないと、プライマリー検索しかできない。なので、セカンダリインデックスを作っておく必要があります。セカンダリインデックスって聞くと難しく聞こえるけど、イメージは新しいTBLを作ってそこから検索してね。って感じ。

###LSI(ローカルセカンダリインデックス)
ローカルセカンダリインデックスは公式の見解では下記の通り。早い話がパーティションキーはそのままで、ソートキーで新しく検索するイメージ。
>ローカルセカンダリインデックスは特定のパーティションキー値の代替ソートキーを維持します。またローカルセカンダリインデックスには、ベーステーブルの一部またはすべての属性のコピーが含まれます。テーブルを作成する際に、ローカルセカンダリインデックスに射影する属性を指定します。ローカルセカンダリインデックスのデータは、ベーステーブルと同じパーティションキーと、異なるソートキーで構成されます。これにより、この異なるディメンションにわたってデータ項目に効率的にアクセスできます。クエリまたはスキャンの柔軟性を向上させるために、テーブルごとに最大 5 つのローカルセカンダリインデックスを作成できます。

###LSIの具体例
ThreadテーブルからLastPostIndexを作って検索する。その際に、元々パーティションキーであったForumNameカラムはそのままで、ソートキーのLastPostDateTimeは新たに定義しなおす。
![スクリーンショット 2021-07-30 18.08.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/e014d1b5-b331-b476-9fb6-bb59b0079603.png)

![スクリーンショット 2021-07-30 18.08.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/397e6f40-1645-ba21-4aa4-2c653d0491f6.png)

###GSI(グローバルセカンダリインデックス)
グローバルセカンダリインデックスは公式の見解では下記の通り。早い話が、パーティションキーもソートキーも新たに定義し直して、新規のテーブルを作るイメージ。
>すべてのグローバルセカンダリインデックスには、パーティションキーが必要で、オプションのソートキーを指定できます。インデックスキースキーマは、テーブルスキーマとは異なるものにすることができます。シンプルなプライマリキー (パーティションキー) を持つテーブルを作成し、複合プライマリキー (パーティションキーおよびソートキー) を使用してグローバルセカンダリインデックスを作成できます。またはその逆もあります。インデックスキー属性は、ベーステーブルからの任意の最上位 String、Number、または Binary 属性で構成できます。その他のスカラー型、ドキュメント型、およびセット型は許可されません。

###GSIの具体例
GameScoresテーブルからGameTitleIndexテーブルを作成する。その際にパーティションキーもソートキーも新しく作る必要がある。

![スクリーンショット 2021-07-30 18.15.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/898533e2-9e2e-47e4-8926-f928b2bd5891.png)
![スクリーンショット 2021-07-30 18.16.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/2f317ab4-4f8f-619d-d91a-2e3059b5e7fd.png)
⚠️【Safari】a要素やbutton要素などにタブフォーカスが当たらない

- テキストフィールドにはフォーカスできる
- `tabindex`属性を設定してもフォーカスできる要素とできない要素がある

**結論：** Safariの設定が原因

## 解決策

Safariのデフォルト設定では、`Tab`キーでフォーカスがあたる要素が限定されています。

- テキストフィールド
- ポップアップメニュー
- `tabindex`属性が指定されている「もともとがフォーカス可能ではない要素」（**要出典**）

この状態で、上記以外のフォーカス可能な要素にフォーカスするためには`Option`キーを同時に押下する必要があります。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142709/d318541e-c8e1-1e63-cf7e-cb35fde26fbb.png)

以下の手順で設定を変更すると、他のモダンブラウザ同様`Tab`キーのみで、すべてのフォーカス可能な要素にフォーカスすることができます。

1. Safariを起動
2. メニューバーのアプリケーションメニュー、「Safari」から「環境設定」を開く
3. 「詳細」タブを選択
4. アクセシビリティの項目、「Tabキーを押したときにWebページ上の各項目を強調表示」にチェックを入れる

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142709/4f37ba10-0c85-f49d-b1c6-f9ccc54f2e75.png)

この状態で`Option`キー＋`Tab`キーを操作すると、テキストフィールドやポップアップメニューなどのみにフォーカスを当たるようになります。
AtCoder Beginner Contest 212 参戦記

# AtCoder Beginner Contest 212 参戦記

## [ABC212A - Alloy](https://atcoder.jp/contests/abc212/tasks/abc212_a)

2分半で突破. 書くだけ.

```python
A, B = map(int, input().split())

if A > 0 and B == 0:
    print('Gold')
elif A == 0 and B > 0:
    print('Silver')
elif A > 0 and B > 0:
    print('Alloy')
```

## [ABC212B - Weak Password](https://atcoder.jp/contests/abc212/tasks/abc212_b)

4分で突破. 書くだけ.

```python
X = list(map(int, input()))

if X.count(X[0]) == 4 or all(X[i + 1] == (X[i] + 1) % 10 for i in range(3)):
    print('Weak')
else:
    print('Strong')
```

## [ABC212C - Min Difference](https://atcoder.jp/contests/abc212/tasks/abc212_c)

12分半で突破. 単純に2重ループの *O*(*NM*) で駄目なら、にぶたんで *O*((*N+M*)log<i>M</i>) にすることを思いつく. A<sub>i</sub> 以下の B のインデックスを見つけて、その前後だけ差分を取ればいい.

```python
from bisect import bisect_left

N, M = map(int, input().split())
A = list(map(int, input().split()))
B = list(map(int, input().split()))

B.sort()

result = 10 ** 9
for a in A:
    i = bisect_left(B, a)
    if i != 0:
        result = min(result, abs(a - B[i - 1]))
    if i != M:
        result = min(result, abs(a - B[i]))
print(result)
```

A も小さい順に並べてしまえば、にぶたんを使わなくても順次 A<sub>i</sub> 以下の B のインデックスを見つけることができる.

```python
N, M = map(int, input().split())
A = list(map(int, input().split()))
B = list(map(int, input().split()))

B.sort()

result = 10 ** 9
i = 0
for a in sorted(A):
    while i != M and B[i] < a:
        i += 1
    if i != 0:
        result = min(result, abs(a - B[i - 1]))
    if i != M:
        result = min(result, abs(a - B[i]))
print(result)
```

## [ABC212D - Querying Multiset](https://atcoder.jp/contests/abc212/tasks/abc212_d)

6分で突破. 操作2をバカ正直にやると *O*(*Q*<sup>2</sup>) になって TLE. 袋の中の数字と袋の外の補正値を足すと本当の数値になるという持ち方にすると操作2が *O*(1) になる. 操作3をバカ正直にやるとやっぱり *O*(*Q*<sup>2</sup>) になって TLE するので、優先度付きキューか平衡二分探索木の出番です. Python には組み込みの平衡二分探索木がないので heapq になるいつもの奴.

```python
from sys import stdin
from heapq import heappop, heappush

readline = stdin.readline

Q = int(readline())
t = 0
result = []
bag = []
for _ in range(Q):
    query = readline()
    if query[0] == '1':
        _, X = map(int, query.split())
        heappush(bag, X - t)
    elif query[0] == '2':
        _, X = map(int, query.split())
        t += X
    elif query[0] == '3':
        result.append(heappop(bag) + t)
print(*result, sep='\n')
```
2021/07/30開催 Connpassイベントランキング

# 申込数TOP5

|順位|イベント名|グループ|申込数|定員|
|:---:|:---|:---|:---:|:---:|
|:one:|[LayerX福島氏に学ぶ、 BtoB/ DX事業の作り方](https://theseed.connpass.com/event/219990/)|[シードベンチャーキャピタル「THE SEED」](https://theseed.connpass.com/)|380|405|
|:two:|[Engineer Career Study #3 「成長を実感し続けられるキャリアのあゆみ方」](https://forkwell.connpass.com/event/218735/)|[Forkwell](https://forkwell.connpass.com/)|356||
|:three:|[【オンライン開催】銀座Rails#35@リンクアンドモチベーション](https://ginza-rails.connpass.com/event/216491/)|[銀座Rails](https://ginza-rails.connpass.com/)|274|450|
|:four:|[Amplify Boost Up #01](https://aws-amplify-jp.connpass.com/event/217715/)|[AWS Front-end Community](https://aws-amplify-jp.connpass.com/)|245||
|:five:|[7/30-31 Open Source Conference 2021 Online/Kyoto](https://ospn.connpass.com/event/214013/)|[OSPN(Open Source People Network)](https://ospn.connpass.com/)|238||
【Ktor】CORSの設定をしてみた

## 概要
今回はKtorでCORSの設定をしてみましたので、メモ書きとして残しておきます。なお、KtorでのCORSの設定については[こちらのドキュメント](https://jp.ktor.work/servers/features/cors.html)に、設定の概要などが記載されています。

## 設定項目
取り急ぎ、APIサーバにおいて最低限必要と思われる、以下の項目を今回設定してみました。

* method：`Get`、`Post`、`Put`、`Delete`、`Options`を設定します。
* host：APIのリクエストを行うフロントエンドのURLを設定します。なお、今回はURLの`authority`と`schema`を設定してみました。
* allowCredentials：`true`を設定します。
* allowNonSimpleContentTypes：この項目はKtor独自の項目のようで、json形式のリクエストを受け取りたい場合は`true`を設定します。[こちら](https://fetch.spec.whatwg.org/#simple-header)に記載されている、simple content type以外のリクエストを受け取りたい場合、trueを設定する必要があるようです。

## 実装サンプル
フロントエンドのURLを`application.conf`に定義します。

```conf:application.conf
serverInfo {
    frontendUrl = "http://localhost:3000"
}
```

Ktorの`Application.module`にCORSの設定を行います。

```kotlin:Application.kt
fun Application.module() {
    val frontEndUri = URI(environment.config.property("serverInfo.frontendUrl").getString())
    install(CORS) {
        method(HttpMethod.Get)
        method(HttpMethod.Post)
        method(HttpMethod.Put)
        method(HttpMethod.Delete)
        method(HttpMethod.Options)
        host(frontEndUri.authority, schemes = listOf(frontEndUri.scheme))
        allowCredentials = true
        allowNonSimpleContentTypes = true
    }
}
```
[10] PowerShell実践例 ... GUIアプリケーションを画面上の指定位置に移動させる



|本シリーズのトップページ|
|:--|
|https://qiita.com/robozushi10/items/0b0605257ad39bc22895|


# はじめに

PowerShell 6系 で GUIアプリを画面上の特定位置に移動させる処理をした.

このときに下記コードを利用させてもらったので、使用方法をご紹介する.　

## 利用させてもらったコード置き場

https://superuser.com/posts/1324170/revisions
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/aeead293-67a2-cb30-6010-e440da632b84.png)


# 手順

## 1. GUIアプリを特定位置に移動させるコードを配置する

[上述の URL のコード](https://superuser.com/posts/1324170/revisions)を `josefz.ps1` として配置する

**josefz.ps1**

```powershell
    [OutputType('System.Automation.WindowInfo')]
    [cmdletbinding()]
    Param (
        [parameter(ValueFromPipelineByPropertyName=$True)]
        $ProcessName,
        [int]$X,
        [int]$Y,
        [int]$Width,
        [int]$Height,
        [switch]$Passthru
    )
    Begin {
以下略
```

## 2. GUIアプリを最前面に表示させる toactive.ps1 を配置する

[[07] PowerShell実践例 ... GUIアプリの消極的自動操作](https://qiita.com/robozushi10/items/19c55f6eee158663ca4a#1-対象の-gui-アプリabcを最前面表示する) に記したコードである.

**toactive.ps1**

```powershell
Param (
  [parameter(ValueFromPipelineByPropertyName=$True)]
  $ProcessName
)

Add-Type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms

$P = (Get-Process -Name $ProcessName | Get-Unique)

# 選択したアプリケーションをアクティブにする
[Microsoft.VisualBasic.Interaction]::AppActivate($P.Id)

```


## 3. 上記 1, 2 のコードを使ってアプリの位置を変える

今回は次のように移動させる.

|項目|値|
|:--|:--|
|移動先|画面左上. つまり (0, 0) の位置である|
|移動させたいアプリ名| ABC |
|移動後の画面サイズ(幅)|400|
|移動後の画面サイズ(幅)|500|


次のコード「**Move-X0Y0W400H500.ps1**」を作成する.

**Move-X0Y0W400H500.ps1** 

```powershell
Add-Type -AssemblyName Microsoft.VisualBasic
Add-Type -AssemblyName System.Windows.Forms

# プロセス名「ABC」のアプリを最前面にする
.\toactive.ps1 -ProcessName 'ABC'

# プロセス名「ABC」のアプリを (0, 0) に移動させて且つ画面サイズを 幅400, 高500 にする
.\josefz.ps1 -ProcessName 'ABC' -X 0 -Y 0 -Width 400 -Height 500 -Passthru

# 移動後もアクティブにしたいので、プロセス名「ABC」のアプリを最前面にする
.\toactive.ps1 -ProcessName 'ABC'
```

## 4. Move-X0Y0W400H500.ps1 を実行する

```powershell
.\Move-X0Y0W400H500.ps1
```

　

JosefZ さんに感謝.

以上.

　

# 参考にしたサイト

|URL|
|:--|
|https://superuser.com/posts/1324170/revisions|
[09] PowerShell実践例 ... プロセス情報から実行ファイル置き場を特定する



|本シリーズのトップページ|
|:--|
|https://qiita.com/robozushi10/items/0b0605257ad39bc22895|


# はじめに

Windows に GUI アプリ「ABC.exe」がある とした場合、
この「ABC.exe」の置き場を特定する処理について記す.

実際の運用では、以下を検査するというものであった.
・「**製品版の実行ファイルが使用されているか？**」(== 誤ってデバッグ版を使っていないか) 

参考にした情報は下記ページであり、本項ではこの中で挙げられているコードを補足する.

|URL|
|:--|
|[it-swarm-ja.com ファイルをロックしているアプリケーションをチェックするためのPowerShellスクリプト？](https://www.it-swarm-ja.com/ja/powershell/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%83%AD%E3%83%83%E3%82%AF%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AEpowershell%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%EF%BC%9F/957596419/)|
|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/a5cd6ab1-53ff-fefd-d9e6-8dac550852b9.png)
|
　
　

# 補足

Linux であれば、次のコマンドで実行ファイル置き場を特定することができる.

・`realpath /proc/<プロセス番号>/exe`

　

# 環境

```
Windows 10 Pro
PowerShell バージョン 6系
```


# 処理概要

次の 1〜5 の処理をする

```
1. 期待する実行ファイル置き場を定義する

2. 上記 1 のプロセス名を定義する

3. Get-Process (== psコマンド)を実行して、2 の名称を持つ「プロセス情報」を抽出する

4. 「プロセス情報」のメンバ Modules にアクセスして実行ファイルパスを得る

5. 上記 4 で得たパスが 上記 1 と一致するか判定する
```

　

# 詳細

```powershell
# 期待する実行ファイル置き場 (🛑上記 1 に該当する)
$EXP = "C:\work\product\ABC.exe"
# プロセス名  (🛑上記 2 に該当する)
$N = "ABC"
# エラー有無. 初期値は "エラーあり". ($True, $False) = (エラーあり, なし)
$ERR = $True 

# 「ps -ef |grep "ABC"」に相当する (🛑上記 3 に該当する)
Get-Process -Name $N | `
  # 1プロセスずつ精査する
  foreach {
    # 「ある 1つのプロセス情報」を $processVar に格納する
    $processVar = $_ 
    # Modules メンバには実行ファイルの情報が格納されている. (🛑上記 4 に該当する)
    $_.Modules | `
    foreach {
      # 実行ファイルのパスが「期待する実行ファイル置き場」と一致するか？ (🛑上記 5 に該当する)
      if($_.FileName -eq $EXP)
      {
        # 実行ファイルのパスが「期待する実行ファイル置き場」と一致したので "エラーなし" にする
        $processVar.Name + " PID:" + $processVar.id
        # 「エラーなし」にする
        $ERR = $False
      }
    }
  }

# 「期待する実行ファイル置き場」で実行されていたか？
if($ERR -eq $True)
{
  # エラーあり. 「期待する実行ファイル置き場」では実行されてなかった
}
```

　

# 参考にしたサイト

| URL |
|:--|
|[it-swarm-ja.com ファイルをロックしているアプリケーションをチェックするためのPowerShellスクリプト？](https://www.it-swarm-ja.com/ja/powershell/%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%83%AD%E3%83%83%E3%82%AF%E3%81%97%E3%81%A6%E3%81%84%E3%82%8B%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AEpowershell%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%EF%BC%9F/957596419/)|
|https://docs.microsoft.com/ja-jp/dotnet/api/system.diagnostics.process.modules?view=net-5.0|
～ ダイクストラ法 ～ チートシート

#目次
[ダイクストラ法とは](#ダイクストラ法とは)
**[実装](#実装)**

もしかして：[ワーシャルフロイド法](https://qiita.com/ysys_Ba/items/13f779b89e52624981df)

#はじめに

チートシートの扱いついては[ここ](https://qiita.com/ysys_Ba/items/d27282b888abbd1f43e7#%E3%83%81%E3%83%BC%E3%83%88%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)を読んでください

#ダイクストラ法とは

[わかりやすいサイト](http://www.deqnotes.net/acmicpc/dijkstra/)

指定した頂点を始点とした場合に、最も到達にかかるコストが低い頂点から順に確定させていくことで、各頂点に到達するのに必要な最低コストを求めるアルゴリズム
始点となる頂点が１つに決まっている場合に有効
計算量が大きいので、始点が全頂点の場合は[ワーシャルフロイド法](https://qiita.com/ysys_Ba/items/13f779b89e52624981df)を使う
**負のコストがある場合には使えないので注意**

#実装

[問題（Atcoderだと簡単な問題がなかったので、AIZU ONLINE JUDGEより）](https://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_A&lang=ja)

```python:Dijkstra's_algorithm.py
import heapq

N,M,S = map(int,input().split()) #頂点の数、辺の数、スタートとなる頂点の番号

root = [] #辺に関する情報を格納する配列
start = [[] for i in range(N+1)] #辺を始点ごとに分類する配列
for i in range(M):
  A,B,C = map(int,input().split()) #辺の始点、辺の終点、移動に必要なコスト
  root.append([A,B,C])
  start[A].append(i)
  
check = [] #最小コストの候補を格納する配列
heapq.heapify(check)
heapq.heappush(check, [0,S])
         
ans = [-1]*(N+1) #各頂点の最小コストを格納する配列
while True:
  cost,now = heapq.heappop(check)
  if ans[now] == -1:
    ans[now] = cost
    for i in range(len(start[now])):
      heapq.heappush(check, [cost+root[start[now][i]][2], root[start[now][i]][1]])
  if check == []:
    break

for i in range(N):
#for i in range(1,N+1): #頂点の番号が1,2,3...と振られている場合（Atcoder用）
  if ans[i] != -1:
    print(ans[i])
  else:
    print("INF")
```

**Atcoderと異なりインデックスが0始まりなので注意**（Pythonと同じだからこっちの方がありがたいけど）
高速化のために[優先度付きキュー](https://qiita.com/ysys_Ba/items/90476af66df4ba954f06)を利用
ライブラリ`shortest_path()`を使うという手もあるけど、Atcoderだとなんかめんどくさいらしい
Vim patchダイジェスト [2021/06]

[Vim](http://www.vim.org/)のリリースされた[patch](https://github.com/vim/vim/commits/master)の説明です。
([8.2.2919](https://github.com/vim/vim/commit/6a43b37b760347b9a1bedf12e41b458000922969) ～ [8.2.3081](https://github.com/vim/vim/commit/11a632d60bde616feb298d180108819ebb1d04a0))
**新機能、大幅な仕様変更には、:four_leaf_clover:が付いています。**
Vim9 scriptの実装/仕様変更/不具合修正も頻繁におこなわれています。

* [runtimeファイル更新](https://github.com/vim/vim/commit/4d8f476176eadfc745bcb8e143460029048f858d): [Todo](https://github.com/vim/vim/commit/4d8f476176eadfc745bcb8e143460029048f858d#diff-fb7eed53e3f2993f9d82c748206eaca82fd1d054a417c6de477bb54373d85643)更新。helpファイル更新。他。
* [8.2.3040](https://github.com/vim/vim/commit/18d46587b985923ef4b90b19a0cf37a094607fec): :four_leaf_clover:`test_gui_drop_files()`を追加しました。テスト用です。
* [8.2.3033](https://github.com/vim/vim/commit/419a40ac9657e39646b2e0f3f71d7736b0c459d1): `:global`の区切り文字に英字を使用してもエラーにならない件を修正しました。
* [8.2.3028](https://github.com/vim/vim/commit/f1e7449d567c630601aa0cec6c663b791785a668): :four_leaf_clover:`test_gui_mouse_event()`を追加しました。テスト用です。(関連patch: [8.2.3036](https://github.com/vim/vim/commit/7237cab8f1d1a4391372cafdb57f2d97f3b32d05))
* [runtimeファイル更新](https://github.com/vim/vim/commit/2346a6378483c9871016f9fc821ec5cbea638f13): [Todo](https://github.com/vim/vim/commit/2346a6378483c9871016f9fc821ec5cbea638f13#diff-fb7eed53e3f2993f9d82c748206eaca82fd1d054a417c6de477bb54373d85643)更新。helpファイル更新。他。
* [8.2.2982](https://github.com/vim/vim/commit/742357718000927d652b1a98d313a3950571c8ec): :four_leaf_clover:Vim9: 将来の追加のために`:abstract`, `:endinterface`, `:interface`, `:static`を予約しました。また、`this`を予約語にしました。(関連patch: [8.2.2956](https://github.com/vim/vim/commit/f05d2fc539c389c3b8142d9fb06fb0443de14902))
* [8.2.2971](https://github.com/vim/vim/commit/544a38e44db0f25ec4fa7a2a4666cf28a2336f33): :four_leaf_clover:ノーマルコマンド `zy` を追加しました。`y`と同じですが、矩形ビジュアルモードの場合、各行の末尾のスペース群をヤンクしません。(関連patch: [8.2.3072](https://github.com/vim/vim/commit/7d7bcc6ba01454c1cbb1dcbf5f11c3a4051535d6))
* [8.2.2957](https://github.com/vim/vim/commit/3a7503c34c65ed15cc08deb5b54aaf2ea51525b4): :four_leaf_clover:`getcharstr()`を追加しました。結果の数値を文字列に変換する以外は`getchar()`と同じです。
* [8.2.2956](https://github.com/vim/vim/commit/f05d2fc539c389c3b8142d9fb06fb0443de14902): :four_leaf_clover:Vim9: 将来の追加のために`:class`, `:endclass`, `:enum`, `:endenum`, `:type`を予約しました。(関連patch: [8.2.2982](https://github.com/vim/vim/commit/742357718000927d652b1a98d313a3950571c8ec))
* [8.2.2940](https://github.com/vim/vim/commit/4f2417ffeedbb687a59a36547e8143724a86bb31): :four_leaf_clover:Windows: gvimのウィンドウをマウスでリサイズするときに、ツールチップでテキストサイズを表示するようにしました。

---
#### 凡例

|表記|意味|
|:------|:------|
|:four_leaf_clover:|新機能、大幅な仕様変更|
|:alien:|Vim開発者向けの追加、変更|
|`'hoge'`|オプション (`:h options`参照)|
|`:hoge`|Exコマンド (`:h :index`参照)|
|`hoge()`|組み込み関数 (`:h functions`参照)|
|`v:hoge`|Vim定義済変数 (`:h v:`参照)|
|`+hoge`|feature (`:h +feature-list`参照)|

---
#### 方針
[こちら](http://qiita.com/h_east/items/23cd0d10932505072e6b#%E6%96%B9%E9%87%9D)を参照。
mac pyenv 環境でtkinterがnomodulenamedになる時の対処法

macでtkinterをinstallしても起動せず、いろいろ格闘した末に起動できたので、どうやって解決したかをまとめてみた。

#使用していた環境・バージョン
・macos mojave (10.14.6)
・pyenv 2.0.4
・tcl-tk 8.6.11 (bottled)[keg-only]
・python3.9.6


#結論
`$ brew install tcl-tk`,
`$ brew install python`した後に
`$ brew install python-tk`を入力

#症状
python3.9.6を使用。tkinteを使うために以下のようなコマンドを打つとエラーが発生。tkinterはpythonの標準ライブラリのはずなのになぜか起動しない。原因はtcl-tkがパソコンに入っていないことらしいが、最後までイマイチよくわからなかった。

```
$ python3 main.py
(中略)
Traceback (most recent call last):
(中略)
    import _tkinter # If this fails your Python may not be configured for Tk
ImportError: No module named _tkinter
```

#参考にした記事

こちら質問の一番上の回答より

https://stackoverflow.com/questions/36760839/why-my-python-installed-via-home-brew-not-include-tkinter

#補足
pythonをアンインストールしてtcl-tkをダウンロード、その後pythonを再ダウンロードと言う記事は山ほどあったが、どれもうまくいかなかった。pathをいじるのもなかなかうまくいかず、結局このコマンド一つで解決できたように思える。
[Delphi] Expression Engine

# Expression Engine
まずはこれを見て！
![calc.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12977/75be4a41-6634-d333-120a-ede1bb4db079.gif)
Bindings の仕組みでなんと式を評価できる。
そう Delphi ならね。

コードは

```pascal
// uses には System.Bindings.Helper を追加
procedure TfrmCalculator.Calc;
begin
  var B := TBindings.CreateExpression([], edtExpression.Text);
  try
    edtResult.Text := B.Evaluate.GetValue.AsExtended.ToString;
  finally
    B.Free;
  end;
end;
```

たったこれだけ！

B.[Evalute](http://docwiki.embarcadero.com/Libraries/ja/System.Bindings.Expression.TBindingExpression.Evaluate) は [TValue](http://docwiki.embarcadero.com/Libraries/Sydney/ja/System.Rtti.TValue) 型を返すので、あとはよしなに。

ネタ元は

マルコカントゥのブログ
https://blog.marcocantu.com/blog/2021-may-delphi-expression-engine.html

その日本語訳
https://blogs.embarcadero.com/ja/using-delphis-expressions-engine-ja/

オブジェクトを登録すればそのプロパティを使ったりもできるので、Eval といっても差し支えない様な気がする。

# おわりに
Eval が使えるとなるとかなり強力な機能と言える。
上手く使えば関数電卓が再現できそう！
Rails ユーザー編集ページと更新

##ユーザー編集ページ
```users/edit.html.erb
<%@users.errors.full_messages.each do |messages|%>・・・１
<%=message%>・・・１
<%end%>
<%=form_tag("/users/#{@user.id}/update",{multipart:true}do%>・・・2
<input name="name" value="<%=@user.name%>">
<input name="image" type="file">・・3
<input name="email" value="<%=@user.email%>">・・4
<input type="submit" value="保存">・・2
<%end%>
```
・・1配列@user_errors.full_messagesから要素を一つずつ取り出して、messageに代入。それを<%=message%>で表示
・・2保存ボタンをクリックするとフォームで入力した内容がURL"/users{@user.id}/update"　に送信される。また、画像を送信したいときには　multipart:trueを記述する。
・・3画像ファイルを選択するボタンを表示することができる
・・4初期値

```users_controller.rb
def edit 
@user=User.find_by(id: params[:id])
end
```
userコントローラーのeditアクションでは、idがURLで入力した値の投稿者データを@userに代入した
##ユーザー更新
```users_controller.rb
def update
@user=User.find_by(id: params[:id])/1
@user.name=params[:name] /2
@user.email=params[:email]/3
if params[:image]/4
@user.image_name="#{@user.id}.jpg"/5
image=params[:image]/6
File.binwrite("public/user_images/#{@user.image_name}",image.read)/7
end
```
・・1idがURLで入力した値である投稿者データを@userに代入
・・2名前がフォームで入力した値である物を変数@user.nameに代入
・・3メールアドレスがフォームで入力されたものを変数@user.emailに代入
・・4画像が送信されているかを判定
・・5usersテーブルの画像のファイル名をimage_nameカラムに（保存）上書き
・・6送信される画像ファイルを受け取る。
・・7画像を「public/user_images」内に保存。変数imageに対し、readメソッドを用いることでその画像データ（今回はimage)を取得