OmniAICreator/Qiita-1.07M huggingface dataset:
[swift]ではじめるiPhoneアプリ開発

# swift（スウィフト）を知ろう
### swiftの特徴とは？


swiftは、現代的なプログラミング機能に加えて、開発者にとっても学習がしやすい言語と言われています。ちなみに僕自身も初めてプログラミングを始めようと思ったときに最初に触ったのがswiftであり、経験0ではじめるにはおすすめの言語だと思っています。　
[about swift](https://swift.org/)
appleのサイトではswiftとは誰もが圧倒的に優れたアプリケーションを作れる、オープンソースの言語として紹介されていますので上のリンクからチェックしてみてください。

## 特徴１ swiftは高速である　
swiftは日本語訳で迅速という意味で、鳥のあめつばめを示す意味でも使われています。　
swiftは他のプログラミング言語と比較して、検索アルゴリズムが高速だと言われています。　

## 特徴２　swiftはモダンである　
モダンとは現代風という意味です。swiftでは、他のプログラミングでも採用されている新しい機能を、積極的に取り入れています。　

## 特徴３ swiftは安全である
swiftはプログラミングの記述ミスやバグが起こりにくい仕組みを採用しています。　

## 特徴４　たくさんのApple製品で動くアプリが作れる　
swiftで作れるアプリは、iphoneやipadで動くアプリだけではなく、 Mac製品などのたくさんのApple製品で動くアプリを作ることが出来ます。　

## 特徴５　swiftはオープンソースである。　
オープンソースとは、プログラムソースを一般に公開して、誰もが使って良いとする考え方です。オープンソースであれば、一般人もswiftの改良に参加することができるので、ネット上では日々意見交換され、更なる改良・進化していくことが期待されてるとのことです。　

## まとめ　
iosアプリの開発をはじめる前に、知っておいた方が良いことを軽くですが纏めました。swiftを学習する上で少しでも参考になっていただけたら幸いです。　


##### 参考文献
この記事の内容は以下の情報を参考にして執筆しました。　

[たった２日でマスターできるiPhoneアプリ開発集中講座](https://www.socym.co.jp/book/1278)
Cの基本4 〜演算子〜　備忘録

### はじめに
私は初心者である。この備忘録を参考にされようとしている他の初心者の方は、ここに書かれていることを鵜呑みになさらぬようお願いしたい。何か間違いを見つけた方はコメント欄でご報告頂きたい。

___

### 演算子
整数同士の徐算では結果の小数点以下は捨てられる。それ以外はだいたい想像つくから割愛。

*華氏を摂氏に変えろ*　という問題があった。私の回答は下記
```c
    int fahre, cels;

    printf("Type in fahrenheit\n");
    scanf("%d", &fahre);
    
    cels = (5.0/9)*(fahre - 32);    // 注意
    printf("That's %d in celsius\n", cels);
```
"cels"に代入する行では、`5`を整数型で書くと`5/9`がゼロになるから`5.0`として書く。

##### 論理演算子
真偽値に対して「〜かつ〜」、「〜または〜」、「〜でない」などの論理演算をする。
* 論理積`&&`
* 論理和`||`
* 否定`!`
**これらのオペランドの評価順序は左から右**
[コメント](https://qiita.com/yuto1009/items/e9368e34ac6b906dd767#comment-5f348d0d0f18334294dd)を頂いたので追記
ショートサーキットについて。以下コメント引用
>例えば、
0 && 1 && 2 という式は、0 を評価した時点で、全体 false であるのが決まるので、そのあとの 1 や 2 は評価されません。|| も同様で、左から評価して、true があった時点で、それ以降の項は評価されません。


##### ビット単位の演算
名称だけ記録しておく。必要になったら調べろ。P183

##### 1増やす、1減らす
`x++;`、`y--;`、これらのことをインクリメント、デクリメントと言うのか。
```c
    int x, y;
    x = 1;
    y = x++;
    printf("x = %d\n", x);
    printf("y = %d\n", y);
```
結果は
```c
    x = 2
    y = 1
```
この場合`x`の評価は`2`だが、`y`の評価は`1`だ。
細かいメカニズムはよく分からんな。（P193）

##### 条件演算
C言語唯一の三項演算子で条件演算子`?:`というものがあるらしい。
`A? B: C`というふうに使うとのこと。第一オペランドが真なら第二オペランドの値が演算結果となり、偽なら第三オペランドの値が演算結果になるという代物。使用例が以下（*大きい方の数を求める問題*）。
```c
    int max, x, y;
    x = 10;
    y = 15;
    max = (x > y) ? x : y;
    printf("max = %d", max);    // 結果は15が表示される
```
これは以下のコードと同じような意味。
```c
    if (x > y) {
        max = x;
    }
    else {
        max = y;
    }
```
コードが短くなるし、そこまで難しくないな。
けど[このような投稿](https://qiita.com/raccy/items/0b25b2f106e2a813828b)もあるから濫用には注意する。

___

今日はちと疲れたからここまで

>今回の内容は富永和人氏の[新しいC言語の教科書](https://www.amazon.co.jp/%E6%96%B0%E3%81%97%E3%81%84C%E8%A8%80%E8%AA%9E%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E5%86%A8%E6%B0%B8%E5%92%8C%E4%BA%BA-ebook/dp/B07P1TC98P)を参考に書き留めてます。
日本語トランスコンパイラ言語 Re:Mind （自作言語）と他言語との構文比較（IF文）

# はじめに

「日本語トランスコンパイラ言語」という処理系のシステム開発現場での需要があるのかという疑問に対して、わたしは「あるかも」と考えておりまして、主たるターゲット層としては、実装スキルを消失させた中高年システムエンジニアを考えております。

詳しい利用シーンのイメージは[こちらへ](https://qiita.com/mylifewithviolin/items/9d58db8a101807c19bde)

## この記事内容の作業目的
[日本語トランスコンパイラ言語 Re:Mind という自作言語](https://qiita.com/mylifewithviolin/items/9d58db8a101807c19bde)の制御構文をターゲット言語のそれと比較して検討する。
とりあえずif文。elseやelse ifはなしとして、あとで考えます。

## この記事内容の保証
※この記事には実装的な情報が含まれます。各言語で書かれた引用ソースの妥当性は保証されません。また、開発中（というよりまだ企画段階）の仕様のため、本記事に開示された自作言語の仕様は予告なく変更される場合があります。
# ターゲット言語の構文イメージ
## ターゲット言語とは
プログラミング言語としてのソース言語を日本語を母語とするテキスト(自然文ではない)として、その変換対象となるプログラミング言語のことです。
現在、下記の言語を想定しています。全機能全ライブラリのサポートは目的としておらず（独自に対象言語のライブラリはインポートして日本語ラッパ上で使えるようにしたいとうい願望はあり）基本的な制御構文のトランスコンパイルが可能としています。
* Java
* C#
* TypeScript
* Go
このあたりのグループはC言語を祖先として構文似てるかも的な思わくあり。

* VBA（Excel用）
オフィスワーカーにとってステップアップスキルとしてまだまだ需要あり。

* Mind
* DNCL
日本語プログラミング言語グループ

# 各ターゲット言語のIF文
では、「Re:Mind」 （自作言語リマインド）と他言語との構文比較第一弾として、各ターゲット言語のIF文を比較して、自作言語のIF文を検討します。
最初に長くならずイメージが比較しやすいよう、elseやelse ifはなしとして、あとで考えます。また、比較判定用の変数の宣言も割愛します。
また、あたらしめの言語がもっている糖衣構文もとりあえず今回対象外です。Mindで「もしも」つけれるとか含む。
## Javs
```java:Java
    if(i>0){
       //todo
    }
```
## C#
```cs:C#
    if(i>0)
    {
       //todo
    }
```
## TypeScript
```ts:TypeScript
    if(i>0){
       //todo
    }
```
## Go
```go:Go
    if i>0 {
       //todo
    }
```
## VBA（Excel用）
```vb:VisualBasic for Application
    If I>0 Then
        'todo
    End If
```
## Mind
```mind:Mind
    Iが　0より　大きい
        ならば　※todo
        つぎへ
```
## DNCL
```mind:DNCL
    もし　i > 0　ならば
        //todo
    実行する
```
各言語のIF構文の間に挟まれているtodoは各言語のコメントアウト符号によるコメントです。
# ソース言語の構文イメージ
## ソース言語のIF文
### Re:Mind
```mind:Re:Mind
    ◇i > 0 の場合
        //todo
    ◇ここまで
```
# おわりに
システムエンジニアというとプログラミング得意なのではと業界外の人は思っていらっしゃるかと存じますが、特に業務システムのエンジニアはそうでもないのが実情です。分業が進んでいる環境ですと、実装工程は製造とかいってアウトソースしたり若手にまかせたりというシーンが少なくないように思われます。ただ、経験値的に、あるいは地頭的に複雑なロジックを組み立てることはできるので、若手のデベロッパーをそういう面から支援している場合は多くあります。

そこで、昨今のこまごまとしたフレームワークの細かい小技はわからないけど、きもとなるロジックはこれだ的なシーンで、年配エンジニアやマネージャ層でも記述できる言語があったらいいなと考えたしだいでございます。

この企画を実現・設計・実装していくには、スキル上の課題や未獲得の知見など多数あることが予想されます。Qiita様の場をお借りして、獲得したスキルや知見の共有、いたらない点のご支援をいただければと考えています。

# 参考リンク

[Mind プログラミングマニュアル ３ 制御構文](http://www.scripts-lab.co.jp/mind/ver8/doc/03-Control-syntax.html#naraba)

[共通テスト手順記述標準言語 (DNCL) の説明](https://www.dnc.ac.jp/albums/abm.php?d=88&f=abm00001247.pdf&n=%E4%BB%A4%E5%92%8C%EF%BC%93%E5%B9%B4%E5%BA%A6%E8%A9%A6%E9%A8%93%E5%85%B1%E9%80%9A%E3%83%86%E3%82%B9%E3%83%88%E6%89%8B%E9%A0%86%E8%A8%98%E8%BF%B0%E6%A8%99%E6%BA%96%E8%A8%80%E8%AA%9E%EF%BC%88DNCL%EF%BC%89%E3%81%AE%E8%AA%AC%E6%98%8E.pdf)

https://qiita.com/mylifewithviolin/items/9d58db8a101807c19bde

https://qiita.com/mylifewithviolin/items/ebb406bf5ea7a4eea24c
Java_3層アーキテクチャについて

ソースを管理する方法として3層アーキテクチャがある。
Webアプリケーションを3つの関心事に分類して実装する。

【プレゼンテーション層】
画面からの入力
画面への出力
@Controller

↓

【ビジネスロジック層】アプリケーションの一番重要
業務ロジック
業務ルール
@Service

↓

【データアクセス層】
データの保存
データの取得
@Repository

参考：https://www.udemy.com/course/intellij-spring-boot/
Astro環境構築

## はじめに
Astroで簡単なWebサイトを作った時の環境構築メモです。

## 事前情報

Node.js: v14.18.0、v16.12.0、またはそれ以上
（執筆当時の情報）

https://docs.astro.build/ja/install/auto/

## Astroとは
コンテンツにフォーカスした高速なWebサイトを構築するためのオールインワンWebフレームワークです。
静的サイトジェネレーター(SSG) の1つです。
ページの読み込みは、「Astroで遅いウェブサイトを構築することは不可能です。」と言い切っているくらいには早いようです。

> Astroは……
コンテンツ重視: Astroは、コンテンツが豊富なWebサイトのために設計されています。
サーバーファースト: HTMLをサーバーでレンダリングすることで、Webサイトの動作が速くなります。
デフォルトで高速: Astroで遅いウェブサイトを構築することは不可能です。
簡単に使える: 専門家でなくても、Astroで何かを構築できます。
充実した機能と柔軟性: 100以上のAstroインテグレーションから選択できます。

引用：[Astroを選ぶ理由](https://docs.astro.build/ja/concepts/why-astro/#astro%E3%81%AF)

ちなみにAstro公式サイトでは、「astro」「Astro」の2種類の表記があります。
どっちが正しいんでしょうか・・
「Astro」の方が正しい気がするので「Astro」でいきます。

## Astroインストール
以下のコマンドを実行すると、対話型でastroのインストールを進めることができます。
```terminal
npm create astro@latest
```

対話も分かりやすくて親切。。
```terminal
Need to install the following packages:
  create-astro@1.2.4
Ok to proceed? (y) y
√ Where would you like to create your new project? ... ./my-site
√ How would you like to setup your new project? » a few best practices (recommended)
✔ Template copied!
√ Would you like to install npm dependencies? (recommended) ... yes
✔ Packages installed!
√ Would you like to initialize a new git repository? (optional) ... no
◼  Sounds good! You can come back and run git init later.

√ How would you like to setup TypeScript? » Strict
✔ TypeScript settings applied!

  next   Liftoff confirmed. Explore your project!

         Enter your project directory using cd ./my-site 
         Run npm run dev to start the dev server. CTRL+C to stop.
         Add frameworks like react or tailwind using astro add.

         Stuck? Join us at https://astro.build/chat
```

### 開発サーバ起動
下記のコマンドを実行すると、開発サーバが起動します。
```terminal
npm run dev
```

http://localhost:3000 にアクセスすると、Welcomeページが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667439/aae51160-ab05-259a-294a-4df56a3be643.png)

## VSCode拡張機能インストール
コードハイライトを効かせるため、VSCodeの拡張機能をインストールします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667439/8c64101c-e420-c9f6-3272-81aac2ba6bee.png)

## Prettierインストール
```terminal
npm install --save-dev prettier prettier-plugin-astro
```

## Tailwind CSS導入
```terminal
npx astro add tailwind
```

インストールやら設定ファイルの作成やら面倒な作業を対話型でまとめてやってくれます。
終わったら、開発サーバを再起動すると反映されます。

## おわりに
Gatsbyを使った時は環境構築に詰まって諦めたのですが、Astroは何も詰まることなく環境構築がさくっと終わって感動しました。
Astro最高！
これからちまちま記事上げていこうと思います。
express-validatorでJSONのデータ型をチェックする

## 要旨
JSON形式のリクエストボディについて`express-validator`でデータ型をチェックする場合、以下のようにvalidatorを実装する。

``` json
{
    "string": "abc",
    "int": 123,
    "float": 123.456,
    "boolean": true,
    "object": { "key": "value" },
    "array": ["a", "b", "c"]
}
```

``` js
[
    // 文字列
    body('string').isString(),
    // 数値(整数）
    body('int').isInt().not().isString(),
    // 数値(浮動小数点数)
    body('float').isFloat().not().isString(),
    // 真偽値
    body('boolean').isBoolean({ strict: true }),
    // オブジェクト
    body('object').isObject(),
    // 配列
    body('array').isArray(),
]
```
## 詳説
`express-validator`でデータ型をチェックする場合、数値および真偽値については注意する。Validation Chain APIには`.isInt()`, `isFloat()`, `.isBoolean()`などのメソッドが用意されているが、そのまま使用すると意図しない値まで許容してしまう可能性がある。なお、文字列、オブジェクト、配列については注意する必要がないため本項では特に扱わない。

### 数値
`.isInt()`および`isFloat()`は、データ型が文字列であっても内容が数値であれば許容する。データ型として数値だけを許容したい場合は、`.not().isString()`を追加して文字列でないことをチェックする。

``` js
// 数値(整数）
body('int').isInt().not().isString(),
// 数値(浮動小数点数)
body('float').isFloat().not().isString(),
```
もし、意図せずに文字列である数値を許容すると、計算結果がおかしくなったりシステムエラーになったりする可能性がある。

### 真偽値
`.isBoolean()`は、引数なしだと 0 や 1 、文字列の`true`と`false`を許容する。データ型として真偽値だけを許容したい場合は、`.isBoolean()`の引数に`{ strict: true }`を設定する。

``` js
// 真偽値
body('boolean').isBoolean({ strict: true }),
```
もし、意図せずに真偽値以外のデータ型を許容すると、文字列の`false`や 0 を真と判定してリクエスト側が意図しない処理が行われる可能性がある。
Djangoで本番(DEBUG=False)でCSSとFaviconが読み込めなかった件

## 目次
[1.問題](#問題)
[2.解決方法](#解決方法)
[3.振り返り](#振り返り)
[4.参考記事](#参考記事)

## 問題
### urls.pyの書き換え
pythonのDjangoフレームワークで、
```python:settings.py(抜粋)
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
```
開発時は上記のようデバッグモードになっているところを、
```python:settings.py(抜粋)
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False
```
と書き換えるとデバッグモードが解除されます。
解除されることによりWebサービス(アプリ)上でエラーが起きてもその詳細な内容がブラウザ上に吐き出されなくなるようです(セキュリティ上はこちらが良いですよね)。

デバッグモードでは下記のような表示だったサイトが、
![スクリーンショット 2023-02-07 22.12.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224055/3f2f0895-198b-0bcb-d405-38199b600242.png)
デバッグモード解除(DEBUG=False)にしたとたんに、下記のようになってしまいました。どうもCSSとFaviconを読み込んでいないようです。どちらも”アプリフォルダの”staticフォルダに入っていたものです。
![スクリーンショット 2023-02-07 22.13.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/224055/8311427a-6552-2324-de48-1f220671d09e.png)
## 解決方法
もともとurls.pyは下記のようになっていましたが、
```python:urls.py
mysite URL Configuration
from django.contrib import admin
from django.urls import path, include, re_path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
]

```
下記のように書き換えました。
settings.py, serveのimportをしました。
それとurlpatternsのところ、3行目を追記しました。
```python:urls.py
from django.contrib import admin
from django.urls import path, include, re_path

from django.conf import settings
from django.views.static import serve 

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('blog.urls')),
    re_path(r'^static/(?P<path>.*)$', serve,{'document_root': settings.STATIC_ROOT}), 
]
```
## staticフォルダをプロジェクトフォルダ直下へ追加して解決
アプリケーションフォルダの下にstaticフォルダ(中にcss, iconフォルダ)があり、デバッグモードの環境ではそこを見に行ってくれていたのですが、プロジェクトフォルダ直下、manage.pyと同じ階層にstaticフォルダ(アプリフォルダのものと同じ構成)を追加しました。

これで解決しました。

## 振り返り
Djangoフレームワークではプロジェクトがあってその下に複数のアプリケーションをぶら下げることができる構造になっていて、フォルダの構造も同様になっていますよね。デバッグモード(開発環境)上では、各アプリのstaticフォルダの下にcssやiconを入れればそれが各アプリ上で反映されるという形ですが、本番環境ではmanage.pyと同じ階層(プロジェクトフォルダ直下)にstaticフォルダがまとめられる、ということですね、多分。学び多し…。

## 参考記事
https://qiita.com/kimisyo/items/0a67f129904a427cf92d
https://qiita.com/usodamasijp/items/2d5e9040548f7b52f5e8
【Xcode】シュミレーターにペーストしたい

# はじめに
iOS開発をしているときに、Macでコピーした内容をシュミレーターにペーストしたい時があると思います。

https://wayohoo.com/article/4088

このようなやり方でできるそうですが、私の環境ではできませんでした。
他にやり方がないか調べていたらstackoverflowにあったので記録しておきます。

最初に言っておきますが、日本語入力はできませんでした笑

# 設定方法
下記のリンクを開きます。

https://www.icloud.com/shortcuts/603da847b5dd48eebe010be1c056639e

「ショートカットを入手」を選択します。
![スクリーンショット 2023-02-07 21.55.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/3296f1a2-e310-b664-5ebb-b9116b5ff7d8.png)

「ショートカットを開く」を選択します。
![スクリーンショット 2023-02-07 21.56.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/bd05dfdf-52b8-4a0e-d856-ae249f68d7b5.png)

「ショートカットを追加」を選択します。
![スクリーンショット 2023-02-07 21.57.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/a6df8671-9ff8-083a-7321-b2fdcfe77763.png)

メニューバーにショートカットのアイコンが表示されていればOKです。
![スクリーンショット 2023-02-07 22.00.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/1727bf6e-204e-c45e-5248-8da505184840.png)

# 使い方
テキストフィールドをタップして入力できる状態にします。
![simulator_screenshot_79A574C2-29AD-4684-B400-EAF4E84D0DBF.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/c8795772-c80f-3d21-8fea-fddf9b224c01.png)

メニューバーにあるショートカットアイコンを選択して、「M1 - Copy Paste on Simulator (bypass)」を押します。
![スクリーンショット 2023-02-07 22.08.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d12be0f3-d314-ea19-d339-e788e637486b.png)

初回の実行では「許可」が求められます。
「許可」を選択します。
![スクリーンショット 2023-02-07 22.06.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/d6a28648-7563-b8f9-1e96-13b4534fcbb1.png)

# 注意
シュミレーターのキーボード設定が画像のようになっていないと機能しません。
![スクリーンショット 2023-02-07 22.13.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/709210f1-75ec-08b9-3528-7e62104497c7.png)

# おわり
日本語入力は全くできませんでした笑
ローマ字と数字は得意みたいです笑

ちょっと中身をいじれば日本語入力もできるようになるかな？？

とりあえずやりたかったことはできました笑

# 参考記事
https://stackoverflow.com/questions/71569778/copy-paste-not-working-in-xcode-13-simulators-with-m1-macbook-pro
【Rails】モデルのカラムで選択肢を指定したいときはenumerize gemを使おう

# どうした？
ToDoアプリを作成しています。
各Todoに対して
* waiting(未着手)
* working(仕掛中)
* done(完了)

の選択肢を持った`status`カラムを付与する時に便利になりそうなenumerize gemを導入し、設定する方法をアウトプットします。

# 手順

## gemのインストール

Gemfileにenumerizeを記載します。
```ruby
gem 'enumerize'
```
記載したら`bundle install`しましょう。

## モデルに選択肢を設定

**マイグレーションファイル**
マイグレーションファイルにて、Todoモデルに`status`カラムを付与する指示を与えます。
このとき、新規レコード作成時にバリデーションに引っかかるのを防ぐためにデフォルト値を指定すると良いでしょう。
```ruby
t.string :status, null: false, default: :waiting
```

**モデル**
モデルファイルで`status`の選択肢を配列形式で与えます。
Enumerizeモジュールの呼び出しも忘れずにおこないましょう。
```ruby
extend Enumerize
enumerize :status, in: %i(waiting working done)
```

**seed(おまけ)**
サンプルデータを作るときのコツです。
例えば100個のデータに`status`をランダムで与えたいとき、次のように指定します。
```ruby
todos_array = []
100.times do
  statuses = %w(waiting working done)
  todos_array << {
    # 略
    status: statuses[rand(3)]
  }
end

Todo.create!(todos_array)
```
`rand(n)`は0~n-1の間の整数をランダムに返すメソッドです。
`statuses`は配列なので、`statuses[n]`は配列のn番目を出力します。
この値を`status`カラムに指定すれば、ランダムなステータスを代入することができます。

## 日本語設定
選択肢を日本語設定しましょう。
`config/locales/ja.yml`に以下のように指示します。
```ruby
ja:
# 略
  enumerize:
    todo:
      status:
        waiting: 未着手
        working: 仕掛中
        done: 完了
```


## 確認
`rails c`でコンソールに入り、選択肢を確認します。
```ruby
Todo.status.options
=> [["未着手", "waiting"], ["仕掛中", "working"], ["完了", "done"]]
```
無事に3つの選択肢が設定されていることが確認できました。

さらに、設定した値は以下の方法で取得することができます。

```ruby
todo = Todo.first

#　statusの物理値をそのまま出力
todo.status
=> "waiting"

# statusの値を日本語で出力
todo.status_text
=> "未着手"
```

## 選択肢フォームに実装

html.erbファイルで選択肢フォームを実装するときは、`form_with`ブロックの中で下記のように指定します。
```erb
<%= f.select :status, Todo.status.options %>
```
このとき、オプションには`Todo.status.options`を指定していることに注目してください。
これにより、以下のようなHTMLが出力されます。
```html
<select name="status" id="status">
  <option value="waiting">未着手</option>
  <option value="working">仕掛中</option>
  <option value="done">完了</option>
</select>
```
これにより、**日本語で選択し、物理名で登録する**ことができます。
これは、`Todo.status.options`が`["日本語表記", "物理名"]`の配列からなる配列になっているためです。
つまり、上のフォームを展開すると以下のようになります。

```erb
<%= f.select :status_text, [["未着手", "waiting"], ["仕掛中", "working"], ["完了", "done"]] %>
```
詳しくは下の記事と形を比べてみましょう。

https://railsguides.jp/form_helpers.html#%E3%82%BB%E3%83%AC%E3%82%AF%E3%83%88%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%E3%82%92%E7%B0%A1%E5%8D%98%E3%81%AB%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B

# まとめ

以上でRailsでenumerize gemを導入し、モデルのカラムを選択肢から選べるようになりました。
enumerize gemは本記事で紹介した以外にも独自メソッドを持ちます。
機能を最大限に使いこなせるようになりたいです。

## 参考

https://opiyotan.hatenablog.com/entry/rails-gem-enumerize
README.mdにサービスの概要を

### はじめてのアプリ開発
せっかくなので記録を残してみようかと、軽いノリではじめてみたいと思います。
　　
初心者の恥ずかしい様をどうかお許しください。
　　
　　
　　
　　
[RUNTEQ](https://runteq.jp/)というプログラミングスクールで約700時間学んだ後でのポートフォリオを作る段階に入りました。
**1000時間の学習**が駆け出しエンジニアとして認めてもらうための第一歩とのことで、残り３００時間も働きながら地道に進めたいと思います。

実のところ12月の時点では2月上旬に本リリースまで進むつもりでしたが、コロナや仕事の忙しさに対応できず、ほとんど手をつけられずにいました。。
今も現職の資格勉強で一杯一杯ですが、Webエンジニアになりたい気持ちもあるので、疲れがたまらない程度にやっていきたいです！


　　
***

　　
　　
先ずは企画ですね、
スクールで自分と同じ境遇（家族を持ち子育て真っ最中）の仲間たちと話す機会があって、それぞれ子どもの健康や休日のレジャーなどに悩みがあることを知り、**私が家族と楽しんでいる家庭菜園をみんなにもシェアしたい**と思い、家庭菜園に関するポートフォリオを作ることに決めました。

[ポートフォリオのGitHub](https://github.com/SHOBRIO/kitchen_garden)

  
サービス名は現時点で決まっておりませんので、とりあえずKitchenGarden（家庭菜園）としました。なんの捻りもなくてすみません。


　　
　　

以下は現時点での荒いREADMEですが、直接記事に載せたいと思います。

# kitchen_garden

子どもが小さいときのお出かけ先に困っている家族へ
1つの鉢植えからシェアワークまで、健康とおいしい体験を生み出す
”家庭菜園”と”あなた”をつなぐサービスです。

##### メインのターゲットユーザー
- 20~40代
- 家庭菜園が身近でない子育て世代。

##### ユーザーが抱える課題
1.　子どもが小さいと、お出かけ先として公園以外の候補がほとんどない
2.　週末にお出かけを予定する際に変化を加えるのが大変
3.　同じ場所に外出が多いと、夫婦のコミュニケーションがマンネリする
4.　家庭菜園 = 畑という概念が強く、身近に感じられない。はじめかたがわからない。
5.　種類ごとに育て方を検索するのが大変。

##### 解決方法
1~2. 1つの提案として、施設への外出ではなく、家や共同畑を利用した家庭菜園を知ってもらう
3. 自然と生まれる共同作業によって、コミュニケーションのマンネリを解消できる
4. 小さい鉢植えや庭のプランターで育てられる野菜を紹介する
5. ガイドを表示して育て方を検索する手間を少なくする

---
---

## 実装予定の機能

未登録ユーザー
- [ ] 野菜の育成スケジュールを確認できる
- [ ] 投稿を閲覧できる
- [ ] 投稿をキーワード検索できる
- [ ] 投稿をタグで絞ることができる
- [ ] 気になる投稿に関連する野菜の育成スケジュールを確認できる
- [ ] 気になるユーザーのプロフィールを確認できる
- [ ] ユーザーの新規登録ができる

登録ユーザー
- [ ] プロフィール機能が利用できる
ニックネーム、世帯人数、理想のスケール、好きな野菜
理想規模 = 部屋の中でさりげなく or　　玄関外（ベランダ）の小スペースで　or お庭のスペースで or 共同畑で本格的に
- [ ] 投稿のCRUD機能が利用できる
本文（100字程度）、画像、タグ（ツイッターのイメージ）
- [ ] 野菜の管理画面"が利用できる
- [ ] お気に入りのユーザーをフォローできる
- [ ] 投稿に"いいね"できる
- [ ] 投稿に"コメント"できる


**●家庭菜園を手助けするための機能**
（以下も登録ユーザーが利用できるサービスで考えています）
- [ ] 育てる野菜のCRUD機能
- [ ] ガイド機能
ガイドとは土づくりから収穫予定までのタスクをカレンダーに表示して手助けを行うこと
タスクの種類によってはステータス機能を利用できる
- [ ] 日誌機能
タイトル、本文、画像、タグ
日誌は任意で投稿できるようにする。
- [ ] 水やり通知機能"（メール, LINEなど）on offは選択できるようにする

**○管理ユーザーの機能**
|項目|一覧|詳細|作成|編集|削除|
|:--:|:--:|:--:|:--:|:--:|:--:|
|登録ユーザー|○|○|||○|
|管理ユーザー|○|○|○|○|○|
|野菜データ|○|○|○|○|○|
|タグ|○||○|○|○|
|日誌|○|○||○|○|
|ステータス|○||○|○|○|
|投稿|○|○||○||
|コメント|○|||○||

## リリース後、追加で考えている機能

- [ ] グループ機能
育成野菜を管理する画面"を共有できる
グループ間でタスクのステータス、日誌が同期される。
- [ ] 通知機能
- [ ] パスワードのリセット

---
---

## なぜこのサービスを作りたいのか？
　私は妻と子どもと３人ぐらしで、家庭菜園をはじめたきっかけは、家族との有意義な時間を作りたかったからです。当時はコロナ前でしたが、毎回休みを旅行や遠出をするわけにもいかないので、ショッピングモールや公園が定番になります。マンネリが解消され、無農薬でおいしい野菜を作りつつ、食費も浮くし、息子にもよい経験になれば１石3丁くらいに思っていました。
　　
　実際に家庭菜園を行うなかで家族との絆が深まるのはもちろん、普段気にせず食べている食べ物の安全や”興味関心を高める”きっかけとして、家庭菜園はとても良い効果をもたらしてくれました。（誤解しないで欲しいのは、私は健康ヲタクではありません。家族でファストフード店も行くしお菓子も大好きです。）
　また、畑を借りなくても玄関先のプランターや家中で育てられる野菜を知り、誰もがスペースをそこまで気にすることなく始められることも家庭菜園を広めたいと思うきっかけになっています。
　
　P.S.共同畑では水やりや追肥などの助け合いがありますが、畑は作業した跡がわかりにくいのでグループ機能により別ユーザーともタスクのステータスや日誌の共有をできるようにしたいと考えています。この機能は家族をはじめ、家庭菜園をする仲間たちとのやり取りに役立ちます。


## スケジュール
※学習の遅れにより大幅変更となりました
  

企画〜技術調査：12/1〆切
README〜ER図作成：1/19 〆切
メイン機能実装：2/1 - 2/28
β版をRUNTEQ内リリース（MVP）3/1〆切
本番リリース：3月中旬


　　
今回は以上です！
マークダウンで書き直すいい機会になりました笑
次回は画面遷移図、大体できているので簡単に紹介させていただきます。
Vue ディレクティブ

## はじめに
Vueを使う必要があったので学習を始めた
一度ディレクティブを学んだ人が、さっと見て思い出せるような記事です。

## データバインディング
*マスタッシュ構文でデータバインディング*
*dataを変更するとviewも変更される*
```js
// js
const app = Vue.createApp({
  data: () => ({
    message: "Hello Vue.js",
    count: 0,
    user: {
      lastName: "tee",
      firstName: "baru",
      prefecture: "Tokyo"
    },
    colors: ["Red", "Green", "Blue"]
  })
})

app.mount('#app')
```
```html
<div id="app">
  <p>{{ message }}</p>
  <p>{{count}}</p>
  <p>{{user.prefecture}}</p>
  <p>{{colors[1]}}</p>
</div>
```

## ディレクティブ
*vueに指示を与える仕組み*
*`v-`で始まる*

*v-bind*
```html
<!-- 属性のタグにはマスタッシュ構文は使えない -->
<!-- 省略して:だけでもOK -->
<input type="text" v-bind:value="message">

<!-- dataによってclassをtoggleさせる場合の例 -->
<span v-bind:class="{done: todo.isDone}">{{ todo.item }}</span>
```

*v-if*
```html
<!-- 表示/非表示の切り替えが可能  toggle: booleanを用意 -->
<p v-if="toggle">Hello</P
```

*v-for*
```html
<!-- 配列の数文タグを出力できる -->
<!-- (color, index)で番号も取得できる -->
<p v-for="color in colors">
  {{ color }}
</p>

<!-- 対処をobjにすることも可能 -->
<p v-for="(value, key) in user">
  {{ key }}: {{ value }}
</p>
```

*v-on*
```html
<!-- イベント処理 -->
<!-- clickした際にonClickメソッドを実行する -->
<button v-on:click="onClick">Click!</button>
<p>{{ now }}</p>
```
```ts
const app = Vue.createApp({
  data: () => ({
    now: '-' // 初期値
  }),
  methods: {
    onClick: function() { // click event用のmethodを定義
      this.now = new Date().toLocaleString()
    }
  }
})
```
```html
<!-- 機能を停止させる -->
<form v-on:submit.prevent>
</form>
```

*v-model*
```html
<!-- 双方向binding -->
<!-- dataを変更してもviewを変更しても、互いに変更が反映される -->
<p><input type="text" v-model="message"></p>
<p><input type="text" v-model="message"></p>
<!-- $dataでdataオブジェクトを表示できる -->
<pre>{{ $data }}</pre>
```

---

*v-once*
```html
<!-- 初回だけバインディング それ以降は静的に評価-->
<p v-once>{{ message }}</p>
```

*v-pre*
```html
<!-- 要素とすべての子要素のコンパイルをスキップ -->
<p v-pre>{{ message }}</p> <!-- 表示: {{ message }} -->
```

*v-html*
```html
<!-- プレーンなHTMLを挿入 -->
<!-- バックエンドから取得したHTML等を表示する時に使える -->
<!-- XSS脆弱性に気をつける -->
<p v-html="message"></p>
```

*v-cloak* *読み方は「クローク」*
```html
<!-- インスタンスの準備が終わると取り除かれる -->
<!-- ページをした瞬間にマスタッシュがチラつくのを防止 -->
<p v-cloak>{{message}}</p>
```
```css
[v-cloak] {
  display: none
}
```

*v-text*
```html
<!-- Mustache構文の代わりにディレクティブを使う -->
<!-- 使う動機がないので原則使わない -->
<p v-text="message"></p>
```

*javascript式を使う*
```html
<!-- 式である必要がある 文は使えない -->
<!-- 式: 評価して値が得られるもの -->
<!-- 式例: 値, 三項演算子  -->
<p>{{ number + 1 }}</p>
```
Python の学習を始めました

# はじめに
今回、新たなプログラム言語を学習しようと思い、その対象として`Python`を選びました。
選んだ理由としては、新興のIT分野で活用されている事。
　→IoTのデバイス制御、AIの機械学習、投資関連の分析など。
また、それらのサンプルコードやライブラリが多く公開されている（らしい）ので、学習し易そうとの想定で選びました。
自分の学習の記録ならびに備忘録になればと思い、暫く投稿していこうと考えています。
そして、これから同じ様に`Python`を学習される方にとって、有意義な情報になれば良いな～とも思っていますので、宜しくお付き合いください。
# 学習を始める
`Python`について、全く分からないので、会社の同僚から学習用のサイトを教えて貰ったので、そのサイトを参考にして進めました。
（その同僚も`Python`の学習を始めたので、勉強仲間として情報交換させて貰っています。（今の所、教えて貰う一方。）:sweat_smile:）

「Python japan」のサイトで公開している[「ゼロからのPython入門講座」](https://www.python.jp/train/index.html)を使わせて頂きました。
ここでの説明は、[Google Colaboratory (Colab)](https://colab.research.google.com/)（ブラウザ上で`Python`を実行できるGoogleが提供するサービス）を使用していて、`Python`の実行（開発）環境を作る必要がないので最初のハードルがとても低いです。![ゾロからのPython入門講座.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/c11f8178-0062-ef9f-f899-22249762e379.png)
# Google Colab を使う
Google Colab を使う為の準備は、「ゼロからのPython入門講座」の[「Google Colab の準備」](https://www.python.jp/train/experience/colab.html)に詳しく説明されていますが、ここでは簡単に説明します。
先ず、Google のアカウントを持っている必要があります。
そして、Google にログインします。
続けて、Google Colab（⇒ [https://colab.research.google.com/](https://colab.research.google.com/)）にアクセスします。
![Colaboratoryへようこそ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/86062ef0-0cfd-c14f-88af-b95f35b1a696.png)
上記の画面が表示されたら、右下の「ノートブックを新規作成」をクリックします。
![コードの入力画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/5b8cd4c6-f64d-dc11-3e46-b8adda3cbb37.png)
上記の画面が表示されたら、セル（黒丸(▶)の右側）に下記のプログラムを入力します。
（コードは「ゼロからのPython入門講座」の[「ばえるPython」](https://www.python.jp/train/experience/next-sample.html#%E5%88%A5%E3%81%AE%E7%94%BB%E5%83%8F%E3%82%82%E8%A1%A8%E7%A4%BA%E3%81%97%E3%81%A6%E3%81%BF%E3%81%BE%E3%81%97%E3%82%87%E3%81%86)より）
```py
import io
import requests
import PIL.Image

response = requests.get("https://www.python.jp/sampledata/Japanese_Squirrel_WUXGA.jpg")
PIL.Image.open(io.BytesIO(response.content))
```
![初めてのPython_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/bbd934d6-a401-4b87-f994-697c24a56345.png)
黒丸(▶)をクリックすると`Python`のプログラムが実行されます。
![初めてのPython_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510221/70ec58f6-6462-7901-2f11-f12d72ada935.png)
上記の画面が表示されれば成功です。

とても簡単に`Python`を実行できました。
メール-to-ケースとメールリレーは併用時の検証


# 事前準備
・Salesforce環境
　個人開発環境、または、PlayGround
・SendGrid ※技術検証の為Freeでも良い
　https://sendgrid.com

# 設定

## １．メール-to-ケース設定
場所：SF設定画面の左側メニュー → 機能設定 → サービス → メール-to-ケース
SF設定画面でmailtocase@***.co.jpをルーティングメアドとして登録し検証します。
![1.mailtocase.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/16977662-7d2b-7263-740d-16dd647410ea.png)

## ２．メール転送の設定
mailtocase@***.co.jpの管理画面※で転送先をステップ１のメールサービスアドレスに指定します。
※メールサービスより画面が違います。
![2.mailtocaseTransfer.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/b79897cb-0b8d-ecbd-f810-ad92126c44c5.png)

## ３．SendGridの設定
### ３.１ Senderの新規作成
場所：SendGrid管理画面の左側メニュー → Settings → Sender Authentication → Create New Sender
ステップ１のメアドを転送対象としてSendGridの管理画面でメール転送を設定します。
FROM＝ステップ１のメアドの意味は、SendGridに送信してくるメールのFROMがステップ１のメアドになる場合はこのSenderに入ります。
![3.SenderAuthentication.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/fe7098c8-b052-4354-0210-89f0cfefd52b.png)

### ３.２ API Keyの新規作成
場所：SendGrid管理画面の左側メニュー → Settings → API Keys → Create API Key
API Keyの名前と権限などを指定して作成されます。SF設定画面でメールリレーを設定する際に使用します為作成されたレコードパスワードをメモしてください。
![apikey.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/b16cee8d-3323-5cad-488e-8d1c02053692.png)

## ４．メールリレー設定
### ４.１ メールリレーの設定
場所：SF設定画面の左側メニュー → メール → メールの配信設定 → メールリレー
|項目|設定値|備考|
|:---|:---|:---|
|ホスト|自由|例：smtp.sendgrid.net|
|ポート|25|転送のメールサーバより違う|
|SMTP認証を有効化|YES|sendgridの場合がYES|
|認証種別|認証テキスト||
|ユーザ名|apikey|sendgridの場合が固定値の"apikey"|
|新パスワード|3.2でメモしたパスワード||
|新パスワードの確認|3.2でメモしたパスワード||

![mailrire.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/a7448b89-2b94-9b57-fa5d-cfe61f9a121d.png)

### ４.２ メールドメイン検索条件の設定
場所：SF設定画面の左側メニュー → メール → メールの配信設定 → メールドメイン検索条件
|項目|設定値|備考|
|:---|:---|:---|
|送信者のドメイン|*||
|受信者のドメイン|*||
|メールリレー|ステップ4.1で作成されたメールリレー||

![mailcondition.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/315e90ad-2e2c-e7f0-748a-1c0e8015ae21.png)

### ここまでは設定が完了でした。


# 動作確認

## １． ケース登録
個人メールにてmailtocase@***.co.jpに送信し、ケースを投稿します。
![4.case.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/a663353a-f694-cf78-3910-bb96ab304d8f.png)

## ２． ケース起票者に返信
### ２.１ SF詳細画面で起票者にメールを返信します。
![5.answer1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/0761b535-5ba2-ce14-74d8-420e8f7b619a.png)

### ２.２ 個人メールでSF詳細画面からの返信メールは届きます。
"sendgrid.net経由"って明記されます。
![6.gmail_answer1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/d0e03c9e-e80d-418e-007a-489a00227a52.png)

## ３． ケース管理者に返信
### ３.１ 個人メールにてメールを返信します。
![gmailanwser.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/6c40e1a2-05f6-39f1-f268-732ac8de5596.png)


### ３.２ SF詳細画面に返信メールは届きます。
![8.answer2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3123085/181f57b4-9cdc-cdc0-8dc4-24a9fd6fa57e.png)


## おまけ
メールリレーを採用してもメール-to-ケースのメールやり取りはうまく行きました。
メモ　MacBook Air (M1)でFlutterインストール時のJavaのエラー

# Macについて

MacBook Air M1, 2020
チップ　Apple M1
OS Ventura 13.2

# 状況

下記を参照し、Macをインストール

https://docs.flutter.dev/get-started/install/macos

Javaは別途homebrewでインストール済み

```
% flutter doctor 
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.7.1, on macOS 13.2 22D49 darwin-arm64, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.1)
[✓] Xcode - develop for iOS and macOS (Xcode 14.2)
[✓] Chrome - develop for the web
[!] Android Studio (version 2022.1)
    ✗ Unable to find bundled Java version.
[✓] VS Code (version 1.75.0)
[✓] Connected device (2 available)
[✓] HTTP Host Availability

! Doctor found issues in 1 category.
```

Android StudioにバンドルされているJavaが見つけられないとのエラーが発生。
（それ以外は、問題なし）

# 解決

```
cd /Applications/Android\ Studio.app/Contents/
ln -s jbr jre
```

Android Studioのパッケージ内にあるContentsフォルダ内のjbrに対して、jreというシンボリックリンクを貼る

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119135/7f29e69e-deed-0e63-6ae1-48934db12e13.png)

# 調査方法

Googleで検索したところ、stackoverflowで同様の質問が投稿されている。

https://stackoverflow.com/questions/68569430/unable-to-find-bundled-java-version-with-flutter-doctor-after-updating-android

中を見たところ、jreに対して、jdkのシンボリックリンクを貼るように記載されているが、jreフォルダが存在しない。
上記ページの下の方を見ると、解決に記載した方法が載っていたので、実施したところ、成功。
投稿では、macOS VenturaかつCPUがIntelと書いてあるが、コメントでM2で成功したと記載があるので、OSによるのかもしれない。
秋月のカラーOLED 0.95インチで遊ぶ(Arduino UNO)P-14435



x 過去ログをみよ 
x カラーOLEDは、容量が大きいためArduino UNOには、向かない(ほぼデモのみ)


目的
カラーOLEDのテスト

SSD1331その互換機の標準的なライブラリになっている
Adafruit SSD1331　+ Adafruit GFXのインストール で
文字列を表示して遊ぶ

1.Adafruit SSD1331 OLED Driver Library for Arduino を　インストール
2.Adafruit GFX Library を　インストール


[QT095B]
通販コード　P-14435
発売日　2019/09/02


sclk 13　, SCL
mosi 11 , SDA
cs 10 , CS
rst 9 , RES
dc 8 , DC

3.3V , 3.3V
GND , GND


https://akizukidenshi.com/catalog/g/gP-14435/


https://qiita.com/caa45040/items/39360e3f2950dd7ad879


https://qiita.com/caa45040/items/3c57c159be0fd0f7a718


https://qiita.com/caa45040/items/35a7ee9c49a6d78bd535


https://qiita.com/caa45040/items/574231109a31cb6c55eb








![o_cop375.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/e2c4a69d-816b-dc29-bff8-778be55d0a07.jpeg)







```c++



//test_ssd1331_uno_0207

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1331.h>
#include <SPI.h>


// You can use any (4 or) 5 pins
#define sclk 13
#define mosi 11
#define cs   10
#define rst  9
#define dc   8


// Color definitions
#define BLACK           0x0000
#define BLUE            0x001F
#define RED             0xF800
#define GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define WHITE           0xFFFF


Adafruit_SSD1331 display = Adafruit_SSD1331(&SPI, cs, dc, rst);

//初期化
void setup() {

  display.begin();

  //display.fillScreen(BLACK);

}//setup


//メインループ
void loop() {

  // 画面表示をクリア
  display.fillScreen(BLACK);

  // テキストサイズを設定
  display.setTextSize(3);
  // テキスト色を設定
  display.setTextColor(WHITE);
  // テキストの開始位置を設定
  display.setCursor(0, 10);


  // 1行目に数字を表示
  display.println("UNO");

  delay(1000); //1秒待つ

}//loop




```
2月7日なので、207の入社エントリを書いてみる

# はじめに

株式会社207でフロントエンドエンジニアをしているalternacrowです。
2022年11月に入社してから早3ヶ月が経ち、完全裁量労働制かつフルリモートの環境にも慣れてきました。
1ヶ月もしないうちにぬるっと溶け込み、皆に受け入れてもらいつつも的確なフィードバックをもらっており毎日楽しく仕事をしています。
207では2月7日は入社エントリを書く日になっている(今日知った)ので、早速人生初の入社エントリを書くことにしました。

# これまで

略歴ですが、エンジニアになったのは28歳頃で、

1. SES（VB.NETでWindowsアプリケーション）
2. 受託会社（インフラ->フロントエンド）
3. 自社開発（WEBフロントエンド）
4. 自社開発（WEB、アプリをフルスタック）

と、渡り歩いてきました。
基本的に必要であればなんでも手を出すタイプで、フロントをやるついでにPHPやSQLを書いたり、C/C++をかじったりしてました。
おかげさまで見事に器用貧乏になりつつも色々な経験をでき、日々楽しく開発させていただけたことに感謝しています。

前職ではTypeScript/JavaScriptでインフラからフロントエンドまでフルスタックに開発を行っていました。
TypeScript、React、React Nativeが開発の中心で、TypeScriptスキーの自分としてはこの上ない幸せでした。
またチームや周りのエンジニアやチームにも恵まれ、毎日プロダクト開発に没頭していたのを覚えています。

# 転職理由

チームや業務、待遇に対して不満は無かったのですが、掲げているバリューと実際の方針との乖離が半年近く続いたことで転職を考えるようになりました。
現状をなんとかしたいと思い、他チームのエンジニアと1on1をしたり、チームに違和感を投げかけたり、チームビルディングに動いたりしていました。
最終的にはエンジニア部門と経営陣がぶつかり、改善は難しいかもしれないと思い転職を決めました。

# 207を選んだ理由

転職では下記を主軸に応募していました。

1. 会社の文化が合うこと
2. 今いる人たちと一緒に働きたいと思うこと

1の文化ですが、207は3つのバリューを掲げています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684679/768a7a26-e004-ac24-0c68-e23a635b27dc.png" width="600">

特にBe Openには惹かれるところがあり、個人の抱える違和感を開示することで全体で改善に取り組める期待がありました。

2については、カジュアル面談時に1日業務体験をさせてもらえることになり1日実際にフルリモートで働いてみたり、CTOやエンジニアの方と飲みに行ったりなど、フィッティングにはかなり時間と労力を割いていただきました。
そういった関わりの中で、この人たちと働きたいと思うようになりました。

# 入社してみての感想

一番入社してよかったと思ったのは、CEOのバリューへの求心力です。
バリューが必ず事業成長の推進力になるという確信があり、私自身も共感するところで説得力もありました。
この点は前職で抱えていた違和感を払拭するものでした。

元々物流には興味がなく、入社当初はTypeScript/ReactNativeで開発できる方が魅力的に感じていました。
ただ、実際にプロダクトの開発や現場と関わる人たちとの雑談などを通して、ラストワンマイルに興味を持つようになり、現場の課題を解決したいと思えるようになりました。
これは私の性格上こうなるだろうなとも思ってましたが、セクショナリズムの排除が生きている証拠だと考えています。

# これから

バリューの体現者が多い会社です。
まだまだ課題は多いですが、バリューの体現と事業成長が密接につながっているので、もっとバリューを体現していける自分になりたいと思っています。
207のメンバーで勝つビジョンにわくわくしています。

# さいごに

最後に宣伝で、207では絶賛仲間を募集中です！
バリューに共感したり、ラストワンマイルの課題を解決していきたい方は応募待ってますb

https://207-inc.super.site/recruit
定期的に送るメールについて考える

# はじめに
日次、週次、月次…と定期的に送るメールについて
今まではテンプレートを作成して都度値変えて…とやっていたのですが、
もう少し楽にできないかな…と考えているので、その思考プロセスを記録として残します。

# （いまのところの）結論
Outlook　VBAを使って
こんな感じのを作りました。
例として毎日送る日報を想定しています。

```
Sub 日報メールの作成()
  Dim myItem As Outlook.MailItem
  Set myItem = Application.CreateItemFromTemplate("フォーマットファイルパス.oft")
  today = Format(Date, "yyyymmdd")
  Dim attatchNippoPDF As String
  Dim attatchNippoPDFFileName As String
  attatchNippoPDFFileName = "作業日報_" + today + "_なまえ.pdf"
  
  attatchNippoPDF = "添付ファイル保存先" + attatchNippoPDFFileName
  
  myItem.Subject = Replace(myItem.Subject, "%今日%", today)
  myItem.Body = Replace(myItem.Body, "%今日%", today)
  myItem.Display
  If Dir(attatchNippoPDF) <> "" Then
    myItem.Attachments.Add (attatchNippoPDF)
    MsgBox "作成しました！送る前にPDFの内容をもう一度確認しましょう！"
  Else
    MsgBox attatchNippoPDF & vbCrLf & "が存在しません。先に作成しましょう！"
    myItem.Close olDiscard
  End If
    
End Sub
```

# 実際にやってみた

前提として、添付で送るPDFを、所定のフォルダに作成しておく必要がありますが、
それさえ作成しておけば、送付メールはこれでいけるかなと思います。
作成していない場合は、「先に作成しましょう！」の旨のダイアログを出して、作成したMsgを保存せずに終了します。

## テンプレート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/fd4593ed-4d32-adb0-9f86-0e23cf3130d6.png)
こんな感じのテンプレートを用意しました。
ソースでは本文のエイリアスも置換していますが、
今回は件名部分だけ変わる感じのテンプレートです。

## 動かしてみた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/a7df207e-feaf-f9ad-cd93-f0634f6f2c9f.png)

作成しました！のダイアログが出ました。
件名のエイリアスも、しっかり今日の日付に置換されています。
OKをクリックすると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/5ad06710-9606-fdba-6065-138f85f6d010.png)
添付ファイルもばっちり添付されました。
いえーい。


# 参考文献
そもそもOutlook VBAの情報が非常に少ないので、
探すの結構苦労しました。
以下の3つを参考にして作りました。

https://extan.jp/?cat=7

https://monologu.com/modify-outlook-template-by-macro/

https://outlooklab.wordpress.com/

# おわりに
毎日使っているメール、コピペでも簡単に作れるじゃん！
と言われたらその通りなんですが、もう少しだけ簡単にしたいな…と思う方に届けば幸いです。

また、もっと楽にできるよ！とか
こういうコード書いたらもっと対応できる幅広がらない？
等ありましたらコメントいただけるととても嬉しいです。
いいねもください（豹変）

ちなみにお師匠様に「定期的に送るメール、テンプレからコピペするのめんどくさくないですか？」って言ったら「えぇ～～～！？」（絶句）と言われました。
[laravel,mariadb]mariaDB使用環境でwhereHasの中でwhereInを使ったらバグった話

## 出現した環境
laravel 8.81.0
mariaDB 10.5.x
php 8.1.x

## 何が起きた？

下記のようなソースコードを書いたら、（mysql環境だと正しく動くのに）mariaDB環境ではcount()のみが動きget()が動かないという現象が起きました。


```php:app/Http/Controllers/xxxxController.php
====前略====

$tagNames = ['テストタグ１','テストタグ2'];

$searchQuery = Projects::query()
        ->when((!empty($tagNames) && !$searchNoTags), function ($query) use ($tagNames) {
          $query->whereHas('tags', function ($query) use ($tagNames) {
            $query->whereIn('tags.name', $tagNames);
          });
        });

dd($searchQuery->count()); // "100" など正しい件数が表示される
dd($searchQuery->get()); // 0件で出力される

====後略====
```


## 解決方法

筆者の場合はwhereHasの中のwhereInで文字列検索するのを止める（先にidを取得してそちらをwhereInに利用する）ことで正常に動きました。

```php:app/Http/Controllers/xxxxController.php
====前略====

$tagNames = ['テストタグ１','テストタグ2'];
$tagIds = Tag::whereIn('name', $tagNames)->pluck('id')->toArray(); // 検索用のtags.idの配列を準備

$searchQuery = Projects::query()
        ->when((!empty($tagIds) && !$searchNoTags), function ($query) use ($tagIds) {
          $query->whereHas('tags', function ($query) use ($tagIds) {
            $query->whereIn('tags.id', $tagIds); // idで検索
          });
        });

dd($searchQuery->count()); // "100" など正しい件数が表示される
dd($searchQuery->get()); // count()と同じ100件が出力される

====後略====
```

## 原因についての推測

正直全く確信が持てていませんが、個人的にはmariaDBが実装しきれていなかった部分なのかなと推測しています。
（具体的には副問合せの中の`where xx in (y,z,..)`は文字列で検索すると本問合せの結果を出力できないバグがあるのかなと推測しています。）

この件以外でも、groupByを使うときはselectに書いたすべての項目を明示的に書くことを求めたりされて、mysqlでは動くのにmariaDBでは動かないことが何度かあったりしたので、mysqlより融通が効かないのかなぁという印象です。

## おわりに
laravelというよりはmariaDBの話になってしまいましたが、laravelの書き方という意味では、バグったときは深いネストのwhereInで文字列検索しているところを直すといいかもしれません、というメッセージを込めたということでご理解いただければと思います。
db insert

```java
public class Outer {
    public static void main(String[] args) {
        try {
        Connection con = DriverManager.getConnection("jdbc:derby://localhost:1527/data/Sample");
            try(con) {
                shokai(con);
                String sql = "insert into firsttable values (?, ?)";
                PreparedStatement ps = con.prepareStatement(sql);
                ps.setInt(1,60);
                ps.setString(2,"sixty");
                int ret = ps.executeUpdate();
                System.out.println("insert count:" + ret);
                shokai(con);
            }
        } catch (SQLException ex ) {
            ex.printStackTrace();
        }
    }
    static void shokai(Connection con) {
        try {
            String sql = "select * from firsttable";
            Statement st = con.createStatement();
            ResultSet rs = st.executeQuery(sql);
            while(rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                System.out.println(id + ":" + name);
            }
        } catch (SQLException ex ) {
            ex.printStackTrace();
        }
    }
}
```
```
10:TEN
20:TWENTY
30:THIRTY
40:xxx
50:fifty
insert count:1
10:TEN
20:TWENTY
30:THIRTY
40:xxx
50:fifty
60:sixty
```
executeQueryはexecute, getResultSet
exequteUpdateはexecute, getUpdateCount
に置き換えることができる
executeはResultSetをreturnしているかどうかをtrue/falseで返す


```java
public class Outer {
    public static void main(String[] args) {
        try {
        Connection con = DriverManager.getConnection("jdbc:derby://localhost:1527/data/Sample");
            try(con) {
                shokai(con);
                String sql = "insert into firsttable values (?, ?)";
                PreparedStatement ps = con.prepareStatement(sql);
                ps.setInt(1,50);
                ps.setString(2,"sixty");
                boolean bl = ps.execute();
                int cnt = ps.getUpdateCount();
                System.out.println("insert count:" + cnt);
                shokai(con);
            }
        } catch (SQLException ex ) {
            ex.printStackTrace();
        }
    }
    static void shokai(Connection con) {
        try {
            String sql = "select * from firsttable";
            Statement st = con.createStatement();
            ResultSet rs = null;
            if(st.execute(sql))  rs = st.getResultSet();
            while(rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                System.out.println(id + ":" + name);
            }
        } catch (SQLException ex ) {
            ex.printStackTrace();
        }
    }
}
```
開発チーム内で振り返りをやってみた

## 背景
新規発足した小規模チーム（3名体制で私はメンバ）で、発足後まもなく中規模程度の案件をこなしました。
最終的には無事リリースを迎えられましたが、開発中は想定外が発生することも多く、お世辞にも順調にリリースを迎えられたとは言えない状態でったので、リーダに相談し振り返りの機会を設けることにしました。
どのフレームワークを使うかの選定や、振り返りのファシリテーションは私が担当することになったので、その際に調べたことや振り返り中に意識したことをメモ書き程度に残しておこうと思います。

## どのフレームワークを使ったか
今回はKPTを採用しました。
KPTを採用した理由としては、利用するシーンが今回のケースと合っていたこと、KPTのそれぞれで何を議論するかが直感的に理解できたことが採用理由です。（有名なフレームワークとして聞いたことがあったのも採用した理由としては大きかった気がします）

## 出た意見をどうまとめるか
付箋を皆で貼り付けて意見を出し、話し合うのが基本的な進めかただと思いますが、メンバ全員がリモート勤務ということもあり、オンラインで完結する必要がありました。
そのため、以下のプランを考えました。
1. スプレッドシートを皆で編集する
1. 同時編集ができるKPT用のツールを参加者に導入してもらう
1. マインドマップツールで参加者の意見を自分がメモする

マインドマップツールは予め利用していた（コストゼロ）、かつ視覚的にもわかりやすく、同時編集によりグダる懸念もないため、今回は3を採用しました。

## 実施時間
グランドルール説明：2分
K：5分
P：5分
T：15分
でトータル30分程度を目標としていましたが、P、Tが思いのほか白熱したこともあり、気が付けば50分程度のボリュームとなっていました。
計画よりP、Tをそれぞれ10分程度増やしても良かった気がします。

## 参考としたもの
グランドルールや、KPTのそれぞれで何をするのかについては以下を参考にさせていただきました。

http://objectclub.jp/download/files/pf/KPT_TIPS.pdf


## 感想
振り返りを行ったことにより、二の轍を踏まないように今後何をすべきかが整理できました。（お互いに良かったところも挙げあえたので、モチベーションの向上にも多少は繋がった？）
チームとしての質の向上やや成果物の品質向上のためにも、やるべきことを整理して終わりではなく、ネクストアクションに繋げることを忘れないようにしようと思います。
また、今回はマインドマップツールで意見をまとめましたが、ここは改善の余地がありそうだと感じました。
共同編集ができないことにより、自分が記載している間は他の人が発言できない時間があったため、ボトルネックとなっていた気がします。
振り返りも今回の1件だけではないと思うので、より意味のある場にするためにも、まとめ方については検討してみようと思います。
db select

no argument: Statement
one or more argument: PreparedStatement

```java
public class Outer {
    public static void main(String[] args) throws Exception{
        Connection con = DriverManager.getConnection("jdbc:derby://localhost:1527/data/Sample");
        try(con) {
            System.out.println(con);
            String sql = "select * from firsttable where id<=?";
            PreparedStatement ps = con.prepareStatement(sql);
            ps.setInt(1,20);
            ResultSet rs = ps.executeQuery();
            ResultSetMetaData md = ps.getMetaData();
            int columnCount = md.getColumnCount();
            System.out.println("col count : " + columnCount);
            
            try(rs) {
                int colIndex = 0;
                while(rs.next()){
                    
                    System.out.print(rs.getString("ID") + ":");
                    System.out.println(rs.getString("NAME"));
                    for(int i=0;i<columnCount;i++) {
                        colIndex = i + 1;
                        System.out.println(" "+ md.getTableName(colIndex) + ":" + 
                                md.getColumnName(colIndex) + ":" +
                                rs.getString(colIndex));
                    }
                }
            }
        }
    }
}
```
```
org.apache.derby.client.net.NetConnection@17d0685f
org.apache.derby.client.net.NetConnection@17d0685f
col count : 2
10:TEN
 FIRSTTABLE:ID:10
 FIRSTTABLE:NAME:TEN
20:TWENTY
 FIRSTTABLE:ID:20
 FIRSTTABLE:NAME:TWENTY
```
【LeetCode】Binary Searchの公式Tutorialを読んでみた② [Find the Upper/LowerBound Value]

## 1. 記事の概要
* LeetCodeのStudy Plan(Binary Search)では、一番最初の問題で公式解説を確認する事ができます。
* 当記事は、その解説を読みながら、自分なりに要点をまとめた備忘録です。
* 言語は、**Swift**を想定しています。

### 1-1.　前回の記事
https://qiita.com/Tim_Leitch_2023/items/ac97699eaecc1e7fd533

## 2. 記事の結論
* UpperBound/LowerBoundのどちらを採用するかを決める。
* (array[mid] == targetの場合)、UpperBoundならmid+1を、LowerBoundならmid-1を返す。

## 3. 課題
* 昇順に並んだ[Int]型のArray[-7,-4,3,9,9,9,12]から、target=9をinsertすべき場所を出力してください。

## 4. アプローチ2: 上界/下界を見つける

### 4-1. 前回のおさらい
* まず、[Int]型の任意の配列**Array**を用意します。
    * この時、Arrayは、数字の小さいものから昇順に並び替えられているものとします。
* 配列のindexには必ず最初のindexと最後のindexが存在します。それを便宜的に**left**, **right**とします。
* これにより、全てのindexは[left, right]の範囲内にあると考える事ができます。

```
//Array
[-7,-4,3,9,9,9,12]

//この際、left: -7、right: 12となる。

//よって、Arrayに格納されている全てのindexは-7　~ 12の範囲内に存在すると考えられる。
```

### 4-2. 探索方針
* こういうケースの場合、2つの方法が考えられます。
    * **finding the upper bound(以下Upper)**　
    * **finding the lower bound(以下Lower)**
* Upperは、可能な限り右端に挿入する。
* Lowerは、可能な限り左端に挿入する。


```Swift
//Example
var target = 9
var upperArray: [Int] = [-7,-4,3,9,9,9,12]
var lowerArray: [Int] = [-7,-4,3,9,9,9,12]
```
* upperArrayだと、targetを[9,12]の間に、lowerArrayだと[3,9]の間にtargetを入れようとするイメージです。


### 4-3. ピポットポイント(pivot point)の設定(おさらい)
* 次に検討することは、**pivot point**を設定してあげることです。
* pivot point（以下pivot）とは、探索範囲を2つに分割するための中間地点です。
* pivotを設定したら、Arrayのmiddle indexとtargetの値を比較する必要があります。
    * こうする事で、条件式に該当しない半分については、検索する必要がなくなるため、検索量を半減させることが出来るメリットがあります。
* 探索範囲が少ない競プロの問題だと、全探索ゴリ押しでもACを叩き出す事ができますが、検索量が増えて配列の要素数が1,000や10,000クラスになってくると、処理スピードが遅く、長くなってしまいますので、pivotを使って、探索範囲を削減していく必要があります。

### 4-4. 例外処理
コードを一文追加しましょう。
```Swift
return -1
```

## 5. コード全体
### 5-1. コード全体(UpperBound)

```Swift
var left: Int = 0
var right: Int = 8
var nums: [Int] = [-7,-4,3,9,9,9,12]
var target: Int = 9

print(searchIndex())

func searchIndex() -> Int{
    while (left < right) {
        var mid = left + (right - left) / 2;
        if (nums[mid] <= target) {
            left = mid + 1;
        } else {
            right = mid;
        }
    }
    
    if (left > 0 && nums[left - 1] == target) {
        return left - 1;
    } 
    
    return -1; 
}
```

### 5-2. コード全体(LowerBound)
```Swift
var left: Int = 0
var right: Int = 8
var array: [Int] = [-7,-4,3,9,9,9,12]
var target: Int = 9

print(searchIndex())

func searchIndex() -> Int{
    
    while (left < right) {
        var mid = left + (right - left) / 2;
        if (nums[mid] >= target) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }
    
    if (left < nums.count && nums[left] == target) {
        return left;
    } 
    
    return -1;
}
```

## 6.最後に
* 何かご指摘事項などございましたら、コメント欄等でお知らせしていただけると幸いです。 

## 7. 参考ページ
* https://leetcode.com/problems/binary-search/solutions/2794222/binary-search/?envType=study-plan&id=binary-search-i
プリザンターの編集画面に表示されるリンクをクリックし、個別で設定したURLに遷移したい

 # はじめに
プリザンターでリンクを設定すると、編集画面下部にリンクが表示される機能があります。通常、リンク先のURLに遷移することができるが、ほかの遷移先に設定したいということでした。また、リンクテーブルに3行リンクがあるときにそれぞれの行で設定したURLに遷移するスクリプトを作成しました。

 # ソースコード
```javascript

//既存のリンクを取り除く
$('リンクテーブルID').addClass('not-link');
//更新ボタン・リロードした後もURLが埋め込まれる
$p.events.on_editor_load = function () {
    //テーブルに設定されている遷移先URLを指定
    //1行目
    let toUrl1 = '1行目に設定する遷移先URL';
    //2行目
    let toUrl2 = '2行目に設定する遷移先URL';
    //3行目
    let toUrl3 = '3行目に設定する遷移先URL';
    //リンクをクリックした際に同タブ内で遷移しないように遷移元URLを指定
    let fromUrl = '遷移元URL';
    //タイトルをクリックした際に同タブ内で遷移しないように設定
    $('[id = "リンクテーブルID"] tr:nth-child(1) a').attr("href", fromUrl);
    $('[id = "リンクテーブルID"] tr:nth-child(2) a').attr("href", fromUrl);
    $('[id = "リンクテーブルID"] tr:nth-child(3) a').attr("href", fromUrl);

    //テーブルに設定されている1行目のタイトル以外をクリックした際の処理
    $(document).on('click', 'リンクテーブルID tr:nth-child(1)', function () {
        //別タブで遷移
        open(toUrl1);
    });
    //テーブルに設定されている1行目のタイトルをクリックした際の処理
    $(document).on('click', 'リンクテーブルID tr:nth-child(1) a', function () {
        //別タブで遷移
        open(toUrl1);
    });
    //テーブルに設定されている2行目のタイトル以外をクリックした際の処理
    $(document).on('click', 'リンクテーブルID tr:nth-child(2)', function () {
        //別タブで遷移
        open(toUrl2);
    });
    //テーブルに設定されている2行目のタイトルをクリックした際の処理
    $(document).on('click', 'リンクテーブルID tr:nth-child(2) a', function () {
        //別タブで遷移
        open(toUrl2);
    });
    //テーブルに設定されている3行目のタイトル以外をクリックした際の処理
    $(document).on('click', 'リンクテーブルID tr:nth-child(3)', function () {
        //別タブで遷移
        open(toUrl3);
    });
    //テーブルに設定されている3行目のタイトルをクリックした際の処理
    $(document).on('click', 'リンクテーブルID tr:nth-child(3) a', function () {
        //別タブで遷移
        open(toUrl3);
    });
}

```

 # さいごに
最近はjavascriptを使って、HTMLの要素を取得したり、設定したりする業務をこなしているので、徐々に慣れてきました。今回のスクリプトはリンクテーブルに3行設定されているときに、それぞれの行にそれぞれのURLを設定し、行ごとに別で遷移するというスクリプトを実装しました。また、タイトルをクリックした場合とタイトル以外をクリックした場合とで遷移先が異なるため、場合分けをして処理を実装しました。
VisualStudioでGitを使ってソースコードを管理する方法

# 1. はじめに
* VisualStudioでGitを使いたい
* Gitの基本的な操作（コミット、プッシュ、プル）以外で知らない操作方法を知りたい

# 2. Git for Windowsのインストール
* Visual Studioから[ツール] > [ツールと機能を取得]を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/1cec4c6a-95ff-3881-a369-c5d2c6ff9e69.png)
* 個別のコンポーネントのGit for Windowsをチェックして、変更ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/aeceeb38-c97a-a588-537b-69364293a46a.png)

# 3. Gitリポジトリの作成（ローカル）
* Visual Studioから[Git] > [Gitリポジトリの作成]を選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/1256a734-7de9-9e90-8b54-5def63879450.png)
* ローカルのみを選択して、作成ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/e23521ac-f0bc-6b24-d7e8-0a44401a4f1f.png)
 
# 4. 一部のファイルをコミットする (ステージ)
* Git変更エクスプローラーからステージングするファイルのみ+ボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/45634e5f-5da0-551b-d9a7-8f8bc3da5371.png)
* コミットメッセージを入力して、ステージング済みをコミットボタンをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/33ee1adb-c6b1-bbaf-14bb-597e66403873.png)
* ステージのファイルのみコミットできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/af5a3269-ece2-c0fd-fa9f-6fa9f51556f9.png)

# 5. 変更前後の比較
* 未変更のものと比較から表示できる
* 左上の上下の矢印で変更した箇所へジャンプできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/bb9a901d-a460-550d-7f12-d802952e28aa.png)

# 6. コミットの戻し方
* リセット：Gitの履歴を削除して、ソースを戻す
    * 変更を保持：リセットしたソースを残す
    * 変更を削除：リセットしたソースを削除する
* 元に戻す：Gitの履歴を残して、ソースを元に戻す（マージ対象）

# 7. 参考文献
https://www.udemy.com/course/vsgithub/