Node.js 環境変数の設定

こんにちは、皆さん!
今回はNode.jsで安全に環境変数を設定する方法について紹介していきたいと思います。


  • トピック:
  1. 環境変数とは?
  2. なぜ環境変数を使うのか?
  3. なぜ環境変数を安全に保護しないといけないのか?
  4. どうやって安全にキープするのか?
  5. では、試してみましょう!!


環境変数とは?

***環境変数の基本を飛ばしたい方はこちら!***
簡単に言いますと、外部から与えられるデータのことです。直接コードの中ではそのものを書かずに他のファイルからそれを読み取ります。


なぜ環境変数を使うのか?

Google Mapをアプリケーションに応用しようと思ったときにAPIというものが必要になってきます。相手側のサービスを利用するにあたっての個人のIDみたいなものです。権利書みたいでもあり、そのAPIがないと利用できません。

なぜ環境変数を安全に保護しないといけないのか?

ウェブ上のコードというのはとても簡単に他人に見られます。先ほどのAPIというのはいうと、数字とアルファベットの羅列です。だから、見られたらそのまま盗まれます。そして、あなたの名義でその権利書を使い、その人のアプリケーションを作る。料金のかかるAPIですと、他人のために金を払うことになります。だから、環境変数にその危ない部分を移し、なおかつその環境変数を含んだファイルを見られないようにすることが大事なのです。


どうやって安全にキープするのか?

まず、Node.jsでは下記のように環境変数にアクセスできます。

process.env.API_KEY

envの後に環境変数の名前をつければアクセスできます。
ローカルでは他のファイルに保存しておけば、アクセスできます。このファイルに関してはgitignoreしっかりとオンラインにシェアされないように
プロダクション、つまり、オンラインでは例えば、Herokuならconfig環境変数を保存すれば他人には見られないので安全にキープできます。

では、試してみましょう!!

僕のコードをhttps://github.com/Eric1015/node-environment-variables-exampleに載せておきましたので、参考にしてください。
おススメはそのコードをダウンロードして、この記事通りに見て、そして、ローカルやHerokuで試してみることです。
まず、コードの構造について少し説明します。configディレクトリーの中にあるのが環境変数を管理する部分です。
prod.jsがプロダクション、test.jsがテスト、dev.jsがローカルという形でそれぞれがそれぞれの環境の変数を管理しています。
次にindex.jsファイルで環境に応じてどのファイルのデータを返すかを決めます。

if (process.env.NODE_ENV === 'production') {
    module.exports = require('./prod');
} else if (process.env.NODE_ENV === 'test') {
    module.exports = require('./test');
} else {
    module.exports = require('./dev');
}

ここにあるように環境ごとにそれぞれの変数を管理しているファイルを返すのです。
あとは.gitignoreの方でローカルとテスト環境の変数が外部に漏れないようにフィルターするだけ

# モジュールはわざわざプッシュする必要はない
node_modules

# ローカルとテスト環境の環境変数はGithubに表示されないようにします
config/dev.js
config/test.js



以上で環境変数の設定は完了。そしたら、server.jsで実際にどう使うかを見てみましょう!
ここではMongooseを使う際のURLを環境変数を使い、各環境で違うデータベースにアクセスできるようにします。
まず、ローカルとテスト環境のデータベースのURLを設定します。

// dev.js
module.exports = {
    DB_URI: "mongodb://localhost:27017/environment-variables-app"
}
//test.js
module.exports = {
    DB_URI: "mongodb://localhost:27017/environment-variables-app-test"
}

次にプロダクションの方の変数も定義したいのですが、プロダクションではサーバー側の設定から環境変数がパスされてきます。例えば、Herokuでこのアプリケーションを使うのなら、そこで、変数の名前をDB_URIとし、実際のURLを入れ、下記のようにその変数にアクセスします。

// prod.js
module.exports = {
    DB_URI: process.env.DB_URI
}

これならGithubに載せても他人から情報を盗まれませんね!
では、いよいよserver.js内のコードを見ていきましょう!
まず、外部から必要なものをインポートしてきます。このとき、require('./config')となっていてディレクトリーをインポートしようとしているように見えるが、実はindex.jsを認識して、そこにたどり着いているのです。
次にconst url = config.DB_URI;環境変数にアクセスし、MongoDBのURLを取得します。
そして、最後にサーバーをスタートします。

const express = require('express');
const mongoose = require('mongoose');
const config = require('./config');

const url = config.DB_URI;
const port = process.env.PORT || 8080;

// MongoDBデータベースに接続
mongoose.connect(url, function (err, res) {
    if (err) { 
      console.log ('ERROR connecting to: ' + url + '. ' + err);
    } else {
      console.log ('Succeeded connected to: ' + url);
    }
});

// サーバーをスタートする
const app = express();

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => console.log(`Example app listening on port ${port}!`))



実際にこのサーバーをスタートすれば、コンソールで実際にどのMongoDBのサーバーに接続したかが見れます。


では、次はHerokuでどうやって設定するかです。
まずはHerokuのconfigを確認してみましょう!

$ heroku config

すると、まだ何も入れてないので、空の状態です。
HerokuでMongoDBを使おうとすると、mLabというアドオンを入れる必要があるので、それを入れてみましょう!

f:id:Programming_Shop:20190318080104p:plain
mLabのコンソール画面(左上のロゴを参照に)


追加した後にもう一度heroku configとやると、今足したmLabのURLが見れるはずです。

MONGODB_URI: mongodb://heroku_3636wvfr:ka9cqpra6f4r8g3gfk8n2la4bs@ds255797.mlab.com:55797/heroku_3636wvfr

こんな感じで出てくるのだが、今のアプリではDB_URIという環境変数でアクセスしているので、環境変数をこの名前で新たに追加しましょう!!
下記のコマンドを入力して、configに環境変数を追加しましょう!

$ heroku config:set DB_URI=mongodb://heroku_3636wvfr:ka9cqpra6f4r8g3gfk8n2la4bs@ds255797.mlab.com:55797/heroku_3636wvfr

後ろの部分はご自身のMongoDBのURLを入れてくださいね!
ここで、またコマンドでconfigを開くと、

DB_URI:           mongodb://heroku_3636wvfr:ka9cqpra6f4r8g3gfk8n2la4bs@ds255797.mlab.com:55797/heroku_3636wvfr

この内容が追加されています。
これでHerokuのサイト上でもアクセスできるようになります!!


まとめ

今回は環境変数を有効かつ安全に使う方法について見てきました。
僕もはじめはこんなに簡単に設定できるのかと感心しました。
みなさんの役に立つことを願います!
では、また次回まで✌
記事更新はツイッターで告知するので、ツイッターの方でもフォローお願いします!
twitter.com



最新版 2019年にプログラミング始めるならJavaScript↓↓
programming-shop.hatenablog.com


最新版 2019年にプログラミング始めるならJavaScript

こんにちは、皆さん!
初めてプログラミングをやる人も今まで他の言語でプログラミングをやってきた方も2019年に始めるのなら、絶対JavaScriptを使いましょう!
今回の記事ではなぜ僕がそのような結論に至ったのかを皆さんにシェアしていきたいと思う。

  • トピック:
  1. JavaScriptとは?
  2. 簡単なシンタックス
  3. 豊富な使い道


JavaScriptとは?

では、初心者も多いことでしょうからまずはJavaScriptとは何かについて説明しようと思う。
まず、JavaScriptプログラミング言語である。これはつまり、C++PythonJavaRubyなどの他のプログラミング言語と同じ分類であることがうかがえる。なぜこんなにもたくさんプログラミング言語が存在するのか?ってなるよね。実はそれぞれの言語はもともとある目的のために作られているのだ。例えば、Pythonはデータを扱うようなアプリケーションを作るためにもともとは作られていて、おかげでデータの図式化などが他のプログラミング言語に比べてとても簡単に実行できるのだ。では、JavaScriptはどうなのか?
JavaScriptはウェブサイトの開発を主な目的として作られた。例えば、あるウェブサイトでボタンを押した後、ポップアップが出てきたり、計算機が作動して計算をしてくれるなどの動作を可能にしているのがJavaScriptなのだ。

さあ、簡単なJavaScriptの導入が終わったところでいよいよ本題に入りましょう。いったい僕がここまでJavaScriptをおススメする理由は何なのか?
今回は主に2つの理由を紹介していきたいと思う。

プログラミングを初めてやる人にとって難易度が低いことはモチベーションをキープする上でも大切である。ここではJavaScriptシンタックス(つまり、書きだしたコード)がいかに簡単なのかを他のプログラミング言語と比較していこうと思う。

Javascriptシンタックスに詳しい人はどうぞ2つ目の理由へ(豊富な使い道

1.タイプを指定しなくてもよい
Javaでは変数を定義するときに下記のようにその変数のタイプを指定する必要がある。

int number = 10;
boolean hungry = true;
String key = "Hello";

これは正直めんどくさいと思う人が多いと思う。いちいちタイプが違うせいでエラーが出たりするので修正しに戻らなければならない。
だけど、JavaScriptでは同じキーワードを使っていかなるタイプの変数も定義できる。

var number = 10;
var hungry = true;
var key = "Hello";

これは上記のJavaと同じ結果をもたらす。見ての通り、みんなvarで定義可能なのだ。

2.セミコロンを忘れても大丈夫
先ほどの例で1行ごとに;(セミコロン)が最後についているのが分かると思う。これはJavaでは必須であり、忘れるとこれまたエラーが発生する。同様にJavaScriptでもセミコロンは必須であるのだが、JavaScriptはなんとプログラマーが付け忘れたところに自動でつけてくれるので、まだ慣れてなくてよく忘れる初心者にとってはすごくありがたいのだ。

3.インデントではなく、{}を使うから見やすい
Pythonでは{}ではなく、インデント(行の最初にスペースを設ける)でコードをブロック分けする。例えば、if文を書くときに下記のようにインデントでif文の内容を示す。

hungry = true
if hungry
    print "I am hungry"
else
    print "I am not hungry"
print "Done"

一見簡単に見えるこのコードも例えば、print "I am not hungry"の前のスペースを忘れていたら、if文の中にあるとはとらえられなくなり、結果が異なるものとなる。
でも、JavaScriptは{}でこの仕切りを作っているためPythonほど簡単に間違えることはない。

var hungry = true;
if (hungry) {
    console.log("I am hungry");
} else {
    console.log("I am not hungry");
}
console.log("Done");

このようにJavaScriptは{}でどこからどこまでがif文なのかを決めるので、もし、console.log("I am not hungry")の前にスペースを入れてなくても{}内にあるから正しく読み取られるのだ。

豊富な使い道

さて、ここからがJavaScriptが他のプログラミング言語と大きな差をつけるようになった最も大きい原因だ。

思い出してほしいのが、JavaScriptは主にウェブ開発に使われる言語だ。そして、そのウェブサイトであっても大きく分けて2つの方面からの開発がある。1つはフロントエンドであり、主にユーザーがウェブサイトを開いたときに見れるものである。基本的に文字やスタイリングはHTMLとCSSでできるのだが、ここにボタンクリックやアニメーションを入れたり、ツイッターAPI(データを取得したり、変更したりをプログラミングを通して可能にしてくれるもの)にアクセスしてデータを取得するなどといったものはJavaScriptでないとできない。それに対してもうひとつバックエンドというものが存在する。俗にいう、ウェブサーバーに相当するものだ。これは通常ユーザーから直接見えることはなく、ユーザーが訪れたウェブサイトとコミュニケーションをとり、必要なデータをデータベースから取り出したり、データベースに保存したりする。そのほかにもユーザーのログインなどのパスワード確認もこのサーバーを通して行われる。
この2つは結構やることに違いが大きく、仕事探しの時にも、「フロントエンドの開発者を探してます」とか「バックエンドの開発者を探してます」と区別されたりする。

さて、基本的なウェブ開発での役割分担を知ったうえで、いよいよJavaScriptにはどんなことができるのか見ていきましょう!

  • フロントエンド開発

まずはユーザーが直接見るウェブサイトに動きをつけたり、様々なサーバーとコミュニケーションをとってデータをユーザーのわかりやすい形で届けるフロントエンド。純粋にJavaScriptだけでも作ることができるが、そのJavaScriptの力を大きく引き上げてくれるフレームワークを紹介しようと思う。
フレームワークとはプログラミング言語をベースにした開発を簡単にしてくれるものだ。もしも、プログラミング言語を日本語とするのなら、フレームワークは敬語といった感じだ。敬語がなくても、仕事はできる。しかし、敬語ができないと、なかなかじゃないけど、営業マンとしていい仕事はできない。そんな感じでフレームワークはなくても何かを作ることはできるが、その場合、ものすごい労働力を必要とする。そして、フレームワークは基本的にあるプログラミング言語をベースに作られる。

React

f:id:Programming_Shop:20190126084609p:plain
Reactのロゴ

まずは今最も大きな使用率を誇るReactだ。ReactはFacebookの優秀なプログラマーたちが作り出したフレームワークであり、元はFacebookのウェブサイトだけで使われていたが、今はオープンソースとして一般人にもアクセスができるようになった。
では、このReactを使うとどうなるか?
まず、一番大きな利点としてはウェブサイトの読み込みにかかる時間が格段に減るということ。Facebookをよく使う人なら気づいているのかもしれないが、Facebookサイト内であるコラムをクリックしたりした場合、下記のように上のヘッターは残して、下の内容部分だけが読み込み中状態になる。

f:id:Programming_Shop:20190126084927p:plain
Facebookサイトのローディング

普通にJavaScriptで書いたサイトはページからページに移るときにサイト上のすべてのものがリフレッシュされるが、Reactをベースに作ったサイトは必要な部分だけを更新するのだ。これによって格段にウェブサイトの読み込みが速くなり、ユーザーにとってより使いやすいサイトになるのだ。


  • バックエンド開発

お次はサーバーの方の開発。こちらも先ほどのフロントエンド同様、フレームワークを使っていくのが普通である。
バックエンドといえば、昔からあるPHPRuby on Railsがすごく人気を取っているが、いづれJavaScriptとは異なったプログラミング言語をベースに作られている。だが、現在、JavaScriptをベースにしたフレームワークがその急激な人気の上昇を見せている。

NodeJS

f:id:Programming_Shop:20190126090209p:plain
NodeJSのロゴ

なんとバックエンドでもJavaScriptが使えるようになったのだ。それまではデータベースも駆使した大きなウェブサイトを立ち上げようとすると、JavaScriptと少なくとももうひとつプログラミング言語を勉強しなくてはならなかったが、NodeJSの登場により、JavaScriptだけを学習すれば、様々な動きがついてしかもデータベースも利用した高度なウェブサイトが作れるようになったのだ。
下記のグラフを見ればNodeJSの人気の上昇が分かるでしょう。

f:id:Programming_Shop:20190125155747p:plain
NodeJSと他のフレームワークの使用率比較

NodeJSにはさらに他のフレームワークに比べて比較的早い処理ができるという利点がある。これはJavaScriptがもともと非同期プログラミング言語であることを利用したものだ。ここでは深く掘り下げないが、非同期とは同時にいくつかの処理を行うことができるということである。例えば、ブラウザでファイルをダウンロードしている最中にもブラウザ内で新しいリンクに移ったり、ブログを編集することができるのと同じ原理である。この原理をもとに作ったこのNodeJSというフレームワークは非同期で処理を行うことができ、これがその高いスピードを生み出しているのだ。


  • モバイル開発

次に少しウェブ開発から離れるが、なんとJavaScriptでモバイル開発ができるようになったのだ!!
ここで使うフレームワークがReact Native

React Native

f:id:Programming_Shop:20190129092952p:plain
React Nativeのロゴ

先ほどのReactとロゴが似ているが、違うものである。こちらもまたFacebook社の開発したフレームワークである。React Nativeが画期的な理由が大きく分けて2つある。
1.ウェブ開発に似たコードの構造
1つめはもともとモバイル開発ではSwiftでiPhoneのアプリ、Javaでアンドロイドのアプリを書くことになり、そのコードの構造もウェブ開発の時のものとは全く異なる。しかし、React Nativeの登場により、これまでウェブ開発をやってきた人たちはこれまで使ってきた言語そのままにモバイル開発ができ、Reactをベースにしているので、さらにより簡単にモバイル開発を始めることができるようになったのだ。
2.iPhoneとアンドロイドを一人二役
2つめの理由はもともとiPhoneとアンドロイドでは別々に異なる言語でアプリのコードを書かないといけなかったのが、React Nativeを使えば、両方かけちゃうということだ。これはいろんな立場の人にとって利益がある。まず、コードを書くプログラマーからすると、一つの言語だけで2つのプラットフォームのアプリを作ることができる。一方、経営者からすると、iPhoneとアンドロイドそれぞれのアプリのコードを書く人を一人ずつ雇う必要がなくなり、人件費節約にもなるのだ。


Tensorflow

f:id:Programming_Shop:20190129095759p:plain
Tensorflowのロゴ

少々難易度が上がるが、話題の機械学習JavaScriptでできるのだ。もっともメジャーなグーグル社の開発したTensorflowライブラリーは一番人気のPythonだけでなく、JavaScriptバージョンも用意されている。
先に述べたフレームワークでビジネスを始めるのなら、ウェブサイトとモバイルアプリを作った後は機械学習の力も借りて、客のニーズにもっと正確に答えられるようにデータを分析することになるでしょう。その時にはかなり活躍するはずだ。
さらに、大きな企業ではそのようなデータを研究する人(データサイエンティスト)を募集しているところもいるので、機械学習を勉強して損はないでしょう。海外ではすでにエンジニアと同じかそれ以上の給料を稼げる一つの仕事になっており、エンジニアを雇う大きな会社では基本的にデータサイエンティストも別で雇っている。
もし、統計や数学などの計算に自信があるのなら、将来的にチャレンジしてみる価値はあると思う!

まとめ

ここまで僕の個人的なJavaScriptを2019年に勉強すべき理由を見てきた。このようにシンプルなシンタックスを使い、さらに様々なアプリケーションに応用できるプログラミング言語JavaScriptをおいてほかにはない。特にウェブ開発をする人にとってはどちらにせよ習わないといけない言語であり、そこに別の言語を足すという新たな負荷を減らせるという意味ではかなりプログラマーにとってフレンドリーである。
もちろん、他のプログラミング言語を下位として否定する意味はないので、JavaScript以外の言語を選んでも大丈夫でしょう。ですが、将来性を考えると、JavaScriptにたどり着く可能性が高いので、いっそのこと最初からJavaScriptで行くのが仕事獲得の最短距離でしょう。


ご精読ありがとうございました。では、また次回まで✌
記事更新はツイッターで告知するので、ツイッターの方でもフォローお願いします!
twitter.com

RspecでJSONオブジェクトの値を確認する

こんにちは、皆さん!

Railsウェブアプリケーションを作っていく上で、その品質を保証するためにRspecは欠かせない。そして、最近ではRailsAPIを作る人たちも増えてきている。そんなAPIなのだが、普通コントローラーがJSONオブジェクトという形でデータを返してくる。今回はそのオブジェクト内の値をチェックする方法を紹介したいと思う。


  • トピック:
  1. 今回使うモデルの説明
  2. うまくいかない例
  3. うまくいく例


今回使うモデルの説明

今回はUserモデルを使い、メール、パスワード、確認パスワードの3つを使ってユーザーを作成(つまり、POSTリクエスト)、そして、そのアクションで作られたユーザーをJSONオブジェクトとして返すという形をとる。下記がUserコントローラーのcreateアクション。

    # users_controller.rb
    def create
        @user = User.create(user_params)
         render json: @user, status: :created
    end

    private

    def user_params
        params.require(:user).permit(:email, :password, :password_confirmation)
    end

ベースのテストコードは下記のようになっている。今回はここにもう一つコードを足して、JSONとして返ってきたオブジェクトのメールがもともと入れたメールと同じか確認する。

    # users_controller_spec.rb
    describe "POST create" do
        it "should create a user with valid params" do
            post :create, params: {user: {email: "example@example.com", password: "foobar", password_confirmation: "foobar"}}
            expect(response).to have_http_status(:created)
        end
    end

覚えておくべきことは

  • ここで使うのはcreateアクションだけであること
  • そのアクションではJSONオブジェクトのUserが返され、:createdというステータスがついてくること
  • そのステータスはテストコードのPOSTリクエスト後に確認がされていること
  • response.bodyに返されたJSONオブジェクトの詳細が入っていること

では、実際に両方の例を見ていこう!!

うまくいかない例

まずよくやっちゃううまくいかない例。僕もこれをよくやりがちなのだが、JSONオブジェクトだからといって下記のようにそのままキーを使って値を取り出そうとするパターン。

    describe "POST create" do
        it "should create a user with valid params" do
            post :create, params: {user: {email: "example@example.com", password: "foobar", password_confirmation: "foobar"}}
            expect(response).to have_http_status(:created)
            expect(response.body['email']).to eq("example@example.com")
        end
    end

これはいつもJavaScriptでキーを使って値を抜き出してる人からしたら、とても常識的なやり方。しかし、Rubyでは下記のように想定外のことがおこり、テストが下記のようにフェイルしてしまう。

  1) V1::UsersController POST create should create a user with valid params
     Failure/Error: expect(response.body['email']).to eq("example@example.com")

       expected: "example@example.com"
            got: "email"

       (compared using ==)
     # ./spec/controllers/users_controller_spec.rb:16:in `block (3 levels) in <top (required)>'

これはつまり何かというと、response.body['email']の結果がemailになっているのだ。
試しにputs response.bodyresponse.bodyの内容をアウトプットしてみた。そしたら下記の結果が得られた。

{"id":841425152,"email":"example@example.com","created_at":"2018-12-30T19:26:45.289Z","updated_at":"2018-12-30T19:26:45.289Z"}

これって当たり前だけど、JavaScriptのキーと値のペア式になっているのだ。でも、これこそが問題の原因。なぜなら、Rubyでのキーと値のペア式はJavaScriptのそれとは違うからだ。皆さんもご存知かと思うが、下記のようなシンタックスRubyのやり方。

{"id"=>841425155, "email"=>"example@example.com", "created_at"=>"2018-12-30T23:07:17.457Z", "updated_at"=>"2018-12-30T23:07:17.457Z"}

そう、=>のような矢印でシンボルを表現するやり方だ。では、次にどうやったらRubyのわかる形に変更できるかについて見ていこう!!

うまくいく例

では、いったいどうやってRuby式のキーと値ペアにするのかというと、この関数を使うのだ。

JSON.parsse()

これは単純にJSONオブジェクトをRubyのわかるものに変えるだけなのだ。言うなら、to_json()関数の逆をやっているのだ。
よって、先ほど、puts response.bodyJavaScriptの形になっていたものはputs JSON.parse(response.body)と改めることで下記のようになる。

{"id"=>841425155, "email"=>"example@example.com", "created_at"=>"2018-12-30T23:07:17.457Z", "updated_at"=>"2018-12-30T23:07:17.457Z"}

つまり、うまくいくRspecのコードは下記のようになる。

    describe "POST create" do
        it "should create a user with valid params" do
            post :create, params: {user: {email: "example@example.com", password: "foobar", password_confirmation: "foobar"}}
            expect(response).to have_http_status(:created)
            expect(JSON.parse(response.body)['email']).to eq("example@example.com")
        end
    end


まとめ

どうだったでしょうか?
このように問題を発見することができれば、あとはしっかりとしたRubyの知識があればこのような問題は解決できる。なので、何かエラーに面したときはいろいろとプリントアウトしてみて、手掛かりを探しましょう!!
皆さんのテストコードがより素晴らしいものになることを祈ります。


ご精読ありがとうございました。では、また次回まで✌



Herokuのステージングブランチとは?(導入編)↓↓
programming-shop.hatenablog.com

Herokuのステージングブランチとは?(実践編)

こんにちは、皆さん!

ここではどうやってHerokuでステージングブランチを作れるのか、そして、そこで役に立つちょっとした予備知識と一緒にお伝えしようと思う。Herokuのステージングブランチについての解説はこちらの導入編を参照してください。→
Herokuのステージングブランチとは? (導入編) - Programming_Shopの日記


  • トピック:
  1. ステージングブランチの作り方
  2. プロダクションのコードを更新する
  3. ステージングブランチにプッシュ先を変更する
  4. ステージングブランチの注意点
  5. Herokuのメンテナンスモード
  6. おまけ


ステージングブランチの作り方

では、さっそく最初のステージングブランチを作っていきましょう。
まず、Herokuアカウントを開いて、そして、ステージングブランチにしたいアプリを選びます。ここでは、僕自身のHerokuで例を挙げていく。下記のようにHerokuのアプリケーションがいくつかある。ここでthis-will-be-stagingをステージングブランチにするとしよう。なので、まずそのアプリケーションの詳細に入る。
f:id:Programming_Shop:20181210112059p:plain
ホーム画面からアプリへ


その後、ダッシュボードからDeployをクリック。
f:id:Programming_Shop:20181210112449p:plain
ダッシュボードからDeploy


そしたら、パイプラインを作成するので、Choose a pipelineからCreate new pipelineを選択。
***注意***
ここで、本家の方に選ぶHerokuのアプリ内のコードはステージングブランチに選んだコードに変更されるので、くれぐれも失いたくないコードの入ったHerokuアプリを本家として選ばないでください!!

f:id:Programming_Shop:20181210113210p:plain
新しいパイプラインを作成する


このパイプラインというのはつまりは2つのHerokuのアプリケーションをつなげるようなものである。そしたら、いつでもステージングブランチのコードを本家の方にプッシュすることができるのだ。
名前を付けてパイプラインの作成は完了。ここでは、heroku-staging-testという名前にした。

そしたら、おそらくこんな感じの画面になったでしょう。まだステージングブランチだけで本家がないので、ここで追加していく。Add appをクリック。

f:id:Programming_Shop:20181210115121p:plain
本家を追加するための画面


ここで、今回は最初にホームページで見せたthis-will-be-productionが本家なのでサーチバーからタイプして選択した。そしたら、下記のようにパイプラインが完成。
f:id:Programming_Shop:20181210115256p:plain
パイプライン完成!


次はステージングブランチのコードを本家にプッシュして本家のウェブサイトのコードを更新していく。

プロダクションのコードを更新する

ここまででとりあえず、ステージングブランチと本家の間にパイプラインを作ることに成功した。ここからは実際に運用していくステージで、ステージングブランチにいれた新しいコードを本家にプッシュして、反映させる。
f:id:Programming_Shop:20181210115329p:plain
ステージングブランチから本家にプッシュ
この赤丸を打ったボタンがまさしくこれまでいつでもステージングブランチのコードを本家にプッシュすることができるといっていたボタンなのだ。


ここで、Promoteというボタンをおして、プッシュを完了すると、下記のような画面になる。
f:id:Programming_Shop:20181210115512p:plain
プッシュ完了!


これはただいまステージングブランチと本家のコードはまったく同じであるということを言っているのだ。そして、以降ステージングブランチのコードを変えるたびにこのボタンが先ほどのボタンのようになり、またプッシュすることができるようになる。


こうしてパイプラインのセットアップが完了した後にホームページに戻ると、下記のように先ほどの2つのアプリが1つにまとまっているでしょう。
f:id:Programming_Shop:20181212032205p:plain
パイプライン完了後のホームページ

ステージングブランチにプッシュ先を変更する

ステージングブランチの作り方とウェブサイトのコードをステージングブランチから更新する方法について話してきた。しかし、どうやったらステージングブランチのコードを更新できるのか?
これについて話す前に、まず注意したいのはステージングブランチはステージングブランチという特別な名前を与えられているが、結局は1つのHerokuのアプリケーションであることを肝に銘じてもらいたい。なので、いつもHerokuにプッシュするようにステージングブランチに更新したコードをプッシュすることができるのだ。


ここで、今エディターで編集しているコードのプッシュしている先がステージングブランチになっていない場合は下記のようにプッシュ先を設定しましょう。
まず、Herokuのページからまずステージングブランチのアドレスをコピーします。ステージングブランチのアプリを開いて、Settingsをクリック。ちょっとスクロールしたところに下記のようなものがあるので、この赤丸のところをコピー。
f:id:Programming_Shop:20181212040637p:plain
ステージングアプリのアドレスをコピー


その後、編集しているコードのディレクトリーをターミナルで開いて、下記のようにHerokuへのプッシュ先を設定する。
(heroku addressの部分に先ほどのコピーしたアドレス。<>は不要)

git remote add heroku <heroku address>

こうすれば、今後Herokuにプッシュする際にはステージングブランチの方にコードが行くようになる。

ステージングブランチの注意点

ステージングブランチを使っていく上で、いくつか覚えていただきたい注意点がある。

  • ステージングブランチと本家ではデータベースが別々である

ここでもう一度おさらいするが、ステージングブランチもまた1つのHerokuアプリであるので、それ自身にデータベースも存在し、これは本家の方と別のものである。なので、ステージングブランチで新たに足したデータは本家には反映されないし、逆に本家で追加したデータもまたステージングブランチには反映されない。
しかし、これがまたステージングブランチのいいところで、ステージングブランチで様々なデータをテストする際にそれが本家に影響を与えるかどうか気にしなくていいということである。

  • 必要なアドオンを再追加する

これまたアプリが分かれているためだが、本家で使われているHerokuのアドオンでテスト時に必要になるアドオンはステージングブランチにもしっかり追加しよう。例えば、メール送信をテストしたいのなら、sendGridを追加する。

こちらもまた本家と同じように追加しないと、アプリがうまく動作しないかもしれないのであるのなら追加しましょう。また、その変数の使い方によるが、テストするために本家とは違うテスト用の変数を設定してもよいでしょう。

Herokuのメンテナンスモード

最後に、ステージングブランチのコードを本家にプッシュする際にとても役に立つメンテナンスモードについて説明していこうと思う。
実は、Herokuにはメンテナンスモードがあり、いつでもユーザーがその状態を変更できる。もしも、メンテナンスモードになっている状態で、そのウェブサイトに行くと、下記のようにウェブサイトのコンテンツを見ることができないようになっているのだ。
f:id:Programming_Shop:20181212043746p:plain
Herokuのメンテナンスモード


これがなぜ役に立つのかというと、ステージングブランチのコードを本家にプッシュする際に、Herokuは一度、アプリを止めるので、ユーザーの邪魔をしてしまうのだ。特にアクセスが集中している本家のサイトだと多くのユーザーに影響を与えやすい。なので、一度本家をメンテナンスモードにして、ユーザーのアクセスを無効にして、変にユーザーのデータ更新を邪魔しないようにするのだ。
これもまた簡単で、本家の方のアプリのSettingsに行って、下記の画面までスクロール。
f:id:Programming_Shop:20181212044435p:plain
メンテナンスモード変更のボタン


このボタンでメンテナンスモードをオンにしたり、オフにできる。また、もし、本家の方のアドレスをいれたディレクトリーがあるのなら、下記のようにターミナルからでも設定できる。1つ目でメンテナンスモードにし、2つ目でメンテナンスモード解除。

heroku maintenance:on
heroku maintenance:off



1つだけ注意したいのは、ステージングブランチをメンテナンスモードにしても意味ないので、先ほどアドレスを設定したステージングブランチではなく、本家でこのコマンドを使うことを覚えておこう。

おまけ

Herokuはデフォルトでアカウント1つにつき5個までしかアプリを持つことができない。この条件で行くと、ステージングブランチとか作ると、すぐに2個分のアプリのスペースを取ってしまう。なので、できれば、クレジットカードを登録しよう。登録するだけなら、何もお金を払うことはない上、さらに、持てるアプリの数が一気に200個まで増加するので、オススメ!

まとめ

以上で、Herokuでのステージングブランチの使い方の説明になる。Herokuを使って、アクセスの多い大きなウェブサイトを管理していく上で、何段階にもなるテストはサービスの質を確証する上で、大事になってくる。その際に、ステージングブランチはユーザーに影響を与えずにHeroku上でのテストを可能にしてくれるとても便利な機能である。みんなもぜひステージングブランチを有効活用して、さらなるウェブサービスの向上に精進してください。


ご精読ありがとうございました。では、また次回まで✌



Herokuのステージングブランチとは?(導入編)↓↓
programming-shop.hatenablog.com

Herokuのステージングブランチとは?(導入編)

こんにちは、皆さん!

ステージングブランチというものをみなさんもどこかで一度は聞いたことがあるかもしれない。特にすでに会社でHerokuを使っているという場合はなおさらである。今回はWeb開発を効率化し、そして、メインテナンスをより簡単にさせてくれるステージングブランチについて紹介していきます。(実践編はこちら→
Herokuのステージングブランチとは?(実践編) - Programming_Shopの日記


  • トピック:
  1. ステージングブランチとは?
  2. ステージングブランチの利点


  • リソース:
  1. Managing Multiple Environments for an App | Heroku Dev Center


ステージングブランチとは?

***注意***
以下の内容を理解するにはGitの知識が少し必要になってきます!

まず、初めにステージングブランチとは何かについて説明していこうと思う。ざっくり簡単に言うと、GitのマスターブランチがHerokuにデプロイしたコードでステージングブランチはGitのマスターブランチ以外のブランチといえる。つまり、実際に運営しているウェブサイトとは別にもう一つ同じ内容のウェブサイトを持つことができるということだ。
もっと一般的な例でいうのなら、劇を例に挙げて、ローカルでのテストが練習、ステージングブランチでのテストがリハーサル、そして、本家のウェブサイトにデプロイが本番といったような感じだ。(以下の図参照)

f:id:Programming_Shop:20181209092651p:plain
劇とウェブサイト構築の対称
そして、Gitでマージするように、このステージングブランチのコードはいつでも本家の方のウェブサイトにプッシュすることができるのだ。

ステージングブランチの利点

では、本題ですね。いったいなぜステージングブランチを使う必要があるのか?
大きく分けてステージングブランチを使うことには2つの利点があります。

  • Herokuにデプロイした際、エラーがあっても、ユーザーに影響を与えない

Herokuとローカルでテストしたときに内容が違うことはよくある。例えば、レイアウトのサイズ感が少し違う(これに関してはどうしてなっちゃのかいまだに謎)など。これをユーザーが直接見る本家のウェブサイトにデプロイしないで、ステージングブランチにデプロイすることで、事前確認ができ、修正することができる。

  • Herokuでしかテストできない要素がある

少し1個目とも被るが、例えば、メールをユーザーに送信するものなどは確かにローカルでテストコードを書いてテストしてみることもできるが、やはり、最終的にはHerokuにデプロイした後の状態で確認する必要がある。この時、本家に直接デプロイすると、ユーザーもその新しいエラーのあるかもしれない機能に触れる可能性があり、非常に望ましくない。なので、まずはステージングで確認するところから始める。

これらを踏まえると、下記のような仕事の流れができる。

f:id:Programming_Shop:20181209093901p:plain
ステージングブランチと仕事の流れ
このようにプログラマーはローカルとステージングの間を行き来し、最終的に完全なものだけをユーザーに届けるのというシステムになっているのだ。

まとめ

導入編はここまで。次は実践編で実際にどうやったらHerokuでステージングブランチを実行することができるのかを紹介していきます。実際に自分のアプリケーションに取り入れたい人はぜひ下記のリンクからどうぞ↓↓
Herokuのステージングブランチとは?(実践編) - Programming_Shopの日記


ご精読ありがとうございました。では、また次回まで✌



Herokuのステージングブランチとは?(実践編)↓↓
programming-shop.hatenablog.com

Ruby on Rails開発のインターン (Day 36 最終日)

こんにちは、皆さん!

ついにインターン最後の日がやってきた!時間がたつのって本当に早い。インターン初日がまるで昨日のことのように感じられる。振り返ってみると、弁当たくさん作ったな(笑)
まあ、結果的にプログラミングに関して様々な知識を身につけられた気がする。すごくためになるいい経験だった。
最後の日に関してだが、おそらく新しくこれとしたことを始めることはないだろうが、ここまで僕が書いてきたコードの整理などをしてちゃんと他の人に引き継いでもらえるようにすることが主となるかな。最後の日も楽しんでいこう!


  • トピック:
  1. ネステッドルートを使い、Railsにおけるルートを効率よく定義する


  • 疑問:


  • 問題:


  • 学習した内容:
  1. Railsでルートを効率よく定義する方法


  • 今後やってみたいこと:


  • リソース:
  1. Rails のルーティング | Rails ガイド


ネステッドルートを使い、Railsにおけるルートを効率よく定義する

なんとここまで来て、やっと長いURLをネステッドルートで定義した方が効率がよく、コードとしてもきれいに見えることを知った。
今回はRailsガイドでその基礎を学んだ。(Rails のルーティング | Rails ガイド

この機能は難しくないし、僕も結構好き。もう本当にコードがきれいになる。
例えば、ネステッド状態のコントローラー、post/:id/image/:id(簡単に言うと、たくさんの写真を持ったたくさんの投稿を持つウェブサイトであり、このように指定することでその中の一つの投稿の一つの写真を出してくれる)。このURLを書くときにshowアクションのためだけにこう下記のように書きたくなるかもしれない。

get 'post/:id/image/:id', to: 'images#show'

しかし、これをさらにほかのアクションに対してもやらなくていけなく、それはまた大変な量のコードなのであり、間違いも発生しやすい。
だが、下記のようにネステッドの機能を使うことでこれがすごく簡単になるのだ。

resources :posts do
  resources :images
end

これだけで基礎的なRESTfulのアクションすべてを作り出したことになる。

もちろんいくつかのアクションに制限をかけたいときも簡単。例えば、投稿のeditアクションだけをなくしたいのなら

resources :posts, except: [:edit] do
  resources :images
end

ネステッドルートの更にいいところはcollectionフレームが使えることだ。これがあるだけでRESTfulに該当しない基本的でないアクションも簡単に定義することができるのだ。例えば、helloアクションをpost controllerに追加したいとする。そしたら、posts/helloでそのURLを構築したいのなら、普通、下記のようにすればできる。

get 'posts/hello', to: 'posts#hello'

しかし、collectionがあればこのように書き換えられる。

resources :posts do
  collection do
    get 'hello'
  end
end

これはより簡単だし、何より見やすい。あとでここに何か追加したいときはそのままこの枠の中に足すだけで前半部分のposts/をもう入れなくて済む。また、posts/部分が変わる場合も一か所だけ変えればすべてが一緒に変わるという。

まとめ

というわけで、僕の短期インターンに幕を閉じるときがやってきた。僕はとにかくこの自由でフレンドリーな環境が大好きだ。ここでは本当にたくさんのことを学ぶことができた。Railsに限らず、どうやってやることリストを管理し、効率よく仕事を進めていくかなど一般的で共通なスキルも学べた。大人として成長できた印象を受ける。個人的に給料以外はすべて納得だった(笑) まあ、スキルアップして次はもっとたくさん払ってくれるところ探すしかないね(笑)
最後の一日ということで、新しいことを始めることもできなかったが、存在するバグをいくつかすぐに直すことができたのでいいとしよう。最後にこの小さなコミュニティーに貢献できてよかった。
最後にマネージャーと少しこれからの僕のプランについて話し合った。彼は僕が来学期を終えた後、どんなことをするのか結構興味津々であった。今のところ、僕の考えでは、Airbnb, Twitter, Google, Microsoftのような大きなIT会社で働いてみたいなとは思っている(僕なんかを採用してくれるのならの話だが(笑))。明るい自分の将来を願いつつ、2か月間本当にお世話になりました。


ご精読ありがとうございました。では、また次回まで✌





Day 35はこちら↓↓
programming-shop.hatenablog.com

Ruby on Rails開発のインターン (Day 35)

こんにちは、皆さん!

ついにインターン終了まであと1日のところまでやってきた。引き続きデータインポートの機能実装をやっていく方針。今のところ、リダイレクトできないから、何か問題が起きても画面に何の変化もない。もしかしたら、もっといい方法が見つけて、ユーザーに失敗したときにエラーメッセージを返せれたらなというところだね。


  • トピック:
  1. Railsでダウンロードボタンを作る
  2. グローバル変数の代用


  • 疑問:


  • 問題:


  • 学習した内容:
  1. Railsでダウンロードボタンを追加する方法


  • 今後やってみたいこと:


  • リソース:
  1. ruby on rails - How to create a download button (link) for a local image (png) - Stack Overflow
  2. ruby - Rails Global Variable becomes nil across controller actions - Stack Overflow


Railsでダウンロードボタンを作る

これを学習した後、もっと早くこれを習っていたのならと思うくらいだった。すごく優秀な機能であり、アプリの可能性を一気に広げてくれるなと思った。***これからの内容には僕の以前のブログで見つかるような予備知識が必要な場合がある。***

とりあえず、ダウンロードボタンの基本はこう:

<%= link_to "Download", action: :download %>

これがごく普通のダウンロードというアクションを控えたリンクの作り方。
しかし、これだけではdownloadアクションが定義されていないことになる。なので、このダウンロードボタンのあるビューが所属するコントローラーに行き、downloadアクションを関数として追加する。
この関数はユーザーにファイルをダウンロードさせるだけで特に他のことはしないので、中身はだいたい下記のような感じになる。

  def download
    send_data to_csv, filename: "error_lines.csv"
  end

send_dataについて以前のブログを参照するとよいでしょう
こうやって書くと、 "error_lines.csv"というファイルをユーザーに送ることになる。
よし、これでダウンロードボタンの機能はほぼ完成!
だが、ほとんどの場合、このボタンをスタイリングしたいことでしょう。特にお手頃のBootstrapでこうやって

<%= link_to "Download", action: :download, class: "btn btn-primary" %>

そして、ローカルサーバーで開いてみると、あれっ!!!ボタンがスタイルされていない!ってなるはず。
僕も同じエラーが起き、いったいなぜなのかディベロッパーツールを使って確認すると、ボタンが下記のようになっていることに気が付いたのだ。
f:id:Coding_Studio:20180824051438p:plain

それでこれがlink_toというアクションをHTMLタグの中でどのように使うのかに問題があるのだと思った。
そして、いろいろ試した結果下記のでうまくいった。

<%= link_to "Download", {action: :download}, class: "btn btn-primary" %>

そう、つまり、アクションの部分を{}に入れる必要があったのだ。これでどこからどこまでがアクションなのかわかるというわけだ。

あるコントローラー内の複数のアクションである変数を使いたかったので、もっとも簡単といわれるグローバル変数にしてみた($を変数の前につける)

class UsersController < ApplicationController
$var = Array.new
...
end

これでそれぞれのアクションの中で$varというようにこの変数にアクセスできる。

しかし、これはHerokuにプッシュすると、うまくいかなかった。どうやら以前に投稿したグローバル変数がメモリ容量を急速に加速させてしまう可能性を秘めているからかHerokuではリダイレクトしたり、レンダーをすると、グローバル変数をすべて削除してしまう。なので、他のアクションでその値を定義した後にその関数をアクセスしようとすると、想定していた値がそこにはなかった。少し調べてみたが、グローバル変数という選択肢は存在するが、やはり、使わない方がいいというのが一般的な考えだった。

それで探してみたら、かわりにその値をハッシュに入れるのだった。職場のプログラムではログイン機能があったため、セッションのハッシュを使うことにした。

session[:var] = Array.new

値を保存し、様々なコントローラーでも使えるので、かなり重宝できる使用法だと思う。そして、こんな有用なものが学べたことに感謝する。

まとめ

今日はHeroku上でインポート機能のコードがよりいいUIとUXとともに動くようにコードを書いていった。最終的にはうまくいったのですごく嬉しかった。出来上がった後二度見するくらいダウンロード機能を一つのボタンに組み込んだことがカッコよく思えてしかも大きな達成感を感じた。最終日は何をするのか今のところ何もわからないが、何か面白いことを最後にやらせてくれたらうれしいな。


ご精読ありがとうございました。では、また次回まで✌



Day 36(最終日)はこちら↓↓
programming-shop.hatenablog.com


Day 34はこちら↓↓
programming-shop.hatenablog.com