OmniAICreator/Qiita-1.07M huggingface dataset:
Ruby on Rails [学習記録-第8章-]

#devise用のビューファイルを作成する
* deviseでログイン機能を実装すると、ログイン・サインアップ画面は自動的に生成されるがビューファイルとしては生成されない。これは、deviseのGem内に存在するビューファイルを読み込んでいるため。
* ビューファイルに変更を加えるためには、deviseのコマンドを利用してビューファイルを生成する必要がある。
*下記のコマンドを実行し、devise用のビューファイルを生成する。

```bash:
$ rails g devise:views
```

* サインアップ画面はapp/views/devise/registrations/new.html.erb、ログイン画面のビューはapp/views/devise/sessions/new.html.erbというビューファイルが対応しています。

#カラムを追加するマイグレーションファイルの作成
* カラムを追加するマイグレーションファイルを作成するためには、下記のコマンドを実行。

```
$ rails g migration Addカラム名To追加先テーブル名 追加するカラム名:型
```
```bash:sample
$ rails g migration AddIntroductionToUsers introduction:text
# usersテーブルにintroductionカラムをtext型で追加するマイグレーションファイルの作成
```

#登録画面のビューを編集
* DB側の準備は整ったので、ユーザーの新規登録画面にニックネームを登録するためのフォームを追加。

##text_field:maxlengthオプション
* maxlengthは、text_fieldというinputタグを生成するヘルパーメソッドにつけることができるオプション。

```bash:registrations/new.html.erb
<div class="field">
　　<%= f.label :nickname %> <em>(6 characters maximum)</em><br />
   <%= f.text_field :nickname, autofocus: true, maxlength: "6" %>
</div>
```

#ストロングパラメーターを編集
* 通常のリクエストの場合は、コントローラに記述してあるストロングパラメーターで受け取れるパラメーターを制限。
* しかし、deviseでログイン機能を実装した場合のパラメーターの受け取り方は通常とは異なる。
* ログイン時に送られてくるパラメーターを制限するストロングパラメーターは、deviseのGem内に記述されているため編集することはできない。
* deviseでは初期状態でサインアップ時にメールアドレスとパスワードのみを受け取るようにストロングパラメーターが設定してあるので、追加したキーのパラメーターは許可されていない。
* 追加のパラメーターを許可したい場合は、application_controllerにおいてbefore_actionにconfigure_permitted_parametersメソッドを設定する。

```rb:application_controller.rb
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?

  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:nickname])
  end
end
```
django-extensionsとdjango-debug-toolbarの導入

#django-debug-toolbar
pipでインストールしてsettings.pyとurls.pyを編集するだけで導入できます。

##1. インストール
```;
pip install django-debug-toolbar
```

##2. settings.pyとurls.pyの編集

###settings.py
```python:INSTALLED_APPS
INSTALLED_APPS = [
    # 省略
    'debug_toolbar',
]
```

```python:MIDDLEWARE
MIDDLEWARE = [
    # 省略
    'debug_toolbar.middleware.DebugToolbarMiddleware',
]
```

```python:settings.pyの末尾
INTERNAL_IPS = ['127.0.0.1']
```

###プロジェクトのurls.py

```python:urls.py
from django.conf import settings # <--追加
from django.urls import path, include

#省略

#末尾に追加
if settings.DEBUG:
    import debug_toolbar
    urlpatterns = [
        path('__debug__/', include(debug_toolbar.urls)),
    ] + urlpatterns
```

#django-extensions
こちらはpipでインストールしてsettings.pyを編集するだけで導入できます。

##1.インストール
django-extensionsのrunserver_plusを使用する場合、WerkzeugというWSGI Webアプリケーションライブラリが必要なのでそれも一緒にインストールします。

```:
pip install django-extensions Werkzeug
```

##2.settings.pyの編集

```python:INSTALLED_APPS
INSTALLED_APPS = [
    # 省略
    'django_extensions',
]
```

これで```python manage.py runserver_plus```で起動できるようになったかと思います。

#まとめ
導入しただけで実際に扱ってはいないので、今後扱っていきたいです。
Elmで生のHTMLをそのまま表示させる

## ElmのXSS対策

Elmは非常に堅牢なアプリケーション開発に向いた親切でとても良くできた言語で、通常はXSS脆弱性を引き起こすことができないようになっています。
そのため、もちろん文字列として持っている生のHTMLを表示しようとして

```elm
import Html exposing (Html)


view : Model -> Html Msg
view model =
    div
        []
        [ text raw
        ]


raw : String
raw = """
    <div>
        こんにちはこんにちは
    </div>
    """
```

このようにしても、実際には

```html
<div>
    &lt;div&gt;こんにちはこんにちは&lt;/div&gt;
</div>
```

こういうHTML相当のものに変換されます。

## 生のHTMLを埋め込みたくなったら

じゃあ、生のHTMLをそのままHTMLとして埋め込みたくなったらどうしたらいいのでしょうか？

まず大前提として、生のHTMLは生肉と同じくらい危険です。
生肉なんてヤギでも食べません。
（草食動物だから）

![sakura.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16345/657ab56c-bbf2-1758-8462-fe6d3c853ad8.jpeg)


生HTMLを表示したくなったら自分の設計を疑うべきです。
全然関係ないけど、アニサキスとサニタイズってなんか似てるよね。

## それでもやりたい

Elm 0.18 であれば[危険🐐スクリプト芸](https://qiita.com/arowM/items/93201dd5aded6e264e19)を使うことができましたが、あまりにも危険なので0.19では禁止されました。
Elm 0.19ではあきらめるしかないのでしょうか？
（再三いいますが、普通はあきらめて設計を見直したほうが良いと思います）

なんと、裏技があるのです。
[Elmのアプリ内でコードをハイライト表示する](https://qiita.com/arowM/items/101d55fd4d718966e67b)でも使った[elm-explorations/markdown](https://package.elm-lang.org/packages/elm-explorations/markdown/latest/)を使います。
これはもともとマークダウンのテキストを Elmの `Html`型に変換する機能を提供しますが、その変換時に「HTMLをそのままサニタイズしないでHTML型に変換する」というオプションが用意されてます。
いぇーい。

![sakura2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16345/9f6c5756-187d-0a18-f30f-99d72a575a42.jpeg)


それが[Options型](https://package.elm-lang.org/packages/elm-explorations/markdown/latest/Markdown#Options)の `sanitize`っていうオプションです。
これを `False`にして `toHtmlWith`関数で `Html`型に変換してやれば良いんです。

先ほどの例はこうなります。

```elm
import Html exposing (Html)
import Markdown exposing (defaultOptions)


view : Model -> Html Msg
view model =
    Markdown.toHtmlWith
        { defaultOptions
            | sanitize = False
        }
        []
        raw


raw : String
raw = """
    <div>
        こんにちはこんにちは
    </div>
    """
```

わーい かんたん！

[さくらちゃんにご飯をあげる](https://www.amazon.co.jp/gp/registry/wishlist/20ZV2VC57615B/ref=nav_wishlist_lists_1)
[さくらちゃんをもっと見る](https://twitter.com/hashtag/%E3%81%95%E3%81%8F%E3%82%89%E3%81%A1%E3%82%83%E3%82%93%E6%97%A5%E8%A8%98?src=hash)
[他の記事を見る](https://qiita.com/arowM)
![end.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16345/4a3d11c2-2027-cd01-75eb-1fdd3f3cb3a8.jpeg)
SSHでbind: Cannot assign requested addressとなった時の対応方法

- 環境(Docker)
    - CentOS Linux release 7.6.1810 (Core)
    - OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017

# 事象 : SSHでポートフォワードしようとしたらなんか言われた
別段、接続できないわけでも何でもないが気になった。

```bash
$ ssh -N -L 1521:10.0.1.2:1521 -i ~/.ssh/key.pem ec2-user@1.23.45.67
bind: Cannot assign requested address
```

# 原因 : IPv6のポートを使用しようとしているため
[ssh 接続時に IPv6 のポートを転送しないようにする](http://fishrimper.blogspot.com/2014/07/ssh-ipv6.html)
[SSH port forwarding: bind: Cannot assign requested address | Electricmonk.nl weblog](https://www.electricmonk.nl/log/2014/09/24/ssh-port-forwarding-bind-cannot-assign-requested-address/)

## 対応 : IPv4であることを`-4`オプションで明示する

```bash
$ ssh -N -L 1521:10.0.1.2:1521 -i ~/.ssh/key.pem -4 ec2-user@1.23.45.67
```
Python Django 勉強メモ（インストール～プロジェクト起動）

Django を使ってAPIサーバーを作成するためのメモ。
まずは、環境構築から初期プロジェクトの作成までのメモ。

# 環境情報
 
- OS：Windows 10 (64bit)
- Python：3.7.3
- Django：2.2.2

# Pythonインストール
 
- 以下のリンク先からインストーラーをダウンロードし、実行してインストールする
    - https://www.python.org/downloads/windows/
    - リンク先のページ内からWindows 64bit 版のインストーラーをダウンロードした
        - [Stable Releases] - [Download Windows x86-64 executable installer]
        - Topページからだとなぜか32bit版がダウンロードされた。（当時）

# 開発仮想環境（virtualenv）
 
- virtualenv というツールをインストール
    - 開発に必要なライブラリなどをグローバルにインストールせず、開発するものごとにインストールするために仮想環境を利用する
    - 調べると、Python3.3 以降は標準で venv というツールがあるみたいなので、必要ないらしい

- 適当なディレクトリに移動し、virtualenvコマンドを実行し開発用の仮想環境を構築する
    - 実行したディレクトリ配下にvirtualenvコマンドで指定した名称のディレクトリができる
- activateコマンドで構築した仮想環境を起動する
- pipコマンドで仮想環境内にDjangoをインストール

```
# virtualenvインストール
pip install virtualenv

# 仮想環境構築
virtualenv env1

# 仮想環境起動
env1\Scripts\activate

# Djangoインストール
pip install django
```

# 開発仮想環境（venv）
 
- venv利用版
 
```
# 仮想環境構築
python -m venv venv

# 仮想環境起動
venv\Scripts\activate

# Djangoインストール
pip install django
```


# プロジェクト作成
 
- startproject コマンドでDjangoプロジェクトを作成
- 作成したプロジェクトを runserver コマンドで起動してみる
    - ブラウザで、 http://127.0.0.1:8000/ にアクセスし、起動していることを確認する

```
# プロジェクト作成
django-admin.py startproject hello_world

# プロジェクト起動
cd hello_world
python manage.py runserver
```
DatabaseHelper.onCreate()の走るタイミング

#え？table users has no column named name (code 1)？？
sqliteデータベースを作成し、値を格納しようとしたときに発生した。
SQL文は間違ってないはずなのになぁ。

##エラーの意味
そもそもこのエラーは何を意味しているのか。
エラーコードを読むとわかるが、指定したカラム(列)が存在しませんよ。というエラーだ。


##主な原因:
このエラーが発生してからググりまくって調べたところ、主に以下の点が主な原因みたい。

* SQL文のミス：
打ち間違いや文法ミスによるもの。

* onCreate(SQLiteDatabase db) {}実行タイミング：
私がハマっていたのはこちら。
データベースが作成される際にonCreate()も実行される。
データベースが作成されている状態のまま、プログラムが走ると、onCreate()には処理がいきません。
そのため、onCreate()で使うSQL文を一生懸命直しても意味がありません。。。
解決するには、アプリをアンインストールするか、deleteDatabase("sample.db");でデータベースを削除します。

#おわりに
言われてみればそりゃそうだって感じですが、ぼーっとしていたら見落としてしまう。
基本的なところにこそ落とし穴があるのかなぁ。
SSHで鍵を指定したらWARNING: UNPROTECTED PRIVATE KEY FILE!となった時の対応方法

- 環境
    - CentOS Linux release 7.6.1810 (Core)
    - OpenSSH_7.4p1, OpenSSL 1.0.2k-fips  26 Jan 2017

# 事象 : SSHで鍵を指定してポートフォワードしようとしたら怒られた
```bash
$ ssh -N -L 1521:10.0.1.2:1521 -i ~/.ssh/key.pem -4 ec2-user@1.23.45.67
The authenticity of host '1.23.45.67 (1.23.45.67)' can`t be established.
ECDSA key fingerprint is SHA256:xxxxx.....
ECDSA key fingerprint is MD5:xx:xx:....
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '1.23.45.67' (ECDSA) to the list of known hosts.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0664 for '/home/ponsuke/.ssh/key.pem' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Load key "/home/ponsuke/.ssh/key.pem": bad permissions
Permission denied (publickey).
```

# 原因 : 指定してる鍵の権限が広すぎるから
[仮想マシンの起動](https://aws.amazon.com/jp/getting-started/tutorials/launch-a-virtual-machine/)

## 対応 : 権限を変更する

```bash
$ sudo chmod 400 .ssh/key.pem
[sudo] password for ponsuke:

$ ls -l .ssh/
total 8
-r--------. 1 ponsuke ponsuke 1696  6月 13 12:00 key.pem

$ ssh -N -L 1521:10.0.1.2:1521 -i ~/.ssh/key.pem -4 ec2-user@1.23.45.67
```
Laravel＋OracleのクエリビルダでLIMIT句のtake()が使えないときの代用表記

環境
----
CentOS 7
PHP 7.3
Laravel 5.8
Oracle 11g　←バージョンがかなり古いので、以下は最新のOracleには当てはまらない可能性があります
oci8 2.2

困っていたこと
----

mySQLなどを使っているとき、Laravelのクエリビルダで結果をn件だけ取得したい場合、以下のような感じで実現できます。
公式リファレンス通りですね。

```
DB::table('テーブル名')->take(件数)->get();
```

※公式リファレンスの該当部分: https://readouble.com/laravel/5.8/ja/queries.html

しかし、現在oci8とlaravel-oci8を使ってOracleに接続しているのですが、上の書き方だと以下のような`QueryException`が出てしまいました。

```
Error Code : 918 Error Message :
ORA-00918: column ambiguously defined Position : ●● Statement : （以下略）
```

調べてみると、Oracleには**LIMIT**や**OFFSET**が存在しないらしいです。
そのためtake()では有効なSQLが発行できず、エラーになってしまっているのか？と予想しました。（このあたり調査不足）

対策を探す
----

OracleのSQLを直接書く場合、`ROWNUM`という値をカラムのような形で使用して取得件数を制御できるらしく、
具体的にはwhere句で`ROWNUM = n`などとすることで件数を指定できるようです。`=`だけでなく不等号も使えるっぽいです。
そこで試しに1件だけ取得しようと、クエリビルダで

`DB::table('テーブル名')->where('ROWNUM', 1)->get();`

や

`DB::table('テーブル名')->where('ROWNUM', '1')->get();`

といった形を試してみたのですが、エラーが無くなりません。
原因は分かりませんでした。もしかするとROWNUMが擬似カラムだからでしょうか。

最終的には

```
DB::table('テーブル名')->whereRaw('ROWNUM = 1')->get();
```

のように、WHERE句の中身を直接記載することで取得できました。
（1の部分は実際には可変なので、`ROWNUM =`と数字を結合した文字列をwhereRaw()に読ませています）
【755】curl, jqコマンドで今までに投稿したやじコメを一気に閲覧

#概要

タイトル通り。

何気にそういったのを手軽にみれたら面白いかなと思い、エモに浸る意味でも調べてみました。
ワンライナーでいけたのがミソ

#手順

OSのターミナルを開いて以下コマンドを入力　※予めjpコマンドをインストールする必要があります
(またmacOSの場合はawkではなくgawkをインストールして使用)

```
curl "https://api.7gogo.jp/web/v3/talks/＜①＞/comments?limit=1000000" | jq '.data[] | select(.user.name == "＜②＞") | .comment | .time, .body[].text' | awk 'NR%2!=0 {print strftime("%Y/%m/%d %H:%M:%S %a",$0)} NR%2==0 {gsub("\\\\n","\n",$0); print $0,"\n"}'
```

①対象となるトークルームのtalkId
②ご自身のユーザー名

トークルームのURLからtalkIdは確認できます。
https\://7gogo.jp/＜この部分がtalkId＞

例：AKB48稲垣香織さんのトークルームの場合
https\://7gogo.jp/inagaki-kaori　//　指定するtalkIdは”inagaki-kaori”となります。

####コマンド実行
実行環境(macOS)

```file:macOS
$ curl "https://api.7gogo.jp/web/v3/talks/inagaki-kaori/comments?limit=1000000" | \
jq '.data[] | select(.user.name == "めいせい") | .comment | .time, .body[].text' | \
gawk 'NR%2!=0 {print strftime("%Y/%m/%d %H:%M:%S %a",$0)} NR%2==0 {gsub("\\\\n","\n",$0); print $0,"\n"}'
```

表示は新着順（ルームによっては表示されるまでにそこそこ時間を要します）
![ 2019-06-18 22.16.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263891/68e68911-7f58-ca70-d769-5c640b3d76b0.png)
最初の頃はなかなかのおじさんぷりを発揮してるなぁ、、(˘ω˘) ![ 2019-06-18 22.18.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263891/aff33a43-2e1d-76de-018a-7ced4cc2d1a5.png)


#コマンド処理の解説

まずトークルームが開設されてから投稿された全やじコメ(全ユーザー分)のJSONデータを取得。

```
curl "https://api.7gogo.jp/web/v3/talks/inagaki-kaori/comments?limit=1000000" |
```
`&limit=1000000`
limitパラメータは取得件数の最大値となります。
limitパラメータを指定しない場合、100件程しか取得されません。
全てのやじコメを取得するには、やじコメの総件数以上の値を指定する必要があるため1000000としています。
[▶やじコメの総件数を確認する方法](#やじコメの総件数を確認する方法)


指定したユーザー名のやじコメとそれに紐づく投稿時間をJSONデータから抽出。

```
jq '.data[] | select(.user.name == "めいせい") | .comment | .time, .body[].text' |
``` 

抽出されたデータを加工して表示。
・投稿時間をunixtimeからシステム標準時に変更
・コメントの文字列に含まれている改行のエスケープシーケンス[\n]を実際の改行として出力


```
gawk 'NR%2!=0 {print strftime("%Y/%m/%d %H:%M:%S %a",$0)} NR%2==0 {gsub("\\\\n","\n",$0); print $0,"\n"}'
```

####やじコメの総件数を確認する方法

以下のURLを押下し最初に表示されるcommentIdの値がやじコメの総件数です。
https://api.7gogo.jp/web/v3/talks/inagaki-kaori/comments?talkId=inagaki-kaori
（talkIdの値はトークルームに合わせて適宜変更して下さい）
![ 2019-06-16 19.35.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263891/4699364f-6cef-ef35-8514-7c4bb5199196.png)


commentIdは一つのやじコメに紐づくユニークIDでコメントが投稿される度、インクリメント採番される値のようです。よって最新のcommentId＝やじコメの総件数となり、この画像の場合は188811件となります。


上記の手順を踏まなくとも、とりあえずlimitに1000000ぐらい指定すれば大概のルームでは問題ないのかなと思われます(希望的観測)


#最後に

とりま、、jqカッケーすね

参考:
https://qiita.com/dev100kg/items/f2d01bfd6b0880f93d58
https://www.setouchino.cloud/blogs/19
ちゃぶだい返しをされたときのモチベーションコントロール方法について

意欲を持って進めてきたプロジェクトが頓挫したり、あらぬ方向だったことがわかって大幅に修正を余儀なくされたりしたときは、人に指示をする立場でもされる立場でもやりきれなさが残る。

吹っ切ってすぐに進める人ならそれでよいが、そんな人は稀であるし、そもそもそういった人はそれなりに挫折を繰り返して慣れているから出来るわけである。

さて、昨日自分自身も、これまで進めてきたプロジェクトに大規模な方針転換が迫られることになった。
今回は、そんな中で少しでもモチベーションを殺さず、スピードも落とさず、成果も上げてゆくにはどうすれば良いかを考えたい。


## まず、自分が辛いということを受け止めることから始める。
何も考えられない。これまでやってきたことが虚しく映る。前向きに考えられない。
ベッドから出られない。シャワーを浴びる気もおきない。食欲もない。

## 続いて過去の経験と今回の経験を照合してみる。
過去には同じような大規模な仕様変更があった。やる気は死んだ。プロマネを責めたり、怒りにまかせて深酒をしたり。

ちなみに自分は感情を表に出すことをあまりしない。変更を告げられた日は涼しい顔をして自分を抑えているが、翌日ベッドから起き上がれないくらいにショックを受けてイジイジしてしまう。

最終的には、仕様変更で廃棄になったソースコードを「供養」することで心の整理が着いた。
具体的には、テストコードのassert文に「Thank you ○○(モジュール名)!」と付けて単体テストをすべて流した。

## さらに、過去の経験と今回の経験の差分を取ってみる。
過去の経験以降で新たに学んだ知識やものの考え方を総動員し、いまの事態に適合することを試みる。

- 何か大きな失敗をして自分に物理的あるいは精神的な危害が及んだか？
    - 及んだ。目の前にある仕事の意味が無くなり、次に何をするか分からなくなった。
    - しかし身体に危害があるわけでもなく、叱責を受けたわけでもない。
    - いままでの生き方は変わる必要があるだろうが、生きていることは変化することである。むしろ変化に対応する術を学べると思えるだろう。

自分のいまの目標は、「**効果的、効率的にプロダクトを構築し、ユーザにきちんと使ってもらえるものを作ること**」である。
しかし、自分のプログラミング能力には疑問があり、現実的に死ぬほどプログラミングが好きなわけではない。
となると、プロダクトオーナーのような立ち位置でユーザビリティや収益性を考える立場を取るか、組織管理者の立ち位置でエンジニアリングをするための効果的な環境づくりをする立場にいるか、どちらかを考えている。
その一方で、プログラミングを「やり切って」いないことも確かである。だから本当に向いているかどうかも分からない。

今回の大規模な方針転換は、自分自身に対して「作り手」の立場でいるか、それとも「価値創造」の立場でいるか、どちらかを選択させるような感じであった。
自分の可能性は信じるが、やることを絞って、より現実的な回答を自分で考える大きなきっかけになるだろう。
**いまの自分の生活を守ることは考えた。しかしそうして守って何か良いことがあるかというと、良いことがなかった**。
選択肢を増やすためには新しいチャレンジが必要で、これまで自分は変化を受け入れるために経験を重ねてきた。
大きく分けて以下の３つである：

- 向上心
    - いまの技能を高める。打ち手を増やす。具体的な方法論に結び付けておく。
    - 自分の物の考え方を変える。
    - 毎日少なくとも２ミリは成長する。
- 好奇心
    - やったことのないことをやってみる。ダメージのない範囲でなんでも経験してみる。
    - つねに、なんでも面白がる。躊躇せずに思い切り楽しむ。
    - 死んだ魚の目をしない。
- 羞恥心
    - 倫理観、道徳意識を高める。
    - 人格的に立派な人間を目指す。でも、やりすぎない。
    - 逃げの言い訳をしてると辛くなる。寝ると忘れるのでさっさと寝る。

## まとめ
ちゃぶだい返しをされたときは自分のこれまでを振り返る大きな機会となることが分かった。
具体的には、過去と現在とこれからの自分を振り返ることで、今後の自分の方向性を考え直すことができることが分かった。
ふりかえりにはエネルギーが必要なので、普段は踏ん切りがつかずに出来なかった。大きな収穫があった。

結局は、スピードが落ちたし成果も上がったかどうかは疑わしい。
しかしモチベーションを殺すことがなかったのは嬉しいことだ。

ルーチンワークとしていた事を見直すことは必要となったが、それまで中途半端にやってきたことではないので、身になってないわけではない。結果として一日、これまでを考えることにはなった。けれど後悔はしていない。

また、こういった精神不安定なときは、新しい考え方を取り入れるには絶好のチャンスでもある。林修やDaigoの動画を見ていたりした。これまで敬遠していたが、人気のある人はやっぱり良いことを言う。Daigoのニコニコチャンネルに入会してみたりした。
Faradayを使ってローカルの開発環境から外部のAPIに接続できない

外部APIを叩くときにFaradayを使って実装していたときに、本番環境ではうまくいくのにローカルの環境ではエラーでアクセスできなかった。
##コード

```ruby
conn = Faraday.new
res  = conn.post do |req|
        req.url                               'https://sample.com/api/sample'
        req.headers['X_APP_API_TOKEN']      = 'amenboakainaaiueo'
        req.headers['Accept']               = 'application/json'
        req.headers['Content-Type']         = 'application/json'
        req.body                            = '{friday: day13th}'
      end
```

##エラー内容

```Faraday::ConnectionFailed: Failed to open TCP connection to :80 (Connection refused - connect(2) for nil port 80)
```
意訳：httpじゃアクセスさせない、出直しなさい


##解決方法

```ruby
conn = Faraday.new('https://sample.com/api/sample')
res  = conn.post do |req|
        req.url                               'https://sample.com/api/sample'
        req.headers['X_APP_API_TOKEN']      = 'amenboakainaaiueo'
        req.headers['Accept']               = 'application/json'
        req.headers['Content-Type']         = 'application/json'
        req.body                            = '{friday: day13th}'
      end
```
Faraday.newするときにhttpsでアクセスするよーってことを明示したら行けました。
How You Can Develop Uber for Trucking

Ever since Uber became an international success, every transportation service has wanted to follow in its footsteps and even surpass it in terms of popularity. The so-called “Uberization” of the logistics industry is occurring rapidly. 
![uploading-0]()

This article will address inquiries we’ve had from customers who are considering creating an Uber for delivery trucks.
https://yalantis.com/blog/create-uber-trucking/
[Rails 6.1] ActionView::Component について

Rails の github レポジトリを見ていたら
Introduce support for ActionView::Component（ https://github.com/rails/rails/pull/36388 ） 
というプルリクを見つけてなかなか面白そうだったので読んでみました。

ActionView::Component を一言でまとめると、ビューコンポーネントを Rails のオブジェクトとして扱えるようにする、というもの。
3月から既に Github のプロダクション環境で使われているとか。

RailsConf でも発表された内容のようです。
https://www.youtube.com/watch?v=y5Z5a6QdA-M

以下、プルリクの内容をかいつまんで翻訳したものです。
# 背景
Rails アプリのビュー開発において次のような問題があった。

#### テスト
Rails ではビューのテストは統合テストかシステムテストが推奨されているが、これだとコストが大きいのですべてのビューをテストするというわけにもいかない。しかもこのテストの仕方だと、せっかくパーシャルに切り分けて共通化しても、テストは DRY じゃなくなって嬉しくない。

#### カバレッジ
テストのカバー率を求める一般的なツールではビューのカバー率を完全には判断できないのでテストがどれくらい書かれているか判断しづらいし、カバー率に実態とのギャップが生まれる。

#### データの流れ
オブジェクトの宣言と違い、ビューでは予期する値についての情報が無いので、そのビューが何をするものなのか理解が難しい。この問題は同じビューを異なる場所で使おうとしたときによく起きる。

#### 基準
Ruby のコーディング基準のようなものをビューでは設定しづらい。

# 実装
### コンポーネントの構築
- `app/components` 配下に `ActionView::Component` の子クラスとして定義する。
- クラスメソッドとして `template` メソッドを定義し、 ERB をヒアドキュメントで書く。
- `initialize` も定義できるが、その他はすべてプライベートメソッドとする。
- バリデータが使える。`initialize` 後、`render` 前にバリデーションがかかる。

```rb
class TestComponent < ActionView::Component
  validates :content, :title, presence: true

  def initialize(title:)
    @title = title
  end

  def self.template
    <<~'erb'
    <span title="<%= title %>"><%= content %></span>
    erb
  end

  private

  attr_reader :title
end
```

### コンポーネントの呼び出し
- ERB 内で `TestComponent.new(title: "my title")` などとしてインスタンス化し、`render` に渡す。
- ブロック引数を与えると、コンポーネント内で `content` として扱うことができる。

```erb
<%= render(TestComponent.new(title: "my title")) do %>
  Hello, World!
<% end %>
```
これは次のような HTML を返す。

```html
<span title="my title">Hello, World!</span>
```

### エラー
上の例では title に対して presence: true しているので、title が空だと怒られる。

```erb
<%= render(TestComponent.new(title: "")) do %>
  Hello, World!
<% end %>
```

```
ActiveModel::ValidationError: Validation failed: Title can't be blank
```

# テスト
コンポーネントはユニットテストできて、テストヘルパーとして `render_component` が用意されている。

```rb
def test_render_component
  assert_equal(
    %(<span title="my title">Hello, World!</span>),
    render_component(TestComponent.new(title: "my title")) { "Hello, World!" }.css("span").to_html
  )
end
```

# 利点
#### テスト
`ActionView::Component` によってビューがユニットテスト可能になる。1テストあたり25ミリ秒で終わるのに対し、統合テストだと最大で6秒かかる。

#### カバレッジ
`ActionView::Component` は一部のコードカバレッジツールで互換性がある。SimpleCov ではある程度うまくいっているっぽい。

#### データフロー
ビューのレンダリングに必要なコンテキストを定義できるので、 `partial` よりも再利用しやすい。

#### パフォーマンス
ベンチマークテストにおいて、 `component` は `partial` よりも5倍の性能を発揮した。

```
Comparison:
           component:     6515.4 i/s
             partial:     1251.2 i/s - 5.21x  slower

```
こちらのデモレポジトリで試せる。
https://github.com/joelhawksley/actionview-component-demo

---
引用ここまで。

# まとめ
ActionView::Component を使うと切り出したビューをオブジェクトとして定義でるようになります。
それによって、変数の検証が可能、ユニットテストができる、さらに partial よりも高速、といった恩恵を受けられます。
ちなみにこの内容は Rails 6.1 から使えるようになりそうです。
重複しない整数乱数発生（０〜N-1）


0から、N-1までの、ダブらない整数の乱数発生コード。

C:
Version 1.5 (6/20)
　N回以上呼び出した時のバグ修正。手直し。LoiuS0616さんのコードから。
Version 1.7　(6/20)
 フィッシャー-イェーツのシャッフルアルゴリズムを使用。

C++:
Version 2.1

Python:
Pythonでも、書いてみました。

#C

```krand.c
/*
   整数での、0からN-1までの、ダブらない乱数発生
   Ver 1.7
   ここでは、Nは、400にしています。
 */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 400
int numbers[N];

void initrnd(void) {
    for(int i = 0; i < N; ++i) {
        numbers[i] = i;
    }

  for(int i = 0; i < N - 1; ++i) {
    int r = rand() % (N - i) + i;

    {
        int tmp = numbers[i];
        numbers[i] = numbers[r];
        numbers[r] = tmp;
    }
  }
}

int rnd(void) {
    static int rcount = 0;
    int t;
    t=numbers[rcount++];
    if (rcount==N) { initrnd(); rcount=0; }
    return t;
}

int main(void) {
    srand((unsigned)time(NULL));
    initrnd();

    for(int i = 0; i < 2*N; ++i) {
        printf("%d\n", rnd());
    }

    return 0;
}

```
#C++

```krand.cpp
//   整数での、0からN-1までの、ダブらない乱数発生
// Ver 2.1
#include <iostream>
#include <random>
#include <vector>
#include <numeric>
#include <cstdlib>
#include <algorithm>

using namespace std;

class krand {
  int rcount;
  vector<int> num;
  void init(int n) {
    N=n;
    for(int i=0;i<n;i++)
      num.push_back(i);
    std::random_device seed_gen;
    std::mt19937 engine(seed_gen());
    std::shuffle(num.begin(), num.end(), engine);
    rcount=0;
   }

public:
  krand(int n) {init(n);}
  int rnd() {
    int t;
    t=num[rcount++];
    if (rcount==N) { 
      std::vector<int>().swap(num);
      init(N); }
    return t;
   }

  ~krand() {
      std::vector<int>().swap(num);
   }
  int N;
};

int main(void) {
    krand r(400),r2(200);

    for(int i = 0; i < r2.N; ++i)
        cout << r2.rnd() << endl;
    for(int i = 0; i < r.N; ++i)
        cout << r.rnd() << endl;

    r.~krand();
    r2.~krand();
    return 0;
}

```
#Python

```krnd.py
#!/usr/bin/python3
import random


class krand:
    def __init__(self, n):
        self.N = n
        self.ini(n)

    def ini(self, n):
        self.ns = [0]*n
        for i in range(n):
            self.ns[i] = i
        random.shuffle(self.ns)

    def rnd(self):
        i = self.ns.pop(0)
        if len(self.ns) == 0:
            self.ini(self.N)
        return(i)

    def __del__(self):
        self.ns = []
        self.N = 1


k = krand(400)
for i in range(400):
    print(k.rnd())
for i in range(400):
    print(k.rnd())
del k

```
gitでどうしてもリモートのブランチがcheckoutできないとき

fetchしていないとかそういう話ではない。

```
>git checkout [ブランチ名]
error: pathspec '[ブランチ名]' did not match any file(s) known to git.
```

かなり古いディレクトリ（サイズが大きいので再cloneしたくなかった）の上に色々弄ったので条件が確かでないが、恐らく下の操作で解決した。

```
> git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
> git fetch origin
> git checkout [ブランチ名]
```

参考：https://stackoverflow.com/questions/35235232/check-out-a-branch-that-exists-in-a-remote

## 追記

single-branchでcloneした（shallow cloneの場合などデフォルトでそうなっている）リポジトリだと`remote.origin.fetch`にそのブランチしか設定されず、この様にfetchしても虚無という事になるようだ。
GitLab12メールサーバ機能設定


# 概要

* GitLab7からGitLab11へ移行中
* 利用者各自でユーザを登録するためメールサーバの機能が必要となる
* smtpはGmailを使用することによって手間を省く

# 手順

## GitLabでメール機能設定

* Configを以下のように変更する

```
$ sudo vi /etc/gitlab/gitlab.rb
external_url 'http://gitlab.geeplus.net'
:
:
### Email Settings
gitlab_rails['gitlab_email_enabled'] = true
gitlab_rails['gitlab_email_from'] = 'hogehoge@fuga.jp'
gitlab_rails['gitlab_email_display_name'] = 'hogehoge'
gitlab_rails['gitlab_email_reply_to'] = 'hogehoge@fuga.jp'
:
:
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "smtp.gmail.com"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "hogehoge@fuga.jp"
gitlab_rails['smtp_password'] = "password"
gitlab_rails['smtp_domain'] = "smtp.gmail.com"
gitlab_rails['smtp_authentication'] = "login"
gitlab_rails['smtp_enable_starttls_auto'] = true
gitlab_rails['smtp_tls'] = false
:
:
```

## GitLabをビルドしなおす

```
$ sudo gitlab-ctl reconfigure
Starting Chef Client, version 13.6.4
resolving cookbooks for run list: ["gitlab-ee"]
Synchronizing Cookbooks:
  - package (0.1.0)
  - gitlab-ee (0.0.1)
:
:
gitlab Reconfigured!
```

## Gitlabを再起動する

```
$ sudo gitlab-ctl restart
```

## Googleアカウントのセキュリティを下げる

* 以下にアクセスする
* https://myaccount.google.com/security

* ”安全性の低いアプリのアクセス”にて”アクセスを無効にする”を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/d779b435-bc51-d08a-ab2f-c26bb902256a.png)

* "安全性の低いアプリの許可: 有効"に変更する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/c12a8be8-8c91-a3c8-d0b5-6cc2657193ba.png)

## メールが届くことを確認する

* メールを確認する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/d20594f6-20a4-3037-438e-b02cf5d7feb2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/6a28bfd0-696d-25f3-7795-7a1eef7b4394.png)



## 遭遇したエラー

### Googleにはじかれる

* 前述の「Googleアカウントのセキュリティを下げる」をやっていない場合に発生

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/75934d50-a769-13da-fc55-1e7b4a716590.png)
Rails5以降の本番環境でデータベースをresetする方法！

チーム開発をしている中で、本番環境のデータベースをresetしたかったんですけど、どうやらRails5から、本番環境においては、db:dropなどのデータベースを破壊する系のコマンド実行を防止する機能が追加されたそうです...

そのような時に、

```terminal
$ RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rake db:drop
```
上記のコマンドを実行すると、例外的にresetできるみたいです...

どうやら、環境変数にDISABLE_DATABASE_ENVIRONMENT_CHECK=1というものを付与すれば良いらしい...

reset出来たので、後は

```terminal
rake db:create RAILS_ENV=production

rake db:migrate RAILS_ENV=production
```

こちらの手順で、本番環境のデータベースを綺麗にすることができました！

本番環境では、末尾に***RAILS_ENV=production***をつけることがポイントです！

---

以上となります！

本番環境は少しいじるだけで、エラーが多発するので、すごく慎重になりますね...

ご静聴ありがとうございました！:relaxed:
UnityでUniTaskな処理を直列に並べて処理をする

この記事は、UniRxとUniTaskが前提になります。
UniRxとUniTaskついてはまずこちらをご覧ください
https://github.com/neuecc/UniRx
https://github.com/Cysharp/UniTask

昨今、Unityが対応しているC#バージョンが上がってきたことにより、UniTaskなどで非同期な処理を書くことが多くなってきました。
しかしUnity上でゲーム表現のリッチ化などもあり、リソースの都合上並列で行うことにできない非同期処理の需要は細々とあるかとおもいます。
自分もそのようなものが必要になったので、UniTaskな処理をまとめてQueueに予約し、逐次的に処理をしていくSequentialProcessQueueというクラスをGist上に公開したので紹介します。

SequentialProcessQueue
https://gist.github.com/yKimisaki/0909e811f4959badba0ad7f8b3a2ee7e

以下はアバターのあるマルチプレイなゲームで、プレイヤーアバターを作るファクトリクラスを想定したものです。

```csharp:SomeFactory.cs
class PlayerAvatarFactory : IDisposable
{
    SequentialProcessQueue queue;

    public SomeFactory()
    {
        // デフォルトはObservable.EveryUpdateですが、引数で変更することができます
        queue = new SequentialProcessQueue(MainThreadDispatchType.FixedUpdate);

        // SequentialProcessQueueで処理が走っているかはIsProcessingで受けることができます
        queue.IsProcess.Subscribe();
    }

    public void Dispose()
    {
        // 必ず不要になったらDisposeしてください
        queue.Dispose();
    }

    // いつプレイヤーが入ってくるかわからない
    public void OnJoinPlayer()
    {
        try
        {
            var cancellationTokenSource = new CancellationTokenSource();
            queue.ReserveProcess(CreatePlayerAvatarAsync, cancellationTokenSource.Token); // 処理を予約

            // 予約を個別にキャンセルできる
            // SequentialProcessQueueで処理が開始する前にキャンセルすればスキップされる
            cancellationTokenSource.Cancel();

            async UniTask CreatePlayerAvatarAsync()
            {
                // 並列にできないとても重い処理

                if (cancellationTokenSource.Token.IsCancellationRequested)
                {
                    // 個別でキャンセルされてる場合はこっち
                    return;
                }

                if (queue.AllQueueCancellation.IsCancellationRequested)
                {
                    // SequentialProcessQueueがDisposeされている等のキャンセルはこっち
                    return;
                }

                // 並列にできないとても重い処理
            }
        }
        catch (OperationCanceledException e)
        {
            // 既にCancellationTokenSourceがキャンセルされてる場合や
            // SequentialProcessQueueがDisposeされている場合は
            // ReserveProcessがOperationCanceledExceptionを吐く
        }
    }
} 
```
SpringSecurityのログイン画面でtoo many redirectsが出てしまった話

# SpringSecurityのログイン画面でtoo many redirectsが出てしまった話
すごく阿呆みたいな勘違いのせいだったのですが、
結構解決に苦労したので備忘も兼ねて

## 起こった事象
認証をSpringSecurity + Cognito でOAuth2認証を行っているアプリを検証環境を作成してデプロイしたところ、
ログイン画面に無限にリダイレクトするようになってしまった。

### その他の関連のある情報
* 全体はSpringBootで構築
* 環境依存情報については新たにapplication-staging.ymlを作成。実行時引数でprofileを切り替えることにした。

## 原因
結論から言うと、profileの切り方が間違っていました。
application-staging.ymlを作った後も、開発環境用の設定が入っていた
application.ymlをそのままにしてしまっていたので、
二つのymlの内容が混ざって読み込まれることになってしまいました。
(profile付きのymlやpropertiesが存在するときはprofile無しのものの内容をすべて上書きすると勝手に思い込んでいました)

実際にはprofile付きのものを読み込んだ後、キーが重複するものだけapplication.ymlの内容で上書きし多様で、キーが完全に一致していた項目と、一部キーがずれていた項目が絶妙に噛み合わず無限リダイレクトという珍妙な結果になったようです。

## 解決策
開発環境用の設定をapplication.ymlからapplication-dev.ymlに分けたところ無事に解決しました。
スクレイピング⇒Google Spreadsheet⇒条件付きでLINE通知

###背景
欲しいデータを定期でスクレイピングしてローカルのCSVに保存することは結構あるし、がっつり開発するときはBigqueryに入れる。ただスマホから確認できないのは不便な時もあるし、ちょっとしたデータならSpreadSheetに書き込めばいいのかなと思った。
それから定期的に追いかけているデータが大きく変動した時にLineに通知が来ると安心である。

噛み砕いて言うならば理想は
GCEでデータを取得⇒SpreadSheetに書き込み⇒条件によってLine通知
である。

今回はpythonを使ってSpreadsheetに書き込み、Line通知について書く。

###GoogleSpreadsheetに接続

この記事を参考に設定した。
https://qiita.com/akabei/items/0eac37cb852ad476c6b9

やったことは、

- google driveのAPI設定
- google spread sheetのAPI設定
- google spread sheetのサービスアカウントの追加(jsonのダウンロード)
- spreadsheetの編集権限をjsonファイルの中のmailアドレスに付与


###コードを書いた

```shell

pip install gspread oauth2client
```



```spreadsheet.py
import gspread
from oauth2client.service_account import ServiceAccountCredentials
import time

scope = ['https://spreadsheets.google.com/feeds',
        'https://www.googleapis.com/auth/drive']

credentials = ServiceAccountCredentials.from_json_keyfile_name('jsonのpath', scope)
gc = gspread.authorize(credentials)

workbook = gc.open('SpreadSheetの名前')
sh = workbook.worksheet('シートの名前')
values_list = sh.col_values('1')
i = len(values_list) +1

#カラムA,B,Cに無限にデータを入れていく。
while True:
    sh.update_acell('A'+str(i),データA)
    sh.update_acell('B'+str(i),データB )
    sh.update_acell('C'+str(i),データC)
    i += 1
    time.sleep(10)

```

特に意味はないコード
カラムAの最後列の番号を取得して、カラムA,B,Cに無限にデータを入れていく。


###Line (Line Notify) と接続
下記のリンクからLine Notifyの登録をする。
https://notify-bot.line.me/ja/

アカウント作成後、マイページからAPIを発行
連絡先は1対1で連絡を選択した。

### コードを書いた

```line_notice.py
import requests

def notice(message):
    line_notify_token = '発行したAPI'
    line_notify_api = 'https://notify-api.line.me/api/notify'


    payload = {'message': message}
    headers = {'Authorization': 'Bearer ' + line_notify_token}  # 発行したトークン
    line_notify = requests.post(line_notify_api, data=payload, headers=headers)
```


### まとめ
spreadsheet.pyの中にif文で条件分岐をして、notice()を呼び出せばいける。

安心感がある。
SQL

SQL とは。。
SQL（Structured Query Language）はリレーショナルデータベース（RDB）の操作を行うための言語。

そもそも、RDBとはデータベースの分類の一つ

データベースは、おもに「階層型データベース」「ネットワーク型データベース」「リレーショナル型データベース」の3つに分類できます。

階層型データベースについて
・データはツリー構造で表す。
・1つのデータが他の複数のデータに対して、親子の関係をもつ。
・データにアクセスするためのルートは一通りしかありません。

ネットワーク型データベースについて
・データは網の目の形で表現されます。
・一つのデータに対し、複数の親を持つような構造で複数の親データへのアクセスが可能。


どちらも、データ構造を理解してプログラム開発をする必要があります。

リレーショナル型データベースについて
・データを行と列から構成される2次元の表形式で表します。
・データ同士は複数の表と表の関係によって関連付けられ、目的に応じて自由な形式で簡単に操作できる。

 

つまり、階層型・ネットワーク型のデメリットを解消した画期的なデータベース。
プログラムとデータの独立性が高いため、データ構造に修正が入ったとしてもプログラムへの影響は極めて小さい、柔軟かつ容易なデータの取り出しが可能。

本題に戻ると、そのRDBを操作するための言語がSQL

SQLはデータベースやテーブルに対して様々な命令を行いますが、
その命令は大きく2つ、データを定義するDDL（Data Definition Language）と、データを操作するDML（Data Manipulation Language）に分類されます。

・DDLの出来ること
命令
機能
CREATE 
データベースやテーブルの作成 
ALTER 
データベースやテーブルの更新 
DROP 
データベースやテーブルの削除 
　

・DMLの出来ること
命令
機能
INSERT 
データの登録 
UPDATE 
データの更新 
DELETE 
データの削除 
SELECT 
データの検索 
データベースの操作　DDL

※ターミナルでの操作

>mysql -u root
    mysqlにユーザー名がrootで接続する
-u    ユーザーを指定するオプション
-p    パスワードを指定してログイン

* SHOW DATABASE;
    * 一覧の表示
* CREATE DATABASE データベース名;
    * データベースの作成
* DROP DATABASE データベース名;
    * データベースの削除
* USE データベース名;
    * 使用データベースの選択
テーブルの操作　DML

プログラムでデータを扱う際には、CRUD(Create, Read, Update, Delete)の四つの処理を正確に行うことが大切になります。
SQLというデータベースを扱う言語では、このCRUDの処理をそれぞれ「INSERT, SELECT, UPDATE, DELETE」という四つの構文で行うようになっています。
* ​SHOW TABLES;
     一覧の表示
* CREATE TABLE テーブル名( colum1 データ型,  colum2 データ型,,,,,,,);
     テーブルの作成
* INSERT INTO テーブル名(colum1,colum2) VALUES(値１,値２）
     データ登録
* ALTER TABLE テーブル名　操作
     ADD 追加
     CHANGE 更新
     DROP 削除
* SELECT * FROM テーブル名;
     データの取得　
     ＊はALL
     colum指定で任意を取得
* SELECT * FROM  テーブル名  WHERE id = 2;
     Id２のレコードを取得
* UPDATE  テーブル名　 SET [COLUMN名] = ”新しい値"
     データの更新
* DELETE FROM [テーブル名] WHERE [条件]
     データの削除
「投稿ルールが守られない問題」でダイアログはできても投稿されなかった問題

# はじめに

[slackで「投稿ルールが守られない問題」を自作のスラッシュコマンドで解決する(設定編)](https://qiita.com/marogoma/items/e3003564c1b8b7b09e29) を見て、めちゃわかる！！と思い、GASで実装してみた。しかしなぜかSlack上でモーダルは表示され入力、送信はできるが、入力内容がSlackに投稿されない。。。

# デバッグ

以下のミニマムですら動かない。。。利用しているライブラリの仕様変更なのかと思い試行錯誤。。。

- [Slack BotをGASでいい感じで書くためのライブラリを作った](https://qiita.com/soundTricker/items/43267609a870fc9c7453)

```js

function test() {
  var slackApp = SlackApp.create('hogehoge');
  var channelId = "#general";
  var message = "Hello World";
  var options = {
    username: "fugafuga"
  }
  slackApp.postMessage(channelId, message, options);
}
```

デバッグしてみると、どうやら権限問題っぽい。

```
{needed=chat:write:user, provided=identify,commands, ok=false, error=missing_scope}
```

# 結論

SlackAPIのbotの書き込み権限がなかっただけだった。

- `chat:write:bot`

![Slack_API.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105093/2c5d6e83-b0b7-58c1-f88b-f2e647ca27a2.png)


「権限変更したから、Slackに再インストールしてね！」って注意書きが出てくるので、再インストールすれば無事Slackに投稿された。。。
地味に時間を食ってしまった。。。
Vue Routerの設定（Laravel環境）

## ルートコンポーネントの作成
```resources/js/components/App.vue
<template>
  <div>
    <main>
      <div class="container">
        <RouterView />
      </div>
    </main>
  </div>
</template>
```
## ページコンポーネントの作成
`resources/js/components/pages`以下にページコンポーネントを作成する

- User.vue
- List.vue

## ルーティングの設定
```resources/js/router.js
import Vue from 'vue'
import VueRouter from 'vue-router'

// ページコンポーネントをインポート
import List from './components/pages/List.vue'
import User from './components/pages/User.vue'

Vue.use(VueRouter)

// パスとコンポーネントのマッピング
const routes = [
  {
    path: '/',
    component: List
  },
  {
    path: '/user',
    component: User
  }
]

const router = new VueRouter({
  // ページのリロード無しにURL遷移を実現する 
  mode: 'history',
  routes
})

export default router
```

## app.jsの編集
```resources/js/app.js
import Vue from 'vue'
// ルーティングの定義をインポート
import router from './router'
// ルートコンポーネントをインポート
import App from './components/App.vue'

new Vue({
  el: '#app',
  router,
  components: { App },
  template: '<App />'
})
```
関数を用いての計算アプリ　Swift

swiftを勉強中の初心者です。
私は今、関数を使用しての計算アプリを作成中です。
resultの値をprintで出力し、このresultの値を@IBOutlet var result: UILabel!このラベルに表示をしたいのですが、なかなかうまく行きません

色々と試したこと
１）result.text = print(y).description　→use of unresolved identifierというエラーが出ます。
２）result.text = y.description →use of unresolved identifierというエラー


    
    @IBOutlet weak var tasizan1: UITextField!
    @IBOutlet var tasizan2: UITextField!
    @IBOutlet var result: UILabel!

    override func viewDidLoad() {
        self.tasizan1.keyboardType = UIKeyboardType.numberPad //数字のみ表示する
        self.tasizan2.keyboardType = UIKeyboardType.numberPad //数字のみ
        super.viewDidLoad()
       
    }

    func number() {
        let a = Int(tasizan1.text!)
        let b = Int(tasizan2.text!)
        let y:Int = a! + b!
     
       
        print(y)
    }
    
    
    override func didReceiveMemoryWarning()
    {
    super.didReceiveMemoryWarning()
    
        
    }
    
    @IBAction func resultButton(sender: UIButton) {
        result.text = print(y).description　
    }
}
アドバイスの方よろしくお願いいたします。
アソシエーションにおけるclass_nameの定義！

こんにちは！

アソシエーションを利用してく中で、たくさんのオプションがあることを知ったので今回はその中でも、class_nameについて触れていきたいと思います！

## class_nameオプションとは？
関連を設定するモデルクラス名を指定します！
利用場面としては、関連名と参照先のクラス名を異なるものにしたい場合に指定します！

実際のコードを見ながら、説明していきます！

```ruby:model/tweet.rb
class Tweet < ActiveRecord::Base

belongs_to :user
has_many :comments

end
```

上記のTweetモデルには、Userモデルの関係が定義されているのが確認できます。
したがって、@tweet.userのような形で、@tweetに紐づいたuserレコードを取得することができます！

アソシエーションのメソッド名とクラス名が一致しているときはそれで問題ありませんが、メソッド名を変えたいこともあります...

***そんな時に、class_nameオプションが活躍します！***

```ruby:model/tweet.rb
class Tweet < ActiveRecord::Base

belongs_to :owner, class_name: 'User'
has_many :comments

end
```

上記のように記述することで、@tweet.ownerのような形で、@tweetに紐づいたuserレコードを取得することができます！

---

以上となります！

他にお気付きの点などありましたら、コメントお願いします！

ご静聴ありがとうございました！:relaxed:
Rider備忘録(Mac)

# ショートカット
[公式ショートカットまとめ(ナビゲーション・検索)](https://pleiades.io/help/rider/Navigation_and_Search__Index.html)

## ファイル内の使用箇所をハイライト
**option + shift + f11**
**esc**でハイライト解除

## エクスプローラーウィンドウで現在のタブのファイルの場所を示す
**option + shift + l**

## 矩形選択的なもの
altを２回押した後押しっぱなしにして矢印キー
または
altを押しながらマウスドラッグ

## デバッグ実行中、例外が発生した時に対象の箇所でブレークするための設定
option+command+B
![スクリーンショット 2020-10-02 16.31.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188476/e8f9b437-c05a-a3b6-0f5a-573834fee01c.png)

## 不要なusing削除
ctrl+alt+o

## 名前空間(NameSpace)を一括でリネーム
変更したい名前空間名を選択してCtrl+Shift+Rからリネーム可能
https://pleiades.io/help/rider/Refactorings__Adjust_Namespaces.html


# 機能
## ブックマーク
### とりあえずブックマークする
1. ブックマークしたい行を選択状態にする
2. Navigate/BookMarks/Toggle Bookmark
3. Favoritesウィンドウでブックマークを確認

### ブックマーク削除
Favoritesウィンドウで削除したいブックマークを選択してデリートキーを押す

## Git
### Blame
行数が表示されているところを右クリックして、Annotate with Git Blameを選択することで変更日時と変更者を確認することができる。

# トラブル
## 構文エラー、シンタックスなどが機能しない
行数が多いファイルだとこの機能が自動的に切られていた。
<img width="1680" alt="スクリーンショット 2019-06-19 11.08.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/188476/14a8605d-0275-f476-2b31-9ddfa5c40ef0.png">
赤い四角で囲われている箇所でInspectionsを設定することで解決した

# その他
## カラースキーマの設定
[カラースキーマ掲載サイト](http://color-themes.com/?view=index)でダウンロードしたものを、
Riderにインポートすることで設定ができる。
[カラースキーマのインポート方法](https://pleiades.io/help/rider/Settings_Colors_and_Fonts.html)
Rails kaminariについて

#はじめに
kaminari使ってたら意外と忘れていたのでメモります。

#gemのインストール
```
gem "kaminari"
```
```
$bundle
```

#設定ファイルの作成

```
$rails g kaminari:config
```

#bootstrap４の適応

```
$rails g kaminari:views bootstrap4
```
で完了

#コントローラーの設定

以下の設定でBlogテーブルとページネーションがひも付きました。
現状ページに対していくつ表示するかの設定をしていないため、デフォルトの設定になっています。
確かデフォルトだと25個だったような気がする。
並びもidの１番から順番にです。


```rb:controllers/blogs_controller.rb

def index
   @blogs = Blog.page(params[:page])
end
```

#ビューの設定

```erb:blogs/index.html.erb
<%= paginate @blogs %>
```
これを好きなところに書くだけで表示されます。

#ページの表示件数の指定
```controllers/blogs_controller.rb
def index
   @blogs = Blog.page(params[:page]).per(10) #1ページに対しての表示件数
end
```
後ろにPer(1０)とか書くだけ、１０件表示します。

#並び順を入れ替える

```controllers/blogs_controller.rb
def index
   @blogs = Blog.order(updated_at: :desc).page(params[:page]) #updated_atの新しい順
end
```
とかで並び替えが出来ます。

#日本語の設定

gemを入れます。

```
gem 'rails-i18n'
```
```
$bundle
```

config/locales/ja.ymlを作る。

```yaml:config/locales/ja.yml
ja:
  views:
    pagination:
      first: 最初
      last: 最後
      previous: 前
      next: 次
      truncate: ...
```

でrb:config/application.rbを日本語設定に変更する。
一行追加します。

```rb:config/application.rb
require_relative 'boot'

require 'rails/all'

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module BlogPortfolio
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 5.2

    # Settings in config/environments/* take precedence over those specified here.
    # Application configuration can go into files in config/initializers
    # -- all .rb files in that directory are automatically loaded after loading
    # the framework and any gems in your application.
    config.i18n.default_locale = :ja #この行を追加します。
  end
end
```
以上で設定完了です。もし、サーバーを立ち上げぱなしなら、再起動してください。おそらく、反映されないと思いますので。

#配列に対してペイジネーションを作成

[kaminariを使って配列に対してのページャーを作成する](https://qiita.com/Konboi@github/items/ef62a511ea35270b71be)
Railsでフォームの内容をcookieに保存する

#目的
データベースを用いずに、フォームの内容を保存する。

#方法
まずは viewファイルにフォームを用意します。

```erb:
<%= form_for(:data, url: fluit_path) do |f| %>

   <%= f.label :"好きな果物" %>
   <%= f.text_field :fluit, class: 'form-control' %>

   <%= f.check_box :check %> 林檎を食べたことがある。
　 
   <%= f.label :"好きな果物（セレクト）" %>
   <%= f.select :select, ["葡萄","蜜柑","檸檬"] %>

   <%= f.submit "保存",  class: "btn btn-success" %>
  <% end %>
```

`form_for` を用いて任意のアクションに `:data` を飛ばします。

```rb:
def fluit
    cookies.permanent[:fluit] = params[:data][:fluit]
    cookies.permanent[:check] = params[:data][:check]
    cookies.permanent[:select] = params[:data][:select]
...
end
```

任意のアクションで `:data` を受け取り、`cookies` に格納します。
ここではほぼ永続の `.permanent` でクッキーを生成していますが、自分で期限を設定することもできます。

参考：[Rails チュートリアル ｜ 9.1.2 ログイン状態の保持](https://railstutorial.jp/chapters/advanced_login?version=5.1#sec-login_with_remembering)

あとはフォームでクッキーの値を受け取るだけです。

```erb:
<%= form_for(:data, url: fluit_path) do |f| %>

   <%= f.label :"好きな果物" %>
   <%= f.text_field :fluit, class: 'form-control', value: cookies[:fluit] %>

   <%= f.check_box :check, checked: ischeck(cookies[:check])  %> 林檎を食べたことがある。
　 
   <%= f.label :"好きな果物（セレクト）" %>
   <%= f.select :select, ["葡萄","蜜柑","檸檬"], :selected => cookies[:select] %>

   <%= f.submit "保存",  class: "btn btn-success" %>
  <% end %>
```

テキストフォームは単純に `value: cookies[:fluit]` で受け取るだけで、セレクトボックスもだいたいそんな感じです。
チェックボックスは `checked:` に `true` か `false ` を渡す必要があるので少々工夫が必要です。
`cookies[:check]` の値は `0` か `1` になっています。

```rb:
  def ischeck(x)
    x == "1" ? true : false
  end
```

今回はヘルパーに三項演算子を使ったメソッドを書いて、それで補完しました。

これにて完成です。
Ruby on Rails [学習記録-第6章-]

#デバックツール
* pry-railsはRails向けに開発されたデバッグツール。
* デバッグツールとは、作業の際にバグの有無を確認したり、処理を止めてソースコードが正しいかを確認する際に使用するツールのこと。
* デバッグツールを使いこなすことで、より開発がしやすくなる。
* pry-railsの機能の中で最も使用するのはbinding.pry(バインディングプライ)という機能。これは、binding.pryという文字列をソースコードの中に記述することで、binding.pryという文字列が存在する部分でRailsの処理を止めることができる。

#ルートパス
* localhost:3000」や「app.me」のように、パスを付けないホスト名だけのURLのことをルートパスと言いう。
* 以下の例のように、`root コントローラ名#アクション名`とすればルートパスにアクセスした際に見せる画面を指定できる。

```rb:route.rb
Rails.application.routes.draw do
  root  'コントローラ名#アクション名'
end
```

#orderメソッド
* allメソッドを利用した場合、通常であればレコードはid順に取得されますが、下記のようにorderメソッドの引数として("id DESC")とすれば、レコードは逆順に並び替えられます。

```rb:apps_controller.rb
def index
  @contents = Content.all.order("id DESC")
end
```

#ページネーション
* 長い文章を複数のページに分割して、各ページへのリンクを並べアクセスしやすくすること。
* ページネーションを実装する際には「kaminari」というGemをインストールして使用。

##kaminari:pageメソッド
* kaminariを導入すると、モデルクラスにpageメソッドが定義されます。このメソッドは、ページネーションにおけるページ数を指定。

##kaminari:perメソッド
* perメソッドもpageメソッドと同様、kaminariというgemをインストールすることで利用できるメソッド。1ページあたりに表示する件数を指定する。

```rb:sample_controller.rb
  変数名 = クラスを利用して取得したレコードのインスタンス.page(params[:page]).per(ここに1ページで表示したい件数を入力)
```
```rb:apps_controller.rb
 @apps = App.order("created_at DESC").page(params[:page]).per(5)
# created_atはツイートが作成された日時
```

#kaminari:paginateメソッド
* ページネーションのリンクを表示したいときに使用するメソッド。
* paginateメソッドの引数は、コントローラで定義した変数を指定する。

```html:index.html.erb
  <div class="contents row" >
    <% @apps.each do |app| %>
      <div class="content_post" style="background-image: url(<%= app.image %>);">
        <%= simple_format(app.text) %>
        <span class="name"><%= app.name %></span>
      </div>
    <% end %>
  <%= paginate(@apps) %>
</div>
```
平均の落とし穴

#目次
・平均の例
・平均の定義
・平均の落とし穴

#平均の例
平均の厳密な定義は確率論を使うことになりますが、大雑把にいうと平均とはデータの真ん中を表した指標です。

（例１）５人の身長がそれぞれ、170cm,165cm,160cm,155cm,150cmだとすると、５人の身長の平均は下記のように計算します。
$$160= \frac{170+165+160+155+150}{5}$$
（例２）５人の身長がそれぞれ、200cm,200cm,160cm,120cm,120cmだとすると、５人の身長の平均は下記のように計算します。（例１）よりデータのばらつきがありますが、平均は一致しています。
$$160= \frac{200+200+160+120+120}{5}$$
（例３）サイコロ投げを考えます。「１」～「６」の出る確率はそれぞれ$\frac{1}{6}$として、確率の合計は明らかに$1$になります。出る目の平均は下記のようになります。
$$3.5= 1×\frac{1}{6}+2×\frac{1}{6}+3×\frac{1}{6}+4×\frac{1}{6}+5×\frac{1}{6}+6×\frac{1}{6}$$


つまり、平均とは取りうる「値」に「その割合（確率）」を掛け、全てのパターンで和をとったものです。（例１）と（例２）は全体を$\frac{1}{5}$で割っていますが、全体からみた1人の割合が$\frac{1}{5}$とも言い換えられますので、確率が$\frac{1}{5}$となり（例３）と同じ計算をしているという事に注意してください。

#平均の定義
$n$パターンの値を取りうる場合を考えます。取りうる値を$x_1,・・・,x_n$、それぞれに対応する確率を$p_1,・・・,p_n$とおいて、$\sum_{i=1}^{n}p_i=1$とします。このとき平均を　$$\sum_{i=1}^{n}「取りうる値x_i」×「x_iをとる確率p_i」$$で定義します。平均は「**期待値**」ともいいます。

平均は感覚的には**データの真ん中**というイメージでいいですが、データによっては真ん中からズレていることもあるので注意しなければなりません。それを説明します。

#平均の落とし穴

上記の（例１）と（例２）ではデータの平均は同じですが、（例２）の方が各データが平均周辺から離れており、データにばらつきがあります。つまり平均はデータの特徴の一つの目安にはなりますが、得られる情報は限られているということです。

平均を見ることによって誤った解釈をすることもあります。
下記の図は厚生労働省のページから引用した平均所得金額のグラフです。

![新しいビットマップ イメージ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/429192/95ab1061-546f-ad59-255a-5e3b17697080.jpeg)

平均所得金額は５６０万円と書いてあります。図を見ずにこの金額だけ知ったら５６０万円付近の人が多いんじゃないかと思ってしまいそうですが、実際は３００万円～４００万円の人が一番多いことが図から見て取れます。最も多い階級を**最頻値**といいますが、この最頻値と平均値との乖離がなぜ起こるかというと、図の右側に所得金額が非常に高い人たちがいて、この人たちが平均所得金額を押し上げているのです。

※ちなみに図中の**中央値**とは、データを大きい順にならべたときに丁度中心にあるデータをいいます。

このように平均を知るだけではデータの解釈を誤ってしまうことがあるので、データがどのようにばらついているのか、その分布はどのようになっているのかを意識することが大事だといえます。平均の意味を正しく理解していないと統計データにだまされてしまいます。

#参考資料
 [厚生労働省の国民生活基礎調査の概況](https://www.mhlw.go.jp/toukei/saikin/hw/k-tyosa/k-tyosa17/index.html "Qiita")
集合

```py
my_friends = {'A', 'C', 'D'}
A_friends = {'B', 'D', 'E', 'F'}

print(my_friends & A_friends)
print(my_friends | A_friends)
print(my_friends ^ A_friends)
```

```my_friends & A_friends```
で my_friends 且つ A_friends
![a且つb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441463/bc694fc7-0aa5-eb96-5174-baacf9c1bc91.jpeg)
```my_friends | A_friends```
で my_friends または A_friends
![aまたはb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441463/420426c2-e5bd-1f43-69f2-9d775037c6d9.jpeg)
```my_friends ^ A_friends```
で排他
![排他.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/441463/b7bcb929-c565-4b80-10b0-75d6e6b00fe4.jpeg)


```py
fruits = ['apple', 'banana']
fruits.append('apple')
fruits.append('orange')
fruits.append('banana')
kind = set(fruits)

print(fruits)
print(kind)
```

果物リストにappleとbananaがあり、
apple、orange、bananaを買い足した。
リストにある果物の種類を重複なしのユニークでkindに格納
fruitsリストとkindを出力
Vuetifyで手っ取り早くフォントを変更する

# 環境
```
$ vue -V
3.8.4
```
# やり方
App.vueに下記のようなcss(scss)を追加する

```html
<style lang="scss">
* :not(.v-icon) {
  font-family: "Hiragino Kaku Gothic Pro","メイリオ", sans-serif!important;
}
</style>
```

###記述例

```vue:App.vue
<template lang="pug">
  v-app
    router-view
</template>

<script lang='ts'>
import { Component, Vue } from 'vue-property-decorator';
@Component
export default class App extends Vue {}
</script>

<style lang="scss">
* :not(.v-icon) {
  font-family: "Hiragino Kaku Gothic Pro","メイリオ", sans-serif!important;
}
</style>
```

#補足
かなり強引なやり方だと思うので、あくまでも **手っ取り早く** 変更する方法です。
他に良い方法があればそっちを行うのが良いと思います。
(そして僕にも教えていただけると嬉しいです。)
[Vue]WEBアプリのショートカット機能の実装で、Vueのシステム修飾子を使おうとしたら、ものすごく微妙だった件

# 今日のコード
<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="html,result" data-user="riotam4" data-slug-hash="GbqGwM" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="[Vue]システム修飾子サンプル">
  <span>See the Pen <a href="https://codepen.io/riotam4/pen/GbqGwM/">
  [Vue]システム修飾子サンプル</a> by riotam (<a href="https://codepen.io/riotam4">@riotam4</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
必ず入力欄を選択した状態で、「alt + c」を入力してください。
# 解説
v-onディレクティブの、特殊な書き方の１つ。
任意のキーをキーアップした際に、v-onディレクティブでtestメソッドを発火してくれます。

なお、任意のキーというのは「alt.67」の部分で指定されていて、今回であれば「alt」と「c(=67)」と指定されている。
また、キーアップは押下した瞬間ではなく、厳密には押して離した瞬間になります。
#ショートカット割り当てに微妙な件
システム修飾子を使った機能は直感的に実装できるし、便利そうだなと感じたのですが、実はこれ、**入力欄を選択していないと実行できません**。
ディレクティブがinputタグに付いているので、それもそうかと思い、**divタグに付けてみると、起動してくれませんでした…残念**

色々試してみたところ、buttonタグなどの一部のタグでは起動できるのですが、**基本的にinputタグぐらいでしか起動してくれない様子**。
そのため、ショートカットとして使うには、このディレクティブを仕込んだinputタグ（入力欄）を選択した上でショートカットを押してもらう必要があります。
マウスを使わないで良いようにするために、ショートカットを実装したいのに…残念
# それでも、なんとかショートカットとして使うとしたら…
focusメソッド等を使って、ページを開いた瞬間に、ディレクティブを仕込んだinputタグにフォーカスさせる…みたいなことで対応できなくはないかと。
でも、それ、なんか…ねぇ…って感じですよね。

# 結論
そもそも、このシステム修飾子はショートカット割り当てとして使うべきものではなかったのかもしれないです。
じゃあ、どういうときを想定しているのだろうか。
使い方間違っているよ！等々、何かありましたら、ぜひコメントください。

最後までありがとうございました。
Angular 8 Modal Tutorial with Angular Material Dialog

In this tutorial, we are going to go through abut Angular 8 Modal with Angular Material Dialog component. To create a Modal box in Angular 8 web application, we use Angular material UI library. Angular material UI library offers a wide range of UI components to create real-world web and mobile apps.

click here to read more
https://www.positronx.io/angular-8-modal-tutorial-with-angular-material-dialog/
Inserting Extra Space in HTML Web Page

Today we are going to talk about HTML Space; space referred to the position at a distance from one another. We’ll learn in this tutorial how to add space in HTML. When it comes adding space in HTML web page, there are multiple methods available through which we can add space in HTML.
DigitalOcean Affiliate
We are 

click here to read more
https://www.positronx.io/inserting-extra-space-in-html-web-page/
Firebase Authentication in Angular 8 with AngularFire2

Firebase Authentication in Angular 8 with AngularFire2 tutorial will be the most popular topic nowadays. Firebase is a real-time NoSQL database to create modern web and mobile application. Setting up an authentication system with Firebase in your web and mobile apps is very easy.


click here to read more
https://www.positronx.io/firebase-authentication-in-angular-8-with-angularfire2/