OmniAICreator/Qiita-1.07M huggingface dataset:
StrongParametersの使い方

#はじめに
本記事では「StrongParametersを使用するとどんな利点があるのか」「基本的な使い方」についてまとめていきます！
#StrongParametersの歴史
rails4から導入された機能。
rails3までMassAssignmentを使用していたが、脆弱性の問題があった。

#StrongParametersで何ができるのか？
>strong parametersを用いることで、Action Controllerのパラメータが許可されるまでActive Modelの「マスアサインメント」に利用されることを禁止できます。つまり、多くの属性を一度に更新したい場合は、どの属性のマスアップデートを許可するかを開発者が明示的に指定しなければなりません。大雑把にすべての属性の更新を一括で許可してしまうと、外部に公開する必要のない属性まで誤って公開してしまう可能性が生じるため、そのような事態を防ぐための機能です。[Railガイド]

・開発者が意図的に必要な属性のみを指定し、取得することができる
・マスアサインメント脆弱性の問題を防ぐことができる。
・意図しない情報の更新や作成を防ぐことができる。


#使い方
サンプルコードを使いながらそれぞれのコードについて解説していきます。
###ビュー
privateを指定した場合以下のようにモデルを指定する必要がある。
「params.require(:user)..」の場合。

```
<%= form_with model:@user do |form| %>
```
##コントローラ
###[ユーザー情報の取得]

```
private
 def user_params
   params.require(:user).permit(:name,:email)
 end
```

####private(呼び出し制限)
privateの配下にメソッドを定義することで、クラス外からのアクセスを防ぐことができる。他のクラスではprivate配下のメソッドを使用することができないということ。
※注意点としては、privateはコントローラの最下部に設置すること。配下にあるメソッド全てをアクセス制限してしまうから。
また、protectedという他のインスタンスでも使用できるようにするメソッドもあるが使用頻度は低い。
####params.require(キーのオブジェクトを指定)
require(:user)とすることで、特定のオブジェクト(user)を定め、キーを指定して取得することができる。
requireを使用する場合、permitでキーを指定する必要がある。
####permit(キーの取得)
permit(:キー)とすることで、そのキーの値を取得することができる。
また、permit!とするとrequireで指定したmodelのキーを全てに権限を与え、取得することも可能。
###merge(外部の値を取得)
paramsでは取得していない値を指定することができる。

```
params.require(:user).permit(:name,:email).merge(user_id: @current_user.id)
```
###[呼び出し方]

```
def create
 @user = User.new(user_params)
end
```
User.new(メソッド)とすることでprivateで定義したメソッドの情報を取得することができる。
この場合、user_paramsで指定したキー全てを取得することができる。



##まとめ
・ストロングパラメーターを使用することで取得する値を制限することができ、マスアサインメントの脆弱性を防ぐことができる。
・メソッドを定義することで簡単に値を取得することができ、リファクタリングにもなる。


##補足(param is missing or the value is empty: user)
requireを使用した時に以下エラーが発生したのでその対処法について。

```
params.require(:user).permit(:content...)
```
![スクリーンショット 2021-04-18 21.58.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613784/d9660517-8417-9c08-bc14-e3e0fe5ed41e.png)
param is missing or the value is empty: user
エラー内容としては、paramsが存在しないか空の状態であるということ。
結論から言うと、

```
params.permit(:content,:material,:period)
```
require(:user)を消しちゃうとエラーは解決できる。
画像でも確認できるようにパラメーターに値は入っているけど、存在しないという内容のエラーになっている。
原因については、以下の記事がわかりやすかった。
[param is missing or the value is empty エラー](https://teratail.com/questions/169855)

```
content: params[:user][:content]...
```
恐らく、今回の場合だと、上記のようにキーが重複しているため、おきたエラーだと思う。
間違っていたらご指摘いただけると嬉しいです。

###追記2021/4/21
params is missing..なのでメソッドの中身をデバックを使用しで把握することでより原因がわかりやすい。



##参考資料
[Railsガイド](https://railsguides.jp/action_controller_overview.html#strong-parameters)
[【Ruby on Rails】ストロングパラメータって何なの？](https://qiita.com/ozackiee/items/f100fd51f4839b3fdca8#%E3%83%A2%E3%83%87%E3%83%AB)
[rubyonrails.org](https://api.rubyonrails.org/classes/ActionController/Parameters.html)
[【Rails】param is missing or the value is empty:について](https://qiita.com/Takka_Log/items/32dae78d7e3892e7b051)
Power Automate Desktop を使ってみた（CSVファイルの読み込み）

# 事前準備
読み込み対象のCSVを作成します。

* 保存先フォルダ
D:\

* ファイル名
読み込み.csv

* 読み込み.csvのファイル内容
行数,説明
1,1行目
2,2行目




# フロー作成
## CSV読み込み
左側の
　　ファイル　＞　CSVを読み取ります
をフローに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/a6d42e8c-a758-8dd0-48a9-16982242462b.png)

下記の通り読み取るCSVファイルの情報を設定する画面が表示されるので、適宜指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/39e5793c-9c6c-a1b3-dd1f-5c9287b88e80.png)
※ここでは
　　ファイルパス：D:\読み込み.csv
　　エンコード：UTF-8
を指定しています。

## CSVの行数分の繰り返し処理
左側の
　　ループ　＞　For each
をフローに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/c1cf6c1a-045d-6e50-d50b-fd7cff03ea13.png)

「反復処理を行う値」に「CSV読み込み」で生成された変数「%CSVTable%」を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/d996d6bd-a9d9-59e2-4f17-4ba39e4b7156.png)

## メッセージ表示（ＣＳＶの内容確認用）
左側の
　　メッセージボックス　＞　メッセージを表示
をフローに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/592861f8-45c9-c0e3-ad96-42f21c22cfa0.png)
CSVの値を取得する方法について

* %CurrentItem[0]%のように番号で指定
* %CurrentItem['行数']%のようにCSVの項目名

の2通りあります。
今回はどちらでもCSVの値が取得できることの確認として、
「表示するメッセージ」に
%CurrentItem[0]%
%CurrentItem[1]%
%CurrentItem['行数']%
%CurrentItem['説明']%
を指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/66297b7f-092b-e6c3-6c25-cec844509f2d.png)

# 作成したフロー確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/07ffa9bc-320e-f4e0-12fc-b8f68b0b533f.png)



# 実行結果
下記のメッセージが表示され、
CSVの内容が読み込めていることが確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/14de41cd-6547-fc96-f17d-c344c207fce6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/53ad057b-a953-8731-7ab3-173de0bf06e8.png)
Power Automate Desktop を使ってみた（メインフローからサブフローを呼び出し）

# 概要
エンジニアであればイメージできると思うのですが、
処理を外出しにしたい場合があると思います。
当記事では

* メインフローで変数を指定
* メインフローからサブフローを呼び出し
* メインフローで指定した変数の値でブラウザを表示

の手順を記載いたします。


# フロー作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/cefe346c-e6cb-9608-c070-c0d18b0647be.png)

# サブフロー作成（1）
※ここではメインフローから呼び出すために作成だけおこない、
　処理は作成しません。　

サブフローをクリックするとプラスボタンが表示されるので、
プラスボタンをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/00b2e73a-bf68-00ce-1e24-8e42e287b378.png)

下記の画面が表示されるので、任意のサブフロー名を入力します。
※今回はデフォルトのまま「Subflow_1」とします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/913feceb-00cf-c1c9-2c5d-c5db28043c77.png)

すると、下記の通り作成した「Subflow_1」が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/f314eed0-fcf5-9ec4-acdc-1ae583f4cd5f.png)

# メインフロー作成
左側に表示されいる
　　変数　＞　{X}変数の設定
をフローに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/a46b30ab-0c11-5b60-ac5c-0eadf1876f46.png)
変数の設定画面が表示されるので、
　　設定：URL
　　宛先：https://www.yahoo.co.jp/
を入力してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/29b90de0-d3e4-e91a-0e44-9501554e24c7.png)

左側に表示されている
　　フローコントロール ＞　サブフローの事項
をフローに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/1bbc3b2d-2bd0-afd2-98cd-e322a821d5d9.png)

下記の画面が表示されるので、
作成したサブフローを指定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/0cba46c0-a26e-ce36-2583-f4588d28ea11.png)

# サブフロー作成（2）
左側に表示されている
　　Webオートメーション ＞　新しいInternet Explorer
をフローに追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/d7454126-045e-49bf-a75e-d216a23da3f1.png)

初期URLにメインフローで指定した変数「URL」を指定するため、
「%URL%」を入力してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/f8dc17d2-22a1-65bb-0567-4ed2ad7665cf.png)

※{X}をクリックすると下記のように使用可能な変数が表示されるので、
　選択しても可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/128b3f50-ddd7-6075-187c-6fcd33bcd58f.png)


# メインフロー、サブフローの確認
上記の手順をすることで下記の通りフローが作成されていると思います。
## メインフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/2a86f5bf-bd7a-ea58-5707-bff0ff9fc893.png)

## サブフロー
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/f356cf2a-a0fe-cbca-7419-3e6a04e9c155.png)


# 実行確認
メインフローを実行すると、
メインフローで設定した変数「URL」の値でブラウザが表示されます。
Power Automate Desktop を使ってみた（フロー作成、実行）

# 概要
当記事では、
* フローを作成（IEを起動し特定のサイトにアクセス）
* フローの起動
の手順を説明します。

# フローを作成（IEを起動し特定のサイトにアクセス）
「新しいフロー」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/47c2384c-aa49-392b-1424-e21e3f5aac92.png)

任意のフロー名を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/946822c3-f513-9df5-4c45-9f725c3d28f6.png)

すると、下記の画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/e23acbb1-9b24-572f-f661-0c44062c093f.png)

左側にある
　　Webオートメーション　＞　新しいInternet Explorerを起動します
をマウスで「Main」内にドラッグ＆ドロップします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/08302066-d32e-efe7-485e-55389dad265f.png)

下記の画面が表示されるので、
「初期URL」に「https://www.yahoo.co.jp/」を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/73108a30-c583-e90b-b837-26396109229f.png)

以上でフローの作成は完了です。
ちなみに上記の手順で下記の表示になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/531e3977-27c9-f14a-2a83-b2fb509b27a9.png)

# 実行
上段にある三角のボタン（▷）をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/1c020589-db98-8dd8-cdfe-cd3d9740e245.png)

すると下記の画面が表示され、フローで指定したURL「https://www.yahoo.co.jp/」にアクセスできたことが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/67e761b3-c7f2-ca26-5994-e8c391179adb.png)
Power Automate Desktop を使ってみた（環境構築）

# ダウンロード
下記URLにアクセス後、「無料で試す」を押下しダウンロードできます。
https://flow.microsoft.com/ja-jp/robotic-process-automation/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/99586ca0-9595-9a53-fb3f-5f9b5c81bca0.png)


# インストール
基本的にはデフォルトで設定されている内容で問題ないですが、
インストールフォルダなど好みで選択してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/c6e1bb38-e40c-fdb2-106c-542f48650c2c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/93250a09-dd25-1dee-383d-d0079453ad34.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/e15a3ae4-1112-3230-aeac-14fd241488d4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/d745ec6f-a074-5430-ab27-10e269d6f797.png)

# 起動
起動するとログインを求められるのでログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/dbfb6432-c6a1-38ad-4bc3-0225fc0e448f.png)

国、地域の選択を求められるので、適切に選択してください。
※今回は「日本」を選択しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33640/8e90a192-e30a-8596-c665-35124a24787a.png)
JavaScript基礎メモその1

# 文字を出力する(表示）
「console.log("○○");」というコードを書くと、( )の中の○○という文字がコンソールに出力される。
末尾のセミコロン( ; )を忘れないようにする。
>```Javascript
console.log("Hello World");
```

結果
Hello World

# コメントアウト
文頭に『//』を書くとその行はコメントとみなされる。
>```Javascript
//コメントアウト
```

結果
※コメントは出力されない

##文字列と数列
『"5 + 2"』のようにクォーテーションをつけると文字列と解釈されそのまま表示される
>```Javascript
console.log(5 + 2);
console.log("5 + 2"); 
console.log("3" + "5");
```

結果
7
5 + 2
35

# 変数
変数は『let 変数名 = 値』と定義する。
letは変数の宣言、nameは変数名、"jhon"は代入する値となる。
>```JavaScript 
let name = "john";
console.log(name);
console.log("name");
console.log("name" + name);
```

結果
john
name
namejohn

#変数の更新
『変数名 = 新しい値』と書くと値が更新される。
>```Javascript
let name = "john";
console.log(name);
name = "Kate";
console.log(name);
```

結果
john
Kate

# 変数自身の更新
例　変数numberに3を足す。
>```Javascript
let number = 2;
console.log(number);
number = number + 3;
console.log(number);
```

結果
2
5

# 更新省略形
x = x + 10 → x += 10と省略できる。
- * / % も同じように省略できる。

>```javascript
let number = 2;
console.log(number);
number += 3;
console.log(number);

結果
2
5

#定数

変数と違い定数は値を更新することはできない。
>```javascript
const name = "john";
console.log(name);
```

結果
john

# テンプレートリテラル
テンプレートリテラルを用いることで、文字列の中に定数(変数）を埋め込むことができる。
文字列全体をバッククォーテーション（ ` ）で囲む必要がある。
>```javascript
const name = "たかし";
console.log(`こんにちは、${name}さん`);

結果
こんにちは、たかしさん

#if文
if文を用いることで『もしも〇〇ならば※※を行う』という条件分岐ができる。
>```javascript
const number = 12;
if (number > 10) {
  console.log("numberは10より大きいです");
}
```
結果
numberは10より大きいです

#比較演算子1
>```javascript
const number = 12;
console.log(number < 30);
console.log(number <= 12);
console.log(number > 12);
console.log(number >= 12);

結果
true
true
false
true

#比較演算子2

>```javascript
const number = 12;
console.log(number === 12);
const name = "john";
console.log(name !== "jhon");

結果
true
false

#else
if文が成り立たない時の処理を行うときに用いる。
『もしも〇〇ならば※※を行う、そうでなければ□□を行う』という処理ができる。
>```javascript
const age = 17;
if (age >= 20) {
  console.log("私は20歳以上です");
} else { 
  console.log("私は20歳未満です");
}

結果
私は20歳未満です

#else if
elseよりもさらに条件を増やしたい場合にelse ifを用いる。

>```javascript
const age = 17;
if (age >= 20) {
  console.log("私は20歳以上です");
} else if (age >= 10) {
  console.log("私は20歳未満ですが、10歳以上です");
} else {
  console.log("私は10歳未満です");
}

結果　
私は20歳未満ですが、10歳以上です

#条件式
『かつ』は『&&』で表し、『または』は『||』で表す
>```javascript
const age = 24;
if (age >= 20 && age < 30) {
  console.log("私は20代です");
}

結果
私は20代です

#switch文
switch文はある値によって処理を分岐する場合に用いる。
switch文ではbreakが重要でありbreakがないと合致したcaseの処理を行ったあと、その次のcaseの処理も実行されてしまう。
>```javascript
const color = "赤";
switch (color) {
  case "赤":
    console.log("ストップ！");
    break;
  case "黄":
    console.log("要注意");
    break;
}

結果
ストップ！

#switch文 - default
switch文の条件の値がcaseのどれにも一致しなかった時、defaultのブロックが実行される。

>```javascript
const color = "黒";
switch (color) {
  case "赤":
    console.log("ストップ！");
    break;
  case "黄":
    console.log("要注意");
    break;
  default:
    console.log("colorの値が正しくありません");
    break;
}

結果
colorの値が正しくありません
Swift - frameとboundsの違い

#はじめに
初回の投稿ですが、お手柔に宜しくお願いします〜
ところで、frameとboundsの違いについて結構最近やっとわかった、記録しておこうかなと思います。
#frameとは
frameはsuperviewが基準にして相対的な座標・大きさを返すプロパティ
#boundsとは
boundsは要素自身が基準にして相対的な座標・大きさを返すプロパティ
#コードで理解

```sample.swift
let yellowView: UIView = UIView()
    
yellowView.backgroundColor = UIColor.yellow

yellowView.frame = CGRect(x: 50, y: 50, width: 100, height: 100)

self.view.addSubview(yellowView)

// Yellow ViewのFrameとBoundsをプリントアウト
print("Yellow View Frame: \(yellowView.frame)") // Frameをプリントアウト
print("Yellow View Bounds: \(yellowView.bounds)") // Boundsをプリントアウト
```
結果は以下：
![截圖 2021-04-18 21.24.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1326861/83e8ea5b-b85c-8450-d7d9-7f33157474be.png)
boundsは自分自身が基準なので、特に設定してない場合x、y両方0です。
#画像で理解
![截圖 2021-04-18 19.16.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1326861/f9bbdab3-8034-e33e-6517-e52454438a79.png)
#boundsを設定した場合はどうなりますか
yellowViewにredViewをaddし、さらにyellowViewのboundsのx、yを（-20,-20）にしてみましょう。

```sample2.swift
let redView: UIView = UIView()

redView.backgroundColor = UIColor.red

redView.frame = CGRect(x: 0, y: 0, width: 50, height: 50)

yellowView.addSubview(redView)

print("Red View Frame: \(redView.frame)")
print("Red View Bounds: \(redView.bounds)")
```
結果はこうなってます：
![Simulator Screen Shot - iPhone 8 - 2021-04-18 at 21.51.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1326861/f4706013-b1fe-594f-f0e4-5667781577dc.png)
![截圖 2021-04-18 21.46.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1326861/1e9145f0-9164-7a7b-a3b1-b7677b173421.png)

また、yellowViewのboundsのx、yを（-20,-20）にしてみましょう。

```sample3.swift
yellowView.bounds = CGRect(x: -20, y: -20, width: 100, height: 100)
```

実行してみたら
![Simulator Screen Shot - iPhone 8 - 2021-04-18 at 21.55.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1326861/53b0f16a-1b91-3f5e-9b72-da1cb131b7aa.png)
原因は、yellowViewの原点座標は(-20,-20)になり、redViewの原点座標は(0,0)のままなので、redViewは右下に移動してしまいました。
HTMLとCSSだけでGoogle風検索ボックスを作ってみた

# 環境について
この記事ではWindows10のChromeブラウザーを利用しています。

# はじめに
Google風検索ボックスを作るにあたって今回は検索ボックスを以下のように分けることにしました。
![search_box.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1278153/c5d35e12-adf9-8388-8211-8b7d196bb1c9.png)
検索マークの領域と検索ボックスの領域と音声入力ボタンの領域をそれぞれ作成し、最後にCSSでうまくまとめようというわけです。
また、HTMLを ```index.html``` 、CSSを ```style.css``` に書き込むことにしました。

# 検索マーク、検索ボックス、音声入力ボタンを用意
検索バー全体を ```kyc-search-bar```, 検索マークを```kyc-search-mark```, 音声入力ボタンを```kyc-search-mic```とし、検索マークと音声入力アイコンはMaterial Icons を利用しました。

https://fonts.google.com/icons

また、検索ボックスは```autocomplete```オフにして、ブラウザ標準の検索候補を表示しない設定にしてあります。(恐らくこちらの方が見やすくなる。)

```html:index.html
<div class="kyc-search-bar">
    <i class="material-icons md-21" id ="kyc-search-mark">search</i>
    <input class="kyc-search-box" type="text" placeholder="検索" autocomplete="off">
    <i class="material-icons md-21" id ="kyc-search-mic">mic</i>
</div>
```

# CSSで検索バー全体をデザイン
検索バー全体は```display: flex```と```align-items: center```を利用することできれいに横並びにし、枠線は```border```で表現しました。
また、検索ボックスは ```width: 100%```とすることで検索バーの中いっぱいに表示しています。
モバイル対応としては、幅が480px未満の端末では横幅全体に検索ボックスを表示させるようしました。

```css:style.css
.kyc-search-bar{
    display: flex;
    align-items: center;
    justify-content: center;
    height: 45px;
    width: 550px;
    border-radius: 30px;
    margin: 5px;
    border: solid 1px #dcdcdc;
}
    
.kyc-search-box{
    font-size: 16px;
    width: 100%;
    border: none;
    outline: none;
}

i.kyc-search-mark{
    margin-left: 10px;
    margin-right: 5px;
    color: #9aa0a6;
}

i.kyc-search-mic{
    margin-right: 10px;
    cursor: pointer;
    color: #9aa0a6;
}

@media only screen and (max-width:480px){
    .kyc-search-bar{
        width: 90%;
    }
}
```
# 最後に
全コードは <a href ="https://github.com/voicenoid/google-search-box">GitHub</a>、
デモページは<a href ="https://voicenoid.github.io/google-search-box/">こちら</a>。
また、説明不足の点などがございましたらコメントにてご指摘よろしくお願いいたします。
Google ColabでDETRをCOCOdataset使って評価してみる

DETRを動かしてみようと思い、公式のGithubを見ながらgoogle colabでプログラムを動かしてみました。colabも初めて使ったのでそこ含めて色々メモしました。
DETRのGithub
https://github.com/facebookresearch/detr
#手順
1.google driveにgoogle colabの新規ファイルを作る
2.driveにcolabをマウント
3.cloneコマンドでリポジトリをコピー
4.cocoデータセットをダウンロードしてdriveに配置
5.main.pyを走らせて評価データで評価する

---
では詳しく見ていきます
まずcolabのファイルを新しく作ります。
My Driveにmachine_learningというファイルを作りその中にtestrun_script.jpynbを作りました。
どうやら大体はjupyter note bookと同じようですね。

次にdriveにcolabをマウントします。
次のコードを実行します

```python
from google.colab import drive
drive.mount('/content/drive/')
```
![スクリーンショット 2021-04-18 20.08.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205215/33c8285e-09e8-ce51-6633-3156261985bd.png)
実行結果のリンク先に飛んでコードをコピーして貼り付けましょう。
![スクリーンショット 2021-04-18 20.08.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205215/dcb3c121-2d35-a513-0140-17c442416263.png)
成功したらこのような表示が出ます

cloneコマンドでgithubから引っ張ってきます

```python
!git clone https://github.com/facebookresearch/detr.git
```
続いてデータセットを用意するため以下のリンクからダウンロードします
2017 Train images [118K/18GB]
http://images.cocodataset.org/zips/train2017.zip
2017 Val images [5K/1GB]
http://images.cocodataset.org/zips/val2017.zip
2017 Train/Val annotations [241MB]
http://images.cocodataset.org/annotations/annotations_trainval2017.zip
今回は評価だけ行うのでVal imagesとannotationsのみで構いません
これらをdriveに保存するのですが、ディレクトリは公式に指定されています。

```
path/to/coco/
  annotations/  # annotation json files
  train2017/    # train images
  val2017/      # val images
```
こんな感じにして欲しいらしいです
なのでdriveにダウンロードされたdetrにpath、その中にto、その中にcocoとフォルダを作り最後のcocoにtrain2017とanntationsを解凍してつっこみます。
こんな感じです。

![スクリーンショット 2021-04-18 21.10.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205215/2db100c7-1ae6-31d8-1f90-eb063fc49758.png)

いよいよval dataを使い精度を評価します
detrフォルダ内に適当にcolabを作ります。
タブの編集>ノートブックの設定>ハードウェアアクセラレータからGPUに切り替えます。
先ほどと同様にマウントして%cdでdetrまで移動します。
![スクリーンショット 2021-04-18 21.16.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205215/679c45f3-0e8a-7445-428c-2d3a757b8d90.png)
そして次のコマンドでdetr内のmain.pyを走らせます

```
!python main.py --batch_size 2 --no_aux_loss --eval --resume https://dl.fbaipublicfiles.com/detr/detr-r50-e632da11.pth --coco_path path/to/coco 
```
実行されて私の場合は37分ほどでevaluationが完了しました。
![スクリーンショット 2021-04-18 19.12.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205215/3e2fa031-1082-4148-4bd0-e8e8cf9b4fb8.png)

#データセットの置き場所がよくわからなかった話
最初データセットをdatasets内に適当に置いて実行したら
![スクリーンショット 2021-04-18 18.20.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1205215/ac9862ee-17fa-dd38-5ac5-0e1cc8fc18a9.png)
とエラーが出た
rootにファイルが存在していないらしい。
/path/to/cocoと相対パスでmain.pyから実行されているためpathファイルをdetr内に写した。
それでもまだエラーが出る。
なんでだろうと思い、スクリプトを遡ってみるとargparseで指定されているコマンドライン引数の--coco_pathで渡された値がroot = PATH(arg.coco_path)とbuild_cocoに渡されるパスになっていたので --coco_pathの引数を見ると/path/to/cocoとなっている。
ここで今まで気づかなかったけど相対パスなんだから/path/to/cocoじゃなくてpath/to/cocoとか./path/to/cocoじゃない？と思って変えたらうまく動きました。
この解決方法あってんのかな。。。
【初心者】PHP static修飾子

## はじめに
PHPのオブジェクト思考について学習している際に、static修飾子の挙動がわかりづらかったので調べました。（自分メモ）

## アクセス修飾子
アクセス修飾子としてよく使われるものは3つ。

* public・・・どこからでもアクセス可能
* private・・・同じクラス内からアクセス可能
* protected・・・クラス内とクラスを継承した子クラスからアクセス可能

## static修飾子とは
・あるクラスの全てのオブジェクトが一つの変数を共有したい時にグローバル変数を使わずに共有可能。
・クラスのインスタンスを生成することなく（つまりnewせずに）、staticで定義されたプロパティやメソッドを利用できる。

```animal.php
//動物クラスを定義
class Animal {
    public $name;
    public static $category = "動物";
}
$cat = new Animal();
$cat->name = "ネコさん";
$dog = new Animal();
$dog->name = "イヌさん";

echo $cat->name;        //ネコさん
echo $cat::$category;   //動物

echo $dog->name;        //イヌさん
echo $dog::$category;   //動物

// newしなくても使える
echo Animal::$category; //動物
```

上記の`$cat::$category;`は`$dog::$category;`はインスタンスとして静的プロパティを用いているが、`Animal::$category;`はインスタンスを生成せずにプロパティを用いることができている。このように<b>オブジェクトのインスタンスを生成せずに呼び出すことができる</b>。
このため、擬似変数$thisは、staticとして宣言されたメソッドの中から呼び出すことはできない。
【JavaScript】半角全角を考慮してテキストを改行させる方法

Canvasで意外と手こずった部分なので復習も兼ねて、似たようなものを作る人に少しでも参考になればと。Canvasに限らず使えると思う。


```diff_javascript
//改行して分割された文字列を入れるための配列
var textArray = [];
var text = '';
//改行させたい半角での長さ
const kaigyou = 8;
```
```diff_javascript
//文字列のバイト数を取得
const ByteCount = (string) =>{
    var byte = 0;
    for (i = 0; i < string.length; i++){
        if(string[i].match(/[ -~]/)){
            byte += 1; //半角の場合
        }else{
            byte += 2; //全角の場合
        }
    }
    return byte ;
}
```
```diff_javascript
//何文字目で改行するかを取得
const SliceCount = (string) =>{
    var count = 0;
    var byte = kaigyou;　
    for (i = 0; byte > 0; i++){
        if(string[i].match(/[ -~]/)){
            byte -= 1; //半角の場合
        }else{
            byte -= 2; //全角の場合
        }
        count++;
    }
    //byteが０になった時点で何文字カウントされたかを戻り値として返す
    return count;
}
```
```diff_javascript
const InputTextA = () =>{
  var byteRest = byte //残りのバイト数という変数
  var row = 0; 
  //HTMLでidをTextに設定してある項目の文字列を代入
  text = document.getElementById("Text").value;
  byte = ByteCount(text);

  textArray[0] = text; 
    //残りのバイト数が一行分より長い間はぐるぐる回す
    while(byteRest > kaigyou){
        var sliceNum = SliceCount(text);
        textArray[row] = text.slice(0,sliceNum);
        textArray[row + 1] = text.slice(sliceNum);

        text = textArray[row + 1];
        byteRest -= kaigyou; //１行分のバイト数を引く
        row ++;
    }
    DisplayText();

}
```



```diff_javascript
//テキストを描画
const DisplayText = () =>{
    if(text != ""){
        ctx.font = "23px 'ＭＳ ゴシック'";
        var row = 0;
        var byteRest = byte
        while(byteRest > 0){

            ctx.fillStyle = 'black';
            ctx.textBaseline = 'top';
            //30pxずつずらすことで改行している
            ctx.fillText(textArray[row],0, row * 30);

            row++;
            byteRest -= kaigyou;
        }
    }
}
```
下の画像で８バイトで改行できることが確認できます。
![benzumaker (6).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601978/5258389f-98fb-77cc-dc28-9cb250c804bc.png)
![benzumaker (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601978/fa5aa09f-ad80-e0f8-ebd9-f1af7beea7b7.png)
![benzumaker (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601978/b607c937-e696-4e20-ada1-4c32fae9daee.png)
GitHubのissueを活用した個人アプリの開発ステップ

##開発ステップ


###ステップ１　issueの作成

まず、GirHubの作業リポジトリでissuesを開き、New issueをクリックする。
タイトルを入力（必須）し、内容を入力（☑︎を押すとチェックボックスが作成されるので便利、『・』や『番号』などある）、完了したらSubmit new issueをクリックしてissueを作成する。
issueが作成されるので、このissueに基づいてブランチを作成する。このときissueに#番号が作成される。この#番号でコミットを紐付ける。
 
###ステップ２　ローカルリポジトリでブランチを切る

 ```
 # ローカルリポジトリ、ターミナルでブランチを作成。
 # ブランチ名に issue の #番号 を入れるとわかりやすい（ブランチは特に関連付けされる訳ではない）。
 $ git checkout -b ブランチ名#番号 もしくは $ git branch ブランチ名#番号
 $ git checkout ブランチ名#番号
 ```
###ステップ３　ローカルリポジトリ、ブランチ上でひたすら作業

issueを意識して作業をする。作業中に issue と作業内容がズレるやるべきことが出てきたらその都度備忘録的にissueを作成してもOK。

###ステップ４　ローカルリポジトリでコミットとリモートリポジトリにプッシュ

作業が終わった場合。変更内容を確認 → ステージに上げる → コミット → リモートにプッシュをする。

  ```
  $ git status
  $ git diff
  $ git add .
  （このとき コミットコメントに issue の #番号 を必ず入れる。）
  $ git commit -m '投稿機能実装 #番号'
  $ git push origin ブランチ名#番号
  ```

###ステップ５　GitHub（リモートリポジトリ）でプルリクエストを作成しマージする

プルリクエスト作成の前にGitHubに行ったらissueをクリックし、コミットがissueと関連付けられていることを確認できたらプルリクエストを作成する。タイトルにコミットコメントが自動で入力される（この#番号によりissueとプルリクエストも関連付けされる）。適時コメントを入力（チーム開発の場合はレビューをしてもらうため、それを意識してコメントできると良い）。Create pull request でプルリクエストを作成し、Merge pull requestでマージを完了する。

###ステップ６　issueを確認してクローズする
issueに移りCloseボタンを押して、Closedと表示されていれば完了。

###ステップ７　ローカルリポジトリのマスターブランチをリモートリポジトリと同じ状態にする

最後にローカル環境でマスターブランチに移動して更新

```
 $ git checkout master 
 $ git pull origin master
```
500 server error エラーの原因を確認する方法

#はじめに
AWSでデプロイした際に本番環境のみ上記のエラーが出ました。また、ローカルでも同じエラーも出たことがありました。500 server errorと表示されるだけでエラーの原因が分からず手探り状態になりました。これを解消するためにlogsファイルを使用してエラーの原因を突き止める方法を投稿いたします。

#条件
envファイルを作成・編集以外の対処になります

#投稿者の環境
MacBook Pro (13-inch, 2019, Two Thunderbolt 3 ports)
macOS Big Sur バージョン11.0.1
PHP 7.3.23
Laravel Framework 6.20.7

#エラー画像
現役エンジニア曰く、始末書を書かされるぐらい致命的なエラーみたいです・・・
![“スクリーンショット” 2021-04-18 20.12.41.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/4eed156f-6336-e79a-9ecf-376862060d69.jpeg)


#エラーの原因を探る方法
今回はlogファイルを使用しエラーの原因を突き止めます。
ターミナルを起動して下さい。本番環境のみ500 server errorが出る方はEC2を立ち上げて下さい。

###ステップ1
問題のあるwebアプリケーションをディレクトリ先に移動して下さい。

```
cd /Applications/MAMP/htdocs/webアプリケーション名
```

###ステップ2
logsファイルにディレクトリ先を変更。

```
cd storage/logs
```

###ステップ3
catでファイルの閲覧を表示させます。laravel.logはlogsファイルの中にあるファイル名になります。

```
cat laravel.log
```

###ステップ4
上記を実行するとlaravel.logのログの一覧表が大量に出てきます。#0から#60ぐらいまで出ると思いますが#0までスクロールして下さい。その上にエラー文が表示されていると思います。これを解決したら500server errorを解決できると思います。複数エラー出ている可能性もありますので一つずつ対処して下さい。投稿者はこの様なエラーが出ました。
![“スクリーンショット” 2021-04-18 20.41.46.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/698439/f1a731c4-2e6e-99e9-a61d-a1862569e1e6.jpeg)


#補足 logとは
アプリケーションは、1つのリクエストを取っても様々な処理が行われており、機能を維持しつつ拡張していかなければいけません。そのためにアプリケーションの状態を記録として残しておくことがログの役割です。

処理の中で適切にロギングすることで、開発する上で重要な情報を得ることができます。身近なことでいうとデバッグです、「この入力の時にこの処理起こるのおかしいな？どんな値として渡されているんだろう？」などロギング処理を埋め込むことで処理途中のアプリケーションの状態の一部を確認することができます

#最後に
如何でしょうか? envファイルを作成・編集する投稿が多いですがこの様な対処のQiitaはないと思いますので是非、参考にして下さい!

#参考文献
[Laravel自体で発生したエラーのログはどこにでていますか？](https://teratail.com/questions/140767)
[ログを表示！Laravelでlogを出力させる方法【初心者向け】](https://techacademy.jp/magazine/18779)
【備忘録】MAMPが起動しなくなった時の対処法

備忘録

<h1>エラー内容</h1>
MAMPが起動しなくなった。

<q>Apache couldn't be started because port 8888 is in use by some other software.</q>

というエラーが発生した。

どうやら、MAMPで使用したいポート8888を何かで使ってしまっているらしい。

8888の使用状況を確認して、削除しなければ。。。

<h1>解決方法</h1>

ターミナルで下記を順番に実行

1、ターミナルで、ホームディレクトリから下記を実行
  $ sudo lsof -i -P | grep "LISTEN"

2、パスワードを求められるので、自分PCのロック解除パスワードを入力

3、10秒程待つと、ポートの状態が一覧で表示される
　※ここで、各行の右側の方に「8888」という数字を発見。

4、「8888」という数字がついた行の左側にある数字を使って、ポート使用の削除を実行する
  $ kill -9 XXXX （XXXXは該当する番号を入力）

5、改めて、1、のコマンドを実行
  ※4、で削除したものの表示がなくなっていると思います。

6、再度、MAMPを起動し、無事成功
Rubocop

# RuboCopの導入・実行手順
Rubyの静的コード解析ツールであるRubocopの導入方法について簡単にまとめておきます。
***
導入の流れ

1.Gemインストール
2.Rubocopファイル設定
3.Rubocop実行
***
### 1.Gemインストール

```ruby:Gemfile
group :development do
  gem 'rubocop', require: false
end
```
```:ターミナル
bundle install
```

### 2.Rubocopファイル設定
ファイル作成

```:ターミナル
touch .rubocop.yml
```
ファイル設定

```:.rubocop.yml
AllCops:
# 除外するディレクトリ（自動生成されたファイル）
# デフォルト設定にある"vendor/**/*"が無効化されないように記述
 Exclude:
   - "vendor/**/*" # rubocop config/default.yml
   - "db/**/*"
   - "config/**/*"
   - "bin/*"
   - "node_modules/**/*"
   - "Gemfile"


# 1行あたりの文字数をチェックする
Layout/LineLength:
 Max: 130
# 下記ファイルはチェックの対象から外す
 Exclude:
   - "Rakefile"
   - "spec/rails_helper.rb"
   - "spec/spec_helper.rb"

# RSpecは1つのブロックあたりの行数が多くなるため、チェックの除外から外す
# ブロック内の行数をチェックする
Metrics/BlockLength:
 Exclude:
   - "spec/**/*"

# Assignment: 変数への代入
# Branch: メソッド呼び出し
# Condition: 条件文
# 上記項目をRubocopが計算して基準値を超えると警告を出す（上記頭文字をとって'Abc'）
Metrics/AbcSize:
 Max: 50

# メソッドの中身が複雑になっていないか、Rubocopが計算して基準値を超えると警告を出す
Metrics/PerceivedComplexity:
 Max: 8

# 循環的複雑度が高すぎないかをチェック（ifやforなどを1メソッド内で使いすぎている）
Metrics/CyclomaticComplexity:
 Max: 10

# メソッドの行数が多すぎないかをチェック
Metrics/MethodLength:
 Max: 30

# ネストが深すぎないかをチェック（if文のネストもチェック）
Metrics/BlockNesting:
 Max: 5

# クラスの行数をチェック（無効）
Metrics/ClassLength:
 Enabled: false

# 空メソッドの場合に、1行のスタイルにしない　NG例：def style1; end
Style/EmptyMethod:
 EnforcedStyle: expanded

# クラス内にクラスが定義されていないかチェック（無効）
Style/ClassAndModuleChildren:
 Enabled: false

# 日本語でのコメントを許可
Style/AsciiComments:
 Enabled: false

# クラスやモジュール定義前に、それらの説明書きがあるかをチェック（無効）
Style/Documentation:
 Enabled: false

# ％i（）構文を使用していないシンボルで構成される配列リテラルをチェック（無効）
Style/SymbolArray:
 Enabled: false

# 文字列に値が代入されて変わっていないかチェック（無効）
Style/FrozenStringLiteralComment:
 Enabled: false

# メソッドパラメータ名の最小文字数を設定
Naming/MethodParameterName:
 MinNameLength: 1
```
### 3.Rubocop実行
Rubocop実行　＋　check内容自動修正

```:ターミナル
bundle exec rubocop -a
```
以上です
【iOS】テストの環境作成手順 (実機ビルドでテストする方法)


##この記事を書いた過程
前回の記事同様に、ほとんどiOS開発をした事がない状態で、iOSアプリのテストのタスクが回ってきたので手順をまとめました。
僕と同じ状態の人の助けになればと思います！

今回は、プッシュ通知機能があるアプリケーションをXcodeで実機でビルドしてテストを実施しました。
(※AWS SNSを利用してプッシュ通知を飛ばします。)

**前提**
Xcode 12
macOS Big Sur バージョン11.2
Swift 5.1

**流れはこんな感じです！**
1.テスト用の証明書の発行。
2.プロビジョニングファイルの作成。
3.Xcodeで作成したプロビジョニングファイルを使用するように設定する。
4.プッシュ通知が届くように設定する。
5.実機でビルドする。

####やっていく！

####1.テスト用の証明書の発行
・Xcodeで [Preference] → [Account] で 開発用アカウントでログイン。
・開発者を選択して、[manage certificates]をクリック。　左下の「+」から「Apple Developement」を選択して証明書を作成。
・Developer Center にログインして、証明書をダウンロードする。

####2.プロビジョニングファイルの作成
・Developer Centerにログイン(1と同じアカウント)
・[Profile] → [iOS App Development]を選択して、[Continue]
・該当のApple IDでを選択して、[Continue]
・1で作成した、証明書を選択して[Continue]
・テストで使用したいデバイスを選択する。(※新しくデバイスを登録したい場合は、上記、テスト用IOSデバイスの登録を参照)
・任意の名前を入力して、[Generate]をクリック。
・[Profile]で作成したプロビジョニングファイルを[Download]しておく。

####3.Xcodeで作成したプロビジョニングファイルを使用するように設定する。
・[Project] → [Targets] → [Build Setting] → [Signing] → [Code Signing Identity]で「IOS Developer」を選択
・[Project] → [Targets] → [General] → [Singing (Debug)] の[Provisioning file]から[Download Profile]を選択。2で作成したプロビジョニングファイルを選択する。

####4.プッシュ通知が届くように設定する
・[Project] → [target] → [Sigining & Capabilities] を開く
・[+Capabilities]をクリックして「Push Notification」を選択。
・[Background Modes]を選択。 → [Remote notifications]を選択。

####5.実機でビルドする
・プロビジョニングファイルに登録したiphoneをPCに接続。
・ビルドする機種に接続したiphoneを設定して、[▶︎]ボタン(ビルドボタン)をクリック。

**※テストする上での注意**
・テストでは、開発用のプラットフォームアプリケーションを使用してプッシュ通知を飛ばす必要がある。(AWSコンソールでで確認できる。)
・使用するプラットフォームアプリケーションのプッシュ通知証明書の期限が切れていないかを確認する必要あり
→　今回はここでハマりました。バックエンドのロジックが開発用と本番用で同じプラットフォームアプリケーションを使用するロジックになっていた為、プッシュ通知が飛ばなくて悩みました。。。


**参考**
○テスト用IOSデバイスの登録
https://support.smartbear.com/testcomplete/docs/app-testing/mobile/ios/preparing/registering-devices.html

○プロビジョニングファイルについて
https://qiita.com/edo_m18/items/6f10e57f95b25d9dab4e
https://qiita.com/fujisan3/items/d037e3c40a0acc46f618
https://zenn.dev/mhackit/scraps/355fe56dc7b4c8

○Bundle IDについて
https://qiita.com/miyamotok0105/items/f24a4e10a2877ae70bc4

○色々な用語の説明
https://qiita.com/toto_kit/items/df84cd687919ec28591b
[個人的な意見]価値あるプロダクト開発をするための考察

## この記事の目的
知識をつけるためではなく、価値を生み出すプロダクト（誰かの役に立ち、お金の流れができるもの）を作るにはどうすればよいか筆者なりに考えたことを記述します。

※きっとツヨツヨなベテランエンジニアの皆様には不快な思いをさせてしまうかもしれないため、考えが合わない時は広いお心でスルーしていただきたいです。
また共感いただけて良策をお持ちの場合、こうした方が良いのではといったご意見は歓迎しております。

※技術的内容にはなっていませんのであらかじめご了承ください。

## なぜ書いた？
筆者は今年の年始にunityで開発をしていたのですが、途中差し込みでやりたいことができました。

それが今日終わったのでまた開発に戻ろうと思って自分が作っていたものを見た時に、「え？これで遊べっていうの？？ていうか２ヶ月かけてこれしかできてないの？？」という感想を持ちました。

これまで筆者は、「プログラムとは理解してから組まなければならない。だから知らないことがあるうちは学んでから組み立てよう。」と思ってきたのですが、今日再開しようと思ってその手法で道のりを考えた時に、「自分が作りたいものはこのままいくと（低レベルな作品が出来上がるのが）5年後かな。」と思いました。

そこで冷静に考えてみたのですが、「5年かけたら、そもそも今使っている技術が最新鋭から3~4年遅れて大衆用に降りてきているため実質8~9年くらい前のゲームクオリティになる。5年後に今から9年前の技術レベル（例：パズドラ）か...しかも多分当時のクオリティにすら及ばないな...」となりました。

ここで対策はどうすればいいんだろうと考えていて、自分なりに結論が出たため記事にしようと思いました。
（個人で作る場合には学びたいのか価値を作りたいのか基準で考えて、戦略を練らないと結局何も出来上がらず終わってしまうと思ったため、自分への戒めも込めて記述しました。）

※学びたい場合は終わらなくていいのでぜんぜんOKだと思ってます。

## 主張したいこと

筆者が主張したいことはずばり`価値はまだ世に出回っていないものに付随する。だからすでに出来上がっているソースコードを考えるな、借りてきて組み合わせることに時間をかけろ`です。

価値あるプロダクトとはこれまでなかったプログラムです。

その中で求められているのは、誰が作ったか・綺麗なコードかではなく、”ちゃんと動くか” だけです。

なのでそこにフォーカスしてプログラムを作るのが価値を提供したいプログラマにとって大事になってくると思います。


## 筆者がこの主張をしている詳しい理由（箇条書きで列挙します）
- オブジェクト指向で隠蔽の性質を推奨しているように、昔の偉人たちの考えでは、プログラムを作る時最初から動いているものについては全て理解しなくてもよいという結論にあるのではないかと気づきました。
隠蔽している部分の理解が必要になったら学ぶ、それまでは求める挙動をしたら次を作るで良い、と考えられます。

- 基礎を組み合わせて端から端まで０ベースで挙動を作るのには、思いつくこと（設計）・表現すること（実装）・抜け漏れがないこと（テスト、運用/保守）を全てを実施する必要があります。元々ないものに関してはその作業は仕方ないと思いますが、すでに誰かが作ってくれたものがあるのにそれを使わないということは、使う人にその作業の時間分丸々差をつけられることになってしまいます。
例としてawsを取り上げてみます。
全て自分で作る考えでいく場合、極論awsも組むことになります。それを仮に１人で頑張って20年で組めたとします。しかしそれは20年前に提供されている価値なので、出来上がった頃には手作りしたawsの二番煎じはニーズがなくなっています。逆にその頃にはawsを使いこなしてきた人が浮いた時間を時代に求められる価値に投入することができます。結果後者の方が価値のあるプロダクトを作ることができるようになります。

- 新しい価値を生むときはバグったら初めて調査→理解すれば間に合うと思います。それよりもこだわって誰かと同じものを遅れて出してしまう方が自分の時間を有効活用できず機会損失につながってしまっていると考えられます。

- ただし、逆に既存の修正・リプレイスは直したい部分が明確だと思うので、その場合はちゃんと理解してオブジェクト指向に則って一行一行理解してファイルを構成していくと決めることで棲み分けをする必要があるため、理解の後に構築を求める方の需要ももちろんあると考えています。ただ今回は新規プロダクトを作る時の考え方として主張したいので、こちらでただし書きをさせていただきます。

## 最後に一言
つらつら長文を書きましたが、作業の前に`時間の使い方を間違ってないか`、`プロダクトの成長率は鈍化してないか`、`目的がぶれていないか（自分はものを作りたいのか、コードの書き方に詳しくなりたいのか）`を振り返ってみるのは、今後の作業全体を考えたとき、良い時間の使い方になるのではないかと思います。
vimでMarkdownを書きながらPreviewしたいので、previmを使う

### 目的

マークダウンを書いている時に、記法があっているかの確認をしたいときなどに

プレビューを表示する方法を調べました。

vimのプラグインの作者のサイトを見つけました。

作者曰く、下記点が既存の「Vim + Markdown環境」でのビューワーとの違いとのことです。

> Vimだけで完結します。

### 解決策

#### 前提

※ vimのプラグイン管理ツールとして、NeoBundleを使用しています。

#### 本題

1. vimの設定ファイルにNeoBundleで使用するプラグインを記述する
2. markdown形式の読み込みとキーマッピング

1.

    NeoBundle 'tyru/open-browser.vim'
    NeoBundle 'kannokanno/previm'

例えば、 ~/.vimrc などに設定します（※ ご自身の設定ファイルに記載してください）


2.

    autocmd BufNewFile,BufRead *.{md,mdwn,mkd,mkdn,mark*} set filetype=markdown

    " Previm
    let g:previm_open_cmd = ''
    nnoremap [previm] <Nop>
    nmap <Space>p [previm]
    nnoremap <silent> [previm]o :<C-u>PrevimOpen<CR>
    nnoremap <silent> [previm]r :call previm#refresh()<CR>

この設定をしておくと、「スペース」+「p」 => 「o」で編集中のマークダウンファイルのプレビューがブラウザで開きます。

ブラウザから印刷するとプレビューの表示のまま、印刷できます。

### 参考URL

- [Vim - 依存ツールなしにMarkdownプレビューできるprevimプラグインを作った](http://kannokanno.hatenablog.com/entry/2013/06/11/225806)
- [Previmでmarkdownをプレビューする設定](http://yoshiko.hatenablog.jp/entry/2014/04/18/Previm%E3%81%A7markdown%E3%82%92%E3%83%97%E3%83%AC%E3%83%93%E3%83%A5%E3%83%BC%E3%81%99%E3%82%8B%E8%A8%AD%E5%AE%9A)
バッチファイルで文字列長を取得する

Y子です。
今回は、文字列の長さを取得する方法を考えます。
考えましたが、どうもスマートな方法がなく、「1文字ずつ削るループを回して、文字列が空になったらループ回数が長さ」という泥臭い方法に落ち着きました。

# 概要・用途
引数に与えた文字列の長さを返します。
用途は幅広いと思いますが、たとえば「○桁以上は○○処理」のような判定に使えます。
_【[確認環境：Windows 10 Home (Bld. 19042.928)](https://qiita.com/koiwaiwaiko/items/ef2d457ae1e1a7c8b698 "Windows10のバージョンを確認・表記する")】_ →パッチ適用しました

# コード
```bat:get_strlen.bat
@echo off

rem 引数がない場合は終了する
if "%~1"=="" (echo 引数がありません & pause & exit /b)

rem 変数初期化(長さ)
set length=0

rem 長さ取得サブルーチンを実行
call :get_strlen %~1
echo 文字数：%length%
exit /b

rem ====サブルーチン====
:get_strlen
  set str_in=%~1
  
  :label_top
  rem 長さ加算
  set /a length+=1
  rem 1文字減らす
  set str_in=%str_in:~1%
  rem 文字列がなくなったら終了
  if not "%str_in%"=="" (goto :label_top)
exit /b
```

文字列長を取得する部分はサブルーチンにし、流用しやすくしました。
サブルーチンの中でループを回し、1文字削るごとにカウンタを+1します。
文字列がなくなったらループ終了し、そのときのカウンタの数値が文字列長です。

```:実行結果
> get_strlen.bat a
文字数：1

> get_strlen.bat 123456
文字数：6

> get_strlen.bat あかさたな
文字数：5

> get_strlen.bat ABCかきく
文字数：6

> get_strlen.bat !"#$
コマンドの構文が誤っています。
```

数値もアルファベットも日本語もカウントできますが、記号は苦手のようです。

# おわりに
Windowsコマンドには、文字列長を取得するものがないんですね。
PowerShell等の既成の機能を使えば、手間もかからず間違いもないかと思いますが、どうしてもバッチファイルだけでなんとかしなければならない場合のために、なんとかする手段を持っておくのも強みになるかもしれません。

ではまた。
フロントエンジニアがCSSだけで「サッカーボール」を作る

#どうも7noteです。再現シリーズ、サッカーボールをcssだけで作ってみた。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/661092/cf9b010e-33c7-f325-2209-bec244617d00.png" width="300" >

前回：[リアルなビー玉を作る](https://qiita.com/7note/items/942a47defa538aad5e97)

cssだけでサッカーボールを作りました。
前回ビー玉を作成したのですが、今回は5角形が多く入ってくるので、svg使わずcssだけの再現だったためソースが少し長くなってしまいました。
もう少し短くかけたらよかったのですが、現状の精一杯ですね。日々勉強です。

## サッカーボールのソース

```index.html
<div class="ball">
  <div class="pentagon c"></div>
  <div class="pentagon t"><span></span></div>
  <div class="pentagon tr"><span></span></div>
  <div class="pentagon br"><span></span></div>
  <div class="pentagon bl"><span></span></div>
  <div class="pentagon tl"><span></span></div>
</div>
```

```style.css
.ball {
  position: relative;
  width: 300px;
  height: 300px;
  border: 1px solid #666;
  border-radius: 50%;
  background-image: radial-gradient(at 30% 30%,#fff 40%, #bbb);
  box-shadow: 30px 70px 5px -30px rgba(0,0,0,0.3);
  overflow: hidden;
}

.ball .pentagon {
  position: absolute;
  width: 50px;
  border-left: 25px solid transparent;
  border-right: 25px solid transparent;
  border-top: 50px solid #000;
}

.ball .pentagon:before {
  position: absolute;
  top: -96px;
  left: -25px;
  width: 0;
  height: 0;
  content: "";
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 46px solid #000;
}


.ball .pentagon.c {
  top: calc(50% + 12px);
  left: 50%;
  transform: translate(-50%,-50%);
}

.ball .pentagon.t {
  top: -15px;
  left: 50%;
  transform: translateX(-50%) rotateZ(180deg) rotateX(60deg);
}

.ball .pentagon.tr {
  top: 28%;
  right: -35px;
  transform: rotateZ(252deg) rotateX(60deg);
}

.ball .pentagon.br {
  bottom: 4%;
  right: 16px;
  transform: rotateZ(322deg) rotateX(60deg);
}

.ball .pentagon.bl {
  bottom: 4%;
  left: 16px;
  transform: rotateZ(36deg) rotateX(60deg);
}

.ball .pentagon.tl {
  top: 28%;
  left: -35px;
  transform: rotateZ(108deg) rotateX(60deg);
}

.ball .pentagon.t::after,
.ball .pentagon.tr::after,
.ball .pentagon.br::after,
.ball .pentagon.bl::after,
.ball .pentagon.tl::after{
  content: '';
  width: 1px;
  height: 150px;
  background: #000;
  position: absolute;
  top: -220px;
  left: 50%;
}

.ball .pentagon span {
  width: 120px;
  height: 1px;
  display: inline-block;
  background: #000;
  position: absolute;
  top: -95px;
  left: 45px;
  transform: rotate(-55deg);
}
```

## 解説

①　5角形を6つ作成します。中心に1つ配置し、残りを5箇所回りに配置します。位置は...適当です。

②　ボールの縁になる円を描きます。回りに配置した五角形が少しはみ出るくらいの大きさにしておき、`overflow: hidden;`で円からはみ出た部分は非表示に設定。

③　回りに配置した五角形に疑似要素で線を付けて中心に向けて線を引きます。さらにspanでも線をつくり、これは回りの五角形同士をつなぐ線にします。

④　最後に立体感を出すために、ボール全体に円形グラデーションをかけて、影を適当に配置して完成！

## まとめ

イラストデータなどをみて「いけるかな」と思ったのですが想定よりも長くソースをかかないといけなくなってしまったので悔やみます。もう少しスッキリかければよかったのですが。

ただかなり柔軟な発送が必要になるのでcssの練習にはとてもいいかもしれないです。実用性はかなり低いですが・・・

また思いついたものを作っていけたらいいかなと思います。
だれかの参考になれば幸いです。

参考：
https://moru-web.com/?p=102
https://www.kitaguniweb.com/cat-webdesign/2014/p-6043/

#### おそまつ！
~ Qiitaで毎日投稿中!! ~
[【初心者向け】WEB制作のちょいテク詰め合わせ](https://qiita.com/7note)
SQLのin句の作成(キーに','を付ける)

# SQLのin句の作成用
* 自分用
* 目的：データ調査時の主キーでSQL作成する際、in句の作成時間短縮
* 今まで：エディタのキーボードマクロ
* これから：対象をクリップボードにコピーしてからpythonプログラムを実行
* 実行するとどうなる：  

■実行前 
aaa 
bbb 
ccc 
■実行後
in ( 
 'aaa' 
,'bbb' 
,'ccc' 
)
# 前提
pyperclipがインストールされていること 
pip install pyperclip
# コード
```python
#! python3
import pyperclip
text = pyperclip.paste()
lines = text.split('\r\n')

for i in range(len(lines)):
    if i == 0:
        lines[i] = ' \'' + lines[i] + '\''
    else:
        lines[i] = ',\'' + lines[i] + '\''
text = 'in (\r\n'
text = text + '\r\n'.join(lines)
text = text +'\r\n)'

pyperclip.copy(text)
```
【たったの3分】WindowsでLinuxコマンドを使えるようにする方法

# 背景
* 転職先でWindowsPCを使っているが、標準のコマンドプロンプトが不便
* コマンドプロンプトでもLinuxコマンドを使える方法を見つけたので紹介する

# WindowsでLinuxコマンドを使えるようにする方法
## 結論
**busybox**を入れましょう。

## 手順
### 1. busyboxのダウンロード
* 以下のサイトからWindows用のbusyboxをダウンロードする。(http://frippery.org/busybox/)
* サイトの下の方に、以下の記載があるので、**busybox64.exe**と書いてあるリンクをクリック

> The 32-bit binary above will work on 64-bit systems but if you have a 64-bit version of Windows > there's some advantage in using the 64-bit executable busybox64.exe. It's 667,136 bytes in size.

### 2. ダウンロードファイルの配置
* ダウンロードしたbusybox64.exeを好きなフォルダに移動
* busybox64.exeを置いたフォルダへPathを通す。

### 3. インストール実施
* コマンドラインでbusybox.exeを置いたフォルダへ移動
* busyboxをインストールする

```
> busybox64.exe --install
````

* インストールできていることを確認する。
(複数のexegz展開されていればOK)

### 4. 起動確認
どこでも良いので、`ls`などのコマンドを実行し、動作することを確認する

# 参考
[Windowsでbusyboxを用いてLinuxの基本的なコマンドを使用する](https://confrage.jp/windows%E3%81%A7busybox%E3%82%92%E7%94%A8%E3%81%84%E3%81%A6linux%E3%81%AE%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B/)
【Laravel】アクセサを使う

##はじめに
例えば、ユーザーの投稿数を取得したい時がある。
その場合、Laravelのアクセサを使えば、テーブルのカラムのように簡単に取得することができる。

##アクセサを使う

先程の例でいくと、アクセサを使わない場合はこんな感じで記述する。

```:view
{{ $user->posts（）->count() }}  
```

このままだと少し冗長でわかりにくいので、アクセサを使い、シンプルにする。

アクセサを使うときは、モデルに`get~Attribute`というメソッドを作成する。

```:User.php
namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    // 省略

    /**
     * 記事の投稿数を取得
     *
     * @return integer
     */
    public function getCountPostsAttribute()
    {
        return this->posts->count();
    }
}
```

このアクセサをControllerやviewで呼び出す場合は、`get`と`Attribute`を取り除いたスネークケースで記述する。

```:view
{{ $user->count_posts }}
```

モデルのプロパティ(テーブルのカラム)のように使えるので、シンプルでわかりやすい。

##おまけ
JSONレスポンスの場合は、$appendsを定義する必要がある。

```
    /**
    * モデルの配列形態に追加するアクセサ
    *
    * @var array
    */
    protected $appends = ['count_posts'];   // 追加

    /**
    * 記事の投稿数を取得
    *
    * @return integer
    */
    public function getCountPostsAttribute()
    {
        return this->posts->count();
    }
```

##参考
https://readouble.com/laravel/7.x/ja/eloquent-mutators.html
https://qiita.com/shonansurvivors/items/cd7ee1c038f9543eab8f
sacファイルからスペクトログラムを作成

#sacファイルからスペクトログラムを作成する

```psd_1day.py
import obspy
from obspy import read
from matplotlib import pylab as plt
import numpy as np
from mpl_toolkits.axes_grid1 import make_axes_locatable

#サンプリング周波数
samplerate = 100

#sacファイル読み込み
sac1 = read('200106_N.MMOH_U.s', debug_headers=True)#読み込みたいファイルをここに入力
#振幅データ（縦軸）
y = sac1[0].data

#データの頭の時刻
starttime = (sac1[0].stats.starttime)
#観測点名
station = (sac1[0].stats.station)
#グラフタイトル用
title = str(starttime) +'  ' + str(station)

#時間（横軸）．
time = np.arange(0, len(y))/samplerate

#グラフとグラフの隙間
plt.subplots_adjust(hspace=0.1)

#波形
ax1=plt.subplot(2,1,1)
plt.title(title)
plt.plot(time, y, color='black', linestyle='solid', linewidth = 0.3)
plt.tick_params(labelbottom=False)
plt.xlim(0, 86400)
plt.ylim(-5e-07, 5e-07)
plt.ylabel("Ground velocity [m/s]")

#スペクトログラム
ax2=plt.subplot(2,1,2, sharex=ax1)
plt.specgram(y, Fs=samplerate,scale='dB', vmin = -200, vmax = -150, cmap = 'jet',NFFT = 1024, noverlap = 512)
plt.ylabel("Frequency [Hz]")
plt.xlabel("Time [s]")
plt.xlim(0, 86400)
#カラーバー
ax=plt.colorbar(orientation='horizontal', aspect=10, shrink=0.2)
ax.set_label('Intensity [dB]')
```
#結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1101426/04e2535d-3588-38e6-1c72-13a931b25479.png)
2020/01/06 松本観測点

カラーバーの位置どうにかしたい
window.rootViewController入れ替え時のアニメーション

重要な点は、`UIView.transition`の`animations`でViewControllerの入れ替えをするのではなく、先に入れ替え処理を書いてから`UIView.transition`を呼び出すこと。（animations引数は空のクロージャ。）

```swift
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?

    ...
    
    func setRootViewController(_ vc: UIViewController) {
        guard let window = window else {
            return
        }
        window.rootViewController = vc
        UIView.transition(
            with: window,
            duration: 0.5,
            options: .transitionFlipFromLeft,
            animations: {},
            completion: { _ in })
    }

}
```

こんな感じでアニメーションさせられます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565474/28949fda-528f-3bea-7075-fb9d2361671f.gif" width="50%" height="50%" />

アニメーションの種類は他にもあるので `.transitionFlipFromLeft` に定義ジャンプして確認してみてください。

ページ送りやフェードのアニメーションもできます。

# 参考

[Swap rootViewController with animation?](https://stackoverflow.com/questions/41144523/swap-rootviewcontroller-with-animation)
NFSサーバーの作り方・設定方法

# はじめに

業務でNFSサーバーを建てる機会があったので作成手順を残します。サーバー側、クライアン側ともにCentOS 7。

# 構成
```
# サーバー側
/var/nfs

# クライアント側
/mnt/nfs
```

# SELinuxをオフ
```
$ vi /etc/selinux/config
SELINUX=enforcing
↓
SELINUX=disabled

$ reboot
```

# サーバー側で行うこと
```
$ yum install -y nfs-utils
$ vi /etc/exports
/var/nfs 192.168.◯.◯/255.255.255.0(ro)

# 反映と確認
$ exportfs -ra
$ exportfs -v

# ファイアーウォールの設定
$ firewall-cmd --permanent --zone=public --add-service=nfs
$ firewall-cmd --reload

$ systemctl start rpcbind nfs-server
```

# クライアント側で行うこと
```
$ yum install nfs-utils
$ mount -v -t nfs 192.168.◯.◯:/var/nfs /mnt/nfs
```

これでいけるはず。
[備忘録]anaconda (仮想環境)きれいにしたら、18GBも容量確保できた話

# TL;TR
- macの容量がなくなったので、anacondaの仮想環境をいくつか削除した。
- macをセーフブートし、最低限の容量を確保する
- 'conda remove' と 'conda clean'を使う


# macの容量がなくなった。
210MBしかなくなり、メモリスワップもできなくなったのか、どんなソフトも容量が足りない、容量が足りないと言い出した。

# セーフブートする
しかし、削除できそうな無駄なファイルは大方なくなっている。

こんなときは、セーフブートの機能を使って、余計なキャッシュを削除してもらう。

# なぜセーフブートをするか
なぜなら、condaを整理するにしても最低限の容量が必要だから。

'conda remove'をした結果、errorを返された。

なおエラー文はわからない。

(エラー文をコピーしていたはずなのに、消失してしまった。)


# 仮想環境の削除
仮想環境のリスト
`conda info --envs`
仮想環境の削除
`conda remove -n [name] `

# 不要なパッケージやキャッシュの削除
仮想環境のキャッシュなどの削除
`conda clean --all `


# まとめ
これでセーフブート+5つ仮想環境を削除して、18GBくらい確保できた。

condaは仮想環境を手っ取り早く作れるので、必要になったらまた作れば良い。

それに最近はcondaは使わないらしいから、いい機会なので移行したいが、、、

# 参考
https://weblabo.oscasierra.net/python-anaconda-clean/
GASを使ってメールの一斉送信を行ってみた

#はじめに
###GASとは
Google App Script(GAS)とは、Googleが開発・提供しているプログラミング言語です。
JavaScriptというWebブラウザ上で動作するプログラミング言語をベースに作成されています。

###GASでできること
①メールの自動送信・返信
Googleフォームなどで申し込みがあった際に折り返しのメールを自動で送信することや、一斉送信などを可能にさせます。
②スプレッドシートでオリジナルの関数を作成する
今回お話するのはこの部分なのですが、スプレッドシートから抽出したデータからオリジナルの関数を作成することができます。
#GASを使ったメールの一斉送信

#概要
####①スプレッドシートを用意
####②Googleドキュメントに送信したいメールの内容を記載
####③スプレッドシートからスクリプトを用意
####④メールを送信する関数を作成
→スクリプトの記載
##①スプレッドシートの用意
まず、データになるスプレッドシートを用意する
![スクリーンショット 2021-04-18 19.53.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619648/5fad9039-84f5-7922-b470-2fc582ce582f.png)
このようにメールアドレスと名前を記載しておきます。

##②Googleドキュメントに送信したいメールの内容を記載
![スクリーンショット 2021-04-18 19.59.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619648/3025d456-160e-0ed7-de73-a30decfc879f.png)
内容は好きに書いていただいて構いません。
※しかし、スプレッドシートに記載しているデータを使いたい場合は｛｝で囲って対応できるようにしておきます。
例：｛お名前｝様
→これは、一斉送信ではあるものの各個人にメールをしっかり送っているように見せるためです。

##③スプレッドシートからスクリプトを用意
では、次はスプレッドシートからスクリプトの用意をしていきましょう！
![スクリーンショット 2021-04-18 20.04.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619648/65106f3e-dbaf-6aa9-132a-9ad03c8080b9.png)
スプレッドシートのツールをクリックして、スクリプトエディタを開きます。
![スクリーンショット 2021-04-18 20.07.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619648/0d1b0c86-c5aa-6c1d-d720-1bb147db4ba2.png)


```
  function myFunction() {
  
}
```
この、myFunctionという関数をいじってメール送信スクリプトを書いていきたいと思います。

##④メールを送信する関数を作成
```
function sendEmail() {
var SheetName=SpreadsheetApp.getActiveSheet();//アクティブなシートを取得する
var SheetRow=SheetName.getDataRange().getLastRow();//シート上のデータが存在する範囲を自動で判別して取得し、データが存在する最後の行番号を取得する
var docMail=DocumentApp.openById('');//DocumentのIDを指定する
var strDoc=docMail.getBody().getText();//ドキュメントのBody（内容）を取得する
var strSubj='【お知らせ】◯月◯日イベント実施について'; //タイトル
var strFrom='〇〇@gmail.com'; //Fromのアドレス
var strSend='井手翔陽'; //差出人の名前
for(var i=2;i<=SheetRow;i++){
var strToAd=SheetName.getRange(i,2).getValue();//メールアドレスを変数strToAdに格納
var strName=SheetName.getRange(i,3).getValue();//お名前を変数strNameに格納
var strBody=strDoc.replace(/{お名前}/,strName);//メールの宛名{お名前}を、を変数strNameに置き換える
GmailApp.sendEmail(
strToAd,
strSubj,
strBody,
{
from: strFrom,
name: strSend
}
);//宛先、題名、内容とオプションで送信元、送信アドレスを指定してGmailからメールを送付
}//スプレッドシートの最終行になるまで、繰り返す
}
```
上記のコードをコピー＆ペーストでスクリプトに貼って実行を押すと関数が走り、スプレッドシートに記載されている宛名に一斉送信されるようになっています。

#感想
GASを使ったメールの一斉送信を備忘録として書かせていただきましたが、やっぱり便利だなと感じます。
更にGASはいろんなツールと連携できるのでたくさん遊べそうですね！！
みなさんもぜひGASを使って普段行っている作業を少しでも楽にしてみてください！

###参考文献
>Google Apps Scriptを使ってGmailでメルマガみたいに一斉送信する方法
>>https://www.acrovision.jp/service/gas/?p=255
$rails newする時のオプション

Railsはコマンドを数回叩くだけで簡単にアプリを立ち上げられるフレームワークだが、rails newする時のオプションには注意した方がいいらしい。


#-hでオプション一覧が見られるよ
rails newのオプションを一覧で見たいときは、`rails new -h`でヘルプ表示すれば一覧を見ることができる。

#Rspecなどminitest以外のテストFWを導入する場合
railsはデフォルトminitestというテストを使用しているが、Rspecなどを使用する場合は以下オプションをつける

`--skip-test`
もしくは`-T`

```teminal.
rails new appname -T
rails new appname --skip-test
```

#フロントをJSでSPAで作成したい場合

`--skip-turborinks`

↓後からでも消せるけど。
[Rails6においてデフォルトで組み込まれているturbolinksを削除する方法](https://kray.jp/blog/must-know-about-turbolinks/)

#DBを変更したい場合

`-d データベース名`

```terminal.
rails new appname -d mysql
rails new appname -d postgress
```