OmniAICreator/Qiita-1.07M huggingface dataset:
【Bootstrap】Railsのeachメソッドで取り出す回数に制限をかける話〜viewで使えた〜

### 解決したいこと
Carouselでviewファイルの作成が完了し、ここには新規投稿を新しいものから順番に表示していくことにしました。
eachメソッドでできそうだな〜と思ったのですが、デフォルトでは表示できる領域が3つになっています。

※下記画像、Headingの部分です
![e629b0f5c726d96fedeeeae5ca76e4c4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887559/e84021d1-09b1-e44e-d25c-414b24ed9e41.png)

DBに入っているデータが4つ以上になった場合、自動で二段目以降が形成されていってしまうので、eachメソッドで取り出す数に制限をかけて3つまでに抑える方法を探しました。



### 元々のソースコード（Heading部分
```ruby

<div class="row">
 <div class="col-lg-4">
  <svg class="bd-placeholder-img rounded-circle" width="140" height="140" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid slice" focusable="false" role="img" aria-label="Placeholder: 140x140"><title>Placeholder</title><rect width="100%" height="100%" fill="#777"/><text x="50%" y="50%" fill="#777" dy=".3em">140x140</text></svg>
  <h2>Heading</h2>
  <p>Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna.</p>
  <p><a class="btn btn-secondary" href="#" role="button">View details &raquo;</a></p>
</div>

〜以下同じものがあと２つ繰り返し〜

```


### 変更したもの
```ruby

<div class="row">
  <% @item.first(3).each do |item| %>　　　　⬅️追加したコード
    <div class="col-lg-4">
      <%= image_tag item.image, width: '360', height: '280' %>
      <h1><%= item.hoge %></h1>
      名前
      <h4><%= item.hogehoge %></h4>
      紹介
      <h4><%= item.huga %></h4>
      <button type="button" class="btn btn-outline-secondary rounded-pill"><%= link_to "詳細を見る" %></button>
    </div>
  <% end %>
</div>

```

`<% @item.first(3).each do |item| %>`
と、することでeachメソッドで配列から取り出す回数を指定しました。
今回のケースだと3ヵ所になるので、`(3)`になります。
DRY精神に則り、同じ部分を２ヵ所削除することができ、見た目もだいぶスッキリしました。

今回のことで自分の想像できる範囲のことはほとんど可能なんじゃないか？と思いました。
プログラミングってすごい技術の集大成ですね。
先人たちの知恵に感謝です。
まずは色々な方法で検索して探して、見つけたものをトライしてみることが大切だと実感しました。

### 参考にさせて頂きました

[Ruby eachループの回数を指定する](https://keruuweb.com/ruby-each%E3%83%AB%E3%83%BC%E3%83%97%E3%81%AE%E5%9B%9E%E6%95%B0%E3%82%92%E6%8C%87%E5%AE%9A%E3%81%99%E3%82%8B/)

ありがとうございました。
Djangoのアプリ作成から仮のトップページの作成まで〜

#はじめに
前回[Djangoの環境構築からプロジェクト作成まで〜](https://qiita.com/Makun1518/items/fe986e950da592a01e4b)という記事を書かせていただきましたが、今回はその続きとして「Djangoのアプリ作成から仮のトップページの作成まで」をまとめていきたいなぁと思います。

また今回の記事も下記の参考サイトを簡易的にまとめたものです。
自分が忘れないようにアウトプット、ついでにみなさんと共有できればいいと思っているので、より詳しく知りたい方は下記の参考サイトをご覧ください。

#参考
* [Django Girls](https://tutorial.djangogirls.org/ja/)
* [Django公式サイト](https://docs.djangoproject.com/en/1.11/ref/django-admin/)

#Djangoアプリの作成
下記のコマンドをうって新規のアプリを作成できる
(仮想環境を起動した状態で行う)

```command-line:command-line
$ python manage.py startapp (アプリ名)
```
今回作成するアプリ名は`app`とします

###現在のファイル構造
```html:file
(作成したディレクトリ)
├── (仮想環境の名前)
├── (プロジェクト名)
│   ├── __init__.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
|
├── app
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   └── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
|
├── requirements.txt
└── manage.py
```
こんな感じになっていればアプリの作成は完了！

###作成されたファイルの説明
`admin.py`
Djangoの機能で管理ページについて記述する

`apps.py`
アプリの設定について記述する

`migrations`
モデルをデータベースに反映するためのファイルを入れとくディレクトリ

`models.py`
Djangoのモデルについて記述する

`tesets.py`
自動テストを記述する

`views.py`
ビューについて記述する

###プロジェクトをアプリに反映させる
アプリを作ったらそれをDjangoに使うよう伝えなければいけない

`(プロジェクト名)/settings.py`でそれらの設定を行う

```python:(プロジェクト名)/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app.apps.AppConfig', #この行を追加する
]
```
`(作成したディレクトリ名)/app/apps.py`を参照するようにする

これで、アプリケーションの作成は完了!

#トップページの作成
###トップページのテンプレートの作成
`app`のディレクトリ中に`templates`というディレクトリを作成して、
さらにその中に`app`と同じ名前のディレクトリを作成する。

```
app
└───templates
    └───app
```
こんなかんじになっていればOK

`app/templates/app`の中にhtmlファイルを作成する
今回は、index.htmlという名前にします

```
app
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│   └── __init__.py
├── models.py
├── templates
│   └── app
│       └── index.html
├── tests.py
├── urls.py
└── views.py
```
構造が複雑になってきたけど上記のようになっていれば良いです

###ビューにテンプレートを指定
`app/views.py`を以下のように記述する

```python:app/views.py
from django.shortcuts import render
def index(request):
    return render(request, "app/index.html") 
```
>説明
引数に`request`を取る関数`index`を定義
`render`という関数を用いて呼び出した値を`return`している

以上で仮のトップページの作成は完了です！

#さいごに
前回も書かせていただきましたが、
自分は最近勉強を始めたばかりの初心者なので間違えている所があったらご指摘していただけたらこちらも勉強になるのでありがたいです。
また、はじめの方にも書きましたが参考にしたサイトの内容を簡易的にまとめた記事なので
これからDjangoを勉強しようとしている方やより詳しいことを知りたい方は参考サイトを見たほうが良いかもしれません。

今回はご覧いただきありがとうございました！
【実務で使うAPIを扱うときの便利ツール】 quicktype.ioの紹介 ~書籍のAPIを例に~

# APIのレスポンスってこんな感じです。

マイクロインタラクションという書籍があるのですが！

例えば書籍のAPIのレスポンス
こんな感じ

https://www.googleapis.com/books/v1/volumes?q=isbn:4873116597

【GoogleBooksAPI：response_マイクロインタラクション_ISBN_4873116597】

```
{
  "kind": "books#volumes",
  "totalItems": 1,
  "items": [
    {
      "kind": "books#volume",
      "id": "RhbBoAEACAAJ",
      "etag": "C2n94dwErsc",
      "selfLink": "https://www.googleapis.com/books/v1/volumes/RhbBoAEACAAJ",
      "volumeInfo": {
        "title": "マイクロインタラクション",
        "subtitle": "UI/UXデザインの神が宿る細部",
        "authors": [
          "Dan Saffer"
        ],
        "publishedDate": "2014-03-20",
        "description": "マイクロインタラクションの概念を提唱する書籍",
        "industryIdentifiers": [
          {
            "type": "ISBN_10",
            "identifier": "4873116597"
          },
          {
            "type": "ISBN_13",
            "identifier": "9784873116594"
          }
        ],
        "readingModes": {
          "text": false,
          "image": false
        },
        "pageCount": 217,
        "printType": "BOOK",
        "maturityRating": "NOT_MATURE",
        "allowAnonLogging": false,
        "contentVersion": "preview-1.0.0",
        "imageLinks": {
          "smallThumbnail": "http://books.google.com/books/content?id=RhbBoAEACAAJ&printsec=frontcover&img=1&zoom=5&source=gbs_api",
          "thumbnail": "http://books.google.com/books/content?id=RhbBoAEACAAJ&printsec=frontcover&img=1&zoom=1&source=gbs_api"
        },
        "language": "ja",
        "previewLink": "http://books.google.co.jp/books?id=RhbBoAEACAAJ&dq=isbn:4873116597&hl=&cd=1&source=gbs_api",
        "infoLink": "http://books.google.co.jp/books?id=RhbBoAEACAAJ&dq=isbn:4873116597&hl=&source=gbs_api",
        "canonicalVolumeLink": "https://books.google.com/books/about/%E3%83%9E%E3%82%A4%E3%82%AF%E3%83%AD%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%A9%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3.html?hl=&id=RhbBoAEACAAJ"
      },
      "saleInfo": {
        "country": "JP",
        "saleability": "NOT_FOR_SALE",
        "isEbook": false
      },
      "accessInfo": {
        "country": "JP",
        "viewability": "NO_PAGES",
        "embeddable": false,
        "publicDomain": false,
        "textToSpeechPermission": "ALLOWED",
        "epub": {
          "isAvailable": false
        },
        "pdf": {
          "isAvailable": false
        },
        "webReaderLink": "http://play.google.com/books/reader?id=RhbBoAEACAAJ&hl=&printsec=frontcover&source=gbs_api",
        "accessViewStatus": "NONE",
        "quoteSharingAllowed": false
      },
      "searchInfo": {
        "textSnippet": "マイクロインタラクションの概念を提唱する書籍"
      }
    }
  ]
}
```

さーこれをモデルにおこして使おうか

ってことで公式ドキュメントを読みながら実装しましょう
https://developers.google.com/books/docs/v1/using

ってならんわ！◯すぞ！めんどくせえ

## プログラマー三大美徳【傲慢・短期・怠惰】
を兼ね備えた私は
こんなものを手動で作っていません！

## ということでモデルをさくっと作るやつー！
https://app.quicktype.io/

![screencapture-app-quicktype-io-2021-01-26-20_13_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138063/bba238da-0b82-1f85-c368-c2326d807a6a.png)


すごいでしょー
ワンパンでさくっと作ってくれます！最高！
愛してる！もう手放せません！！！！
JavascriptでSingletonを実現する方法

function Singleton () {
  // すでにSingleton.instance が存在する場合にはSingleton.instance を返す
  if(typeof Singleton.instance === 'object') {
    return Singleton.instance;
  }
    
  // Singleton.instance は自身を参照する。
  Singleton.instance = this;
  
  return this;
}

var obj1 = new Singleton(); // new を使ってSingletonオブジェクトを作成する
var obj2 = new Singleton(); // new を使ってSingletonオブジェクトを作成する
console.log(obj1 === obj2); // true 2つは同じオブジェクト
[React] Reactの学習をします（2-5）ユーザー認証

#Reactの学習をします（2-5）

引き続き、Reactの学習をしています。

前回の記事　：　[[React] Reactの学習をします（2-4）OR マッパーによるデータベースの利用](https://qiita.com/IwashiMorino/items/60a0b1f1701be57e51fd "[React] Reactの学習をします（2-4）OR マッパーによるデータベースの利用")

##教材

[Reactチュートリアル2：レビューサイトを作ろう](https://zenn.dev/likr/articles/react-with-heroku#%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E8%AA%8D%E8%A8%BC "Reactチュートリアル2：レビューサイトを作ろう")

引き続き、likr さんが公開している「Reactチュートリアル2：レビューサイトを作ろう」という記事を教材に学習させて頂きます。

素晴らしい教材をありがとうございます。

##成果物

このチュートリアル2につきましては、チュートリアルの通りに作成し既にNetlifyに公開させて頂いております。

こちらです　→　[日大文理ラーメンレビュー](https://friendly-hopper-e0a9d5.netlify.app/ "日大文理ラーメンレビュー")

##学習日記

既に作成済ですが、少しずつチュートリアルの内容を読み返してみたいと思います。

※ 教材から箇条書き的に抜粋させて頂きます。

##ユーザー認証

>・本チュートリアルではユーザーの認証機能を提供してくれる Auth0 というサービスを利用します。

>・メニューの「Applications」を開き、「CREATE APPLICATION」と書かれたボタンを押して新しくアプリケーションを作成しましょう。
>・開発環境と本番環境で 2 つのアプリケーションを作る必要があります。
>・「Name」は何でも構いませんが、資料流では開発環境は「Development」、本番環境は「Review App」としておきます。

![025a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/897250/5dfce6a3-0ac2-55ea-420e-cabd8161705c.png)
「Development」と「Review App」という2 つのアプリケーションを作ります。

>・それぞれのアプリケーションで （中略） 開発環境と本番環境のフロントエンドの URL を入力し、画面下部の「SAVE CHANGES」ボタンを押して保存します。

>・開発環境の URL は http://localhost:3000 、本番環境の URL は https://aaa-bbb-ccc.netlify.app/ のような Netlify にデプロイした結果の URL となります。

##サーバーの実装　クライアントの実装

サーバー側、クライアント側で認証機能を加えるため、それぞれチュートリアルの通りにプログラムを変更していきます。

（この辺はもう私の能力を超えすぎていて、プログラムの内容はよくわかっていないです……とりあえず、ヨシとしましょう。）

###レビューの投稿フォームが機能するようにする

以下２点の作業をします。

・client/src/pages/RestaurantDetails.js を編集
・実際に API サーバーに対して認証情報を付けて POST リクエストを行う処理を client/src/api.js に加える

###最後にデータベースをクリアして本番環境の更新を行う

サーバー側、クライアント側の更新を行い、本番環境が動作するようにします。

これで、このチュートリアルは終わりますが、私にはまだ難しかったですね・・・。（もう少し理解を深められるようにしていきたいと思います。）
Gin の使い方

参考ページ
[Quick start](https://github.com/gin-gonic/gin#quick-start)

## インストール

```bash
mkdir gin_work && cd gin_work
go mod init gin_work
go get -u github.com/gin-gonic/gin
```

## サンプル

```go:example.go
package main

import "github.com/gin-gonic/gin"

func main() {
	rr := gin.Default()
	rr.GET("/ping", func(cc *gin.Context) {
		cc.JSON(200, gin.H{
			"message": "pong",
		})
	})
	rr.Run()
}
```

サーバーの実行

```bash
go run example.go
```

http://localhost:8080/ping にアクセスする

```bash
curl http://localhost:8080/ping
```

```bash
http :8080/ping
```

## Parameter を使うサンプル

```go:parameters.go
package main

import "github.com/gin-gonic/gin"
import "net/http"

func main() {
	router := gin.Default()

	// This handler will match /user/john but will not match /user/ or /user
	router.GET("/user/:name", func(c *gin.Context) {
		name := c.Param("name")
		c.String(http.StatusOK, "Hello %s", name)
	})

	// However, this one will match /user/john/ and also /user/john/send
	// If no other routers match /user/john, it will redirect to /user/john/
	router.GET("/user/:name/*action", func(c *gin.Context) {
		name := c.Param("name")
		action := c.Param("action")
		message := name + " is " + action
		c.String(http.StatusOK, message)
	})

	// For each matched request Context will hold the route definition
	router.POST("/user/:name/*action", func(c *gin.Context) {
//		c.FullPath() == "/user/:name/*action" // true
	})

	router.Run(":8080")
}
```

サーバーの実行

```bash
go run parameters.go
```

クライアントからアクセス

```bash
curl http://localhost:8080/user/john
```

```bash
curl http://localhost:8080/user/john/send
```

```text
$ http :8080/user/john
HTTP/1.1 200 OK
Content-Length: 10
Content-Type: text/plain; charset=utf-8
Date: Tue, 23 May 2023 06:33:17 GMT

Hello john
```

```text
$ http :8080/user/john/send
HTTP/1.1 200 OK
Content-Length: 13
Content-Type: text/plain; charset=utf-8
Date: Tue, 23 May 2023 06:33:07 GMT

john is /send
```

## 確認したバージョン

```text
$ go version
go version go1.20.3 linux/amd64
```
【PHP】正規表現で都道府県を取り除く

# やりたいこと

PHPで正規表現を用いて、住所から{都道府県}の部分を取り除き、{市区町村}以下を抽出したい。
具体的には、`preg_replace()`関数を用いて、{都道府県}部分を空文字列`''`に置換することで取り除く。

```php
$address = '東京都港区芝公園4丁目2-8';
echo preg_replace(正規表現パターン, '', $address);
// 港区芝公園4丁目2-8
```

# やったこと

正解にたどり着くまでの経緯を、ダメだったパターンを交えて記す。
(本記事では正規表現パターンの詳しい説明は割愛します)


### ダメなパターン1 

正規表現パターン：`/.*(都|道|府|県)/`
(任意の文字を0回以上 + 都・道・府・県のいずれか にマッチ)

```php:sample1
$address = '東京都港区芝公園4丁目2-8';
echo preg_replace('/.*(都|道|府|県)/', '', $address);
// 港区芝公園4丁目2-8 (正しい！)
```

```php:sample2
$address = '栃木県宇都宮市旭1丁目1-5';
echo preg_replace('/.*(都|道|府|県)/', '', $address);
// 宮市旭1丁目1-5 (おかしい！)
```
sample1では、東京都の部分がうまくマッチして置換できているが、
sample2では、宇都宮市の「都」までをパターンとしてしまい、「宮市旭1丁目1-5」となってしまっているので誤り。

### ダメなパターン2

正規表現パターン：`/^.{2,3}(都|道|府|県)/`
(先頭に任意の文字が2~3回 + 都・道・府・県のいずれか にマッチ)

```php:sample3
$address = '東京都港区芝公園4丁目2-8';
echo preg_replace('/^.{2,3}(都|道|府|県)/', '', $address);
// 東京都港区芝公園4丁目2-8 (おかしい！)
```

sample3では、東京都の部分が取り除かれると思いきや、元の文字列と同じ文字列が返されてしまった。

調べてみたところ、日本語はマルチバイト文字なので、`{2,3}`の部分でバイト数がうまく機能していないことが判明した。
この場合、パターン修飾子「u」をつけて、対象文字列がUTF-8エンコードされていることを明示するか、
文字数指定の部分を3バイト換算(`{6,9}`)で書き換える必要がある。

```php:sample4
$address1 = '東京都港区芝公園4丁目2-8';
echo preg_replace('/^.{2,3}(都|道|府|県)/u', '', $address1);
// 港区芝公園4丁目2-8 (正しい！)
echo preg_replace('/^.{6,9}(都|道|府|県)/', '', $address1);
// 港区芝公園4丁目2-8 (正しい！)

$address2 = '栃木県宇都宮市旭1丁目1-5';
echo preg_replace('/^.{2,3}(都|道|府|県)/u', '', $address2);
// 宇都宮市旭1丁目1-5 (正しい！)
echo preg_replace('/^.{6,9}(都|道|府|県)/', '', $address2);
// 宇都宮市旭1丁目1-5 (正しい！)
```

```php:sample5
$address = '東京都府中市日吉町1−1';
echo preg_replace('/^.{2,3}(都|道|府|県)/u', '', $address);
// 中市日吉町1−1 (おかしい！)
```

sample4では、日本語のバイト数問題を解決して正しく置換できた。
しかし、sample5のような住所だと、「東京都」ではなく「東京都府」の部分までマッチしてしまっているので誤り。

### 成功パターン

上の2つの間違ったパターンを経て、以下のような結論に落ち着いた。

正規表現パターン：`/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u`
(東京都 or 北海道 or 大阪府 or 京都府 or 先頭に任意の文字が2~3回 + 県にマッチ)

```php:sample6
$address1 = '東京都港区芝公園4丁目2-8';
echo preg_replace('/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u', '', $address1);
// 港区芝公園4丁目2-8 (正しい！)

$address2 = '栃木県宇都宮市旭1丁目1-5';
echo preg_replace('/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u', '', $address2);
// 宇都宮市旭1丁目1-5 (正しい！)

$address3 = '東京都府中市日吉町1−1';
echo preg_replace('/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u', '', $address3);
// 府中市日吉町1−1 (正しい！)

$address4 = '岐阜県山県市高木1000-1';
echo preg_replace('/(東京都|北海道|大阪府|京都府|^.{2,3}県)/u', '', $address4);
// 山県市高木1000-1 (正しい！)
```
東京都, 北海道, 大阪府, 京都府は完全一致でマッチさせ、
先頭にきた〇〇県または〇〇〇県をマッチさせることで、
正しく都道府県部分を取り除くことができた。

# おわりに
正規表現は奥が深い......
gem は Ruby のライブラリーのこと，じゃない

Ruby の初心者向け記事でしばしば

* gem とは（Ruby の）ライブラリーのこと

という記述を見かけます。
いや，gem は確かにライブラリーなんだけども，「gem とはライブラリーのこと」と表現すると間違いです。

gem はライブラリーのなかでも，RubyGems という仕組みでパッケージされたもののことです。

ということは，そうでないライブラリーもある，ということですね。
まず，Ruby 本体に組み込まれているライブラリーがあります。これは「組込みライブラリー」と呼ばれ，この中に String，Array といったクラスや Enumerable，Comparable といったモジュールが含まれています。これらのクラス，モジュールは組込みクラス，組込みモジュールと呼ばれます。
当然 `require` せずに使います。gem 形式にはなっていません。

組込みクラスとは別に「標準添付ライブラリー」というものがあります。date, pathname, fileutils，csv などが該当します。
標準添付ライブラリーは，その名のとおり Ruby 本体と一緒に配布されており，インストールしなくても使えるライブラリーです。ただし，`require` は必要です[^req]。

[^req]: ちょっとややこしいのですが，`pp` ライブラリーのようにユーザーがあらわに `require` しなくても暗黙に `require` してくれるものもあります。

標準添付ライブラリーには，gem 形式になっているものとなっていないものがあります[^ge]。
Ruby のバージョンが上がるごとに標準添付ライブラリーの gem 化が進んでいます。gem 化することで，Ruby のバージョンに縛られずにライブラリーのバージョンを上げることが可能になりますので，gem 化の進展はありがたいことですね。

なお，古い Ruby でも標準添付ライブラリーに代えて gem 版を使うことができます。
例えば，Ruby 2.4 に標準添付されている csv ライブラリーは gem 形式になっていませんが，Ruby 2.4 で最新の csv gem を使うことができます。

[^ge]: gem 形式になっている標準添付ライブラリーは default gem と呼ばれるものと bundled gem と呼ばれるものに分けられます（誰か解説を書いてくれないかな）。

組込みでも標準添付でもないライブラリーはどうでしょうか。
単一の Ruby スクリプトファイルを「ライブラリー」と呼んで `require` してもかまいませんよね。なので，ライブラリーは gem 形式でなければならない，ということはありません。
しかし，たとえ社内限定とか自分だけが使うものであっても，ライブラリーは gem 形式にすることをオススメします。バージョンや依存関係の管理，配布・保管が楽だからです。
ましてや公開して広く使ってもらうライブラリーなら gem 形式一択でしょう。

なお，RubyGems が登場する前は，ライブラリーは `setup.rb` というファイルを用意し，これを使ってインストールしてもらうやり方が一般的だったように思います。
この時代，RubyGems.org のようなライブラリー集積場として，RAA: Ruby Application Archive というサイトがありました。
Deviseを使った新規登録画面で、エラーメッセージが表示されている時にリロードをするとRouting Errorが出てしまう事への対処法

タイトルの通りです。


新規登録画面でのURLは
/users/sign_up
と表示されますが、
入力ミスでエラーメッセージが表示されている時のURLは
/users
に変わってしまうため、
そこの画面でリロードを押すと普通にusersのindexページに飛ぼうとしてしまい、
特にusersのindexは今回作ってなかったため、Routing Errorが表示されてしまっていました。


対策として、
usersのgetをダミーで作り,（dummyしか思いつかなかった。。）


```言語:routes.rb
  get 'users' => 'users#dummy'
```

新規登録画面に飛んでもらう

```言語:users.controller.rb
  def dummy
    redirect_to new_user_registration_path
  end
```

だけでエラーは
表示されずにすみます！


気づかないで実装してる方も多いと思いますが、
気付いてしまってどうしても気になる方はどうぞお試しください。
M1 macでpod installができない。sudo gem install ffiをしても治らない(rbenvが原因)

#環境
- 2021/01/26時点
- M1チップのMacBook airを使用
- ターミナルは基本的にrosettaを利用しないでarm64を利用
- [この記事](https://zenn.dev/ress/articles/069baf1c305523dfca3d)に乗っ取ってhomebrewをarmとintelを使い分けられるようにして、homebrewを利用してrbenvをインストール
- rbenvで2.7.2をインストールしてglobalに設定
- rbenvで入れたrubyにcocoapodsをインストール

#起きている問題
- `pod installl`が動かない。
→原因としては[このissue](https://stackoverflow.com/questions/65445365/cocoapods-installation-fails-on-macbook-pro-m1-apple-silicon-mac)で語られていること

- 上記記事にある解決策を試しても解決しない
記事の中では一旦ffiをアンインストールしてターミナルをrosettaを利用してintelに切り替えて、↓をしろと言っている
`sudo gem install ffi`
日本語の参考記事→[M1チップ(Apple Silicon)搭載のMacでCocoaPodsが動かない時の対応](M1チップ(Apple Silicon)搭載のMacでCocoaPodsが動かない時の対応)

#原因
- cocoapodsのインストール先をrbenvでインストールしたrubyにしていたことが原因。issueの中でも以下のようにコメントがある

>For anyone using a non-system ruby with rbenv and facing issues with ffi - switching to the system ruby (atleast locally in the project directory) and following the above steps helped me

#解決策
- xcodeを利用するディレクトリだけsystemのrubyを使用するように設定
- ターミナルはrosettaを利用してintelにする
- systemのrubyに対してcocoapodsをインストール
    - `arch -x86_64 sudo gem install cocoapods`
- 同様にffiをインストール
    - `arch -x86_64 sudo gem install ffi`
- あとは普通に`pod install`すれば動くはず。ちなみに一度intelで上の工程を行えば`pod install`するときはarmでも動く
    - ※追記(2021/02/05)：やはりarmでは動かなかった。`pod install`するときには、[この記事](https://zenn.dev/ress/articles/069baf1c305523dfca3d)と同様に設定している場合は`switch-arch`でintelに切り替えてから行う必要がある。
    - ちなみに、今のterminalがarmかintelかを判断をするには`uname -m`と実行するとわかる


# 感想
- なぜrbenvで入れたcocoapodsが動かないのか？

→ffiというライブラリがarmに対応していないのが原因らしい。rbenvはarmに対応しているため、arm版のrbenvでいれたrubyは`opt/homebrew/`配下にインストールされる。そのため、そこにcocoapodsを入れると動かないのか？　よくわからない
- systemのrubyにcocoapods入れるのがちょっと気持ち悪い。環境汚したくないとか考えると、できれば全部rbenvの中だけ完結するようにしたい。

→ほとんどの記事でpodの操作の時には`sudo`をつけているから、そもそもcocoapodsはsysytemのrubyに入れるのが常識だったりする？？ (rbenvで入れたrubyにインストールするときは`sudo`が必要ない)　


- iOS開発する時にrubyをsysytemの切り替えるの忘れそう



Twitterもやってるので、よければフォローお願いします。
→https://twitter.com/ObataGenta
Git でやらかした時の対処法

ここで紹介する方法は非常に危険なため、100%自分のブランチでない限りは使わないことをお勧めします。


## ローカルを任意のコミットまで戻す

```shell
git reset --hard <コミットハッシュ値>
```

## 任意のコミットまで戻したローカルの変更をリモートに反映させる

```shell
git push -f origin <ブランチ名>
```
Unity 開発環境の MRTK バージョンを確認する方法

# はじめに
MRTK ( Mixed Reality Toolkit for Unity) を使ったMRアプリケーション開発をしていると、今見ているプロジェクトは、どの MRTK のバージョンを使ってるんだっけ？と分からなくなる場面がたまにあり、MRTKバージョン固有の known issue に詰まるケースがあったので、 使用中のMRTK バージョンの確認方法についてメモ書きを残しておきます。

# 開発環境の MRTK バージョンを確認する方法
MRTK Foundation パッケージをインポートしたプロジェクトでは、
以下ディレクトリ配下に Version.txt というテキストファイルが存在しており、
このファイルに MRTK のバージョン情報が記載されている。

``(PJフォルダ)/Assets/MRTK/Core/Version.txt``


> <img width="400" alt="image.png (12.0 kB)" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/516cdfec-b701-bbda-51dd-9c2b9871666c.png">
>
> 実際のファイルの中身 

バージョンの異なる MRTK を短期間に触る場合は、
各バージョンの Known Issues に注意して開発を進めていきましょう。

初歩的な内容でしたが、お読みいただきありがとうございました！
SendGridのWeb APIでメールを送る方法(python)

# 全世界で利用されているメール配信サービスのSendGridを使って簡単にメールを送ります。

大まかな手順
- SendGridアカウント登録
- API Key発行
- SendGridライブラリのインストール
- プログラムの記述


## SendGridアカウント登録
まずは、[SendGrid](https://sendgrid.kke.co.jp/app?p=signup.index)でアカウント登録してください。
少し質問項目が多いですが、用途に合わせて真面目に回答しましょう。
問題なければ１～２日でアカウント作成が完了します。（無料利用で大丈夫です）

## API Key発行
アカウント作成後、API Keyを発行します。
SendGridの[管理ページ](https://app.sendgrid.com/)を開きます。

[Settings]->[API Keys]、[Create API Key]の順でボタンをクリックして設定画面を開きます。
![スクリーンショット 2021-01-19 9.46.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531595/f83a0dd6-3524-44b9-cf21-1f548bd76611.png)

API Keyでのアクセス権限を設定します。
[API Key Name]を入力し、[API Key Permissions]は[Restricted Access]を選択します。

![スクリーンショット 2021-01-19 9.53.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531595/00618848-5268-4c9c-f879-8634e407e5ba.png)

[Access Details]は[Mail Send]>[Mail Send]を有効にします。(バーの右側にある丸い箇所をクリック)
![スクリーンショット 2021-01-19 9.53.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531595/3877cfc1-0c65-2512-98fa-13dd852b2105.png)

それだけ有効にしたら、[Create & View]で発行
![スクリーンショット 2021-01-19 9.54.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531595/cb1f233e-264e-1bc6-c62f-b4419a452f18.png)

画面に表示されたAPI Keyをメモしてプログラムで読み込みます。

## SendGridライブラリのインストール
sendgridライブラリのインストールは[GitHub](https://github.com/sendgrid/sendgrid-python.git) からダウンロードしてくるか、pip installコマンドでインストールします。

```qiita:terminal
$ pip install sendgrid
```

## プログラムの記述
[公式ドキュメント](https://sendgrid.kke.co.jp/docs/Integrate/Code_Examples/v2_Mail/python.html)をコピーして貼り付けます。

```qiita:python3
# using SendGrid's Python Library
# https://github.com/sendgrid/sendgrid-python
import sendgrid

client = sendgrid.SendGridClient("SENDGRID_APIKEY")
message = sendgrid.Mail()

message.add_to("test@sendgrid.com")
message.set_from("you@youremail.com")
message.set_subject("Sending with SendGrid is Fun")
message.set_html("and easy to do anywhere, even with Python")

client.send(message)
```

以上です。
bulletml.jsの研究 その3

#概要

bulletml.jsの研究です。
bulletを調査。

#サンプルコード

```
<bulletml xmlns="http://www.asahi-net.or.jp/~cs8k-cyu/bulletml">
  <action label="top">
    <repeat>
      <times>100</times>
      <action>
        <fire>
          <direction type="sequence">23</direction>
          <bulletRef label="straight"/>
        </fire>
        <wait>1</wait>
      </action>
    </repeat>
  </action>
  <bullet label="straight">
    <action>
      <wait>20+$rand*50</wait>
      <changeDirection>
        <direction type="absolute">180</direction>
        <term>10</term>
      </changeDirection>
    </action>
  </bullet>
</bulletml>
```

#説明


撃ち方は変わってませんが、撃つ弾の定義、bulletがbulletRefに変わっています。 bulletRefは、その後ろのlabelでラベルづけされたbulletの要素を参照します。 この例だと、action要素の下にあるstraightラベルがついたbullet要素です。

bullet要素の中をみてみましょう。bullet要素の中にもアクションが書かれています。 最初はwaitアクションです。ここでは待つフレーム数の中に数式がかかれています。 このように、数を指定するところでは、数式を用いることもできます。 使えるのは四則演算と余りを求める%、括弧、0から1の間の乱数を発生させる$rand変数 などです。この例では20から70(20+50)のフレーム数待つように書かれています。

その次はchangeDirectionアクションです。このアクションはdirection要素で 指定された方向に弾を向けます。この場合はabsolute180度ですので、真下です。 その次のterm要素は、何フレームかけて方向を曲げるかを書きます。 この場合は10フレームかけて少しずつ下方向に弾を曲げます。

スタートしてみましょう。さきほどの回転砲台の弾が途中から下方向に変わって 落ちてきます。

#成果物

https://embed.plnkr.co/plunk/llMtCcl4xiv9pCYd

以上。
ProgateでHTML,CSSを学んでみた（5日目）

#概要
Web開発に興味が出てきたのでとりあえず一通り必要そうなものを触ってみることにしました。
ただ触るだけだと忘れてしまいそうなのでメモとして学んだことを書いてみます。
ここにあるコードはほぼ全てProgateで出てきたものです。

##入力フォームの作り方
入力フォームの作り方は\<input>と\<textarea>の2種類ある。
\<input>要素は1行のテキスト入力を受け取るための要素。
\<textarea>要素は複数行のテキスト入力を受け取るための要素。
\<input>には終了タグが不要。
\<input type="submit">のようにtype属性を指定すると送信ボタンなどが作れる。
以下にtype属性にどんなのがあるかまとめられている。
[\<input>の使い方とtype属性の一覧をサンプル付きで紹介](https://webliker.info/39533/)

```hoge.html
        <input class="contact-submit" type="submit" value="送信">
```

##複数の要素にCSSを適用する。
以下は、inputとtextareaの要素にCSSを適用した例。

```hoge.css
input, textarea{
    width:400px;
    margin-top:10px;
    margin-bottom:30px;
    padding:20px;
    font-size:18px;
    border: 1px solid #dee7ec;
    }
```
【PostgreSQL】バックアップとリストアをコマンドで実行

ただ単にタイトル通りのことをしたかっただけなのにやたらと苦労したのでまとめ。

# この記事で扱うもの

* [バックアップのコマンド](#バックアップ)
* [リストアのコマンド](#リストア)

※実際に使用しているコマンドについてのみ記載する。

# バックアップ
[PostgreSQL 12.4文書 - pg_dump](https://www.postgresql.jp/document/12/html/app-pgdump.html)

バックアップするには`pg_dump`コマンドを使用する。

```bash:基本形式
pg_dump [connection-option...] [option...] [dbname]
```

```bash:説明するパラメータ
pg_dump -h [IPアドレス/ホスト名] -p [ポート番号] -U [ユーザ名] -d [データベース名] -Fc -v -f [バックアップファイル名]
```

## 説明
* `-h [IPアドレス/ホスト名]`
データベースサーバーのIPアドレス、またはホスト名を指定する。
ローカルにデータベースがおいてあるのであれば、`localhost`と指定するか、もしくは省略できる。

* `-p [ポート番号]`
データベース接続に使用しているポート番号を指定する。
デフォルトのままであれば`5432`と指定するか、もしくは省略できる。

* `-U [ユーザ名]`
接続オプション。
データベース接続に使用しているユーザ名を指定する。
省略した場合、コンピュータ名となる模様。**※未検証**

* `-d [データベース名]`
バックアップしたいデータベースの名前を指定する。
このパラメータを省略して`[dbname]`部分に指定することもできる。

* `-Fc`
バックアップの出力形式。
`-F`と`c`を組み合わせたもの。
`c`の他に`p` `d` `t`とあるが、特段の理由が無ければ`-Fc`と指定する。

* `-v`
バックアップの進捗がコンソール上に表示される。
省略可能。

* `-f [バックアップファイル名]`
任意のファイル名を指定する。
絶対パス／相対パスのどちらを指定しても問題ない。
拡張子の指定もない。
`backup`でも`backup.dump`でもなんでもいい。

## 使用例
```bash:使用例
pg_dump -h localhost -p 5432 -U postgres -d dbname -Fc -v -f backup.dump
```

# リストア

[PostgreSQL 12.4文書 - pg_restore](https://www.postgresql.jp/document/12/html/app-pgrestore.html)

バックアップするには`pg_restore`コマンドを使用する。

```bash:基本形式
pg_restore [connection-option...] [option...] [filename]
```

```bash:説明するパラメータ
pg_restore -h [IPアドレス/ホスト名] -p [ポート番号] -U [ユーザ名] -d [データベース名] -v -c --if-exists -j [ジョブ数] [バックアップファイル名]
```

## 説明
* `-h [IPアドレス/ホスト名]`
データベースサーバーのIPアドレス、またはホスト名を指定する。
ローカルにデータベースがおいてあるのであれば、`localhost`と指定するか、もしくは省略できる。

* `-p [ポート番号]`
データベース接続に使用しているポート番号を指定する。
デフォルトのままであれば`5432`と指定するか、もしくは省略できる。

* `-U [ユーザ名]`
接続オプション。
データベース接続に使用しているユーザ名を指定する。
省略した場合、コンピュータ名となる模様。**※未検証**

* `-d [データベース名]`
リストアしたいデータベースの名前を指定する。

* `-v`
リストアの進捗がコンソール上に表示される。
省略可能。

* `-c`
データベース内のテーブルが削除されてからリストアが実行される。
`pg_restore: エラー: could not execute query`なるエラーが発生する場合に追加。
省略可能。

  * `--if-exists`  
`-c`と併用するパラメータ。  
`DROP`文に`IF EXISTS`が追加される。  
削除対象のテーブルが存在しない場合に`DROP`文が実行されなくなる。  
省略可能。

* `-j [ジョブ数]`
リストア処理が複数セッションで並列処理される。
CPUのコア数を目安に指定する。
処理速度が改善する場合がある。
省略可能。

* `[バックアップファイル名]`
任意のファイル名を指定する。
絶対パス／相対パスのどちらを指定しても問題ない。

## 使用例
```bash:使用例
pg_restore -h localhost -p 5432 -U postgres -d dbname -v -c --if-exists -j 4 backup.dump
```

# オマケ
変数にパスワードを設定しておけば何回もパスワードを入力しなくて済む。

```bash
SET PGPASSWORD=postgres
```

その他、各変数に値を設定しておけば対応するパラメータを省略できる。

```bash
SET PGHOST=localhost
SET PGPORT=5432
SET PGUSER=postgres
SET PGDATABASE=dbname
```
【Nuxt】動的ルーティングをすぐ忘れるからまとめてみた

#はじめに
本記事へのアクセスありがとうございます。
動的ルーティングの詳細について理解度を深めるため、忘れないようにするために簡潔にまとめてみます。
では、さっそく見ていきましょう。

#基本的なルーティング方法
想定ディレクトリは下記の通りです。

```
├─pages
│  ├─index.vue
│  ├─test
│  │   └─test.vue
```
##nuxt-linkを用いる

```.pages/index.vue
<template>
   <nuxt-link to="/test">testへ遷移</nuxt-link>
</template>
```
##router-linkを用いる 【nameを使う】

```.pages/index.vue
<template>
   <router-link :to="{name: 'test'}">testへ遷移</router-link>
</template>
```
##router-linkを用いる 【pathを使う】

```.pages/index.vue
<template>
   <router-link :to="{path: 'test'}">testへ遷移</router-link>
</template>
```

##router-pushを用いる 【nameを使う】

```.pages/index.vue
<template>
   <btn @click="transition()"> submit </v-btn>
</template>

<script>
export default {
  methods: {
    transition() {
      this.$router.push({ name: 'test' })
     },
   }
}
</script>
```
##router-pushを用いる 【pathを使う】

```.pages/index.vue
<template>
   <btn @click="transition()"> submit </v-btn>
</template>

<script>
export default {
  methods: {
    transition() {
      this.$router.push('test')
     },
   }
}
</script>
```
#paramsを使ったルーティング方法
想定ディレクトリは下記の通りです。

```
├─pages
│  ├─test
│  │   ├─_hoge
│  │        └─index.vue
```
##paramsを使ったルーティング引数なし

```.pages/index.vue
<template>
   <btn @click="transition()"> submit </v-btn>
</template>

<script>
export default {
  methods: {
    transition() {
         this.$router.push({ name: 'test-hoge', params: {hoge: 123 } })
     },
   }
}
</script>
```
##paramsを使ったルーティング引数あり

```.pages/index.vue
<template>
   <btn @click="transition(123)"> submit </v-btn>
</template>

<script>
export default {
  methods: {
    transition(hoge) {
         this.$router.push({ name: 'test-hoge', params: { hoge } })
     },
   }
}
</script>
```
##paramsを使ったルーティング方法 ( _index.vueバージョン )
想定ディレクトリは下記の通りです。

```
├─pages
│  ├─test
│  ├─hoge
│  │  └─_id.vue
```

```.pages/index.vue
<template>
   <btn @click="transition()"> submit </v-btn>
</template>

<script>
export default {
  methods: {
    transition() {
         this.$router.push({ name: 'hoge-id', params: { id : 123 } })
     },
   }
}
</script>
```
##paramsを使ったルーティング方法 ( 2階層から3階層目 )
想定ディレクトリは下記の通りです。

```
├─pages
│  ├─index.vue
│  ├─test   
│  │   ├─ _hoge   
│  │        ├─ index.vue   
│  │        ├─_hoo
　　　　　　　　　 └─ index.vue  
```

```.pages/test/hoge/index.vue
<template>
   <btn @click="transition(123)"> submit </v-btn>
</template>

<script>
export default {
  methods: {
    transition(hoo) { 
         const hoge = this.$route.params.hoge
         this.$router.push({ name: 'test-hoge-hoo', params: { hoge , hoo} })
     },
   }
}
</script>
```
#おわりに
お疲れ様でした。

少しでも役に立ったと思う方がいましたらLGTMをお願いします🙇‍♂️

queryについてのルーティングも気が向いたら追記します。
OpenSSLのEVP APIの依存ライブラリ

# はじめに
* 個人的備忘録です。
* WindowsでOpenSSLのEVP暗号(libcrypto.lib)を使用する際に必要となるライブラリについて記載します。

# 環境
* Visual Studio 2012
* OpenSSL 1.1.1g

# 依存ライブラリ
* Wincrypt32
* Winsock2

上記のライブラリに依存するため、libcrypto.libをリンクする際は、合わせて以下もリンクする必要がある。

* crypt32.lib
* ws2_32.lib
Ansibleでgroupsという変数名は使えない

Ansibleのエラーと闘って得た気づき（解決済み）。

- `groups`に限らず、マジック変数で定義されている言葉は変数名として使うことができない。

---

## 経緯
Ansibleを使ってのサーバ構築をしていた。
OS上のグループの定義を一通り作成

省略しているがだいたい下記のようなものを作成

```
#ap_group.yml
---
groups: 
  - {name: 'group1', gid: 2001}
  - {name: 'group2', gid: 2002}
  - {name: 'group3', gid: 2003}
```

```
#create_group.yml
---
- hosts: all
  tasks: 
  - name: create group
    group:
      name: "{{ item.name }}"
      gid: "{{ item.gid }}"
    with_items: 
      - "{{ groups }}"
```
```
ansible-playbook -l ap -i inventory_file -e @v_ap_group.yml create_group.yml
```

- 実行するymlは汎用性を考えて`hosts: all`とし、インベントリファイルの中からapグループだけを対象として選んで実行
- apグループ以外は別のグループを作成するが、実際には数が多く煩雑なのでvarsファイルごと分けて作成し、実行時に`-e`（`--extra-vars`）で対象を選択

…で、簡単にできるはずだったが、かなりはまってしまった。


## トラブルシューティング
 
出たエラーは、前後省略しているが、これ

```
The error was: 'dict object' has no attribute 'name'

```

と、お決まりのこれ

```
but may be elsewhere in the file depending on the exact syntax problem.

The offending line appears to be:

- hosts: all
  tasks:
  - name:
   ^here 
```

syntax errorかも、というエラーログは
もはや何を信じていいかわからないので、
念のため手元に構文エラーになりそうなものがないかを調べた。

実際にはgroupだけでなく同時にユーザの定義も書いてあり、
varsファイルもplaybookもそこそこ行数があり、じっくり確認したが、とくに見当たらない。

次に、実はこの「dict形式の定義をwith_itemsで回す」の実績がなかったため、
呼び出し方が間違っているのか？と思い、別の定義の仕方をいくつか調べたが、
いまひとつピンとくる情報はなかったので、とりあえずいろいろ試してみることにした。

まず確認してわかったことは、
別ファイルに出してあるvarsを、実行するplaybook内に書いても、何も変わらないということだった。
書き方もいくつか試したが変化なし。
これでもはや定義の仕方の問題である可能性は低い…？


仕方ないので、エラーログでも意味のありそうな方

`'dict object' has no attribute`
を検索し、次のstackoverflowに辿り着いた。

参考：
https://stackoverflow.com/questions/40770286/the-error-was-dict-object-has-no-attribute-ansible-facts2

症例も似ていたが、

>Friendly advice: always check registered variables with debug if you bump on such errors.


このアドバイスを見て、なるほどと思い、やってみた

```
#create_group.yml　debug
---
- hosts: all
  tasks: 
  - name: create group
    debug: msg="{{ item }}"
#    group:
#      name: "{{ item.name }}"
#      gid: "{{ item.gid }}"
    with_items: 
      - "{{ groups }}"
```

すると、参照しているインベントリファイルの内容がずらーっと表示され、気づいた。

これは優先度の高い予約語みたいなものがあるな、と。

というわけで、以下のように変更してやってみることにしたことで、エラー解消。長い闘いであった。


```
#v_ap_group.yml
---
v_groups: 
  - {name: 'group1', gid: 2001}
  - {name: 'group2', gid: 2002}
  - {name: 'group3', gid: 2003}
```

```
#create_group.yml
---
- hosts: all
  tasks: 
  - name: create group
    group:
      name: "{{ item.name }}"
      gid: "{{ item.gid }}"
    with_items: 
      - "{{ v_groups }}"
```


後から確認したが、マジック変数については以下にまとまっていたので参考にされたい。
https://qiita.com/h2suzuki/items/15609e0de4a2402803e9


---
追記：
マジック変数について、公式ドキュメントの記載は[こちら](https://docs.ansible.com/ansible/latest/reference_appendices/special_variables.html#special-variables)

マジック変数以外では、python的に意味のあるものは使えないとのコメントをTwitterでいただいた（ありがとうございます！）

 - 公式ドキュメントの[この辺](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#referencing-key-value-dictionary-variables)
 - Ansibleのソースでいうと[この辺](https://github.com/ansible/ansible/blob/devel/lib/ansible/utils/vars.py#L235)らしい

そもそも公式ドキュメントに、[Creating valid variable names](https://docs.ansible.com/ansible/latest/user_guide/playbooks_variables.html#creating-valid-variable-names)
という部分があってきちんと書かれていたのですね。。

大変勉強になりました。

以上
SPA(Single Page Application)についての理解があいまいだったので、整理するためにまとめてみる

これまで独学でReactを勉強をしてきたのですが、「Single Page Application(以下SPA)ってなに？」と友達に聞かれて上手く説明出来ませんでした。つまり、SPAについてしっかりと理解せずにここまできてしまったので、ここで一度基礎に戻って理解を深めよう、という思惑でこの記事を書いています。

## SPAってなに？

現時点で`SPA`でググって上位表示されているページを引用してみます。

>①SPAとは単一のWebページでアプリケーションを構成する設計構造の名称です。[引用元](https://digitalidentity.co.jp/blog/creative/about-single-page-application.html)


>②SPAとは「Single Page Application」の略で、単一のページでコンテンツの切り替えを行うWeb アプリケーションのアーキテクチャの名称です。SPAではブラウザによるページ遷移を行わずにコンテンツの切り替えなどを行うことで、ユーザー体験（UX）を大きく向上させることができます。 従来のWeb ページでは遷移時にページ全体が書き換わりますが、SPAでは JavaScript を用いてページ内の HTML の一部を差し替えてコンテンツを切り替えています。 これにより、ブラウザの挙動に縛られないUIの実現や、パフォーマンスの向上が可能になります。[引用元](https://www.oro.com/ja/technology/001/)

>③SPAはAdobe FlashやMicrosoft SilverlightといったリッチなUIを提供できるRIA（Rich Internet Application）に代わるフロントエンド開発の技術として、ブラウザの進化やHTML5の登場などによって誕生したアーキテクチャです。HTMLやJavaScript、CSSといったWeb技術で、デスクトップアプリケーションのような快適な操作性を実現できます。[引用元](https://www.atmarkit.co.jp/ait/articles/1702/22/news012.html)


これだけではあまり理解できなかったので、他にもいろいろ調べてみて以下のように理解しました。

- 従来のWebアプリケーション(SPAでないもの)はクライアント側からリクエスト(リンクをクリックしたりボタンをクリックしたり、サーバー側に「このページを見せて」と**要求**すること)をすると、そのリクエストの度にサーバー側でHTMLを生成してそれをクライアント側で表示していた。
- しかしながらこの方法だと、headerやfooterなどコンテンツが変わる可能性の低い部分も含めて`ページ全体のHTMLがリクエストごとに生成されてしまう上にページを再読み込みしないといけない`
- そこで登場SPA。
- 最初の画面の表示のみサーバーからHTMLを取得し、それ以降のリクエストではJavaScriptでDOMを操作することで、`ページの差分(つまり、必要最低限の箇所)のみを更新する`ため、パフォーマンスが向上する
- 従来のWebアプリケーションは1つのページに対して1つのHTMLだったものが、SPAは1つのWebアプリケーションに対して1つのHTML(初期表示時に読み込むもの)。
- これが**Single Page Application**の由来

## 参考
[SPA(Single Page Application)の基本
](https://qiita.com/takanorip/items/82f0c70ebc81e9246c7a)

[今さら聞けない！シングルページアプリケーションとは
](https://qiita.com/RinGoku/items/e44185d6103746b213c3)
Github Desktopでコンフリクトを解消する


#コンフリクト解消
[![Image from Gyazo](https://i.gyazo.com/100215a6ffe00f98f529fd17af34541c.png)](https://gyazo.com/100215a6ffe00f98f529fd17af34541c)
これはコンフリクトが発生しています。
右上のResolve Conflictsをクリックすると、コンフリクトが起きているファイルを確認できます。

[![Image from Gyazo](https://i.gyazo.com/e481d014a0588444287ebc0875701052.png)](https://gyazo.com/e481d014a0588444287ebc0875701052)
<<<<<<<　ユーザー管理機能から　|=======　までの囲まれた部分が、現ブランチでの変更点、
|=======　から　>>>>>>>　master　までがmasterブランチでの変更点です。
変更内容が重複しているため、「コンフリクトが発生してマージできない」状態になります。

解決法は「取り込みたい部分だけ残し、それ以外消す」です。
今回は現ブランチでの変更点を取り込みたいので、masterブランチでの変更点を消します。
皆様はご自分の状況に合わせて作業を進めてください。
[![Image from Gyazo](https://i.gyazo.com/f9df700792e7684e661ad0181830a0d3.png)](https://gyazo.com/f9df700792e7684e661ad0181830a0d3)
そして右上のResolve Conflictsをクリックすると、

[![Image from Gyazo](https://i.gyazo.com/6ffeb8a06d69195e34e85207af07598a.png)](https://gyazo.com/6ffeb8a06d69195e34e85207af07598a)
✔︎Resolvedに変わったのを確認し、
真ん中やや右上に現れた、緑色のCommit mergeをクリックします。

[![Image from Gyazo](https://i.gyazo.com/2fbdff668c9f62c6c1a2e48873cdb9bb.png)](https://gyazo.com/2fbdff668c9f62c6c1a2e48873cdb9bb)
すると、コンフリクトが解消され、マージできるようになります。
for文のネストを図にしてみた

# for文のネストを図でイメージしたい！

まだバージョン1と言ったところですが、
これなら、記述を見て「あああれだな」と思える気がしてます
![for文図解.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528622/0aaac4ab-53cd-088d-1947-7915eb4bb12f.jpeg)
自分用 git操作の手順


cd
移動

git init
初期化

git remote add origin リポジトリURL
紐付け

git remote -v
確認

git add . (もしくはファイル名)
追加宣言

git commit -m '履歴名'
履歴に残す

git push origin master
ローカルから追加

git checkout -b modifyfy-README(ブランチ名)
トピックブランチ（短期間だけ使う一時的なブランチ）はcheckoutと-bフラグを使って作成

git branch
すべてのローカルブランチを一覧表示

git status
確認

git commit -a -m "履歴名"
-a :現存するすべてのファイル（git mvで作成したファイルも含む）への変更を一括でコミット
最後のコミット後に新しいファイルを追加した場合は、まずgit addを実行してバージョン管理下に置く必要
履歴名は現在形かつ命令形

git checkout master
ブランチ移動

git merge modifyfy-README(ブランチ名)
一時的なブランチから変更をマージ

git branch -d modifyfy-README(ブランチ名)
トピックブランチ削除 (必須ではない)
-D : 変更をマージしていなくてもブランチ削除

git push (origin master)
GitHubに変更をpush
一度push済なら後半省略可

git add -A
git commit -m "履歴名"
git push -u origin static-pages(ブランチ名)
最後のコマンドでは、static-pagesトピックブランチをGitHubにプッシュしています。以後は、単に次のコマンドを実行するだけで同じプッシュが行われるようになります。
git push


$ git add -A
$ git commit -m "Finish static pages"
次にmasterブランチに移動し、差分をマージ

$ git checkout master
$ git merge static-pages
コードをリモートリポジトリにアップロード

$ git push

$ rails test
$ git push heroku
AWS CloudShellでAWS CDK (Python & Pipenv)のデプロイするときの準備メモ

## やりたいこと
- AWS CDKのデプロイをAWS CloudShellからやりたい
  - CLIでの接続が難しい、MFAが必要な環境やSAMLでSSOしている環境でも、AWSコンソールからさっと開いてデプロイできる

### ポイント
- **AWS CloudShellは`$HOME`の外部にインストールしたツールは永続化されない**
- **`$HOME`内の永続化ストレージ（上限1GB）に必要なツールをインストールすることで、繰り返し`cdk deploy`を実行する際にパッケージの再インストールが必要なくなる**

## 前提環境
- AWS CDKをPythonで書いている
- Pythonのパッケージリスト管理にpipenvを使っている
- AWS CDKのコードをGitHubなどインターネット経由で接続できるリポジトリにpushしている


## 準備

### リポジトリ
- AWSコンソールからAWS CloudShellを起動する
- 自分のリポジトリをcloneする  
  ```
$ git clone <your_repogitory_url> 
  ```

### pipenv
- AWS CloudShellにはpython3,pip3はあるがpipenvが導入されていない  
  **普通に`sudo pip3 install`でインストールすると永続化されないので`$HOME`配下にインストールする**  
```
$ pip3 install pipenv --user
```
- PipfileのあるCDKアプリのディレクトリに移動しPythonパッケージを一括インストールする  
  Pipfileに記載のPythonバージョンとAWS CloudShellにインストールされたバージョンが異なる場合があるが、コードに互換性がある場合はパスを指定することで警告を無視してインストールする  
```
$ pipenv install --python /usr/bin/python3
```
- pipenvの仮想環境にスイッチすることで、 `$HOME` 配下のパッケージにパスが通った状態になる  
```
$ pipenv shell
```

### cdkコマンド
- AWS CloudShellにはnode,npmコマンドはあるがcdkコマンドは導入されていない。  
  **普通に`sudo npm install -g`でインストールすると永続化されないので`$HOME`配下にインストールする**  
  cdk.jsonが配置されたCDKアプリのディレクトリでインストールする( `node_modules/`配下は.gitignoreされている前提)  
```
$ npm install aws-cdk
```
- グローバルにインストールされていないので、cdkコマンドはnpxコマンドを介して利用する  
```
$ npx cdk list
```

## 利用
AWS CloudShellを起動するたび、以下を実行することでパッケージの再インストールなしにCDKのデプロイが可能

```bash
$ cd <cdk_app_directory>
$ pipenv shell
$ npx cdk list
$ npx cdk diff <stack_name>
$ npx cdk deploy <stack_name>
```

快適！！！
パッケージが全て`$HOME`配下に導入されるので、ディスク容量の上限には注意。
React 画面遷移をスライドアニメーションで表現する方法

#はじめに
今回はReactで画面遷移時のスライドアニメーションの実装方法をまとめてみました。
Reactのライブラリを使用します。

#参考サイト
【The easiest way to slide React routes】
　- [画面遷移をスライドで表現する](https://reactjsexample.com/the-easiest-way-to-slide-react-routes)

ちなみにこちらのサイト、Reactを勉強してる方にオススメです。
機能ごとに検索できて、すごく分かりやすいです。
【React.js examples】
　- [React勉強者オススメ](https://reactjsexample.com)

#実装準備
まず最初は`react-slide-routes`と`react-router-dom`をインポートします。

```
npm info react-slide-routes
npm info react-router-dom
```
現在の最新バージョンを確認して、そのバージョンを`yarn add`します。

```
yarn add react-slide-routes@0.14.0
yarn add react-router-dom@5.2.0
```
これで`react-slide-routes`と`react-router-dom`を使用することができます。

#実装方法
まずはスライドを適応させたいコンポーネントを`BrowserRouter`で挟んであげます。
インポートもお忘れなく。こちらは`index.js`

```react:index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import App from './App';

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById('root')
);
```

そして今回使用するのは、`SlideRoutes, Route, NavLink, useLocation`なので、これらをまずインポートします。こちらは`App.js`

```react:App.js
import React from 'react';
import SlideRoutes from 'react-slide-routes';
import { Route, NavLink, useLocation } from 'react-router-dom';
```
今回は必要最低限のcssでご紹介します。
参考サイトのコードにはもっと整ったcssが載っていますのでご参考ください。
コンポーネントも別ファイルに作らず`App.js`に作っています。
Home,About,Contactの三つの画面をスライド遷移させます。

```react:App.js
const Home = () => <div style={styles.home}>Home</div>;
const About = () => <div style={styles.about}>About</div>;
const Contact = () => <div style={styles.contact}>Contact</div>;

const styles = {
  home: {
    color: '#fff',
    fontSize: '64px',
    background: 'rgba(255, 100, 0)',
  },
  about: {
    color: '#fff',
    fontSize: '64px',
    background: 'rgba(0, 150, 255)',
  },
  contact: {
    color: '#fff',
    fontSize: '64px',
    background: 'rgba(44, 219, 88)',
  },
}
```
そしてこちらがスライド機能の部分です。
`useLocation`でページのURLのpath情報を読み取り、
`duration`はスライドの秒数を指定することが出来ます。

```react:App.js
const App = () => {
  const location = useLocation();

  return (
    <>
      <nav>
        <NavLink to="/" exact>Home</NavLink>
        <NavLink to="/about">About</NavLink>
        <NavLink to="/contact">Contact</NavLink>
      </nav>

      <SlideRoutes location={location} duration={500}>
        <Route path="/" component={Home} exact />
        <Route path="/about" component={About} />
        <Route path="/contact" component={Contact} />
      </SlideRoutes>
    </>
  );
};

export default App;
```
#終わりに
今回はReactの画面遷移をスライドで表現する方法をご紹介いたしました。
画面遷移時にアニメーションがあるのと無いのでは使い心地が違いますよね。
最後まで読んでいただきありがとうございます。また新たな発見を発信したいと思います。
画面キャプチャー(ハードコピー、スクリーンショット)のとり方5選

システムのテストで画面キャプチャーを取得する機会が多いので、いろいろな画面キャプチャーの取り方をまとめる。

## 画面キャプチャー・ハードコピー・スクリーンショット

呼び方は様々ですが、どれも同じ意味。

ハードコピーはもともともは印刷を意味するような言葉だったが、現在では画面を画像ファイルとして保存することを指す。

## 環境

OS：Windows 10

## 1. PrintScreen

ディスプレイに表示されている画面全体のキャプチャーをクリップボードに取得するショートカットキー。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397389/8e731ddf-9f25-3afc-8e2e-1cf0b082c8eb.png)
引用元：https://www.dospara.co.jp/5info/cts_str_pc_screenshot

キーボードのPrintScreenキーを押すことで使える。
（ノートパソコンなどではFnキーを同時に押す必要があることもある）

## 2. Alt + PrintScreen

押した時点で選択しているウィンドウ（アクティブウィンドウ）の画面キャプチャーをクリップボードに取得するショートカットキー。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397389/6479fad5-26ec-3897-8349-6be199da59af.png)
引用元：https://www.dospara.co.jp/5info/cts_str_pc_screenshot


キーボードのAltキーとPrintScreenキーを同時に同時に押すことで使える。

## 3. Windows + Shift + S

Windows10から追加された機能。

選択範囲のキャプチャーをクリップボードに取得するショートカットキー。

ショートカットキーを押下すると、カーソルが表示されるので、キャプチャーしたい範囲を指定することで使える。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397389/7d7274c8-69af-d219-11b3-389872ebfe77.png)
引用元：https://www.dospara.co.jp/5info/cts_str_pc_screenshot

## 4. Chromeでページのスクリーンショットを取る
Chromeでは開発者ツールでページ全体のスクリーンショットを取得できる。
※Chrome以外のChromiumベースブラウザでも利用可能

F12で開発者ツールを表示する。
![2021-01-26_16h38_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397389/0d983c68-1a92-ff5b-1922-248373a0a043.png)

Ctrl + Shift + P を押して`>`が表示された状態にする。
![2021-01-26_16h38_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397389/47e9b78d-9003-a650-175c-37462232fb87.png)

「full」と入力して「Screenshot Capture full size screenshot」を選択する。
![2021-01-26_16h38_55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397389/0f1e1ec3-95fc-ac92-008b-95bf5c709742.png)

スクリーンショットがファイルとしてダウンロードされる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397389/3ef16129-de62-94e6-ec19-8f96a4886fe6.png)

ページ全体のスクリーンショットが取れている。
![2021-01-26_17h28_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397389/ca2e8c4b-a2a2-ad23-5a26-0b46ff15ab00.png)

## 5. Screenpressoを使う（外部ツール）

無料で利用できる画面キャプチャーツール。

常駐させておけばPrintScreenキーで起動もできるので簡単に使えて、ある程度の加工もできるのでスクショしてサクッと修正して共有とかができる。

[Screenpresso：Windows用の究極のスクリーンキャプチャツール](https://www.screenpresso.com/ja/)

## まとめ

個人的にはScreenpressoを使っているが、仕事用のパソコンに勝手にインストールしていいかは現場次第なので、普段はChromeの開発者ツールを使う機会が多い。
ページのURLをファイル名にしてくれるので、どこのページのスクショなのかひと目で分かるのも便利。
動画ファイルからフレームを並べてサムネイルを作成

動画から画像を作成します。1フレームだけで画像にするのではなく、時系列にサムネイルを並べた画像を作りたいと思いました。先に結果だけ見せるとこんな画像です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/d12b22b1-7992-20bf-911a-f1d64172b22d.png)

最初のフレームをメインの画像にして、その下にサムネイルを並べています。

これは昔作った以下の動画をもとに作成した画像です。画像がぼやけてるのは動画の質が悪いのかも。

- [走るRaspberry Pi - YouTube](https://www.youtube.com/watch?v=wFTvOIsHmQo)

こういう画像を動画ファイルから生成するPythonコードを書きました。

OpenCVを使っています。OpenCVについては昨日も記事にしました。

- [動画ファイルからサイズ情報やサムネイルをPythonのOpenCVで取得](https://qiita.com/suzuki-navi/items/ffe449c95fb6e1faf891)

以下がPythonコードです。

```python
import cv2

def buildVideoCaptures(videoPath, outputPath):
    cap = cv2.VideoCapture(videoPath)
    if not cap.isOpened(): return

    # 最初のフレームの画像を取得
    _, first_img = cap.read()

    # 動画のフレーム数を取得
    frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

    # 連続サムネイルを作成
    n = 9 # サムネイルの数
    thumbnail_imgs = []
    for i in range(n):
        # フレームの番号を設定
        cap.set(cv2.CAP_PROP_POS_FRAMES, (i+1) * frame_count / (n+1))

        # 設定したフレーム番号の画像を取得
        _, img = cap.read()

        thumbnail_imgs.append(img)

    # 9つのサムネイルを横に結合
    thumbnails_img = cv2.hconcat(thumbnail_imgs)

    # 画像サイズを取得
    first_width = first_img.shape[1]
    first_height = first_img.shape[0]
    thumbnails_width = thumbnails_img.shape[1]
    thumbnails_height = thumbnails_img.shape[0]

    # 連続サムネイルのリサイズ後のサイズを決定
    new_width = first_width
    new_height = int(thumbnails_height * new_width / thumbnails_width)

    # 連続サムネイルをリサイズ
    thumbnails_img = cv2.resize(thumbnails_img, (new_width, new_height))

    # 最初のフレーム画像と連続サムネイルを縦に結合
    # 最初のフレーム画像の下に連続サムネイル
    concat_img = cv2.vconcat([first_img, thumbnails_img])

    # 画像ファイルで書き出す
    cv2.imwrite(outputPath, concat_img)

buildVideoCaptures("./sample.mp4", "./thumbnail.jpg")
```

最初と途中の全部で10個のフレームを画像として抜き出して、OpenCVの `resize`, `hconcat`, `vconcat` でリサイズや結合しているだけです。
【Android】Intentリンクを作成する

## はじめに
前回はターミナルからadbコマンドでアプリを開いてみた。[前回記事](https://qiita.com/kilalabu/items/7b84694d542250259e78)
今回はリンクをタップするとアプリが開く実装をする。
![book.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670405/fed0f58f-6ca0-5492-6c79-49cf6b79aef5.gif)


## インテントリンクについて
Androidではインテントリンクを使うとWebページから直接アプリを起動できる。
また、タップした時点でアプリがインストールされてなければPlayStoreに遷移することも可能。

### 構文
インテントリンクを作成するには以下の構文に沿って作成する必要がある。
※ 全て設定する必要はない。

```
intent:  
   HOST/URI-path
   #Intent;  
      package=\[string\];  
      action=\[string\];  
      category=\[string\];  
      component=\[string\];  
      scheme=\[string\];
   end;
```

## 作成手順
### ①Manifestファイルの設定
遷移させたいアクティビティにaction,category,scheme,hostの設定を記述する。

```xml:AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bookmanager_android">
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application>
        <!--  application,その他activityの記述は省略  -->
        <activity
            android:name=".AdditionalBookActivity"
            android:label="@string/page_title_additional"
            android:exported="true">
            <!--  遷移させたいactivityに下記を記述する  -->
            <intent-filter>
                <action android:name="android.intent.action.VIEW"/>
                <category android:name="android.intent.category.DEFAULT"/>
                <category android:name="android.intent.category.BROWSABLE"/>
                <data android:scheme="bookapp" android:host="book"/>
            </intent-filter>
        </activity>
    </application>

</manifest>
```


### ②Manifestファイルをもとにintent構文を作成（②は飛ばしてもよい)
```
intent:  
   book
   #Intent;  
      package=com.example.bookmanager_android;
      scheme=bookapp;  
   end;
```
### ③intent構文をもとに作成したaタグを埋め込む

```
<a href="intent://book#Intent;package=com.example.bookmanager_android;action=view;scheme=bookapp;end;">book</a>
```
intent構文をつなげたものをaタグにし、リンク化してくれるアプリ等で試す。
今回はplaycodeを利用した。 https://playcode.io/

## 参考サイト
https://developer.chrome.com/docs/multidevice/android/intents/
https://developer.android.com/guide/components/intents-filters.html