OmniAICreator/Qiita-1.07M huggingface dataset:
rubocopに怒られるAbc Sizeって何？

新卒エンジニアの@yhorikawaです
普段railsを使って開発をしており、rubocopを使う機会があるのですが、
ある日rubocopを実行すると以下のように表示されました

```
Metrics/AbcSize: Assignment Branch Condition size for auth is too high. [17.5/15]
```

毎日のように、このAbcSizeに怒られいったいAbcってなんだろうと思ったのがこの記事を書くきっかけです。

## rubocopの指摘するabc sizeとは
abc sizeとは次のように定義されます

> Assignment -- an explicit transfer of data into a variable, e.g. = *= /= %= += <<= >>= &= |= ^= >>>= ++ --
> Branch -- an explicit forward program branch out of scope -- a function call, class method call, or new operator
> Condition -- a logical/Boolean test, == != <= >= < > else case default try catch ? and unary conditionals.
> A scalar ABC size value (or "aggregate magnitude") is computed as:
>       |ABC| = sqrt((A*A)+(B*B)+(C*C))

http://wiki.c2.com/?AbcMetric より

Assignment：　変数への代入
Branch: 関数の呼び出し
Condition: 条件分岐

この三つをそれぞれ二条の平方根がAbcSizeとなります。
rubocopではこのAbcSizeがデフォルトで１５を超えると警告を出すようになっています

この指摘をされたとき僕が書いていたコードはこのような内容でした

```ruby
start_day = Date.new('2020,12,1')
end_day = Date.new('2020,12,10')
if @user.birthday > start_day && @user.birthday < end_day
  1 + (end_day - start_day)
else
  (end_day - start_day)
end
```
実際にはもっといろいろ書いていましたが、このように
変数への代入も多く、関数呼び出しも条件分岐もあるという形でAbc sizeが大きくなりrubocopに指摘を受けたようです。

## どのように解決するのか
指摘を受けたからには修正したいですが、どのように解決するのでしょうか

1つのメソッドが複雑すぎるためこの指摘をされているので、
メソッドを適切に分割して1つのメソッドの複雑度を下げていくのが良いと思います。

## 力技でなんとかする
上の方法で解決しようと思ったけど、難しい場合rubocopのルールを変更することもできます。
rubocop.ymlに設定を追加しましょう

```yml
Metrics/AbcSize:
  Max: 18
```

これでアラートも出なくなりました！
この方法は普通に解決できなかった時の最終手段です。
アラートを消すためにルールを変更して、rubocopを導入した本来の目的（指摘された箇所を訂正して品質を高めるなど）を見失わないように気をつけてください。
しかし、厳しすぎるルールを設定するのもあまり意味がないので、チームで相談して適切な値を探っていけると良いなと思います。

## まとめ
今回はrubocopを使っているとよく怒られるabc sizeについてまとめてみました。
このルールもそうですが、rubocopに何故怒られているのか知っていけると、自分自身良いコードが書けるようになるのではと思いました。

[Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2020](https://qiita.com/advent-calendar/2020/hikkoshizamurai-connect) 17日目の記事は、いかがでしたでしょうか。
明日は先輩エンジニアの @ysysysys です!! お楽しみに!



## 参考
http://hikitest.hatenablog.com/entry/2015/01/14/034346
https://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Operators
Notionで締切までの日数をカウントする

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2020](https://qiita.com/advent-calendar/2020/notion) 17日目のエントリです。
16日目は[Notionで2つの日付から期間を取得してスプリントを計算する](https://qiita.com/pictiny/items/498f203c97776e5d1b97)でした。

# 日付の計算
プロパティの値を使って何か計算をする場合、 `Formula` というプロパティタイプを使います。
`Formula` を使うと、日付の計算を行うことができます。

## 特定の日付までの日数をカウントする
タスクに締切を設定することがよくあるかと思います。
現在の時刻から締切まで期間を求めることで、締切までの日数を求めることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/1140741b-0f51-d1d9-9885-af10ba70348d.png)

締切までの残り日数を求める計算式は以下のようになります。

```c
dateBetween(prop("締切日"), now(), "days")
```

# まとめ
Formulaを使って締切までの残り日数を求めることができました。

公式ドキュメントは[Formulas](https://www.notion.so/Formulas-28f3f5c3ae644c59b4d862046ea6a541)にありますので、そちらもご覧ください。
[UE4] エージェントのナビメッシュ設定を.iniファイルから設定する

検証バージョン: UE4.26.0
# はじめに
**[目標]**
　・エージェント毎に生成されるナビメッシュの設定を.iniファイルから設定します
　例えば、以下図のように`CellSize`の値を.iniファイルから設定する方法になります。
![2020-12-14_22h17_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/2fa8cf76-e811-8fad-ba35-36ac27332fc8.png)

**[応用]**
　・.iniファイルから一括してナビメッシュの生成パラメータを設定することができます
　・応用として、エージェント毎の設定やナビデータ毎の設定ができるようになります

# 前提
　以下の内容は前提として知っておきたい内容です。

　・レベル上のナビメッシュはRecastNavmesh（NavData）の設定に従って生成されます
　　ナビメッシュの機能や精度はこの設定を調整します。

　・ナビメッシュはエージェント毎に生成されます
　　エージェントに対するナビメッシュの設定はProject Settingsから行います。
　
　・デフォルトのNavData（RecastNavmesh）の設定は`BaseEngine.ini`に設定されています
　　プロジェクトで上書きしたい場合は`DefaultEngine.ini`で再定義するだけです。
　　例えば以下のデフォルト値はProject Settingsでも定義されています。

```:デフォルトのナビメッシュセルサイズの設定値
[/Script/NavigationSystem.RecastNavMesh]
CellSize=19.f
```

# 設定
　以下の手順で独自のクラスを追加して.iniファイルから編集できるようになります。

**[手順]**
 ① カスタムナビデータクラスを作成
 ② プロジェクト設定にナビデータクラスを設定
 ③ .iniファイルにデフォルト定義を追加

---

#### ① カスタムナビデータクラスを作成
 `ARecastNavMesh`を継承した、`MyNavData`というカスタムクラスを作成します。

```
#pragma once

#include "CoreMinimal.h"
#include "NavMesh/RecastNavMesh.h"
#include "MyNavData.generated.h"

UCLASS()
class TESTPROJECT_API AMyNavData : public ARecastNavMesh
{
	GENERATED_BODY()
};
```

#### ② プロジェクト設定にナビデータクラスを設定
 先ほど作成したナビデータクラス `MyNavData`をデフォルトで使用するように割り当てます。
[Project Settings]->[Navigation System]->[Agents]->[Supported Agents]の
`NavDataClass`に`MyNavData`を設定するだけです。

![2020-12-16_11h02_09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/28316cb2-366f-a63a-9475-7e583cb61715.png)

設定は `DefaultEngine.ini`に保存されて以下のように登録されます。

```
[/Script/NavigationSystem.NavigationSystemV1]
+SupportedAgents=(Name="Normal",Color=(B=0,G=255,R=140,A=164),DefaultQueryExtent=(X=50.000000,Y=50.000000,Z=250.000000),NavDataClass=/Script/NavigationSystem.RecastNavMesh,AgentRadius=35.000000,AgentHeight=144.000000,AgentStepHeight=-1.000000,NavWalkingSearchHeightScale=0.500000,PreferredNavData=None,bCanCrouch=False,bCanJump=False,bCanWalk=False,bCanSwim=False,bCanFly=False)
+SupportedAgents=(Name="Special",Color=(B=23,G=0,R=255,A=164),DefaultQueryExtent=(X=50.000000,Y=50.000000,Z=250.000000),NavDataClass=/Script/TestProject.MyNavData,AgentRadius=40.000000,AgentHeight=200.000000,AgentStepHeight=-1.000000,NavWalkingSearchHeightScale=0.500000,PreferredNavData=/Script/TP426.MyNavData,bCanCrouch=False,bCanJump=False,bCanWalk=False,bCanSwim=False,bCanFly=False)
```

以下の部分が自分で追加したナビデータクラスです。
クラス定義には/Script/`[プロジェクト名].[プレフィックスなしのクラス名]`となっています。

```
NavDataClass=/Script/TestProject.MyNavData
```

後はRecastNavmeshと同様に、以下のように上書きする定義を`DefaultEngine.ini`に追加します。
こうすることでカスタムクラスのデフォルト値を反映することができます。

```
[/Script/TestProject.MyNavData]
CellSize=100.f
```

# まとめ
　ナビメッシュを生成するために必要なパラメータ（NavDataのパラメータ）は、レベル上に配置されたRecastNavmeshの設定を直接編集することが可能なため、レベル毎に異なる設定値を保存することもできます。

　これは一見便利ですが、同じエージェントであってもレベルによって挙動が変わるという可能性もあり得ることになるため、統一性の観点でも極力エージェントの設定はProject Settingsで設定が統一されることが望ましいです。
DataPortal: 新機能さかのぼり（ピボット テーブルの複合条件付き書式）

DataPortalのまだ知らない使えそうな機能を求めて、新機能の一覧を遡ってみました。

[ピボット テーブルの複合条件付き書式](https://support.google.com/datastudio/answer/9528890#compound-rules)
> ピボット テーブルで OR および AND 論理演算子を使用して、複数の句を含む条件付き書式ルールを作成できるようになりました。

早速試してみます。

### or
![スクリーンショット 2020-12-17 23.08.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/de264e56-c3ac-9028-e4b9-fe1199a6d675.png)

### and
![スクリーンショット 2020-12-17 23.09.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423506/54bb2118-9531-9dce-4100-48395ce4e3f1.png)



ピボットテーブルは数字がぎっしり詰まってしまい、目が彷徨うような場合があるので、見るべきところを明示できる機能は嬉しいなと思います。
if True >= False:　Python「True」　Go「は？？？」

<FONT color="red"><FONT SIZE=6></FONT>$\huge{True >= False}$</FONT>
　　何だこれ……
## TL;DR
``` python3:Python3
arr = ['りんご', 'ごりら', 'らっぱ']
print(arr[False])
# りんご
print(arr[True])
# ごりら
```
気持ち悪いが過ぎる

## はじめに
バーチャルエンジニアの星野ニアです。
この記事は[星野ニア Advent Calendar 2020](https://adventar.org/calendars/5199) の 17日目（の記事の感想文）です。正しくは記事中に出てきた <FONT color="red">True >= False</FONT> という一文に対するプログラム処理上の疑問の解決です。

## Pythonの条件分岐はTrue

```python3:Python3
if True >= False:
    print('True')
else:
    print('False')
# True
```

## どうして
Python の Bool 型は整数のサブクラスとして実装されているので
1 >= 0 扱いで True が返ってきます。
[Boolean オブジェクト — Python 3\.9\.1 ドキュメント](https://docs.python.org/ja/3/c-api/bool.html)
Falseで割るとZeroDivisionErrorが返ってくる

```python3
print(str(True + False));
# 1
print(str(True + True));
# 2
print(str(False + False));
# 0
print(True / False)
# ZeroDivisionError: division by zero
```

## 他の言語の場合
**型付けゆるふわ言語筆頭 Javascript： true**
Javascriptの0除算結果はInfinityになる

``` javascript:Javascript
console.log(true >= false);
// true
console.log(true);
// true
console.log(true + true);
// 2
console.log(true + false);
// 1
console.log(true / false);
// Infinity
```


**静的型付け Golang ： operator >= not defined on bool**
　振る舞いとしては本当に正しい

``` Go:Go
package main
import "fmt"
func main(){
    if true >= false{
        fmt.Println("true")    
    }else{
        fmt.Println("false")
    }
    // invalid operation: true >= false (operator >= not defined on bool)
}
```
新卒1年目が考える「頼れる先輩」とは


この記事は[ウェブクルーAdvent Calendar 2020](https://qiita.com/advent-calendar/2020/webcrew)  18日目の記事です。
昨日は @wc-takahara さんの「[チームにVueを説明してみた。](https://qiita.com/wc-takahara/items/8136479ccdfb56dcd199)」でした。

#はじめに
はじめまして！ウェブクルーに今年4月に入社した @misa_s です。
現在はセールスとして毎日奮闘しています！

さて、今回は**「頼れる先輩」ってどんな人？**を題材に記事書こうと思います。

1年目の私が「先輩像」を書くのはおこがましいですが…
配属から半年経った今だから思う、頼りたくなる先輩像をまとめてみました。

誰かの先輩になるかもしれない来年の自分に向けて、という意味でも
この場をお借りして残せたらと…


#目次
**3つの「頼りたい」ポイント**
 1.レスポンスの速さ
 2.まずは聞く
 3.いつでも一緒に
**番外編：営業にもいかせる！**
**さいごに**


#3つの「頼りたい」ポイント
まずは、私が業務をしていく中でどんな時・どんなタイミングで頼れるなあ…と
感じたのかを思い返してみました。

その結果…

 1.レスポンスの速さ
 2.まずは聞く
 3.口に出して褒める！

この3つのポイントが重要だったな…との結論が出ました。
（まずは結論から、これもいい先輩ポイントかもです…笑）

###1．レスポンスの速さ
![n0327.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955232/019e7be5-ee2c-6ff4-3de1-c771ff303be4.png)

これに関しては、信頼される人の特徴でもあると思っています。

困ったときに速攻で答えが返ってくると、とにかく**安心**するんです。
先輩に何かを聞くとき、確認するときは自分の中に「不安」があるときでした。

また、すぐに答えることができる＝**知識・経験がある**というさらなる信頼が生まれます。
（これに関しては社外の方との関係構築でも重要だなと思っています）


###2．まずは聞く
![n0297.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955232/eb7808b3-4834-e9e2-9ad6-297b0d34b4ad.png)

「聞く」というよりは「聞いてくれる」にはなりますが、これは私にとってすごく重要なポイントでした。

**その人の考え** や **今どう感じているのか** を聞いてまずは一緒に整理をする、
そして一緒に解決策を考えていく。

そうすることで聞いてもらった側は「自分の考えもしっかり聞いてくれた」と
対等に仕事をしてくれている気持ちになります。

また、教えてもらう側も「先に自分でも考える」が必要になってきます。

・すぐに解決策を聞いた人
・まずは自分で考えてそこから修正した人

この2人が何かを終えたときの**達成感**と**成長度**は一目瞭然なはずです。


###3．口に出して褒める！
![n0270.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955232/0373936b-6248-390c-8ca6-a8bd11837999.png)

特にリモートワークが続いて、すぐに誰かと会話できない時だからこそ
口に出して褒めることが大事だなと考えています。

私の周りには何か成果を出したときに**「さすが！」**と褒める人がたくさんいます。

簡単なように思えますが、こうやって褒めてくれると「自分の頑張りを見ていてくれるんだ…」とモチベーションに繋がります。

また、これが積み重なり、何かした時**すぐに報告しよう**という癖がついたとも思います。
報連相が身に付いたのも実はこの**褒める**がキーポイントになっていたのかもしれません。


#番外編：営業にもいかせる！

「頼れる先輩」のポイントとして列挙したものは、実は私がセールスをしていて、大事だなと思うポイントでもあります。

**レスポンスの速さ**はいわずもがな、対応が早いと信頼に繋がります。
社外の方との関係性を構築するには、もちろん相性もあると思いますが、レスポンスの速さはとっても重要だと身に染みて思います。

**まずは聞く**ということは相手の事を理解することに繋がります。
アウトバウンド営業ではついつい自分のサービスのいいところを話したくなりますが…
相手の状況、ニーズをまずは聞くことで最適な提案を出来ると思っています。
ちなみに私が受注した場合のほとんどは関係ない話でも盛り上がったときです。

**口に出して褒める！**を少し言いかえて、**口に出して感謝を伝える！**にします。
これに関してはお互いにですが、きちんと感謝を伝えることで、気持ちよくやり取りをすることができると思っています。
私は「メールを返してくれた」とか「電話を折り返してくれた」とか日ごろからよくあることにも感謝の気持ちをいっぱいに持つように意識しています。

#さいごに
まずは、生意気にも新卒が頼れる先輩について語った内容をここまで読んでくださりありがとうございました。（**感謝を伝える**をここで実践です）

私が今回挙げた内容は当たり前のようにも思えますが、意外と意識せず実践するのは難しいように思います。

「今は忙しいから返信は後で…」
「答え見えてるから言いたい…！」
「（さすが！）」←心の声

2021年の私がこれらを当たり前にできていることを祈って…ではなく当たり前にできているように、今から実践をしていきます。

まずは皆さんも明日から「さすが！」と周りの人に言ってみませんか？

改めまして、最後までありがとうございました。
![n0220.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/955232/85ec54f0-78ed-4744-968f-c5f728af0775.png)
（イラストは私のお気に入りフリー素材 https://loosedrawing.com/ を使用しました）

#明日の担当は？？

明日は @wc-kawakami さんです！
よろしくお願いします:baby_tone1:
【Linux】コマンド $yum -y installでエラー(yum: command not found)が出た時

「linux ○○ インストール」などと検索すると出てくるyum。

「yum」コマンドはパッケージ管理システムですが、Linuxすべてのディストリビューションで標準で使えるものではないとのこと。

yum: command not foundとエラーが出た場合は、自身のディストリビューションを確認してみてください。

パッケージ管理システムを調べると、代わりに「homebrew」など対応したものがヒットするかと思います。
Rails6でEC2にデプロイする時にハマったポイント3つ

### 経緯
Rails6で作ったアプリをAWSのEC2にデプロイする際にハマったのでそのポイントを書き残しておきます。

### Rails6とRails5で何が違うのか？
モジュールバンドラが変更された。
モジュールバンドラとはCSS、JavaScript、画像などを一つのファイルとしてまとめるためのもの。Rails6ではWebpackerが標準のモジュールバンドラとなりました。Webpackerとはwebpackをrailsで使用するためのGemで、Webpackerを使うためにはwebpackをインストールしなければなりません。そのためRails5でAWSにデプロイする時よりもRails6では手順が多くなります。

### 環境
- Rails 6.0.3.2
- ruby 2.7.1
- DB mySQL 8.0.22
- OS amazon linux2

### 状況
- EC2内の環境構築は終わっている(DBの起動、githubからアプリのclone、webサーバー・アプリケーションサーバーの起動など)
-  `bundle exec rails assets:precompile`でエラーが起きている。

### 1 Node.jsについてのエラー

```
Webpacker requires Node.js ">=10.17.0" and you are using v6.17.1
```
今使用しているNode.jsのバージョンではWebpackerを使うことができないとのエラー。
なので新しいバージョンのNode.jsをインストールします。
Node.jsのインストールに関しては下記の記事が参考になりました。
https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html

下のコマンドで 現在のバージョンが確認できます。

```
nvm current
13.8.0
```

### 2 Yarnについてのエラー
#### webpackをインストールするには
**yarnのインストール**（著者はマシンイメージにAmazon Linux2を使ったのでそのリンクを貼っておきます。）yarnとはjavascriptのパッケージ管理ツールです。webpackをインストールするために必要になります。Yarnのインストールに関しては下記の記事が参考になりました。
https://classic.yarnpkg.com/en/docs/install#centos-stable

下のコマンドでバージョンが表示されていればインストールされています。

```
yarn --version
1.22.5
```


**パッケージをインストール**(package.jsonに書いてあるパッケージをインストールしてくれます。)

```  
yarn install 
```

### 3 エラー出なくなったけどjavascriptが反映されない場合
#### `package.json`のdevDependencies

devDependencies中に書かれているパッケージは開発・テスト環境でしか使うことができません。なので本番環境で使いたいパッケージでが**devDependencies**に書かれている場合は外に移動してあげる必要があります。

※自分の場合**webpack**が**devDependencies**に書かれていたので、本番環境でjavascriptやfont awesomeのアイコンが反映されない、本来`routes.rb`でpostで定義していた通信が、getで行われるといったエラーが起きました。

### 参考
https://techracho.bpsinc.jp/hachi8833/2018_05_24/56977

https://ics.media/entry/12140/#webpack-general

https://qiita.com/chihiro/items/ca1529f9b3d016af53ec
『PHPフレームワーク CakePHP3入門』の内容をCakePHP4で用いる上での諸注意

#対象読者
『PHPフレームワーク CakePHP3入門』(以下本書と呼称)を参考に、cakePHP4環境で学習を進めている方。
この本↓
![cakephp3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961542/c24aab12-60a7-efb3-6756-59a540e90368.jpeg)

#筆者の環境
OS:macOS Catalina
PHP:7.3.24
『PHPフレームワーク CakePHP3入門』:初版
CakePHP:4を使用
#『PHPフレームワーク CakePHP3入門』について
掌田 津耶乃氏が出していらっしゃるこの本、タイトル通りcakePHP3用である。
しかし、最近購入された方はCakePHP4環境で参考とする方が多いと思うので、いくつか注意事項を書いていこうと思う。
というのも、バージョンの違いで起こるようなエラーがいくつかあるからである。
#layout();
例えば、73pに登場するメソッド 、layout();である。これはcakePHP3であれば問題なく動作しレイアウトの指定ができる。
しかし、cakePHP4環境下では以下のようなエラーが出る。
![スクリーンショット 2020-12-17 22.12.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961542/75e86c1e-27e3-c24c-a9af-f37dfceed116.png)
Call to undefined method Cake\View\ViewBuilder::layout()
📋
Error

どうやらCakePHP4環境では、viewBuilder()においてlayout();は定義されていないようである。

調べたところ、
layout();をsetLayout();
に置き換えるとよいそうだ。
#「2-3 フォーム」、フォームのリンクについて
また、この章は他にもエラーが出る場合がある(この本はWindowsかつcakePHP3前提だからだろうか)。
例えば、この章ではフォームを作成するのだが、送信先を本書通り(72p参照)
###action="/hello/sendForm"
として、送信ボタンを押すと
![スクリーンショット 2020-12-17 22.37.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961542/595f3972-bef6-d33b-03ff-6770f683d43a.png)
...と、リンクが見当たらない、という旨のエラーが出る。

実はこのページのURLはhttp://localhost/hello/sendForm~
となっており(正しくはhttp://localhost/cake3app/hello/sendForm~のはず)
"cake3app"が欠落していることがわかる。

よって、
###action="/hello/sendForm"
を
###action="/cake3app/hello/sendForm"
とすればよい。
#$queryや$dataについて(74p参照)
先ほどの章でリンクを改善してもなおエラーが出ることがある。![スクリーンショット 2020-12-17 22.44.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961542/2f877a42-4047-4999-52e6-b550e547b0c3.png)
送信されたフォームの情報が$queryに入っており、それを取り出し表示させようとするのが本書の意図のようであるが、このプロパティはprotectedされているようだ。

ゲッターでアクセスする仕様になっているのでは？
と考え
###$str = $this->request->query['text1'];
を
###$str = $this->request->getQuery('text1');

とすると問題なく動いた。
#newEntity();
それから、本書を全般におけるコントローラーについての記述でよく出てくる
###newEntity();
であるが、cakePHP4ではエンティティが保存されていないときにnewEntity();が呼び出されると以下のような不具合が出るようだ。
![スクリーンショット 2020-12-17 23.00.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/961542/2b315038-51ea-748b-4fdf-b7b809a0bbf5.png)

調べたところ、
https://book.cakephp.org/4/ja/appendices/4-0-migration-guide.html
このガイドに

「Table::newEntity() は、入力として配列を必要とし、検証が実行されずに偶発的な保存がされることを防ぐために、 検証を実施します。つまり、入力無しでエンティティーを作成するには、 Table::newEmptyEntity() を使用する必要があります。」

と記述があった。よって、エンティティに何も保存されていない場合はnewEmptyEntity();を呼び出すのが適切である。

#以上
超初心者がBlender からUnreal Engine4にFBXをインポートするときの覚書

超初心者だけど、自分で作った3Dモデルを自分のゲームで動かしたい！！
ということで、実行してみました。
※今回はボーンやアニメーションのついていない3Dモデルを使うので、ある程度習熟している方にとっては薄い内容となるかと思います※
どこかで見たことがあるドーナツをUE4に出現させます。
![photo_1_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/42e5845a-0c83-655d-8c05-3c4c6bae6641.jpeg)
####メッシュとマテリアルをエクスポート
BlenderのFileからExportを選択し、FBXを選択します。
![photo_19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/04a77d7f-68d9-96e7-c909-5fe088927a9a.jpeg)
出てきたウィンドウの右側のIncludeの「Selected Objects」にチェックを入れて、Geometryのsmootingを「Face」にして「Export FBX」をクリック
![photo_2_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/53ac00a2-cf7e-2ae0-44a8-c174332b4188.jpeg)
![photo_3_inc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/1b7c4554-809c-b5b2-beca-9ad19edbec53.jpeg)
これでメッシュとマテリアルをエクスポートできました。

####テクスチャをエクスポート
Blenderの上のタブの「Texture Paint」を選択
![photo_4_inc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/68620836-b2be-2a78-3b4a-440f102f214f.jpeg)
左側のUV展開図のimageから「Save As...」を選択し、出てきた画面で分かりやすい名称を付けて「Sve As Image」をクリック
![photo_5_inc.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/0051da49-bf90-47a9-8b05-852330e974e6.jpeg)

##ここからUnreal Engine4の作業になります
インポートしたいプロジェクトを開いて、新しいフォルダーを作成。
作成したフォルダにエクスポートしたデータをドラッグ＆ドロップもしくは「インポート」を押してデータを選択してください。
インポートして出てきたウィンドウは特にいじらず、「Import All」をクリック
![photo_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/815a6571-908f-2462-507f-73fbb2dc3c32.jpeg)
これでメッシュとマテリアルのインポートは完了です。

エクスポートしたテクスチャも同じようにインポートします。
こちらはウィンドウは出ません。
全部インポートするとこんな感じ。
![photo_13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/5d80950d-068a-106e-9839-240a108514b8.jpeg)
マテリアルにテクスチャが適用されていないので、白いですね・・・

マテリアルを見ると「Param」がベースカラーにつながっています。
![photo_14.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/7e9f756e-2ff3-cfef-c587-8c662668d68e.jpeg)
「Param」を削除してインポートしたテクスチャをドラッグ＆ドロップして一番上のRGBのピンをベースカラーにつなぎ保存をするとインポートしたテクスチャが適用されます。
テクスチャを適用するとサムネイルに色が付きます。
![photo_21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/b4aa8850-c8fa-9b9e-ac4b-6e6926ee49e7.jpeg)

あとはビューポートにドーナツをドラッグ＆ドロップして配置。
ドーナツが出現しました！
![photo_17.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/509358/6cf4833a-cfb9-c696-12f7-f8acb3921b9b.jpeg)
APIキーをセキュアに管理する方法について調べた

この記事は [ちゅらデータアドベントカレンダーの15日目の記事](https://qiita.com/advent-calendar/2020/churadata) になります。

~~遅刻しました許してください~~

## はじめに

この記事ではAPIキーとひとくくりにしていますが、いわゆる文字列の羅列によって構成されるようなものを指して、これらのキーを流出させないように、また不正利用されないようにどのように管理していくのが望ましいかをまとめていきたいと思います。

## 1. 環境変数に保管する

まず文字列で構成される場合だと、プログラムに直接書いておくことはとても危険な保管方法になります。ましてチーム開発ともなってくると、gitなどを用いたコード管理も必要になるため、プログラムからキーが流出してしまうリスクも高くなってしまいます。なのでできる限り環境変数に保管しましょう。

## 2. 機密情報を扱えるライブラリを使用する
例えば [dotenv](https://www.npmjs.com/package/dotenv) や [direnv](https://github.com/direnv/direnv) のような 機密情報をまとめたファイル(`.env`)をプロジェクトやディレクトリごとに管理することができるライブラリです。

`.env` については多くの言語の間でも共通認識で管理していることが多いためぜひとも推奨したいです。

## 3. サービスごとの制限を活用する

例えばGoogle Cloud Platformに属するAPIキーではキーを利用する元を制限することができたり、利用できるAPIのなかでも部分的に機能を使うための権限だけを与えたりするといったことが可能です。

↓画像はGCPのAPIキー管理画面です。
![スクリーンショット 2020-12-17 22.57.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/3f49dc32-f69c-199d-339f-e8f82ca691cb.png)
![スクリーンショット 2020-12-17 22.59.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186010/b63209f2-6ae8-06b3-6305-075fba3d594e.png)

ここをキッチリしておくことでよりセキュアにAPIキーを管理することができます。

# まとめ

できる人には当たり前の考え方だったりしますが、初めて聞くような管理方法があったならぜひ皆さんの開発に取り込んでいただければと思います。

明日、17日目は @yamachaaan さんが [spaCy 業務で使える自然言語処理ライブラリ](https://qiita.com/yamachaaan/items/946ff307d87925575add) について紹介してくれます！
アドベントカレンダー15日目：SREを読んでみた「Googleにおける自動化の進化」編①

今回から新しい章に入ります。
内容はタイトル通り自動化についてになります。
今回は、まず自動化することの価値について、学んでいきます。

## 自動化する前に
自動化というものをどのように捉えるべきでしょうか？今までの内容から考えると、自動化することは、とにかく良いこと、運用コストを下げるために必要なものという印象があります。しかし、自動化はそのようにどんなことでも解決してしまうものではなく、能力を増幅するものです。自動化といっても、所詮自分が行う決められた手順を行うだけです。手順を誤れば、より問題を増やすだけの結果を生んでしまいます。また、手順書を作って、手作業することよりも、それを自動化することよりも良いのは、そのどちらも必要としない高レベルの設計によってつくられた自律的なシステムです。
なので、自動化をするならば、ただ自動化するのではなく、よく考えて自動化する必要があります。

## 自動化の価値

#### 一貫性
例えば、複数のユーザーで共有して、利用するようなシステムにおいて、管理者はユーザーの追加のようなタスクを行うことになります。
このような作業は、管理者によって行われます。管理者はこの作業に慣れていますが、それゆえに（そうでなくても）この作業が毎回同じように行われることはありません。いくら注意していても機械のように毎回同じことを繰り返せる人はいません。それにより、ミスや見逃し、データ品質の問題などの信頼性に問題が生じます。
まず、自動化にはシステムへの設定に一貫性を持たせることができるというメリットがあります。

#### プラットフォーム
適切な設計と実装がされれば、自動化システムは多くのシステムに適用したり、利益を上げることができるプラットフォームを提供することができます。
プラットフォームは、間違いを集約してくれる利点もあります。コード中のバグの修正も一度で済みますし、人間にタスクのやり方を指示するよりも、プラットフォームを拡張して、追加のタスクを実行できるようにする方が楽です。

#### 高速な修復
プロダクトのライフサイクルの後半で問題が見つかるほど、その修正にはコストがかかります。これは、システムが成長に伴い、複雑性を増していくからです。システムがある程度大きい場合は、間違いをすぐに見つけ出してくれる自動化システムは、修復のコストを下げてくれる可能性が高いです。

#### 素早いアクション
システムが成長し、複雑性を増していきます。
サービスが手作業で管理できる範疇を超えてしまっている場合は、自動化なしでは、長時間にわたり動作し続けることができません。

#### 時間の節約
時間の節約の問題は、範囲を自分に限定すると、自分がその作業を行うことと、それを自動化する労力を天秤にかけることになります。しかし、そのタスクを誰かが行う可能性を考えたとき、その人の労力を減らすことになり、全体の時間の節約になります。オペレータを運用から分離することには、大きな価値があります。

##まとめ
* 自動化によりさらなる問題を起こさないように、よく考えて自動化する必要がある。
* 自分が得たいメリットが自動化により得られるかを考える

#### 参考文献
1. Betsy Seyerほか　SRE サイトリライアビリティエンジニアリング　オライリー　71-73
忘れやすいのでメモ用：Githubに新規リポジトリを作った際のリモート反映からpushまで

# まずは

```
$ echo "# READMEに書くやつ" >> README.md
$ git init
$ git add README.md
ここで大体addするのにgithubには書いてないのが不親切だよな
$ git add .
$ git commit -m "first commit"
$ git branch -M main
$ git remote add origin https://github.com/username/repository_name.git
$ git push -u origin main
```

# ignoreを追加したい

```
$ vim .gitignore
```

# ミスってGitの管理やめたい

```
$ rm -rf .git/
```
自作キーボード2 回路基盤設計

# 回路基盤設計

[前回](https://qiita.com/kirin123kirin/items/77c7f1ffc9bc04698ce5)までは
レイアウト検討は直感的に操作ができて楽しく作成できたが、ここから先はいよいよ未知の領域だ

回路図なんて勉強したことないし、電気のことは何にもわからない。
プラス、マイナスの電流はどっちからどっちに流れるのかすら覚えてない。
おーむのほうそく？なんだっけという感じ、、

ググって自作キーボード一から作るにはKicadというソフトが良いらしい。
回路の勉強よりもソフトの力とYoutubeを見てなんとかすることにした。

1. [Kicadで回路図の書き方](https://www.youtube.com/watch?v=dNfaLM5PUVM&list=PLKe0_8RR2yrSu2fZAs2D8_bfYQ3JGBO-w)
寝る前、2日かかったが全部見た。見ながら操作したらなんとか操作できるようになった。

2. 回路図の基本的な知識がないので現物でテストしながら理解できて来た（ここまで仕事終わりの時間を使って３週間）
   Amazonで[ブレッドボード](https://amzn.to/3arC1pf)というものと、[ジャンパー線？](https://amzn.to/3nzsEYk)というものを買った。
はんだ付けしなくても、線を指で差し替えるだけなので簡単にテストできる。
秋葉原の遊舎工房に行って[Elite-C](https://yushakobo.jp/shop/elite-c/)というマイコンを2つ買った。
ダイオードというのもいるということでAmazonで500個入りの[これ](https://amzn.to/2Wvohl9)と
[簡易的に使えるタクトスイッチ10個入り](https://amzn.to/3nARQxv)を買った

![IMG_20201206_021725.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/6f941135-c72b-2463-ca73-0a5abfe5119f.jpeg)


左と右をつなぐI2C通信というものを使うときに抵抗を挟む必要があること。これがわからず1週間はまった。

参考サイト　https://github.com/qmk/qmk_firmware/tree/master/keyboards/lets_split#wiring
　　　　　　https://beta.docs.qmk.fm/using-qmk/hardware-features/feature_split_keyboard

4.7kΩをつけないとすげー遅延を起こす。写真にある緑の豆みたいな部品。
ブレッドボード買ってマジよかった。

で結局実際にできたのがこれ

## 左手側用の回路図

![basic_L_kairo.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/b189abcc-6b79-ecef-625f-b0ef3cc7dfca.png)


## 右手側用の回路図

![basic_R_kairo.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135714/3fa66a69-c624-f96e-1e54-7937d72c1de7.png)
[Swift]UITableViewのDrag&Dropでセル連結できる

# はじめに
UITableViewCellを長押しで並び替えできるようにDrag&Dropを実装しました。
https://qiita.com/king_of_morita/items/815e78d7d285a8d1190c

ところがDragしたセルを他のセルの上に移動すると右上にプラスアイコンが表示されて、Dropでセルの文字が連結されてしまいます。
セルの連結ができる機能があるのはいいですが、今回は不要なのでセルの連結ができないようにする方法を調べました。

RocketSim Recording - iPhone 12 Pro Max - 2020-12-17 22.24.20.gif

# セル連結できないように修正後
セルの上にDragしてもプラスアイコンが表示されずに、セル連結できないようになっています。

# セル連結できないように修正後
セルの上にDragしてもプラスアイコンが表示されずに、セル連結できないようになっています。

# 修正コード
UITableViewにUITableViewDragDelegate、UITableViewDropDelegateを設定していますが、
実装自体はなくてもOKで、並び替えの処理は`tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath)`
で実装します。

```swift:HomeViewController.swift
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
    return true
}

override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
      // ここに並び替えのデータ更新処理を書きます
    }
}
    
// UITableViewにUITableViewDragDelegate、UITableViewDropDelegateを設定します
func initTableView() {
    tableView.dragInteractionEnabled = true
    tableView.dragDelegate = self
    tableView.dropDelegate = self
}
    
extension HomeViewController: UITableViewDragDelegate {
    func tableView(_ tableView: UITableView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
        return []
    }
}
extension HomeViewController: UITableViewDropDelegate {
    func tableView(_ tableView: UITableView, performDropWith coordinator: UITableViewDropCoordinator) {
      // 中身は不要
    }
}
```

# まとめ
検索するとロングプレスでのDrag&Dropの実装方法は見つかりますが、意外な盲点がありました。
なにか参考になれば幸いです。

# 参考サイト
https://stackoverflow.com/questions/58752989/how-to-prevent-appending-data-to-an-existing-cell-on-drag-drop-of-table-view-cel
【FileMaker】事例紹介：趣味で作ったモノを現場で活かせ

今回は、FileMaker Goのサンプル紹介です。
サンプルと言っても、プライベート用（個人用）に作ってめっちゃ活用しているFileMaker Goアプリです。

# どんなサンプル？
趣味で自分や家族の服やバッグ、プレゼント品などを縫って作ってます。
自分の服はほぼ自作、という、仕事でもプライベートでも物づくりがほぼ日常の私です。
その時に必要になるのがパターン（型紙）です。
ムッチャあります。
現物をカテゴリー分けして保存していたりしますが、「あれ作りたいのに、パターンのサイズはなんだっけ？」と物を漁って散らかします。

そして考えた。

私はアプリ開発者じゃないか！

作れ！
作るんだ！
パターンをリスト化するんじゃい！

作りました。

# 動き
こんな感じです。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">どやぁ<a href="https://twitter.com/hashtag/FileMaker?src=hash&amp;ref_src=twsrc%5Etfw">#FileMaker</a> <a href="https://twitter.com/hashtag/filemakergo?src=hash&amp;ref_src=twsrc%5Etfw">#filemakergo</a> <a href="https://t.co/Ocwss8lsSy">pic.twitter.com/Ocwss8lsSy</a></p>&mdash; Guppy Web Service (@GuppyWebService) <a href="https://twitter.com/GuppyWebService/status/1339568924367589376?ref_src=twsrc%5Etfw">December 17, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# アプリの構成
このアプリは、確かもともとFileMakerにあった「目録」サンプルアプリを元にアレンジしました。
元があると、デザインがとても綺麗だし、欲しい機能は元からあるし、で結構その日のうちに出来上がったと記憶しています。

単純に、パターンショップ情報（マスタ）と、購入したパターンリスト、パターンの詳細の３画面です。
そのうちのパターンリストと詳細画面です。

すごいね、ここに登録してあるだけで、123パターン。
いや、パターン1つにつき、サイズ展開がたくさんあるので、２倍以上はあるんでしょう。
しかも、ここに登録できているのはまだ一部で、登録できていない分もあります。
どんだけ〜！

リストは、とにかくこの１画面で持っているサイズ展開を確認して重複購入を防ごうという作戦なので、サイズ展開と在庫サイズを持たせています。
これ、意外と助かってます。
![IMG_0679.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/5d6524ec-ff61-2cd1-5ac2-30f1a2ba66b1.png)

と言いつつも、実はダブって購入してしまったものも。
![IMG_0681.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/c8c164e3-7f0a-5aa6-6892-000f3dd5f7b1.png)
そう、このダブリがきっかけで自分用にアプリを作ってしまいました。
金額を見ていただけるとわかると思うのですが、一つのパターンで結構なお値段します。
このお値段の元を取るくらい、結構作ってきたので悔いはないのですが、流石にダブリ購入はショックです。

アプリで使っている写真はパターンサイトのものですが、個人でしか使っていないので、許したってください。

# やっぱりサンプルアプリはありがたい
サンプルアプリをそのまま使うのではなく、こうしてカスタマイズする場合もゼロから作るよりは断然楽に、そしてデザイン性が高いものが出来上がるのがFileMakerのいいところだと思います。
仕事として顧客管理や在庫管理は外せないところなので、サンプルで色々勉強させてもらってます。
【Swift】dismissとは

# ViewController自身を破棄するメソッド

です。
英単語としては『解散させる』とか『解雇する、払いのける』とかいう意味。
遷移先の画面でこれを実行すると遷移前の画面に戻る。
実装するとこんな感じ。

```swift:NextViewController
  // 『戻る』というボタンとつなげたアクション
  @IBAction func returnAction(_ sender: Any) {
      dismiss(animated: true, completion: nil)
  }
```

定型文のように書いていたが、 `sender` と `animated` と `completion` はよくわからないまま書いていた。

## sender

『送信者』という意味（send + er）。
デフォルトだと `Any` だけど本当は型を指定するのが好ましいみたい。
この場合では `UIButton` を指定する。controlキーでドラッグドロップしたときプルダウンで選べる。
パッと見たときに `UIButton` と書いてあるほうがわかりやすいのもありそう。

こちらの記事が詳しい。↓

**IBActionのsenderはAnyでなく具体的な型を指定しよう(Swift)**
<https://qiita.com/uhooi/items/e90d06e5d5681d72cbd0>

## animated

アニメーションの有無。
`false` にすると挙動がそっけなくなる。

## completion

英単語では『完了』の意味。コンプリートとかのアレだ。
半自動で生成したときのデフォルトには `nil` ではなく
`completion: (()->void)?`
と書いてある。
これは**クロージャー**が関係するものみたい。
「**値が入ったあとにカッコ内が呼ばれ、値が入るまではカッコの外が呼ばれる**」ものらしいけどいまいち理解ができていない。
とりあえず「completionはクロージャーに関するもの」だと覚えておこう。。
イロレーティングで映画のスコアを再計算してみた

## きっかけ

自分はふだん映画を観た際に、その映画のスコアを[Filmarks](https://filmarks.com/)でつけています。
しかし、明確な基準がなくスコアをつけていることや、観た直後では比較的高くスコアをつけてしまっている傾向がある様で、時間が経ってからこれまでの映画のスコアを振り返ってみると映画同士の好みと齟齬が発生していました。そこで、何か基準を設けて再評価（リスコア）ができないかと思い立ち、試してみました。

## どうやって再評価するか？

再評価をするにしても、全然知見があるわけではありません。
ですが、たまたま昔観た映画『ソーシャルネットワーク』の中で、Facemashというクラスメイトを比較しスコアリングしていた際に[イロレーティング](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%AD%E3%83%AC%E3%83%BC%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0)というものが使われていたということを知っていたため、こちらを用いようと思います。（あれはよろしくないけども、レーティング方法は拝借しよう）

このイロレーティングは囲碁やチェスのレーティングに用いられるものだそうです

## やってみた結果

まずは、Filmarksの自分のページから頑張って映画名と現在のスコアを持ってきます。
（私がFilmarksで記録をつけている映画は120件程度なので、HTMLから文字列抽出で取ってきました。）

イロレーティングを適用するために、各映画のペアのどちらがより好みかというデータを集める必要があります。
120件から任意のペアを持ってきて ${}_{120}C_2 = 7140 $ 通りの判定を行うのは現実的ではないので、今回は現時点のスコアが4.0以上のものを対象として実施してみました。
この件数が28件だったので、$378$ 通りの評価をぽちぽちと...



判定は、この様な感じで実際には28×28のマスを埋めました。
（以下のデータは評価した中でもより好みだと判定された回数が多いものを抽出）
<img width="600px" alt="判定例" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/3e37f174-fe67-02e7-6861-70247c580f56.png">

全通りの判定結果に基づいて、イロレーティングを適用してみた結果が以下です。

<img width="400px" alt="結果" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/265f08c4-6ffe-96aa-8e65-04e9707103cb.png">

う〜ん、概ねあっている様な感じがしますが...
判定例の結果をみると、『TENET テネット』よりも『インターステラー』の方が高くなるはずなので何かおかしい感じがします。

上記の結果はイロレーティングを適用させる順番が左上から右下に順に適用しているためあまり良くないようです。（最終的なレートが高くなる相手と最初の方で比較された場合、レート更新で得られる値は本来よりも低くなってしまうので）

そのため、ランダムな順番で全組み合わせを5回適用する形で回し直してみました。

<img width="400px" alt="結果" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181219/4214fcbf-c3d9-2d25-0dc1-690bb605ce45.png">
※映画のスコアは自分の独断と偏見です。

うん、自分の感覚とあっている気がする！
しかし、これまでつけていたスコアとの乖離がひどいですね...定期的に見直していきたいところです。


## 最後に

今回は映画のスコアリングにイロレーティングを用いましたが、チェス・囲碁の様に5番勝負などの結果を用いてレーティングを変化させることが前提であるので、この様な用い方が正しい訳ではないかと思います。（時間が取れずに調べきれていないですが。）
映画のペアの好みを判定する際に、判断が難しいものがあったりしたので、0-1の判定ではなく5段階評価でどちらが好きかというデータを集めて適用してみるとより良い結果になるのかと考えています。

※レーティングの説明などかなり省略しているので、時間がある時に追記しようと思います。
:class使うとき、classが２個あるのが嫌だ

こういうのは嫌だ
classが２こあるみたい。

```jsx
<div class="squere" :class="{ one: val === 1, two: val === 2,  three: val === 3}"

{{ val }}

</div>
```

まあ、vueがうまくマージしてくれるからいいけど。

もやもやするときは、こうする。

```jsx
<div :class="['squere',{one: val === '1', two: val === '2', three: val === '3'}]"></div>
```

配列で渡せばみんなハッピー。
AWSで就活ポートフォリオっぽい何かを作る

3年のそむです。
この記事は[MYJlab Advent Calender](https://qiita.com/advent-calendar/2020/myjlab)18日目にあたります。
最近は面接でちょっとやらかしたので落ち込んでいます。
よろしくお願いします。
# 背景
就活にあたり、今まで作成したwebページやプログラムなどをざっと見られるページが欲しいと思いました。
ポートフォリオ自体は適当にサーバーを借りれば簡単に作れるものですが、今回は触ってみたいと思っていたAWSを使用することにします。
費用は無料利用枠を使って月額0.5$程度です。（VATがかかるような気がします）
# この記事でやること
AWS(Route53, S3, ACM, CloudFlont)を使用してポートフォリオサイトをwebに公開します。
公開するものはペライチのhtmlファイルです。
中身については取り扱いません。
# 早速作ってみる
## 0. 用意するもの
* 公開したいhtmlファイル、その他
* メモ

## 1. 事前準備(1時間程度)
[こちらの記事](https://qiita.com/tmknom/items/303db2d1d928db720888)を参考にユーザー設定、権限設定等を行います。
Google Aucenticatorのあたりがちょっと手間でした。
## 2. ドメイン設定（1時間〜2時間程度）
アドレスがすっきりしていた方がかっこいいので（重要）、ドメインを設定したいと思います。利用したサイトは[Freenom](https://www.freenom.com/ja/index.html?lang=ja)です。
長期的に利用する場合、お名前.comなどでもう少し信用のあるドメインを取得した方がいいかと思います。
Freenomでのドメイン取得方法は[こちらの記事](https://dev.classmethod.jp/articles/mesoko-r53-cdn/)を参考にしました。（「チェックアウト」までで大丈夫です）

ドメインが取得できたら、FreenomとAWSでの作業を交互に行っていきます。

1. AWS Route53で「ホストゾーンを作成」をクリック、Domain Name欄に取得ドメインを入力して「作成」します。
2. 作成後、NSレコード（ns-000.XXXXXXXX.net.とか）が4件生成されるので、メモ帳か何かに控えます。
3. Freenomで「Use DNS」を選択し、先ほどのNSレコードを2件（どれでもいい）Nameserverとして登録します。
4. 申し込みを完了します。
5. (休憩)
6. Amazon S3で「バケットを作成」し、バケット名を1で取得したドメイン名（XXXXX.tkなど）とします。
7. 作成したバケットに、webページとして表示させたいhtmlファイルをアップロードします。
8. バケットポリシーを変更します。バケットポリシーに以下のコードをコピペします。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::ここはS3のパケット名/*"
        }
    ]
}
```

(コード例は[こちら](https://qiita.com/Mitsuzara/items/b413555dfdf3f805dd22)からお借りしました)

9. （番号が振り出しに戻ってしまった…）静的ウェブサイトホスティングを設定します。 「プロパティ」タブから静的ウェブサイトホスティングをクリック、「このバケットを使用してウェブサイトをホストする」にチェックを入れます。インデックスドキュメントにindex.htmlを入力します。
10. 一段落です。おつかれさまでした。S3のプロパティタブの静的ウェブサイトホスティングの欄でエンドポイントURLをクリックすると、アップロードしたhtmlファイルが表示されていると思います。このエンドポイントURLはメモっておいてください。

## 3. SSL証明書を発行(30分程度)
仕上げとして、Amazon Certificate Manager(ACM)でSSL証明書を発行します。
1. CloudFlontを作成します。「Origin Domain Name」にS3のエンドポイントURLを、「Viewer Protocol Policy」で「Redirect HTTP to HTTPS」を、「Alternate Domain Names」に取得したドメインを、「SSL Certificate」で「Custom SSL Certificate」にチェックしたのち取得したドメインを、最後に「Default Root Object」にindex.htmlを、それぞれ設定します（長くてすみません）。
2. 「Create Distribution」を押し、ひたすら待ちます。30分くらいかかることもあるようです（私は設定でつまずいたため1時間ほどかかりました）。
3. 状態が「Deployed」になったら、Route53に戻り「レコードセットの作成」をします。「エイリアス」を「はい」にチェックし、エイリアス先をCloudFlontディストリビューションに設定します。

これで全ての工程が終了です！お疲れさまでした。
取得したドメインにアクセスして、アップロードしたhtmlファイルが表示されれば完成です。

# まとめ
間違っている部分や、「もっとこうした方がいい」などありましたらご指摘いただけると嬉しいです。
ありがとうございました！

# 参考文献
[AWSアカウントを取得したら速攻でやっておくべき初期設定まとめ](https://qiita.com/tmknom/items/303db2d1d928db720888)
[【解説付き】ポートフォリオサイトを作ってAWSで公開する](https://qiita.com/Mitsuzara/items/b413555dfdf3f805dd22)
[【初心者向け】無料ドメインを使ってAmazon Route 53で実装しながら理解するDNS](https://dev.classmethod.jp/articles/comprehend_how_to_work_name_resolve_with_route53/)
[無料ドメイン(.tk)とRoute53を利用して0円でHTTPS環境を設定してみた](https://dev.classmethod.jp/articles/mesoko-r53-cdn/)
[ACMでDNSによるドメイン検証する方法](https://qiita.com/Hisai/items/616ab73422d3e947bed3)
GAS로 구글 스프레드시트 데이터 이메일과 슬랙으로 보내기

![main.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/48437c1e-75b8-bc2a-0cf3-e4e4ffd6d5d8.png)

## TL;DR
> 1편 [GAS로 네이버 키워드 크롤링하고, 구글 스프레드시트에 저장하기](https://qiita.com/leechungkyu/items/0fc4bcced6cc8ed421a2) 로 누적된 데이터를 이메일과 슬랙으로 보내는 방법을 기록하였습니다.
> [GAS](https://developers.google.com/apps-script)(Google Apps Script)를 사용하였습니다. (무료 + 서버리스)

## How To

### 구글 스크립트
파일 > New > 스크립트 파일 > `send.js`
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/e44f0c7b-e1d0-441d-7274-ef638af39544.png)

##### 코드입력 후 저장
※ 슬랙에 보내기 위해서는 [Slack Incoming Webhook](https://api.slack.com/messaging/webhooks) 값이 사전에 필요합니다.

```javascript:send.gs
function sendFunction() {

  var activeSheet = SpreadsheetApp.getActiveSheet();
  var cell = activeSheet.getActiveCell();
  var rangeData = activeSheet.getDataRange();
  var last_row = rangeData.getLastRow(); // 마지막 행
  var last_col = rangeData.getLastColumn(); // 마지막 열

  // message
  var message = '';
  
  for (i = 2; i < last_row + 1; i++) {
    for (j = 1; j < last_col + 1; j++) {
      var link = activeSheet.getRange(i, j).getValue(); // 2행1열(A2) 부터 시작
      var subject = activeSheet.getRange(i, j + 1).getValue();
      var press = activeSheet.getRange(i, j + 2).getValue(); 
      var date = activeSheet.getRange(i, j + 3).getValue();
      message += "<" + link + "|" + subject + ">" + " " + press + "(" + date + ")" + "\n\n";
      j += last_col;
    }
  }
  
  // send to slack
  var slack_webhook_url = 'https://hooks.slack.com/services/TFN5D0ALR/B01GBTTJGGL/1234567890'; // #z-웹훅
  var payload = {
    'text': message;
  };
  var options = {
    'method': 'post',
    'contentType': 'application/json',
    'payload': JSON.stringify(payload)
  };
  UrlFetchApp.fetch(slack_webhook_url, options);
  
  // send to email
  var e_subject = 'GAS로 네이버 메일에 데이터 보내기';
  var e_body = message;
  var recipient_email = '@naver.com';
  GmailApp.sendEmail(recipient_email, e_subject, e_body);
}
```
##### 코드실행
실행 > 함수 실행 > sendFunction > 계정 선택 > 고급 > 제목 없는 프로젝트(으)로 이동(안전하지 않음) > 허용
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/dd033ca1-bddb-d258-2830-e03ede570a97.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/4d8d88e4-c50c-ac58-c317-b40583588250.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/e7c32705-601d-21b0-c00f-c4dd1e834844.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/7d55e738-3a10-99b0-25dd-11904571f794.png)


`Running function myFunction` 약 2초 내외로 동작되요. > 슬랙, 메일함 각각 확인
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/663b9c52-ba35-45dd-f74d-814d7981bd07.png)

슬랙 확인
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/f4abf0d9-de55-a8e1-dc32-082bc4d1808f.png)

메일 확인
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144058/ec13ec1d-5bbb-e4f1-ef85-d21c998523f1.png)
[Rails] Discordの特定ロールの人間だけがサインイン認証できるようにする

Discordの一部住民だけに利用してほしいサービスを作りたいという人向け。
ロールを取得するにはbotアカウントが必要なので、botの招待は必要になるが、別に管理人権限などなくても出来る。

もともとはeveryoneのロールIDも調べればサーバーの住民ってことを認証できると思ってたけど、どうやらeveryoneのロールIDはないっぽい。残念。

## 0.Discordの開発者アカウントをつくり、OAuth2認証用のClientIDや、botトークンを取得する
[Discord Developer Portal]("https://discord.com/developers/applications")でNew Applicationでアプリ新規作成を行う。OAuth2/Generalの項目で、Client IDとClient Secretを取得する。Redirects設定はあとでいい。

また、botが必要になるので同じアプリ内でbotを作成し、botのトークンを取得する。botの設定は使い方によるだろうが、public bot/server members intent/message content intentの三つだけ自分はオンにした。その状態でOAuth2/URL Generatorの方にいき、botにチェックをいれて、パーミッションを設定するとアドレスが下部にでる。そのアドレスに跳ぶと、botをサーバーに招待できる。

ここらへんの細かい説明は他のサイトにも調べればかなりあるので、まぁたぶん大丈夫だろう（Permission設定とかややこしいけれど）。

## 1.omniauth、omniauth-discordをインストールする
railsの認証といえばdeviseというgemを使うのが普通だが、DiscordなどのOAuth2認証でアカウントをつくるだけならばDeviseは必要ない。Omniauthは配布されているストラテジーをインストールすれば、対応しているサイトのOAuth認証を手軽に実装することができる。

omniauthとomniauth-discordの実装は後で細かく書くが、基本的には[omniauth(twitter/facebook/github)実装まとめ]("https://qiita.com/Hassan/items/176bc2c6fd75a3e00111")をそのままやれば問題無くできる。

## 2.Discordrbをインストールする
railsでDiscordのbot関係を弄るのに必要なgemはdiscordrbなのでこちらをインストール。

~~なお、このgemはlibsodiumというライブラリを使うらしく、自分は開発段階でも本番段階でもこいつにかなーり振り回された。検索しても、これによって苦労したという人がかなり多数いる。音関係に必要らしいが、いらないのなら無視できるようにしたらいいんだけど。herokuでは`https://github.com/xrisk/heroku-opus`、`https://github.com/jonathanong/heroku-buildpack-ffmpeg-latest`、`https://github.com/challengee/heroku-buildpack-libsodium` の三つをBuildpacksに入れることで動くようになったので参考にしてね。~~

昔は強制インストールっぽいと思ってたけど、音関係の機能を使わないなら別に放置でいいらしい。ログで「lisbodiumないけどええんか？」って再三いわれて鬱陶しいけどね。

## 3.DiscordrbのAPIクラスを利用する
想定では、userモデルでサインアップしたユーザーのデータを取得するので、`app/models/user.rb`を弄る。

```ruby:app/models/user.rb
def self.find_or_create_from_auth(auth)

provider = auth[:provider]
uid = auth['uid']
duser = Discordrb::API::Server.resolve_member("Bot " + ENV['DISCORD_BOT_TOKEN'] ,ENV['DISCORD_SERVERID'],uid)
```

Discordrb::APIクラスで、botのAPIを使ったデータの取得が可能なので、ロール情報を含んだユーザーデータがとれる。

roleIDは持っているものそれぞれ調べられるので、たとえば運営権限の人間にだけなど制限ができる。

ユーザー情報にたとえばauthorityみたいなカラムを持たせて、スタッフ相当なら30、管理者は50…みたいな値をもたせれば、あとあと`if @user.authority > 29`みたいな簡単な条件文でページ別のアクセス制限も実装できる。

ちなみに、一応直接ユーザーのguild（サーバー）情報自体も取得しようと思えばできる。（わかりづらいが、本家のdiscordでは参加してるサーバーのことをguildと呼んでいる）

`config/initializers/omniauth.rb`の`scope:`にguildsを描き足し、discord-omniauth自体に

```ruby:Ruby/lib/ruby/gems/2.x.0/gems/omniauth-discord-1.0.0/lib/omniauth/strategies/discord.rb
      info do
        {
          name: raw_info['username'],
          email: raw_info['verified'] ? raw_info['email'] : nil,
          guilds: access_token.get('users/@me/guilds').parsed,
          image: "https://cdn.discordapp.com/avatars/#{raw_info['id']}/#{raw_info['avatar']}"
        }
      end
```
のguildsの項をかきたして、上記のuser.rbでauth['guilds']などでひっぱってこられる。

しかしgemを直接いじるのはいろいろと面倒があると思うので、ちょっと厳しいかもしれない。
Visual Basic Advent Calendar 2013

# はじめに
これは、[Visual Basic Advent Calendar 2020](https://qiita.com/advent-calendar/2020/vb)の17日目の記事となります。

テック系イベント支援サービス「ATND」が、2020年4月14日を最後にサービスを終了しました。
Visual Basic Advent Calendar 2013はATNDを使用していましたので、インターネットアーカイブから取得してきました。

[日本における技術系アドベントカレンダーの歴史](https://yhara.jp/2016/12/01/history-adcal-jp)
他の言語など記事が多くなったのは、2011年あたりからですね。

# Visual Basic Advent Calendar 2013
|日付|発表者|タイトル|
|:--|:--|:--|
|12月1日|-|-|
|12月2日|-|-|
|12月3日|yaju|[Visual BasicでRoslynを使ってみる](http://blogs.wankuma.com/yaju/archive/2013/12/03/328266.aspx)|
|12月4日|-|-|
|12月5日|-|-|
|12月6日|-|-|
|12月7日|はつね|[現在最強のVisual Basic環境を得るにはProductivity Power Tools 2013を得よ](http://blogs.wankuma.com/hatsune/archive/2013/12/07/328278.aspx)|
|12月8日|Ahf|[Visual Basic のラムダ式を改めて考える](http://blogahf.blogspot.jp/2013/12/visual-basic.html)|
|12月9日|yaju|[Visual BasicでRoslynを使ってみる　その2](http://blogs.wankuma.com/yaju/archive/2013/12/09/328280.aspx)|
|12月10日|-|-|
|12月11日|-|-|
|12月12日|-|-|
|12月13日|-|-|
|12月14日|-|-|
|12月15日|yaju|[Visual BasicでRoslynを使ってみる　その3](http://blogs.wankuma.com/yaju/archive/2013/12/15/328290.aspx)|
|12月16日|-|-|
|12月17日|-|-|
|12月18日|-|-|
|12月19日|-|-|
|12月20日|-|-|
|12月21日|-|-|
|12月22日|-|-|
|12月23日|-|-|
|12月24日|yaju|[Visual BasicでRoslynを使ってみる　その4](http://blogs.wankuma.com/yaju/archive/2013/12/24/328304.aspx)|
|12月25日|-|-|

# 最後に
2013年は空日が多くて寂しかったですね。私は4記事書いてます。
2014年からはKeiichi Haraさんからバトンタッチして私の方で主催するようになりました。
インターネット上のzipファイルをリクエストして変数に取り込む

この記事は [Python Advent Calendar の17日目の記事](https://qiita.com/advent-calendar/2020/python) になります。

## TL;DR
```python
# 使用ライブラリ
import io
import json
import urllib.request
import zipfile
```


```python
# データは国土交通省にある行政区域の情報を引っ張ってくる
# ゴールは中身の.geojsonを取り出す
url = 'https://nlftp.mlit.go.jp/ksj/gml/data/N03/N03-2019/N03-190101_47_GML.zip'

req = urllib.request.Request(url)
with urllib.request.urlopen(req) as res:
    data = res.read()
```

```python
# データがzipファイルになっているので中身を抽出して変数に格納する
with zipfile.ZipFile(io.BytesIO(data), 'r') as zip_data:
    geojson_filepath = [name for name in zip_data.namelist() if '.geojson' in name][0]
    with zip_data.open(geojson_filepath, 'r') as gj:
        geojson_data = gj.read()
    geojson = json.loads(geojson_data)
```

## はじめに
誰しもエンジニアとして携わるとおそらく必ず一度はぶち当たる「 **インターネット上のデータを取り込む** 」という行為。例えばテキストファイルとかであれば直接読み出すこととかも可能ですが、いかんせんデータによってはデータ圧縮された形になっており、うまく読み出せないこともあるかと思います。

ライブラリによってはそのライブラリに特化した形で読み込むことも可能ですが、今回は汎用性を考えてPythonの持つ標準ライブラリのみで必要データを「引っ張って変数に取り込む」ことをゴールとしてコードを書きました。解説も交えて何をしているかを紹介していこうと思います。

## データを引っ張ってくる

みんな大好きカエルアイコンのパイセン( @hoto17296 )の[記事](https://qiita.com/hoto17296/items/8fcf55cc6cd823a18217)がまんまです。パイセンいつもありがとうございます。

```python
# データは国土交通省にある行政区域の情報を引っ張ってくる
# ゴールは中身の.geojsonを取り出す
url = 'https://nlftp.mlit.go.jp/ksj/gml/data/N03/N03-2019/N03-190101_47_GML.zip'

req = urllib.request.Request(url)
with urllib.request.urlopen(req) as res:
    data = res.read()
```

初めにURLを載せたリクエストを作成して投げ込み返ってきたデータを読み出しています。

## zipファイルを変数に取り込む

```python
# データがzipファイルになっているので中身を抽出して変数に格納する
with zipfile.ZipFile(io.BytesIO(data), 'r') as zip_data:
    geojson_filepath = [name for name in zip_data.namelist() if '.geojson' in name][0]
    with zip_data.open(geojson_filepath, 'r') as gj:
        geojson_data = gj.read()
    geojson = json.loads(geojson_data)
```

標準ファイルフォーマットのzipファイルを取り扱うことができるPythonライブラリです。Pythonにはzipfile以外にもgzipやbz2(bzip2)やlzma、tar(tarfile)もあるので、1行目の `with zipfile.ZipFile(io.BytesIO(data), 'r') as zip_data:` については、各圧縮ファイルフォーマットごとに書き換えれば同様に対応可能です。

また今回はデータを引っ張ったときに格納した `data` にあるzipのバイナリデータをioライブラリを使って取り込んでいます。これによってローカルストレージからzipファイルを読む感覚で、変数にあるzipデータを読み込むことができます。

2行目では`zip_data`に含まれるgeojsonファイルを抽出して、これを3行目で取り出しています。このときの `open()` はzipfileライブラリ由来なので注意。`read()` できたらファイルの中身がバイナリで取り出せているはずなので、後は用途に応じて煮るなり焼くなり好きにすると良いと思います。

## まとめ

この取り出し方であれば多くの圧縮ファイルフォーマットに対応もできて、取り出したデータについてはローカルストレージにおいてよし、分析に使うならそのままpandasで読み込んでもよしって感じなので、とりあえず困ったらコピペで解決できるかと思います。

最近業務で全然Python書いていなかったので、どうしようかどうしようかと思っていたのですが、学生時代からずっとPython書いてると全然忘れないですね。素晴らしいです。今年は1番乗りでAdvent Calendarを作れたので満々満足です。来年もまた書いていくぞ！
Salesforce と Pardot のインテグレーション　⇒　Pardot でのコネクタの設定

１．インストールする Pardot AppExchange アプリケーションにはどのような方法でアクセスしますか?
２．Salesforce の許可リストに Pardot の IP アドレスを登録するべきなのはなぜですか?
３．Pardot で Salesforce コネクタを検証する場合、誰のログイン情報を使用するべきですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/de214cd2-cb78-a977-3013-6916eee46b59.png)
seedファイル活用

#seedファイルとは

データベースにあらかじめ入れておきたいデータを定義しておくもの
データをあらかじめ定義することで、コマンドで簡単にデータベースへデータを入れることができる

###seedファイルに定義
```rails:db/seeds.rb
Category.create(name:'メンズ')
Category.create(name:'レディース')
Category.create(name:'キッズ')
```
###コマンド実行
```ターミナル
% rails db:seed
```

データベースにデータが入っていたら成功
※上記の場合categoryモデルを作ってからnameカラムを作っておかなきゃいけない
docker-entrypoint.shの前後に処理を実行する方法

# TL; DR

```sh:entrypoint.sh
#!/bin/bash

# 前処理
echo "Do something before execution docker-entrypoint.sh"

# この行を追加
source /usr/local/bin/docker-entrypoint.sh "$@"

# 後処理
echo "Do something after execution docker-entrypoint.sh"
```

```bash
$ chmod +x entrypoint.sh
```

```dockerfile
COPY entrypoint.sh /usr/local/bin

# ENTRYPOINT ["docker-entrypoint.sh"]
ENTRYPOINT ["entrypoint.sh"]
CMD ["apache2-foreground"]
```

# はじめに

WordPressの公式Docker Imageを使って、色々と実行したいことがありました。
ただ、WordPressを立ち上げる前に、DBにデータを挿入する作業など、何かしらShellScriptを実行したい時にどのようにするのが良さそうかを知らなかったので残しておきます。

# docker-entrypoint.sh

公式のDockerImageでは、デフォルトで起動スクリプトを「docker-entrypoint.sh」という名前で保存しておき、そのスクリプトを立ち上げの際に実行することによって、そのContainerで実行したいアプリケーションを起動するという方法が良く採られます。

多くの場合、環境変数などの設定を済ませれば、起動するだけで良いアプリケーションなどのImageに良く用いられる方法ですが、起動前後に別の処理を行いたい場合などは少し不便です。

かといって、自己流の起動スクリプトを使ってしまうと、Imageのバージョンアップによるdocker-entrypoint.shの最新版の恩恵を受けることができません。

このような場合は、そのdocker-entrypoint.shの実行を自己流の起動スクリプトに持たせることを考えます。
sourceを使って、docker-entrypoint.shを展開し、  `"$@"` を使って引数を全て渡すことで解決ができます。

# 方法

以下のようなスクリプトを書きます。
sourceの行で、受け取っている引数を全て引き継ぐことが大事です。

```sh:entrypoint.sh
#!/bin/bash

# 前処理
echo "Do something before execution docker-entrypoint.sh"

# この行を追加
source /usr/local/bin/docker-entrypoint.sh "$@"

# 後処理
echo "Do something after execution docker-entrypoint.sh"
```

作成したスクリプトは、実行可能な権限を与えます。

```bash
$ chmod +x entrypoint.sh
```

```dockerfile
COPY entrypoint.sh /usr/local/bin

# ENTRYPOINT ["docker-entrypoint.sh"]
ENTRYPOINT ["entrypoint.sh"]
CMD ["docker-entrypoint.shへの引数"]
```

# まとめ

sourceコマンド、zshrcの更新に使うコマンドくらいにしか思っていなかったので、感動でした。
WordPressのImageとかを扱う時に便利なので是非！
rails　text_areaで改行入力→そのまま表示させる。

ぶっちゃけこちらの記事参照しただけです笑
https://qiita.com/kamotetu/items/1aa94994985c720668e4

form_forやform_withで
テキスト入力時に改行→全然できてなーい！
ってなりました。
ちゃんとそのまま表示させたいなと。

#問題
入力フォーム

```new.html.erb
<div class="from-group mb-4">
   <%= f.label :introduction, "紹介文", class: "form-label" %><br />
   <%=f.text_area :introduction, class: "form-control", id:"user-introduction", size: "90x5", maxlength: "1000", placeholder: "紹介文を書く"%>
</div>
```
投稿を入力
![スクリーンショット 2020-12-17 21.16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702376/5742e84f-cdaf-7e26-efe2-409dfb2b05b5.png)
表示

```show.html.erb
<%=@user.introduction%>
```
そうすると
![スクリーンショット 2020-12-17 21.39.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702376/657e585a-fc7d-f3c6-f7dc-6af281a8ba42.png)
改行できてない。
これを解決したいということ。

#解決法

```show.html.erb
<%=safe_join(@user.introduction.split("\n"),tag(:br))%>
```
に変えてあげるだけで
![スクリーンショット 2020-12-17 21.45.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/702376/e1283492-9cdd-22d7-20c9-8c39307e8862.png)
うまくいった！

　
この記述は

 * 連続した改行（空白のままの改行）
 * 段落（スペースキーで１文字分の空白を作る）
 
といったことが可能になります。

## ちなみに

入力ホームにバリデーションかけてない際、空白で送信した場合エラーになりました。
そんな時は

```show.html.erb
<%if @user.introduction.nil? %>   # 紹介文が「空」のままだとエラーが出るのでnil?=trueの時を追加
  <%=@user.introduction%>       # バリデーションは無し 
<% else %>
  <%=safe_join(@user.introduction.split("\n"),tag(:br))%>    # 紹介文が「空」じゃない時は正常に反映する
<%end %>
```

で解決しました。
javascriptでdatetimeの表記を変える方法

javascriptでdatetimeの表記を変える方法をメモとして残しておきます。

 inputタグのタイプをdatetimeにすると以下のようになります。

![before.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/938367/ed8ca28b-25bc-4450-f517-b774a30c5305.png)
 
これだと見にくいので以下のようにしたい時は

![after.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/938367/f6477180-7add-169c-9b88-e65d8e8a7f12.png)

datetimeが代入されている変数に.toLocaleString()をつければOK。
Ruby の加減乗除は他の言語と同じ，なの？

加減乗除などの基本的な数値演算について書かれた Ruby の初心者向け記事で，よく

> Ruby の算術演算（or 四則演算，加減乗除 etc）は他の言語と変わりません。

などとして，例えば

```rb
puts 20 + 30 # => 50
puts 16 - 9  # => 7
puts 20 * 3  # => 60
puts 60 / 3  # => 20
puts 10 % 3  # => 1
```

といったコードサンプルが書かれていることがあります。
Qiita でも，年に何本かそういう記事が書かれています。

もちろん「変わる（違いがある）」かどうかは「他の言語」が何であるかによるわけですが，まあ「わりとメジャーな普通っぽい多くの言語」くらいのつもりで書かれているのだと思います。

和・差・積はともかくとして，商と剰余は要注意ですよ。これは言語によってさまざまです。

このコードサンプルの除算で，割り切れるような数が選ばれているのは意図してでしょうか。
割り切れない数の場合にどうなるかは知っておきたいところです。
Ruby では，被除数（割られる数）と除数（割る数）がともに Integer オブジェクトの場合，`/` による除算は「整除法」になります。整除法は商が整数になるよう定義された割り算のことですね。

```rb
puts 10 / 4 # => 2
```

一方が Integer オブジェクトでない場合は整除法になりません。

```rb
puts 10.0 / 4 # => 2.5
puts 10r / 4  # => 5/2
```

上の例で，`10r` というのは数学的に 10 に等しい Rational オブジェクト（有理数オブジェクト）です。「分母が 1 で分子が 10 の有理数オブジェクト」ですね。
`10r / 4` の結果は「2 分の 5」という Rational オブジェクトになります。

このような，整数オブジェクト同士の `/` による除算が整除法になるのは Ruby の著しい特徴です。JavaScript も PHP も

```rb
10 / 4
```

は浮動小数点数の `2.5` になります[^php]。

[^php]: PHP では，被除数・除数が共に整数型で，かつ割り切れるときに限り結果が整数型になり，そうでないときは浮動小数点数になるのだそうです。

さて，整除法についてしっかり把握すべき点が一つあります。それは被除数・除数の少なくとも一方が負数の場合にどうなるか，です。
Ruby は除数が正のとき，被除数の符号に関わらず，整商（整除法における商）は「0 以上，除数未満」の値になります。これは数学的には最もなじみのある自然な整除法の定義ですが[^quo]，プログラミング言語ではむしろ少数派ではないかと思います。

[^quo]: しかし，これが整除法の唯一の定義ではありません。整除法の定義はいくつもあります。

```rb
puts -10 / 4 # => -3
puts 10 / -4 # => -3
puts -10 / -4 # => 2
```

もう一つ大事なことは，Ruby の除算は `/` によるものだけではない，ということです。
まず，被除数・除数の型に関わらず浮動小数点数の商が欲しい場合，[Numeric#fdiv](https://docs.ruby-lang.org/ja/2.7.0/method/Numeric/i/fdiv.html) が使えます。

```rb
puts 10.fdiv(4) # => 2.5
```

一方，被除数・除数の型に関わらず整商が欲しい場合，[Numeric#div](https://docs.ruby-lang.org/ja/2.7.0/method/Numeric/i/div.html) を使います。

```rb
puts 10.0.div(4.0) # => 2
puts 3.5.div(1.5)  # => 2
```

上のコードの二つ目の例のように，整数でない数同士でも整商が得られる，ということが大事ですね[^nid]。

[^nid]: 数学では整除法は整数の世界だけで考えることが多いのですが，小学校の算数では小数の整除法を教えています。小数の整除法に意味があることは，「3.5 m の紐から 1.5 m の紐が何本取れるか」を考えれば明らかでしょう。

逆に，被除数・除数の型に関わらず普通の商が欲しい場合，[Numeric#quo](https://docs.ruby-lang.org/ja/2.7.0/method/Numeric/i/quo.html) を使います。

```rb
puts 10.quo(4) # => 5/2
puts 10.0.quo(4) # => 2.5
```

Integer 同士の場合，割り切れるなら Integer で返し，割り切れない場合は Rational で返すのが特徴です。

以上で分かるとおり，`60 / 3` の結果だけ見て「Ruby の除算は他の言語と同じ」などと言うわけにはいかないのです。

除算について述べるなら剰余についても述べるべきですが，この記事で注意喚起したかったことは以上で尽きているので割愛します。

# 訂正（2023-01-02）

この記事ではもともと整除法のことを「整除」と書いていましたが，整除は意味が異なる用語であることに気づき，「整除法」に訂正しました。