OmniAICreator/Qiita-1.07M huggingface dataset:
logbackのログがWebアプリ停止時に出力されない問題に対する対処方法について

先日・・・Webアプリケーション停止時にログが出力されないという事象に遭遇しました :cry:
その原因と解決方法をメモっておこうかと思います。


# アプリケーションの構成要素

本事象が発生したアプリケーションの構成要素（ざっくりな構成要素）は以下の通りです。

* Tomcat (warデプロイ)
* Spring Framework(Spring MVC)　※諸事情により「Spring Boot」は使ってない・・・
* Logback

# なぜログが出力されなかったのか？

Webアプリケーション停止時に行う処理（破棄処理）にて、「Logbackのログ出力機能を停止する処理」が一番最初に呼び出されていることが原因でした。

ざっくりいうと以下のような流れで処理が実行されていました。

* サーブレットコンテナの停止開始
* Logbackのログ出力機能の停止
* Springのアプリケーションコンテキストの破棄処理 → **ここで出力しているログが出ない・・・**
* サーブレットコンテナの停止完了

# 誰がLogbackのログ出力機能を停止しているのか？

Logback(logback-classic)には、`LogbackServletContainerInitializer` というクラスが含まれており、Servlet 3.0以上をサポートするアプリケーションサーバにデプロイすると、`LogbackServletContextListener`クラスがサーブレットコンテナに自動的に登録される仕組みになっていました。
今回のケースでは、`LogbackServletContextListener`の`contextDestroyed`メソッドの中で「Logbackのログ出力機能を停止する処理」が実装されていました。

# ログを出力するにはどうすればよい？

今回のケースでは・・・

* サーブレットコンテナの停止開始
* Springのアプリケーションコンテキストの破棄処理
* Logbackのログ出力機能の停止
* サーブレットコンテナの停止完了

といった感じで、「Logbackのログ出力機能を停止する処理」が一番最後に実行されるようにすればよさそうです。

# `LogbackServletContextListener` の自動登録の無効化

処理順番を変更するためには・・・まず `LogbackServletContextListener` の自動登録機能を無効化します。無効化する方法はいくつかありますが、本エントリーでは、サーブレットコンテナのパラメータを使って無効化する方法を紹介します。

* `web.xml`

```xml
<context-param>
    <param-name>logbackDisableServletContainerInitializer</param-name>
    <param-value>true</param-value>
</context-param>
```

> **NOTE:**
>
> システムプロパティまたは環境変数を利用して無効化することも可能です。
>
> * http://logback.qos.ch/manual/configuration.html#webShutdownHook

# 手動で `LogbackServletContextListener` を追加

自動登録を無効化した上で、Springのアプリケーションコンテキストの初期化・破棄を行うためのリスナークラス(`ContextLoaderListener`)より前に、`LogbackServletContextListener` クラスを定義します。

```xml
<listener>
    <listener-class>ch.qos.logback.classic.servlet.LogbackServletContextListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
```

こうすることで、（とりあえず・・・Tomcatでは）「Springのアプリケーションコンテキストの破棄処理」が行われた後に、「Logbackのログ出力機能を停止する処理」が実行されるようになりました。

# 関連リンク

* http://logback.qos.ch/manual/configuration.html#stopContext
* https://stackoverflow.com/questions/47184045/spring-predestroy-no-logging-because-logback-stops-too-soon
ゲームプログラミングC++を1から

#はじめに
私は情報理工系の大学院一年生です。
研究も細々としていましたが、自分をブラッシュアップするためのことを全くしておらず、
ひどく後悔しました。そんな自分でも何かできるようになろうと、強化月間のようなものを設けてみようと思い立ち、情報発信の練習もかねて投稿させていただきます。
稚拙な書き手ではございますが、何か得ることがある記事にしていきたいと思います。

#なぜゲームプログラミング？
Unityなどで、簡単なゲームを作ったことはあるのですが、ゲームエンジンの中身がよくわからず、自由に作れている感覚が得られなかったからです。C++をもちいて少しでも低めのレイヤーで自分でコードを打ちながら作っていこうと考えたからです。

#環境とgit

```
OS Windows 10 Home(64bit)
processor Intel Core i7-9750H CPU @ 2.60GHz
RAM 16.0 GB
IDE Visual Studio 2019
```

gitは[こちら](https://github.com/PaxAccipiter/GameProgrammingcCpp)

#本
ゲームプログラミングC++ : [amazon](https://www.amazon.co.jp/%E3%82%B2%E3%83%BC%E3%83%A0%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0C-Sanjay-Madhav/dp/4798157619)

#Chapter1
###今回作ったゲーム
簡単なピンポンゲームです。
青背景に左端に白色のパドル、真ん中に白いボールがあり、パドルでボールをはじくというものです。パドルは上下に動き、WとSキーで操作を行います。

###ゲームループ

1. **概要**<br>
ゲームはフレームごとのループの処理が行われている。そこには、大きく分けて次の3つの処理段階が存在している。
1. **入力処理**<br>
入力となるものは、キーボード、マイク、マウスなど多岐にわたります。それらを受け取る機能がSDLにあるので、それを受け取ることでパドルの動作方向、ゲームの停止を決めています。
1. **ゲーム更新**<br>
ループの速度はプロセッサによってきまってしまうので、更新はデルタタイムを用いて行う。
要は、**実時間の1秒当たり何ピクセル動くのか**を記述することでプロセッサによらない画面上のオブジェクトの速度を表すということ。ここでパドルの次の位置、ボールの次の位置と、衝突判定を行う。
1. **出力処理**<br>
画像に描画する部分。イメージとしては、Rendererは1つのpixelであり、画面サイズ分の配列を持ったバッファの一部をその色で塗ることを繰り返して、最終的に出力を行うというもの。

#躓いたところ
VisualStudioに慣れていないので、この周りについて躓いた部分も書いていこうと思います。
###外部ライブラリの入れ方
プロジェクトのプロパティから

1. C/C++の全般:追加のインクルードディレクトリ
1. リンカの全般:追加のライブラリディレクトリ
1. リンカの入力:追加の依存ファイル

を著者のプロジェクトの設定の通りにすることで、ヘッダファイルなどが探せるようになります。
その他プロパティについて詳しく知りたい方は、[こちらのDocument](https://docs.microsoft.com/ja-jp/cpp/build/reference/property-pages-visual-cpp?view=vs-2019)にあるかと思います。

###SDL_mainの外部参照エラー
今回ゲームを表示するために使っているのはSDLライブラリです。
コンパイル中にLNK2019のエラーが出ました。

```bash:LNK2019error
LNK2019	未解決の外部シンボル "public: __thiscall Game::Game(void)" (??0Game@@QAE@XZ) が関数 _SDL_main で参照されました	
```
これはGameのコンストラクタが宣言されているだけで定義されていないのが問題でした。Game.cppに定義することで解決しました。

###ビルドできるのに.dllが見つからない
実行時にSDL2.dllが見つからないと出てきますが、
これは、ソリューションがあるフォルダ下のDebugフォルダの中にSDL2.dllを入れてあげると問題なく動作するようになりました。
これは、ビルドしたゲームがdllを探すのがdebug直下だからだという理由らしいです。

#おわりに
読んでいただきありがとうございました。
できるだけ続けられるように簡単に記事にしました。
わかりやすくまとめられているようには感じないので、もっと精進したいと思います。
本を読んだ感じとしては、アイデアを文中で与えて、gitで完成コードの感覚をつかみながら自分で書いていくので、わかりやすかったです。
自身のgit内のソースコードに関しては、本の中の課題や、やってみて自分で感じたことをもとに改変している場合があるのでご注意ください。
node.jsでneo4jのOGMを使う④データを操作してみる

#１）準備：テストデータを入れる

適当にテストデータを作ります。

`create (:actor{name:"堺雅人"})-[:ACTS_IN{name:"半沢直樹"}]->(:movie{name:"半沢直樹"})`

`match (a:actor{name:"堺雅人"}) merge (a)-[:ACTS_IN{name:"小見門健介"}]->(:movie{name:"リーガルハイ"})`

`match (m:movie{name:"半沢直樹"})　merge (a:actor{name:"香川照之"})-[:ACTS_IN{name:"大和田常務"}]->(m)`

`match (m:movie{name:"リーガルハイ"})　merge (a:actor{name:"新垣結衣"})-[:ACTS_IN{name:"黛"}]->(m)`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397300/c502e26a-9794-8296-142a-a19758d8cfc3.png)


#2)スキーマ定義を行う

スキーマを定義したjsファイルを入れる[model]ディレクトリを作りスキーマ定義を行います。

```/model/actor.js
module.exports = {
  id: {
    type: 'uuid',
    primary: true
  },
  name: 'string',
    acts_in: {
        type: "relationships",
        target: "movie",
        relationship: "ACTS_IN",
        direction: "out",
        properties: {
            name: "string"
        },
        eager: true // <-- eager load this relationship
    }
}
```

```/model/movie.js
module.exports = {
  id: {
    type: 'uuid',
    primary: true
  },
  name: 'string'
}
```

#3)定義したスキーマを利用してデータを読みこむ

テストデータのnodeを読み込んで出力してみます。

```index.js
        var neode = require('neode');

        //①.envファイルの設定を元にneo4jサーバーに接続
        const instance = new neode.fromEnv();

        //②modelディレクトリ内のスキーマ定義ファイルを読み込む
        instance.withDirectory(__dirname+'/model');

        //③actorノードをすべて読み込む
        instance.model("actor").all()
        .then(actors => {
            //④すべてのactorの出演movie名を出力
            actors.forEach(actor =>{
                console.log("【"+actor.get('name')+"】")
                const acts_ins = actor.get('acts_in')
                acts_ins.forEach(acts_in =>{
                    console.log("出演:"+acts_in.endNode().get("name"));
                })
            })
        })
```


すべてのデータをJsonで出力する場合は下記で取得できます。

```index.js
actors.toJson().then(json=>console.log(json))
```

Collection型で取得したデータに使えるメソッド

+ `length()`・・・データ件数の取得
+ `get(index)`・・・指定したnodeの取得
+ `first()`
+ `map(fn)`
+ `find(fn)`
+ `forEach(fn)`
+ `toJson()` ・・・すべてのJSONデータの取得（Promise）


##条件を指定してデータを取得する

all(properties, order, limit, skip)

instance.model("actor").all({name:"堺雅人"})
[aws] VPCピアリングの動作確認

## 概要

VPCピアリングを実際の環境で試したことがなかったため、手順を簡単にまとめます。

## 環境

`10.0.0.0/16`と`10.1.0.0/16`のVPCを同一アカウント・リージョンで`CloudFormation`を使用し作成しています。
CloudFormation については以下記事にて簡単に概要を記載しているのでそちらを参照してください。

https://qiita.com/hrtkjm/items/0a3b9840b1e9d3b67ffc

|ネットワーク |サブネット| プライベートIP
|--- | --- | ---
| 10.0.0.0/16 |10.0.1.0/24 |10.0.1.81
| 10.1.0.0/16 |10.1.1.0/24 |10.1.1.114

## VPCピアリング

`サービス → VPC → ピアリング接続`を押下し、対象のVPCのピアリング接続を行います。

![スクリーンショット 2020-11-01 23.19.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497547/96ebf2fd-304d-e7a4-ad9f-2f66ace12489.png)

VPCピアリング作成後、接続先にリクエストが飛ぶので承諾を行います。

![スクリーンショット 2020-11-01 23.30.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/497547/8cef9bc1-b910-a5ef-8d55-2ca44a57405b.png)

その後、`ルートテーブル`にルートを追加します。

|送信先 | ターゲット
|---|---
|10.1.0.0/16 | pcx-xxxxxxxxxx

|送信先 | ターゲット
|---|---
|10.0.0.0/16 | pcx-xxxxxxxxxx


動作確認のために、`セキュリティグループ`のインバウンドルールにsshの接続をそれぞれ許可する設定を追加します。


|タイプ | プロトコル | ポート範囲 | ソース
|---|--- |---|--- | ---
|SSH | TCP | 22 | 10.1.0.0/16 

|タイプ | プロトコル | ポート範囲 | ソース
|---|--- |---|--- | ---
|SSH | TCP | 22 | 10.0.0.0/16 

## 動作確認

EC2インスタンスに秘密鍵を配置し、プライベートIPでSSHを行うことができるか確認します。

```
[ec2-user@ip-10-0-1-81 ~]$ ssh ec2-user@10.1.1.114 -i ./xxx.pem
Last login: Sun Nov  1 14:51:09 2020 from 10.0.1.81

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2017.03-release-notes/
Amazon Linux version 2018.03 is available.
[ec2-user@ip-10-1-1-114 ~]$
```

無事`10.0.1.81`の環境から`10.1.1.114`へSSH接続できることを確認できました!
dependabotからのPRがconflictした時の対処法

## dependabotからのPRが溜まってると

- 各dependabot PRをmergeしていくと
- 後半のPRで、dependabot同士の変更がconflictしてしまう...
- 自分で一個ずつconflictを解消していくのも手だが
- dependabotのPR同士が引き起こしたconflictであれば、簡単に直せる


## 解決法2種類

### 1. closeして、reopen

- closeして
- reopenするだけで自動で直せる！

#### conflictしたPRをClose

- closeすると、こんなコメントが

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98082/1089ba72-23ab-7cb3-61e3-40458c0533b1.png)

>If you change your mind, just re-open this PR and I'll resolve any conflicts on it.

- PRを再度オープンにすることで、dependabotがconflictを解決してくれるとのこと

#### Reopen

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98082/9333068b-bce4-525f-b18f-29e585d54b2f.png)

- force-pushされてconflictが修正されていることが分かります

### 2. @dependabot rebase をコメントする

もっと簡単な方法もある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/98082/2121fb8d-d41a-1f9e-c3a9-1388d538c730.png)

ここに書いてある通り、 `@dependabot rebase` をコメントするだけ

## 参考

- 実際にconflictが解消されたPR
https://github.com/CASIXx1/rails-docker-base/pull/232
firebaseConfigの中身がgithubにpushされないようにする方法【React】

firebaseのコンソールで`アプリを追加`をすると、*API key*や*authDomain*などが含まれる`firebaseConfig`が作成され、我々開発者はそれをコピーして、firebase.jsのようなファイルを作成し、そこに貼り付けて、コンポーネントでimportするなどをしてfirebaseを利用します。

ただ、これをそのままgithubにpushしてしまうとapi keyなどの情報が漏れてしまい、不正利用されるなんてこともあるかもしれません。

そこで、`.envファイルを作成してgitignoreする`ことで、githubに公開してしまうのを防ぐことができるので、その方法について説明します。

今回はreactで開発している前提で説明します。
また、firebaseConfigを`firebase.js`に記述しているものとして進めていきます。

## .envファイルをrootディレクトリに作成
まずは.envファイルを作成します。
場所は`public`や`build`などと同じ、rootディレクトリです。

作成したら.envファイルにfirebaseのapi keyなどの公開したく無い情報を記述します。

```.env
REACT_APP_FIREBASE_API_KEY=xxxxxxx
REACT_APP_FIREBASE_AUTH_DOMAIN=xxxxxxx
REACT_APP_FIREBASE_DATABASE_URL=xxxxxxx
REACT_APP_FIREBASE_PROJECT_ID=xxxxxxx
REACT_APP_FIREBASE_STORAGE_BUCKET=xxxxxxx
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=xxxxxxx
REACT_APP_FIREBASE_APP_ID=xxxxxxx
```
### 環境変数のkeyには注意しよう
reactの場合は環境変数のkey、つまりREACT_APP_FIREBASE_API_KEYなどの公開したく無い情報を代入される側は`REACT_APP_`で始める必要があります。
このように記述しないと、firebaseの読み込みが行われません。

逆にいうと、reactの場合、`REACT_APP_`で始めることで、`.env`ファイル内の記述が特に設定をすることもなく読み込んでくれます 😎

## firebase.jsの記述はどうなる？
さて`.env`ファイルが完成したので、`firebaseConfig`の中身を変更しましょう。

```firebase.js
const app = firebase.initializeApp({
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  databaseURL: process.env.REACT_APP_FIREBASE_DATABASE_URL,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID
})
```
先ほど`.env`で設定した変数を利用しているだけです😅

## .gitignoreに.envを追加して完成！！

最後は`.gitignore`に.envと記述して終わりです！！

これで、githubに公開されなくなったはずです。

ちなみにfirebaseはめっちゃ親切なので、もし、githubなどの外部に公開してしまった場合は速攻でメールを送ってくれます。

## 参考
- [create-react-appで環境変数を.envで設定する](https://qiita.com/uni-3/items/b6876a60060789583770)
- [create-react-appのプロジェクトで環境変数を.envから読み込めない原因と解決策](https://qiita.com/wakeupsloth/items/ec19b9fbfddfb1cd58bb)
- [Adding Custom Environment Variables](https://create-react-app.dev/docs/adding-custom-environment-variables/)
コメント機能を実装

#コメント機能を実装してみる
##アプリケーションを作成
```java:ターミナル
% cd projects
% rails _6.0.0_ new mini_talk_app -d mysql
% cd mini_talk_app
% rails db:create
```
##コントローラーとモデルを作成
```java:ターミナル
% rails g controller messages new
% rails g model message text:text
% rails db:migrate
```
##ルーティングを設定
```java:app/config/routes.rb
Rails.application.routes.draw do
  root 'messages#new'
  resources :messages, only: [:create]
end
```
##messages_controller.rbを編集
```java:new.html.erbを編集
<h3>mini_talk_app</h3>
<%= form_with model: @message do |f| %>
  <%= f.text_field :text %>
  <%= f.submit '送信' %>
<% end %>
<div id='messages'>
  <% @messages.reverse_each do |message| %>
    <p><%= message.text %></p>
  <% end %>
</div>
```
##チャネルを作成
```java:ターミナル
% rails g channel message
```
##stream_fromを追加
```java:app/channel/message_channel.rb
class MessageChannel < ApplicationCable::Channel
  def subscribed
    stream_from "message_channel"
  end

  def unsubscribed
    # Any cleanup needed when channel is unsubscribed
  end
end
```
##messages_controller.rbを編集
```java:app/controller/messages_controller.rbclass MessagesController < ApplicationController
  def new
    @messages = Message.all
    @message = Message.new
  end

  def create
    @message = Message.new(text: params[:message][:text])
    if @message.save
      ActionCable.server.broadcast 'message_channel', content: @message
    end
  end
end
```
##message_channel.jsを編集
```java:app/javascript/channels/message_channel.js
import consumer from "./consumer"

consumer.subscriptions.create("MessageChannel", {
  connected() {
    // Called when the subscription is ready for use on the server
  },

  disconnected() {
    // Called when the subscription has been terminated by the server
  },

  received(data) {
    const html = `<p>${data.content.text}</p>`;
    const messages = document.getElementById('messages');
    const newMessage = document.getElementById('message_text');
    messages.insertAdjacentHTML('afterbegin', html);
    newMessage.value='';
  }
});
```
#以上！
git push heroku masterの認証エラー

# エラー内容
gitにpushした後、herokuにあげようとコマンド打ったら以下の認証系のエラーが発生。

```
$ git push heroku master
Username for 'https://git.heroku.com': yuichisan171
Password for 'https://yuichisan171@git.heroku.com': 
remote: !	WARNING:
remote: !	Do not authenticate with username and password using git.
remote: !	Run `heroku login` to update your credentials, then retry the git command.
remote: !	See documentation for details: https://devcenter.heroku.com/articles/git#http-git-authentication
fatal: Authentication failed for 'https://git.heroku.com/musicquest.git/'
```
password忘れたせいか進まない...

# 解決
herokuにログインするコマンドをぶち込みます。

```
$ heroku login
 ›   Warning: heroku update available from 7.41.1 to 7.47.0.
heroku: Press any key to open up the browser to login or q to exit: 
Opening browser to https://cli-auth.heroku.com/auth/cli/browser/ab6b9c8d-641a-47a2-80e1-08d519468767?requestor=SFMyNTY.g3QAAAACZAAEZGF0YW0AAAANMTI0LjM1LjY3LjIzNGQABnNpZ25lZG4GADZ5IoR1AQ.g7NF0zMSV_VBECPITWE6xcIYOPKq0qt_RCEoaKDG0os
Logging in... done
Logged in as <メールアドレス>
```

herokuにpushします

```
$ git push heroku master
Enumerating objects: 92, done.
Counting objects: 100% (92/92), done.
<以下略>
```

お、うまく行きましたね！
同時に**パスワード管理超大事**っすね。

#参考情報
[Heroku - git push heroku master 認証エラー](https://teratail.com/questions/128880)
Javaで湯婆婆を実装してみる

##はじめに
この記事は僕が電車の中で思いついたものを元にした**ネタ投稿**です。
何か技術を書き記したものではありませんのでご容赦ください。
それから、この記事は映画「千と千尋の神隠し」のネタバレになる可能性があります。
「大丈夫！」って人だけ下に進んでください。

##コード

```java:Yubaba.java
import java.util.Scanner;
import java.util.Random;

public class Yubaba {
	public static void main(String[] arts){
		System.out.println("契約書だよ。そこに名前を書きな。");
		
		Scanner keiyakusho = new Scanner(System.in);
		String name = keiyakusho.nextLine();
		
		System.out.println("フン。"+name +"というのかい。贅沢な名だねぇ。");
		
		Random random = new Random();
		int newNameIndex = random.nextInt(name.length());
		String newName = name.substring(newNameIndex,newNameIndex+1);

		System.out.println("今からお前の名前は"+newName+"だ。いいかい、"+newName+"だよ。分かったら返事をするんだ、"+newName+"!!");
	}
}
```

こちらがコードになります。これをEclipseとかIntelliJとかにコピペすれば動きます。
「湯婆婆を実装」とはいうものの湯婆婆そのものを完全再現するというわけではなく、「千と千尋の神隠し」の名シーンの一つである湯婆婆が千尋を従業員として雇うシーンのみの再現となります。~~期待してた人には申し訳ない~~

##コードの解説
###契約書
湯婆婆はまず契約書を渡してきます。

```java
import java.util.Scanner;

//~~~~~~
System.out.println("契約書だよ。そこに名前を書きな。");
		
Scanner keiyakusho = new Scanner(System.in);
String name = keiyakusho.nextLine();

System.out.println("フン。"+name +"というのかい。贅沢な名だねぇ。");

```

Scannerクラスを使ってコンソールから名前の入力を受け取り、変数に保存します。

###名前を奪う
次に湯婆婆は名前を奪います。

```java
import java.util.Random;

//~~~~~~

Random random = new Random();
int newNameIndex = random.nextInt(name.length());
String newName = name.substring(newNameIndex,newNameIndex+1);
```
0以上(入力された文字数)未満で乱数を生成し、入力された文字列からランダムで一文字選んで抜き出します。

```java
System.out.println("今からお前の名前は"+newName+"だ。いいかい、"+newName+"だよ。分かったら返事をするんだ、"+newName+"!!");
```
そして抜き出した一文字を新しい名前として与えます。

##実行結果
![スクリーンショット 2020-10-30 13.24.09.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278363/0bc94b11-5c54-39a5-8127-ede1b147fda4.jpeg)


##おまけ
察しのいい人や、Javaに聡い人はコード全文を見た時点で気づいたかもしれません。「おいおい、こいつ"**名前の入力が空白だった場合**"の処理を書いてないぞ」と。
そうです。このコードには**名前の入力が空白だった場合の処理をあえて書いていない**のです。
なので名前の入力を空白にすると**湯婆婆がクラッシュする**という若干ゃプログラマっぽいネタコードになっています。~~クラッシュ湯婆婆とかいうパワーワード~~
![スクリーンショット 2020-10-30 13.19.33 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278363/78b18b85-9e0e-f698-b716-c533db0165fa.png)
湯婆婆がクラッシュとか面白そうじゃないですか。
あと映画の方でも名前の入力が空白だった場合のセリフなんてなかったしあえてそうしないほうが映画に忠実なのかなってことで許してください(必死の言い訳)。
~~クラッシュもしてなかったけどな~~
(2020/11/05 追記)
ここでは書きませんでしたが「どうしてもエラーを治したい!」って人は[こちら](https://qiita.com/ayhntksm_tama/items/217d8d8751242fcb0786#_reference-11455ce5c6fb75010cc7)にわかりやすく書かれているので参考にするといいかもです。

##最後に
ここまで読んでいただきありがとうございました。
Javaで湯婆婆を実装してみる、ということでJa婆婆を実装してみました。
ネタで内容が全て終わりましたが読んでいただけて幸いです。
~~ジブリファンか黒柳徹子さんにぶっ殺されたら骨だけは拾ってください~~
(2020/11/05 追記)
現在色々な方々が色々なネタで湯婆婆の記事を書いてくださっており、「こんな言語あるんだ」とか「これってこんな感じなのか」ってな感じで楽しく拝見させてもらってます。
特に何も考えないで投稿したネタ記事ですがいろんな人に見てもらって反応をいただいたり別言語でアレンジしてもらったりして嬉しい限りです。
トレンドに湯婆婆の記事が3つぐらい載ってたときとか「ネタ」のタグのページ見たときは声あげて笑いました。
今度から積極的に電車に乗ろうと思います。
(2020/11/08 追記)
湯婆婆タグができてたので追加しないわけにはいかんだろと思い追加しました。
(2020/11/11 追記)
[湯婆婆関連の記事をピックアップした自動更新のランキング](https://qiita.com/torifukukaiou/items/c8361231cdc56e493245)ができたようです。ぜひ見に行ってみてください。
(2020/11/13 追記)
僕の知らない間に[湯婆婆のアドカレ](https://qiita.com/advent-calendar/2020/yubaba)ができたようです。
トップバッターにこの記事載せていいかな…
MacOSで文字コード変換

# MacOSで文字コードを変換する方法
先日、コーディングしたストアドをPostgreSQLでクリエイトしようとしたところ、以下のようなエラーが発生した。

`ERROR:  invalid byte sequence for encoding "UTF8": 0xe5 0xae 0xe6`
エラーの内容としては、ざっくりいうと、DBのエンコーディングは`UTF-8`なのに、異なる文字コードが渡された的な意味だそうです。
Postgresqlのデフォルトのエンコーディングが`UTF-8`になっているため、対象のファイルの文字コードを変換してあげる必要があります。

## 文字コードの確認方法
以下の方法で確認することができる。

```Terminal
$ nkf -g test.sql
```
ただデフォルトでは、`nkf`コマンドが入っていないため、その場合は以下のコマンドでインストールする必要がある。

```Terminal
$ brew install nkf 
```

## 文字コードの変換
| オプション | 内容 |
| :-:| :-- |
| -s | シフトJISコードに変換する |
| -e | EUC-JPに変換する |
| -w | UTF-8に変換する |
|--overwrite| ファイルを上書きする(通常は別でファイルが作成される) |

## 他の対策方法
### SQLファイルの先頭で文字コードを宣言する
今回の投稿内容とは、少し毛色は異なるがSQLの場合、以下の方法で対策することができる

```
\encoding UTF8;
```

#### 参考文献
[【 nkf 】コマンド――文字コードと改行コードを変換する](https://www.atmarkit.co.jp/ait/articles/1609/29/news016.html)
deviseでよく使うメソッドについて

#はじめに
　以前に、deviseの導入等について投稿したので、今回はdeviseで扱えるメソッドに焦点を当てて、説明をする。

【以前の投稿】

[初見で難解だったdeviseを改めてまとめてみた](https://qiita.com/TerToEer_sho/items/b5523ad100d08126a547)
[続・初見で難解だったdeviseを改めてまとめてみた](https://qiita.com/TerToEer_sho/items/9231d4fd8155dd3063be)

###user_signed_in?メソッド
 ユーザーがサインインしてる状態かどうかを判断し、真偽値を返す。

サインインしているユーザーとそうでないユーザーで表示させたいものを変えたいときにif文を用いて使うことが多い。
例えば、サインインしているユーザーには、「ログアウト」サインインしていないユーザーには「サインイン」など

###authenticate_user!メソッド
 ログインしていないユーザーをログインページの画面に遷移させる。
コントローラーにbefore_actionで記述することが多い。ログインしていないユーザーがurlを直接入力されても、遷移させることができる。

###current_userメソッド
`current_user.id`とすると、サインインユーザーのidを取得できる。
サインインしているユーザーとアイテムなどの投稿したユーザーとの照合に用いることが多い。
【Git】git addとgit fetchを今更ながら理解した

エンジニアになる前の学習ではGitHub Desktopを使っていた。
そして、エンジニアになってからはSourceTreeに世話になっている。

gitコマンド及びgit概念についてなんとなくでここまで来ていたが、
[Udemyのセールで購入した教材](https://www.udemy.com/course/unscared_git/)が非常に勉強になり、特に表題のコマンドについて、
これまで完全に間違った理解をしていた。

## git add
ローカルのワークツリーでファイル変更した後は、
ローカルリポジトリにcommit、リモートリポジトリにpushするんでしょ、と言う理解だった。

```
ファイル変更後
→　commit
→　push
```

でも実際はステージと言う段階があって、
ワークツリーからステージへaddして、ステージからリポジトリにcommitされるのが正解だった。これが始めからGUIを使っていると抜け落ちる。

```
ファイル変更後
→　add
→　commit
→　push
```
ファイル変更後にaddすると、addしたファイルを圧縮したものが.git/objects以下に保存される。これだけではなく、圧縮ファイルと元ファイルの紐付けの為にファイルの構造と名前を保持するインデックスが.git/indexと言うバイナリファイルで管理されている。

この辺のデータ構造も理解すると、この後のcommitからpushまでの流れも理解しやすかった。

## git fetch
リモートブランチをローカルブランチに引っ張って来るんでしょって理解だったが、これでは不十分だ。

よく、pushの反対はpullではなくfetchだ、と言われるのだけど、
これで勉強するまでmergeについての理解もあやふやだったと知り悲しくなった。

そもそもpullはfetchしてmergeするもの。
mergeはブランチをくっつけるイメージだったけど、取り込むと言う方が正しい。

で、fetchはリモートリポジトリから最新をローカルリポジトリに持ってくるもの。
またfetchしてきたorigin/masterとmasterは別であり、fetchしてきたリモートブランチの内容を反映するにはmergeしないといけないと言う話。

なんでもかんでもpullが危険と言うのは、masterにいる時にmergeしたくないブランチをpullしちゃったりとかそう言う事なのだけど、これは確かにコマンドラインでは起こり得るのかなと思う。（SourceTreeとか使ってたらまず起こらないと思うけど）
チェックボックスのチェックの数

```html

<p>
<input type="checkbox" class="demo2" name="demo2" id="demo2-1" autocomplete="off">
<label for="demo2-1">デモ1</label><br>
<input type="checkbox" class="demo2" name="demo2" id="demo2-2" autocomplete="off">
<label for="demo2-2">デモ2</label><br>
<input type="checkbox" class="demo2" name="demo2" id="demo2-3" autocomplete="off">
<label for="demo2-3">デモ3</label>
</p>
<p id="link2">Next</p>

<script>
  var s2_1 = document.getElementById('demo2-1');
var s2_2 = document.getElementById('demo2-2');
var s2_3 = document.getElementById('demo2-3');
var l2 = document.getElementById('link2');
s2_1.addEventListener('click',function(){
if (this.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else if(s2_2.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else if(s2_3.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else {
l2.innerHTML = 'Next →';
}
},false);
s2_2.addEventListener('click',function(){
if (this.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else if(s2_1.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else if(s2_3.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else {
l2.innerHTML = 'Next →';
}
},false);
s2_3.addEventListener('click',function(){
if (this.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else if(s2_1.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else if(s2_2.checked) {
l2.innerHTML = '<a href="#">Next →</a>';
} else {
l2.innerHTML = 'Next →';
}
},false);
</script>
```



```html

<label><input type="checkbox" class="chk" name="hage[]" value="299">チェックボックス299</label>
<br /><label><input type="checkbox" class="chk" name="hage[]" value="300">チェックボックス300</label>
<br /><label><input type="checkbox" class="chk" name="hage[]" value="301">チェックボックス301</label>
<br /><label><input type="checkbox" class="chk" name="hage[]" value="355">チェックボックス335</label>
<br /><label><input type="checkbox" class="chk" name="hage[]" value="407">チェックボックス407</label>
<br /><br />
<button type="submit" id="btn1">-----完了-----</button>
```

```javascript

$(function(){
  // 初期状態のボタンは無効
  $("#btn1").prop("disabled", true);
    // チェックボックスの状態が変わったら（クリックされたら）
    $("input[type='checkbox']").on('change', function () {
        // チェックされているチェックボックスの数
        if ($(".chk:checked").length > 0) {
          // ボタン有効
          $("#btn1").prop("disabled", false);
        } else {
          // ボタン無効
          $("#btn1").prop("disabled", true);
        }
    });
});
```

```html

<html>
<head>
<title>ボタン有効／無効変更</title>
<script type="text/javascript">
function enable_button(){
    document.getElementById("button1").value = "　　　有効　　　";
    document.getElementById("button1").disabled = "";
}
function disable_button(){
    document.getElementById("button1").value = "　　　無効　　　";
    document.getElementById("button1").disabled = "disabled";
}
</script>
</head>
<body>
<input type="button" onclick="alert('click')" id="button1" value="　　　有効　　　">
<a href="#" onclick="enable_button()">有効</a>　<a href="#" onclick="disable_button()">無効</a>
</body>
</html>
```
STLについてのメモ書き::vector

#はじめに
情報理工学系の大学院生です。
STLについて調べた内容を自分なりに理解できるように書き溜めておこうと思って記事にしました。
わかりにくいところがあるかもしれません。その時は申し訳ございません。

#STLって？
C++の標準ライブラリに含まてている。standard template libraryの略称です。
**template**と呼ばれるc++の機能を用いて変数の型の対する依存性の少ない機能が実装されています。
STLの一覧はこちらの[Wikipedia](https://ja.wikipedia.org/wiki/Standard_Template_Library)
一覧から、主に**コンテナ**と呼ばれる値を格納するクラスとそれを扱うアルゴリズムや、イテレータが実装されているものになります。

#vector
vectorはコンテナと呼ばれるものです。
vectorのインスタンスは次のように作ります。

```c:vectorの宣言、定義
std::vector<int> v = {2,3,5};
```
いかには簡単に使えるメソッドについて書いておきます。
ほかにもありますが、使い方がわかりやすいものだけ。
詳しく知りたい方は、[reference](https://cpprefjp.github.io/reference/vector/vector.html)を参照してください。

###コンテナの状態

|メソッド名|機能|
|:-----|:-----|
|size|要素の個数を返す|
|empty|要素が空かどうかを返す|

###要素へのアクセス

|名前  |機能   |
|:-----|:-----|
|operator[i]|i番目の要素にアクセス|
|at(i)|i番目の要素にアクセス|

###イテレータの取得
1. イテレータとは<br>

>イテレータ-Wikipedia
>https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%86%E3%83%AC%E3%83%BC%E3%82%BF
>イテレータ（英語: iterator）とは、プログラミング言語において配列やそれに類似する集合的データ構造（コレクションあるいはコンテナ）の各要素に対する繰り返し処理の抽象化である。実際のプログラミング言語では、オブジェクトまたは文法などとして現れる。

Cの配列(a[i])に対して繰り返し処理をするときにi++をしますが、それの抽象化のようなものです。
イテレータの主な構成要素については、以下の記事を見ると雰囲気がわかるかもしれません。
[独自のイテレータを実装する](https://ez-net.jp/article/BA/M8FWSt5L/uJoqEhJrMX1i/)
2. 機能の名前<br>
 
|名前  |機能    |
|:--------|:-------|
|begin|先頭の要素を指すイテレータを返す|
|end|末尾の要素を指すイテレータを返す|

```c:イテレータの使い方の例
if(std::vector<int>::iterator it = std::begin(v); it != std::end(v); it++){
   //処理。実体へのアクセスは*itで行う。
}
```

###要素の追加と削除

|メソッド名 |機能 |
|:---------|:-----|
|push_back(element)|末尾への追加|
|pop_back()|末尾の要素を取り出し、削除|
|insert(iterator,element) | 要素の挿入|

#おわりに
今回書くにあたって文中での引用以外に以下の記事を参考にさせていただきました。
[Standard Template Library](https://ja.wikipedia.org/wiki/Standard_Template_Library)
[STLとは](https://ufcpp.net/study/stl/about_stl.html)
[アロケータ|Programming Place Plus C++編](https://programming-place.net/ppp/contents/cpp/library/032.html)
[イテレータの解説をするなんて今更佳代](https://qiita.com/yumetodo/items/245e94a0e85db9bf5cbb)
本記事を見ていただいてありがとうございました。
より良い記事になるように精進していきます。
GithubのOrganizationのRepositoryを一括git cloneする方法

## 概要
新しいチームにJoinした際に、とりあえずGithubの該当組織のリポジトリを一括cloneしてしまいたいということがあるだろう。
そんな方法が意外と落ちてなかった、かつ、調べるのに時間がかかったため、ここに記載する

## 方法

手順としては
1. github apiにcurlしてリポジトリ詳細情報を取得(`ssh_url` にcloneするのに必要な情報が含まれている)
2. 該当リポジトリにて`ssh_url`の情報を用いて`git clone`

まともな組織であれば、organizationのリポジトリはprivateリポジトリであることがほとんどであると思うので、認証を噛ませてcurlさせなくてはならない。自身がorganizationのメンバであるならば、自身のアカウントのPersonal access tokenを用いれば認証が通るはずだ。:orgによしなに組織名を入れて欲しい。

`-v` をオプションに加えるのは、HTTPヘッダを取得することが目的であるからだ。

```sh
$ curl -v -H "Authorization: token PERSONAL_ACCESS_TOKEN" https://api.github.com/orgs/:org/repos
...
< Link: <https://api.github.com/organizations/100000/repos?page=2>; rel="next", <https://api.github.com/organizations/100000/repos?page=18>; rel="last"
...
[ # リポジトリの詳細情報のリスト
    { ...
```

とまあ、こんな感じでHTTPヘッダと共に、リポジトリの詳細情報のリストが返ってくる。もうこれでいいじゃん、と思うかもしれない。しかし、リポジトリの数が膨大である場合、このレスポンスにはpage=1相当の情報しか返ってこない。違う、そうじゃない、全部ほしいんだ！！ということで、大事になるのが、下記のHTTPヘッダの部分。

```sh
< Link: <https://api.github.com/organizations/ORGANIZATION_ID/repos?page=2>; rel="next", <https://api.github.com/organizations/ORGANIZATION_ID/repos?page=10>; rel="last"
```

これをみると、
「ああ、pagingされていて、page=1からpaga=10(rel="last"部分参照)までpage数があるんだな」
とわかる。
あとは、これをforで回して、順次cloneすればええやん、となる。

下記のforのloop回数は適宜書き換えてくれ。cloneしたいディレクトリ直下で下記を実行。

```clone.sh
for ((i=1; i<11; i++))
do
    curl -v -H "Authorization: token PERSONAL_ACCESS_TOKEN" https://api.github.com/organizations/100000/repos\?page=$i | jq ".[].ssh_url" | xargs -n 1 git clone
done
```

おそらく綺麗に全部cloneされているはずだ。

以上。

## 参考記事

本記事を書くにあたり、下記のサイトを参考にさせていただきました。ありがとうございますm
https://developer.github.com/v3/auth/
https://mseeeen.msen.jp/github-api-get-all-repos-info/
https://tic40.hatenablog.com/entry/2018/03/26/073000
機械学習のためのデータセット

# What 
これは機械学習の初歩的なモデルであるパーセプトロンモデルを実装するためのデータセットを可視化する記事です

#Content
###データセットの可視化 with Numpy Pandas Matplot
パーセプトロンモデルとは何か？についてはここでは述べません。有名なモデルですので調べればいろいろ出てきます。
機械学習を勉強し始めて初めてコーディングしたモデルなのでまとめます。

今回使用するデータセットは、**UCI Machine Learning Repository**という機関？orもしくは一種オープンソースから花に関するデータセットIrisを例題に使います。

まずは、データセットの確認をします。osモジュールとpandasライブラリを使ってオンラインからデータセットを取得し中身を表示します。

```py
import os
import pandas as pd

s = os.path.join('https://archive.ics.uci.edu', 'ml', 'machine-learning-databases', 'iris', 'iris.data')
df = pd.read_csv(s, header=None, encoding='utf-8')
print(df)
```

上記のコードの実行結果は、

```py
       0    1    2    3               4
0    5.1  3.5  1.4  0.2     Iris-setosa
1    4.9  3.0  1.4  0.2     Iris-setosa
2    4.7  3.2  1.3  0.2     Iris-setosa
3    4.6  3.1  1.5  0.2     Iris-setosa
4    5.0  3.6  1.4  0.2     Iris-setosa
..   ...  ...  ...  ...             ...
145  6.7  3.0  5.2  2.3  Iris-virginica
146  6.3  2.5  5.0  1.9  Iris-virginica
147  6.5  3.0  5.2  2.0  Iris-virginica
148  6.2  3.4  5.4  2.3  Iris-virginica
149  5.9  3.0  5.1  1.8  Iris-virginica

[150 rows x 5 columns]
```

とこんな感じで、列は以下の情報が格納されています。150個の花のデータセットとなっています。
ちなみにこのデータセットでは花の種類は`Iris-setona`と`Iris-virginica`の２種類となっています。

```py
 0列: Sepal length, #がくの長さ
 1列: Separl width, #がくの幅
 2列: Petak length, #花弁の長さ
 3列: Petal width,  #花弁の幅
 4列: Class laber   #花の名称
```

続いて、がくの長さとはなびらの長さを軸に取り２次元のグラフで中身をみてみます。ついでに、花の種類毎にプロットを分けます。
Matplotライブラリを使用してグラフを描画します。はじめにライブラリをインポートします。データ操作にはNumpyを使います

```py
import matplotlib.pyplot as plt
import Numpy as np
```

続いて、0列:がくの長さ、と2列:花弁の長さを取得します。`iloc`を使い0〜100行目の０列目と２列目をそれぞれの値を取得します。[０列の値,2列の値]の2要素の1次元リストが返されます。気になる方は`print(X)`推薦です。

```py
X = df.iloc[0:100, [0, 2]].values #右側は1, 3列目のみ取り出している
```
今回は、予めデータセットの中身をみており、先頭50個がIris-setonaのデータとなっています。setosaのデータを赤丸、versicolorを青×でプロットします。2要素の右側の値をx軸に、左側の値をy軸にとるため、下記のように記述します。

```py
# setosaの散布図プロット　赤丸表示
plt.scatter(X[:50,0], X[:50, 1], color='red', marker='o', label='setosa') 
# versicolorのプロット 青×表示
plt.scatter(X[50:100, 0], X[50:100, 1], color='blue', marker='x', label='versicolor') 
# 軸ラベルの設定
plt.xlabel('sepal length [cm]') # がくの長さ
plt.ylabel('petal length [cm]') # はなびらの長さ
# 凡例の設定(左上に配置)
plt.legend(loc='upper left') 
plt.show()
```
実行結果は下記、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/764781/d3e0aa1f-5100-c59f-eb7f-9bf1d5df5361.png)
結果をみるとなんか法則がありそうです。。。

これを使って機械学習アルゴリズムを組みますが、流れはおおよそ以下の通り、（参考図書丸々写すわけにはいかないので・・・）

Step .1 がくの長さに対する学習率w_1, はなびらの長さに対する学習率w_2を適当に定義（乱数を使います）
Step .2 データセットと内積をとり、それぞれの内積計算結果を配列か何かで格納します
Step .3 内積計算結果がある値（例えば0)を境にsetosaかversicolorに分類する。
Step .4 実際のデータと分類結果が合っているかチェックしミスってたら学習率分だけパラメータを適宜更新(forループなどで全データセットについて実施）
Step .5 分類を間違っていた場合をフラグで管理する
Step .6 誤分類が0個になるまでひたすら実施

以上の過程を踏めば無事機械学習が完了します。
実装はここでは載せません、（参考図書の著作権に引っかかりそうなので）

#Comment
これ実は、学習１サイクル毎に誤分類の数をカウントすると、単調に減少せず増加している場面があります。ちゃんと良い方向に学習できているか監視するのも大事ですね・・・
ブログ記事の投稿者別一覧ページを作成

####実現したいこと
ブログアプリのindexページに全ユーザーの投稿が表示されるが、各投稿の「このユーザーの投稿一覧へ」をクリックすると、そのユーザーの記事だけ表示されるページに移動したい


####実現するためにやったこと
①routes.rbファイルに、resourcesで作られるアクションにオリジナルのアクションを追加
→後から見直すと何をしたいのか不明ですが、当時はこれでアクションを追加すればパラメーターとしてuser_idが発生するのだと思っていた

```routes.rb
  get '/user/user_id', to: 'blogs#user'
```
②blogs_controller.rbファイルに下記を追加。whereメソッドでuser_idを指定しようとしています。

```blogs_controller.rb
  def index_user
    @blogs = Blog.where(user_id:params[:user_id])
  end
```
③コンソールにて。rails routesでPrefixを確認してユーザーごとの投稿一覧へのリンク設定

```index.html.erb
<%= link_to 'このユーザーの投稿一覧へ', index_user_blog_path(blog.user_id) %>
```
####発生したエラー
具体的なエラーは発生していないが、クリックして移動した先のページに何も表示されない。実質エラー。

####確認したこと
③をクリックした際のコンソールの内容を確認。
![スクリーンショット 2020-10-26 22.19.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634245/9759f174-4797-2a79-5959-4f678e4b6aff.png)
"user_id"IS NULL と書いてあります！つまり user_id にはなんらかの理由でパラメーター（Parameters: {"id"=>"5"}みたいなやつ）が送られていないということになります。コンソールを細かくチェックしてもパラメーターが送られてきた形跡はありません。

②をチェックしてみましたが、whereの使い方などに問題はなさそうです。

最後にチェックしたのが①です。そもそも、resourcesで設定したアクションの他に追加する場合、    collection doを使います。今回なぜそうしなかったかというと、上にも書いたようにuser_idを指定する必要があったためです(collection doはid指定ができない)。

####分かったこと
上記調べた結果を元に、routes設定に問題がありそうだと仮定。そもそも、resourcesで設定したアクションのほかに追加する場合collectionがあるのだから、idが必要な場合にも同じようなメソッドがあってもいいはず。。。と思って調べたらありました。

https://railsguides.jp/routing.html
ちょっと分かりにくいですが、要するに下記とのことでした。

collection do： idを伴わない新たなroutingを設定
member do： idを伴う新たなroutingを設定

```ruby
member do
  get :index_user
end
```
こういうことのようです。これでコンソールを確認してみると。。。
![スクリーンショット 2020-11-01 23.07.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634245/efb47247-b635-bf10-aba3-fb898c7bd779.png)

パラメーターが送られてきています。ただ、この場合 "user_id" ではなく "id" です。rails routesでは

```
index_user_blog GET    /blogs/:id/index_user(.:format)     blogs#index_user
```
このようになっていますので、送られてくるのは user_id ではなく idで問題ないようです。 blogs_controllerの記述を user_id から id に変更します。

```blogs_controller.rb
(変更前)
def index_user
  @blogs = Blog.where(user_id:params[:user_id])
end

(変更後)
def index_user
  @blogs = Blog.where(user_id:params[:id])
end
```
これでようやく、ユーザーごとの投稿一覧が表示されました。忘れないように①の get '/user/user_id', to: 'blogs#user' は削除。

Railsガイドを参照しました（説明がちょっと難しかったですが）。
https://railsguides.jp/routing.html
下記、Railsガイドより抜粋。

```
2.10.1 メンバールーティングを追加する
メンバー (member) ルーティングを追加したい場合は、memberブロックをリソースブロックに1つ追加します。

resources :photos do
  member do
    get 'preview'
  end
end

上のルーティングはGETリクエストとそれに伴う/photos/1/previewを認識し、
リクエストをPhotosコントローラのpreviewアクションにルーティングし、
リソースid値をparams[:id]に渡します。同時に、preview_photo_urlヘルパーと
preview_photo_pathヘルパーも作成されます。

memberルーティングブロックの内側では、認識させるHTTP動詞をルーティング名ごとに指定します。
指定可能なHTTP動詞はget、patch、put、post、deleteです。
memberルーティングが1つだけしかない場合は、以下のようにルーティングで:onオプションを指定することで
ブロックを省略できます。

resources :photos do
  get 'preview', on: :member
end

:onオプションを省略しても同様のmemberルーティングが生成されます。
この場合リソースidの値の取得にparams[:id]ではなくparams[:photo_id]を使う点が異なります。
ルーティングヘルパーも、preview_photo_urlがphoto_preview_urlに、preview_photo_pathが
photo_preview_pathにそれぞれリネームされます。
```
Pythonでクイックソートの実装

100個の整数からなるリストを乱数で生成して、クイックソートするコードです。
partitionを用いない単純なクイックソートで実装しました。

最後に実行時間を計測するコードをつけています。

```python:quick_sort.py
from typing import List
import random
import time

def quick_sort(numbers: List[int]) -> List[int]:
    
    numbers_set = set(numbers)

    if len(numbers_set) <= 1:
        return numbers

    p1 = numbers[0]
    p2 = 0
    for i in range(len(numbers)):
        if numbers[i] != p1:
            p2 = numbers[i]
            break
    

    pivot = p1 if p1 > p2 else p2

    left_list = []
    right_list = []

    for i in range(len(numbers)):
        if numbers[i] < pivot:
            left_list.append(numbers[i])
        else:
            right_list.append(numbers[i])

    return quick_sort(left_list) + quick_sort(right_list)



if __name__ == "__main__":
    nums = [random.randint(0,100) for _ in range(100)]
    start = time.time()
    quick_sort(nums)
    elapsed_time = time.time() - start
    print ("elapsed_time:{0}".format(elapsed_time) + "[sec]")   

```
IFTTT、integromatで使えるサービスのメモ

#IFTTT

**・Link Shades**
Wifi接続可能なブラインド。
スマホアプリと連携することで、スマホからブラインドの開閉が行える。


**・Spotify**
音楽アプリ
プレイリストを作ったりできる
再生はできない


**・Weather Underground**
天気予報のサービス
天気や気温、日の出日の入り時間を取得可能


#integromat

**・Barcodes**
文字列からQRコードやバーコードを作成

**・Wasabi**
Amazon S3を利用したオブジェクトストレージサービス
ファイルの取り出し、保存ができる

**・Evernote**
メモアプリ
ノートの作成・更新・削除
作成したノートのシェアが可能

**・Datadog**
サーバー監視&分析サービス。スタック/アプリケーションの内部の監視が可能

**・Tookan**
物流管理サービス
トラックの位置情報を管理したり、ルート情報の検索が可能、らしい

**・Caflou**
経営管理＋プロジェクトチーム管理サービス

**・Botstar**
プログラミングなしで、ウェブサイトで動くBotを作成するサービス

**・Feedly**
登録したホームページやWebメディアの情報を効率よく収集できるRSSリーダーのひとつ

**・Phantombuster**
自動データ抽出サービス
AWSのEC2インスタンスにMariaDBをインストールし、DBサーバーにする方法

# はじめに
AWSはAmazon Web Servisesの略で、Amazonが提供しているクラウドサーバーのサービスです。
AWSへの理解度を高めるために、学んだことをアウトプットします。
今回はネットワークとの関係を記載します。


# 今回の流れ
以下の投稿の続きを説明します。
「AWSにDBサーバーの構築とWebサーバーとの接続を行う」（https://qiita.com/daisuke30x/items/46e520f6e6c497a9cea3）

* NATの構築
* インスタンスにDBをインストール

### 設定
VPCのIP範囲 => 10.0.0.0/16
パブリックサブネットのIP範囲 => 10.0.1.0/24
プライベートサブネットのIP範囲 => 10.0.2.0/24


# NATの構築

### NATとは
NATとはNetwork Address Translationの略です。
インターネットから接続されたくないプライベートサブネットですが、DBなどのインストールを行う必要があるため、サブネット側からはインターネットには接続できるようにすることができます。
要するに、インターネット側からプライベートサブネットには接続されませんが、プライベートサブネット側からはインターネットに接続できる一方通行の仕組みを作ることができるものです。

### NATゲートウェイの作成（※有料となります。時間と転送バイト量によって変動しますが、今回は100〜200円ほどかかると思います。）

① AWSマネジメントコンソールで「VPC」ページに遷移し、サイドバーの「NATゲートウェイ」をクリックします。

②右画面の「NATゲートウェイを作成」をクリックします。

③サブネットには「パブリックサブネット」を選択し、「Elastic IPの割り当て」をクリックし、「NATゲートウェイを作成」をクリックします。

※NATゲートウェイはインターネットに接続するために、パブリックサブネットに設置します。

④作成したNATゲートウェイのIDをコピーしておき、サイドバーの「ルートテーブル」をクリックし、プライベートサブネットのデフォルトのルートテーブルの「ルート」タブで「ルートの編集」をクリックし、「ルートの追加」で送信先を「0.0.0.0/0」、ターベットにコピーしたNATゲートウェイのIDを選択し、「ルートの保存」をクリックします。

※ここではプライベートサブネットとNATゲートウェイを接続するために、ルートテーブルにルートを追加しています。

⑤プライベートサブネットからインターネットに接続できるか確認します。
プライベートサブネットに作成したインスタンスにログインし、以下のコマンドを入力してみます。
参考）https://qiita.com/daisuke30x/items/46e520f6e6c497a9cea3
色々なコマンドが試せるはずですが、今回は参考書籍の記述例を記載します。

```:ターミナル
[ec2-user@ip-10-0-2-10]$ curl www.kantei.go.jp
=>　首相官邸のホームページの情報が出力されます。
```

NATゲートウェイは有料なので、不要になったら、削除を忘れないようにしましょう。

# インスタンスにDBをインストール

プライベートサブネットに作成したインスタンスにMariaDBをインストールします。

### インスタンスにDBにインストールする手順

① MariaDBをインストールします。

```:ターミナル
[ec2-user@ip-10-0-2-10]$ sudo yum -y install mariadb-server
```

② MariaDBを起動します。

```:ターミナル
[ec2-user@ip-10-0-2-10]$ sudo systemctl start mariadb
```


# 参考
「Amazon Web Services 基礎からのネットワーク＆サーバー構築」
著者：大澤文孝、玉川憲、片山暁雄、今井雄太

# 最後に
本投稿が初学者の復習の一助となればと幸いです。
LINEでyahoo天気から好きな地域の天気を通知してもらおう！

#開発経緯
現代で誰しもが遭遇したことのあるはず「通信制限」
外出先で自由にスマホを使用できないのは辛いですよね。
~~月のパケット制限を大きくすればよいだけの話ですが~~

そんな中でも通勤や通学、さらには天気が知りたいなんてことは毎日あります。
通信制限中だとすぐにわからなくて困りますよね。

テキストだけでも見られれば何とかなりそう、、、
そこでLINEからメッセージを送ってもらえばいいのでは！？

そんなこんなで、最終目標としては始発と終着をLINEで送ったら返信で知りたい情報が得られることができればなぁということで開発を始めてみました。

多分テキストなら、アプリを見るよりも早くできるはず、、
#yahoo天気の情報を取得
まずは、各駅の情報収集だ！！

と行きたいところですが、まずは手始めにLINEでメッセージのやり取りをすることや、スクレイピングの練習として各地域の天気を通知するシステムを作ります。

ひとまず、yahoo天気からスクレイピングを用いて情報持ってきましょう。

```python
import requests
from bs4 import BeautifulSoup
```

そのためにrequestsを利用してpythonでURLを開きましょう。
そしてURLを開いた後にHTMLやXMLからデータを抽出するためにBeautifulSoupからbs4をimportしましょう。

次に[yahoo天気のURL](https://weather.yahoo.co.jp/weather/)が下記の通りになります。
https://weather.yahoo.co.jp/weather/
このURL先では全国の天気が一目でわかるようになっており、知りたい地域にどんどん掘り下げていくことが可能となっています。

まずは全国から地方のURLを取得しましょう。

```python
target_url= "https://weather.yahoo.co.jp/weather/"
res       = requests.get(target_url)
soup      = BeautifulSoup(res.text, 'lxml')
elems     = soup.find_all("a")

with open("yahooChiku.csv", "w", encoding="utf-8", newline ="") as ychiku:
    writer = csv.writer(ychiku)
    for e in elems:
        chikuNumList = []
        if re.search(r'<a data-ylk="', str(e)):
            if re.search(r'"//weather.yahoo.co.jp/weather/jp/\d.*/"', str(e)):
                row = re.search(r'"//weather.yahoo.co.jp/weather/jp/\d.*/"', str(e)).group().strip('"')
                row = "https:" + row
                chikuNumList.append(row)
                writer.writerow(chikuNumList)
```

BeautifulSoupの使い方などはいろいろ調べてみてください。
自分でも場当たり的にしか使用していないので、知識不足です、、、

このソースコードで行っていることは全国の天気から地方ごとのURLを取り出す処理となっています。
地方のURLが入っているタグは\<a data-ylk>で得られます。ただ、他にもこのタグに含まれている情報もあるので、正規表現を使って各地域のURLが含まれているものだけを抽出します。
タグの情報内ではhttpsが含まれていないため、先頭に「https」を付け加えてcsvに書き込んで保存します。

とりあえず長くなりそうなので、一旦はここまで。

#次回
地方のURLを取得したので次は市区町村のURLと各地域の名前を取るところとLINEで簡単にメッセージを送るところを記事にしたいと思います。

※説明不足や補足等あればぜひお願いします。

ではまた次回！！！
NodejsのSQLiteでカラム名の一覧を取得する方法

https://stackoverflow.com/questions/947215/how-to-get-a-list-of-column-names-on-sqlite3-database
こちらのサイトを参考にしました。

データの確認にはDB Browser for SQLiteを使っていたのですが、DB Browser for SQLite上でSQLを実行するときと、Node.js上のSQLiteモジュールを通して実行したときとで実行できるものが違うようです。
## DB Browser for SQLiteを使う場合

```sql
pragma table_info(tablename)
```
で指定したテーブルのカラム名の一覧が取得できます。
他のSELECTなどのクエリと一緒に使うことはできないようです。


## Nodejsで使う場合

```
db.each("SELECT name FROM pragma_table_info('users')", function(err, args) {
    console.log(args['name']);
});
```
でも取得できるようです。
`pragma_table_info`はDB Browser for SQLiteでは動作しませんでした。
少数チームの業務効率化に取り組んでる話

# 概要
この記事はサーバの知識なんてこれぽっちもなかった自分が、下記を用いてチームの業務効率化に取り組んだ記録です。

* カンバンツール(`Wekan`)
* チャットツール(`Rocket.Chat`)
* Wiki(`Growi`)


1つの記事にはまとめきれないため、3回に分けて投稿しようと思います。
本日は第一弾ということで、経緯とカンバンツール導入までについてお話しようと思います。

# 経緯
なぜ自分が業務効率化に取り組もうと思ったのか?

1. プロジェクトが**全てExcelで管理されていた**から。
1. 連絡が**全てメールでやり取りされていた**から。
1. ノウハウが**全てWordやテキストで書かれており、ファイルサーバで管理されていた**から。

ただし、"セキュリティ上の問題"と言う理由でクラウドサービスは全てNG。
オンプレミスでなんとかするしかありませんでした。
先述した通り、私はサーバの知識なんてこれっぽっちも持っていませんでした。
それでもどうにかしたかったんや…！

# 業務効率化の取り組み その1 カンバンツールの導入
私の職場ではバグ管理ツールが使われています。

* バグをIDで管理。
* 複数のプロジェクトを登録可能。
* CSVやXML形式で指定プロジェクトのバグ一覧をエクスポートできる。

多分どこでも使われている一般的なバグ管理ツールかなと思います。

## Excel管理のバカバカしさ
Excelで管理していた時は、下記のような流れでした。

1. バグが登録される。
2. バグ管理ツールから一覧をエクスポートする。
3. 自分たちのチームに割り当てられたカテゴリーでフィルタリングする。
4. 担当を割り振る。
5. 進捗状況などは自分でExcelに入力する。
6. 完了したら自分でバグ管理ツールのステータスとExcelを更新する。

…無駄多くないですか？
Excel管理はほんとにだめですね。

進捗状況を記入するにも、完了したことも全てExcelに記入する。
↓
でも重くてExcelが開かない。
↓
後回しにして記入を忘れる。
↓
結局ロクな管理ができない。

断言できます。間違いなくこうなります。
忙しい職場なら尚更です。ファイルを開くことに時間をかけるなんてバカバカしい！と思います。

## カンバンツールの導入
「バグの進捗管理もカンバンで行えば、簡単に進捗管理ができるのは？」
という思いつきでカンバンツールの導入を決意。

元々、`Trello`というカンバンツールの存在は知っていましたが、前述の理由で`Trello`は使えません。
調べていくうちに`Trelloクローン`なるワードを見つけ、その後何やかんやあって`Wekan`に辿り着きました。

## 壁にぶち当たる
次のような壁にぶち当たりました。

* `Wekan`とバグ管理ツールの連携方法がない
* 他に連携できるカンバンもない。
* バグ管理ツールも自前のカンバン機能を持ち合わせていない。

じゃあ、どうしたか。
**バグ管理ツールとカンバンツールのインターフェースとなるプログラムを作成しました。**

ちょうどその頃、日本は緊急事態宣言が発令される直前。
発令後に２ヶ月自宅待機を命じられた私はその間に自宅でインターフェースとなるプログラムを作成したのでした。

## 効果
1. 取り組まなければならないタスクの量が一目瞭然になった。
締め日までの日数に対して、残件が多いのか少ないのか。これだけでも危機感が大きく変わります。

2. 担当が明確になった。
自分のタスクはもちろん把握していますが、他人がどのタスクに関わっているのが丸わかりになりました。

第一弾は以上になります。
第二弾はチャットツール導入編を予定しています。
それでは。
Railsでアプリ作成時、大まかな手順の言語化アウトプット

# Ruby on Railsでアプリ作成時の大まかな手順

今回の記事の目的はアプリ作成の際の手順を大まかに言葉で説明したものになります。
勉強を初めて自分のアウトプット用に作成しました。

## 1.準備
ターミナルで以下のコマンドを実行。
・ rails new (バージョン指定) (指定したいデータベース)
・ cd (作成したディレクトリ)

## 2.データベース作成
ターミナルで以下のコマンドを実行。
・ rails db:create
・ rails s

## 3.Gemファイルの編集
必要に応じてRailsのバージョン指定、必要なGemをインストールする。  
完了後、以下を必要に応じてターミナルで実行。
・ bundle install
・ bundle update

## 4.投稿モデルの作成
ターミナルで以下を実行。
・ rails g model (モデル名)

## 5.テーブル作成
マイグレーションファイルを編集し、データベースに作成したいカラムを記述する。完了後にターミナルで以下を実行。
・ rails db:migrate
※一度マイグレートしたファイルは編集してはいけない。編集が必要な場合は以下のコマンドをターミナルで実行してから行う。
・ rails db:rollback

## 6.各アクションごとの設定
以下の流れで各アクションごとの設定を行う。
・ ルーティングの設定
・ コントローラーの作成またはアクションを定義
・ ビューの作成

### ルーティングの設定
```ruby
resources :コントローラー名, only[:アクション]
```
アクションを絞りたい時は、onlyの中の部分に記述していく。

### コントローラーの作成
コントローラー作成の場合はターミナルで以下のコマンドを記述。
・ rails g controller コントローラー名  

コントローラーに必要なアクションを定義する。ポイントは2点ある。
・ データベースから取得した値をビューで使用したいときはインスタンス変数に値を代入し、ビューで使用する。
・ データを保存する場合はストロングパラメーターを使用する。

### ビュー作成
ポイントは以下の2点
・ ヘッダーやフッターのレイアウトはapplication.html.erbを編集。
・ アクションごとのビューはviewsファイルにアクション名.html.erbを作成し、記述する。  

以上のような流れでアプリケーションを作成する。
【Java】Fileクラスの使い方

#プログラミング勉強日記
2020年11月1日
前回はMathクラスを扱ったが、今回はFileクラスの使い方を簡単に説明する。

#Fileクラスとは
　Javaでファイルを扱うために使うクラス。Fileはファイルまたはディレクトリを表すクラスで、ファイルの読み書きやフォルダの中のファイルの一覧取得といったファイルシステム全般で使用する。

#書き方
　取り扱いたいファイルに対して1つのFileクラスのオブジェクトを対応させる。作成したFileクラスのfileオブジェクトを使って、ファイルの内容を読み込んだり書き込んだりすることができる。なので、Fileクラスを使うことでローカルにあるファイルをJavaで扱える。

```java:基本的な書き方
File オブジェクト名 = new File(ファイル名);

// 具体例
File file = new File("c:\\test\\test.txt");
```
　具体例でも示しているのように、ファイル名を指定するときは`c:\test\test.txt`ではなく`c:\\test\\test.txt`のように<b>`\`を2つ重ねて記述する</b>。

　上記の例ではファイルの場所を絶対パスで指定した。ファイルの指定には絶対指定と相対指定が可能で、相対指定の場合はプログラムファイルが置かれている位置を基準とする。

```java:相対パスでの指定
// プログラムファイルと同じディレクトリの中のtext.txt
File file = new File("test.txt");

// プログラムファイルのディレクトリの中のtxtディレクトリの中のtext.txt
File file = new File(".\\txt\\test.txt");
```

```java:Fileインスタンスを用いた操作
// 名前を取得する
String name = f.getName(); 

// 対象が存在すればtrue
boolean b = f.exists(); 

// 対象を削除する
f.delete(); 

// ファイルならばtrue
boolean b = f.isFile(); 
// フォルダならばtrue
boolean b = f.isDirectory(); 

// サイズを取得する
int length = f.length(); 
```


#参考文献
[ファイルの操作！JavaでFileクラスを使う方法【初心者向け】](https://techacademy.jp/magazine/17667)
[Fileクラス](https://www.javadrive.jp/start/file/index1.html)
【Java】プログラムの実行時間の計測方法


Javaで処理時間を計測するにはミリ秒で計測するcurrentTimeMillisメソッドと、ナノ秒で計測するnanoTimeメソッドがあります。
今回はナノ秒で計測し、秒で出力する方法です。

```java
double start = System.nanoTime();

//計測したい処理を記述

double end = System.nanoTime();
System.out.println("処理時間：" + ((end - start) / Math.pow(10, 9))  + "s");
```
Linux システムアーキテクチャ【ランレベル】

【Linux ランレベル】

Linuxのランレベルまとめ。

##init 0 ~ init 6 (init 4 空き)

###init 0

システムのシャットダウン実施
→システム停止

###init 1

シングルユーザーモードでの起動実施
→rootのみログインできるモード
　ネットワークアクセスを行えない。該当マシン上のみ。

###init 2

ネットワーク無しのマルチモードでの起動実施
→ネットワーク無しのマルチモードは、複数ユーザーがログイン可能。
　ネットワークアクセスを行えない。該当マシン上のみ。

###init 3

<strong>サーバー稼働</strong>
通常のマルチモードでの起動実施
→通常のマルチモードでは、SSHなどネットワークを介した複数ユーザーでのログイン可能。
　グラフィックユーザーインターフェースは起動不可。

###init 5

<strong>クライアント稼働</strong>
グラフィックユーザーインターフェースでの起動実施可能。

###init 6

システム再起動実施

##余談

覚えるコマンドが膨大だなと感じています。
手を動かしながら暗記していきます。
スムーズにLinuxを扱えるようになりたいです。
快適！ Webサイト制作に欠かせないVSCode設定

# はじめに
プラグインを入れたらコードを書くときいい感じにコードを整えてくれるって聞いたけど。。。
全然ダメじゃん！インデント整ってないじゃん！

こんな感じで歯がゆい思いをしている人はすぐに以下の手順で設定しましょう！

# settings.jsonを開く
settings.jsonを開くのは分かった
で、そのファイルどこにあるの？
VSCode使いはじめたばかりの頃はここでもう嫌になりました笑

1. 左下の歯車のアイコンをクリックし、表示されたメニューの中から`設定`を選択
1. 右上のファイルから矢印が出ているアイコンをクリック
![opne_settings.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843917/0b7289ab-75d4-4111-8921-b3ade0cc067f.gif)



次にこの画面の右上のファイルから矢印が生えているアイコンをクリック！
![settings.jsonが開きます](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843917/e37286e7-4caa-5e5c-00b7-220cb87bbd47.png)
これでsettings.jsonが開けましたね:grin:

# settings.jsonを編集
編集と書いてますが、コピペで大丈夫です！
以下の内容をsettings.jsonに貼り付けてsettings.jsonを上書きしましょう！

```json:settings.json
{
  // ようこそのタブを非表示
  "workbench.startupEditor": "none",

  // アイコン
  "workbench.iconTheme": "vscode-icons",

  // エディタのフォントサイズ
  //　ここはお好みで！
  "editor.fontSize": 15,

  // ターミナルのフォントサイズ
  //　ここはお好みで！
  "terminal.integrated.fontSize": 15,

  // ファイルを削除するときに確認しない
  "explorer.confirmDelete": false,

  // コード整形のタイミング
  "editor.formatOnPaste": true,
  "editor.formatOnType": true,
  "editor.formatOnSave": true,

  // ファイルの自動保存
  "files.autoSave": "afterDelay",

  // タブサイズ
  "editor.tabSize": 2,

  // 文字の折り返し
  "editor.wordWrap": "on",

  // ミニマップ
  "editor.minimap.enabled": false,

  // ホバーしたときのポップアップを非表示
  "editor.hover.enabled": false,

  // Tabキーでemmetを展開
  "emmet.triggerExpansionOnTab": true,

  // emmetで作成するHTMLのテンプレートの設定
  "emmet.variables": {
    "lang": "ja"
  },

  // HTMLのフォーマット
  "[html]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },

  // JavaScriptのフォーマット
  "[javascript]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },

  // JSONのフォーマット
  "[jsonc]": {
    "editor.defaultFormatter": "esbenp.prettier-vscode"
  },
}
```
ここまでできたらあと少し
残りは必要なプラグインを入れるだけ！

# 必要なプラグインを入れる
プラグインの追加はVSCodeのサイドバーからできます。
![プラグインのアイコンをクリック](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843917/8ba28420-0cce-e1c3-dd7e-715421c8fce1.png)

## プラグイン
Prettierが入ってれば問題ないですが、他のもあると便利なので載せときます！

1. [Prettier](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)
1. [Japanese Language Pack for Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MS-CEINTL.vscode-language-pack-ja)
1. [vscode-icons](https://marketplace.visualstudio.com/items?itemName=vscode-icons-team.vscode-icons)
1. [Auto Rename Tag](https://marketplace.visualstudio.com/items?itemName=formulahendry.auto-rename-tag)
1. [Bracket Pair Colorizer](https://marketplace.visualstudio.com/items?itemName=CoenraadS.bracket-pair-colorizer)
1. [HTML Snippets](https://marketplace.visualstudio.com/items?itemName=abusaidm.html-snippets)
1. [Path Intellisense](https://marketplace.visualstudio.com/items?itemName=christian-kohler.path-intellisense)
1. [Live Server](https://marketplace.visualstudio.com/items?itemName=ritwickdey.LiveServer)

良きコーディングライフを:grin:
Oracleのキャラクタセット

## DB
* キャラクタ・セットとは？
    >Oracleデータベースで利用する文字セットおよびエンコーディング方式を定義したもの
    　–データベース側およびクライアント側で設定できる
    主要な文字コードに対応したキャラクタ・セットが用意されている
    Oracleキャラクタ・セット名は、次のネーミング規則で表される
    　–[地域][1文字あたりのビット数][標準文字コード名]
    * https://www.oracle.com/technetwork/jp/content/charcterset-250314-ja.pdf

* データベース・キャラクタ・セット
    * CHAR、VARCHAR、VARCHAR2で格納する際に利用される文字コード
    * 指定する文字コードによって1文字辺りのバイト数に変動が生じる
* 各国語キャラクタ・セット
    * NCHAR、NVARCHARで格納する際に利用される文字コード
    * ``UTF8``又は``AL16UTF16``しか選択できない
    * AL16UTF16がデフォルト、かつ推奨されているとのこと。
    * 違いはバイト数で格納するか(UTF8)、文字数で格納するか(AL16UTF16)。
    * https://docs.oracle.com/cd/E16338_01/server.112/b56307/ch6unicode.htm
      * 多言語データに使用する列の長さの指定
 * 確認方法

    ```sql
    -- データベース・キャラクタ・セット NLS_CHARACTERSET
    -- 各国語キャラクタ・セット        NLS_NCHAR_CHARACTERSET 
    SELECT PARAMETER, VALUE
      FROM NLS_DATABASE_PARAMETERS
     WHERE PARAMETER IN ('NLS_CHARACTERSET', 'NLS_NCHAR_CHARACTERSET');
    ```

## クライアント
* クライアント・キャラクタ・セット
    * NLS_LANG環境変数を使用して、クライアント・プログラムによって入力または表示されるデータの言語と地域、およびキャラクタ・セットを設定
bundle install、railsコマンド実行時のエラーAn error occurred while installing nokogiri (1.10.10), and Bundler cannot continue. Make sure that `gem install nokogiri -v '1.10.10' --source 'https://rubygems.org/'` succeeds before bundling.の解決法

久しぶりにrailsをコマンドを動かすとエラー。

```
An error occurred while installing nokogiri (1.10.10), and Bundler cannot continue. Make sure that `gem install nokogiri -v '1.10.10' --source 'https://rubygems.org/'` succeeds before bundling.
```

上記のエラーが出ると```bundle isntall```も通らなくなる。

##原因
```which gem、which ruby```でパスが通っていない。

```
$ which ruby
/usr/bin/ruby
```

こうしたい↓

```
$ which ruby 
/Users/shogo/.rbenv/shims/ruby
```


##解決法

rbenvにパスを通すため、シェルの設定ファイル(.bashrcや.zshrc)に以下を追加。

対象アプリのディレクトリで1行ずつ行わなければいけないことに注意。

```
[[ -d ~/.rbenv  ]] && \
  export PATH=${HOME}/.rbenv/bin:${PATH} && \
  eval "$(rbenv init -)"
```