Ruby on Rails開発のインターン (Day 11)
こんにちは、皆さん!
今日の朝はちょうど座った時に避難訓練があった。ちょっとタイミングがね...(笑)
それはさておき、今日はHeroku上のバグを修正できるようにがんばっていくぜ!
- トピック:
- 疑問:
- 問題:
- 学習した内容:
- モデルクラスの中で関数を定義し、他のファイルでそのクラスからなるオブジェクトに対してその関数を使える
- 今後やりたいこと:
- リソース:
モデルクラスの中で関数を使う
User
というモデルがあり、 そのuserには'name', 'email', 'age', 'gender', 'address'があるとしよう。もし、この状況で頻繁にuserの詳細をアウトプットさせるようだったら、毎回下記のようにコードを打ち込むことになる。
"Name: " + @user.name + " Email: " + @user.email + " Age: " + @user.age + " Gender: " + @user.gender + " Address: " + @user.address
これはめんどくさいし、後で修正するときにすごく手間がかかる。
ということで、次のようにapp/models/user.rb
ファイルの中に関数を定義する。
def info "Name: " + @user.name + " Email: " + @user.email + " Age: " + @user.age + " Gender: " + @user.gender + " Address: " + @user.address end
そしたら、詳細をアウトプットしたいとき、info
関数を下記のように使えばできる
# users_controller.rb def index @users = User.all @users.each do |user| puts user.info end end def show @user = User.find(params[:id]) puts @user.info end
これで書くコードの量がだいぶ減る。
後から考えてみれば、Userはapp/models/user.rb
でクラスとして定義されていてUserのオブジェクトであるのなら、Userクラスで定義されている関数はごく普通のOOP言語のように使える。Railsのように最初から結構複雑にいろいろなファイルを作られると案外気づかないものだ(笑)
tunemygc
ジェムはrakeタスクを妨害する可能性がある
heroku run rake db:seed
をするときにエラーが発生し、うまくいかなかった。いろいろ試した。データベースのリセット、Herokuにコードを再度プッシュなど、けどどれもダメだった。それで、諦めて、一個前のコミットに戻った。変わった内容は
Gemfile
の中にtunemygc
ジェムがあるかどうかだけ。そしたら、不思議にもHeroku上でうまく使いたかったコマンドが使えるようになった。結果わかったことは、この特定のジェムに関しては、Heroku上にアドオンがあり、HerokuではGemfile
ではなく、そっちを使うことが望ましかったようだ。よって、存在するジェムのうち、いくつかのジェムはHeroku上でrakeタスクを邪魔し、アプリケーションがうまくいかなくなる。そういう時はググってHeroku用のアドオンがないかを探してみよう!
***通常、クレジットカードの登録を要求されるが、心配はしなくてよい。これらのアドオンは無料なので請求されはしない!!***
まとめ
tunemygc
をどうやってHeroku上で使うかを発見できたので、結構うれしかった。想像以上に時間かかってしまったけど... 。こっからは帰宅後、学校に戻ってからの話。何人かのコンピュータサイエンスの友達に久しぶりに会った。インターン始めて以来初めて会ったからインターンについて色々聞かれた。その中で、なぜ職場ではLinuxを使っているのか聞かれたがよくはわからなかった。中にはLinuxはWindowsやMacOSと違って、オープンソースで情報を提供会社に盗まれないからとかいう理由まで。とりま、明日マネージャーに聞いてみよう!
ご精読ありがとうございました。では、また次回まで✌
Railsでデバッグする方法
こんにちは、皆さん!
今回はRailsをローカルで使う際にデバッグする方法のまとめ。
- トピック:
以下の内容では、デフォルトで入っているが、Gemfile
にbyebug
がインストールされていることを前提とする。
どんなコードを入れるの?
まず、デバッグを他の場所でやったことある人ならブレイクポイントという言葉を聞いたことがあると思う。プログラム実行中にそこに到達するとそこで一時停止するもの。Railsでは代わりに下記のコードを挿入する。
debugger
というコードをブレイクポイントとなるところに入れるだけ
例えば、users_controller.rb
があったとして、下記のようにdebugger
を挿入する
def show @user = User.find(params[:id]) debugger end
そうするとローカルサーバーで/users/1
に到達したときにプログラムが止まり、コマンド上でRubyのコンソールが開かれる。
どうやって使うの?
(byebug) @user.name "Example User"
ブレイクポイントから出るためにはCtrl+D
。もし、他のブレイクポイントがあるなら、今度はそこまで飛ぶ。
まとめ
ご精読ありがとうございました。では、また次回まで✌
Railsでリキャプチャを実行しよう!!
こんにちは、皆さん!
今回はロボット対策のリキャプチャをRailsで実行する方法についてまとめた。
リキャプチャはただロボット対策をするだけでなく、ウェブサイトをよりプロフェッショナルに見せてくれる。一石二鳥ってところだね!!
スターターのコードもあり、それをダウンロードしてこの記事通りにコードを書いていけばRailsでリキャプチャを実行する方法を学習できる。
完成版のコードはこちら↓↓
https://github.com/Eric1015/recaptcha-tutorial
難易度と対象者
- 難易度:★★☆☆☆
- 対象者:中級者
***詳細はこちら→難易度と対象者の設定について - Programming_Shopの日記***
必要条件:
- MVCを理解している
- Herokuにアプリをデプロイできる
トピック:
- スターターのダウンロード
- セットアップと確認
- gemのインストール
- リキャプチャをHTMLに挿入する
- リキャプチャのキーを取得する
- キーを環境変数として設定する
- コントローラーにコードを入れる
- 言語設定を日本語にする
スターターのダウンロード
https://github.com/Eric1015/recaptcha-tutorial-starter
ターミナルからコマンドでダウンロードするなら下記のコマンド
git clone https://github.com/Eric1015/recaptcha-tutorial-starter.git
セットアップと確認
rails s
では、ローカルのそのウェブサイトに行ってみましょう。お好みのブラウザ(chromeを勧める)を開いてlocalhost:3000
をURLに入れてサイトをロード。
下のような画面になったら問題なし
次にHerokuアプリを作りましょう
heroku create
そして、コードをHerokuにプッシュする
git add -A git commit -m "Setup completed" git push heroku master
念のためにローカルの時と同じサイト画面になるか確認
gemのインストール
Gemfile
を開いて下記のgemを追加
gem 'recaptcha', require: 'recaptcha/rails'
そしたら、コマンドからインストール
bundle install
では、次は実際にコードの中に入れましょう!
リキャプチャをHTMLに挿入する
<%= recaptcha_tags %>
これがそのタグ。そして、これを今のアプリケーションに入れると、app/views/users/new.html.erb
ファイルは次のようになる。
<h1>ユーザー登録</h1> <% if flash[:alert] %> <div class="error"> <% flash[:alert].each do |msg| %> <p id="error-message"><%= msg %></p> <% end %> </div> <% end %> <%= form_for(@user) do |f| %> <p>名前 (必須)</p> <%= f.text_field :name %> <p>メール (必須)</p> <%= f.text_field :email %> <p>好きな動物</p> <%= f.text_field :animal %> <br> <%= recaptcha_tags %> <br> <%= f.submit 'Submit', id: 'button', class: 'btn btn-default' %> <% end %>
では、Herokuにプッシュして、再びサイトを訪れてみましょう。
あれ?エラーが起きてる!!
そう、リキャプチャを使うためにはグーグル公式のサイトからキーを取得しなければならないのだ。
リキャプチャのキーを取得する
そしたら、右上のこのボタンをクリック↓↓
その次の画面で下のように記入(Domainsには自分自身のHerokuアプリのURLを入れる)
Domains
の部分はこのAPIキーが使える箇所を制限してくれるもの例えば、僕が
ilovecanada.ca
というウェブサイトを所有していたとしよう。それでここにそれを入れることでこのAPIキーはそのウェブサイトでしか使えなくなるのだ。これはいざAPIキーが他人に漏れた時のために乱用されないようにするためのもの。しかし、今では自分のウェブサイトを指定しないとそもそもリキャプチャを使わせてくれないようだ。
そしたら、以下のように2つのキーが表示されるはずだ(僕のは隠したが)
キーを環境変数として設定する
programming-shop.hatenablog.com
そしたら、以下のようにconfig/initializers/recaptcha.rb
ファイルを作成する
Recaptcha.configure do |config| config.site_key = ENV['recaptcha_site_key'] config.secret_key = ENV['recaptcha_secret_key'] end
これでリキャプチャの2つのキーは環境変数からとるように設定したことになる。
わかったところで、これをまずはHerokuにプッシュ。
そしたら、Herokuに2つの環境変数を入れる。
下のyour_site_key
とyour_secret_key
にそれぞれ自分のキーを入れて以下のコマンドを実行する
heroku config:set recaptcha_site_key=your_site_key heroku config:set recaptcha_secret_key=your_secret_key
では、もう一度Herokuアプリを開いてみよう。次のようになっているはず
おめでとう!リキャプチャが正しく表示されました。
実践してみよう。名前とメールに適当に何か入れて"Submit"ボタンを押す。(これはリキャプチャやってないから拒否されるはず)
なんと!通ってしまった。
実はコードをつけ足さないとリキャプチャの判別をしてくれないのだ。
コントローラーにコードを入れる
verify_recaptcha(model: @user)
このコードで@user
の登録に関してリキャプチャを正解できたか判別する。この手法はform_for(@user)
に少し似ていて@user
のためのフォームみたいに@user
のためのリキャプチャと考えると覚えやすい。
ではこのコードが何をするかなのだが、使用者がリキャプチャを正解できた場合、このコードはtrue
を、正解してない場合はfalse
を返してくる。なので、返ってきたのがtrue
の時だけ何かすればよい。
if verify_recaptcha(model: @user) # your code here end
つまりこんな感じになる。これを今のアプリケーションに入れるとなるとユーザーを作成するときにリキャプチャの判別をする。よって、コントローラーのcreate
関数に上記のコードの形を入れる。
それで、やりたいことはリキャプチャを正解し尚且つ@user
が有効であることを確認したい。そうすると下記のようになるはず。
def create @user = User.new(user_params) if verify_recaptcha(model: @user) && @user.save redirect_to thanks_path else redirect_to root_path flash[:alert] = @user.errors.full_messages end end
では、実際に試してみよう!
先ほどと同じように名前とメールだけ記入して"Submit"ボタンを押す。そうすると...
今回はちゃんと拒否されました。では、リキャプチャを正解したら...
ちゃんと登録できました!!
言語設定を日本語にする
やり方は簡単。app/views/layouts/application.html.erb
の中のhead
タグ内に下記のを追加するだけ!
<script src='https://www.google.com/recaptcha/api.js?hl=ja'></script>
なお、他の言語に指定したいのならこのhl
の後の値を変えるだけ
言語コードの一覧はこのサイトに→https://developers.google.com/recaptcha/docs/language
まとめ
こんな簡単になったのもオープンソースを作ってくれた方々とサービスを提供してくれているグーグルのおかげである。感謝してます!
もしも、何か質問や感想、次の依頼があるのならコメントまたはツイッターまでDMお願いします!!
Ruby on Rails開発のインターン (Day 10)
こんにちは、皆さん!
今日はまだ何をやるのかよくわからないが、思い当たる限り、メモリ使用量を落とすことかな。
- トピック:
- 疑問:
- 問題:
- 学習した内容:
- 普通の画像を
svg
のようなベクター形式の画像に変えることでメモリ使用量を減らすことができる
- 今後やりたいこと:
- リソース:
- Rails: メモリ使用量を制限してHerokuのR14エラー修正&費用を節約した話(翻訳)
- TuneMyGC - optimal MRI Ruby 2.1+ Garbage Collection tuning
一つ一つの
gem
のメモリ使用量の確認方法
上級者になってくると、メモリの管理もし始める。その時にとても役に立つと個人的には思う。
やり方はシンプルで、以下のジェムを
Gemfile
に追加する。
gem 'derailed_benchmarks', group: :development
で、下記のコマンドを実行する。
$ bundle exec derailed bundle:mem
僕の場合はそんなに多くのメモリを使用しているものはなかったけど、リソースの記事を書いた人は合計で100MBものメモリを節約できたのでGemfile
をあまり軽視しないように(笑)
GC チューニングでガベージコレクションを加速させる
ガベージコレクションをより多くさせる方法があって、メモリにかかわる環境変数を変更することで達成できる。この方法をGC チューニングという。
***必要でないのなら絶対にしないこと!!ガベージコレクションをしている間はアプリケーションを止めるのでより頻繁なガベージコレクションはアプリケーションの使いやすさに悪影響を与えるかも***
一番よくつかわれるのは下記の環境変数の変更。
RUBY_GC_HEAP_GROWTH_FACTOR
デフォルトで1.8の値が与えられているこの変数はヒープのサイズが元の1.8倍になったらガベージコレクションを始めるという意味で設定されている。もうわかった人もいると思うけど、この値を小さくすることで理論的にガベージコレクションを開始するのがより早くなるのだ。
GCチューニングのセットアップ
Gemfile
に追加。
gem 'tunemygc'
それで、bundle install
した後、次のコマンドでトークンを手に入れる。
$ bundle exec tunemygc -r email@yourdomain.com
おそらく次のようにトークンが表示されるはず。
Application registered. Use RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d51 in your environment.
GCチューニングの実行
次のように、自分のトークンと環境変数を入れて、実行スタート!
$ RUBY_GC_TOKEN=08de9e8822c847244b31290cedfc1d51 RUBY_GC_TUNE=200 RUBY_GC_HEAP_GROWTH_FACTOR=1.1 bundle exec rails s
3番目の変数が先ほど出てきたもので、ガベージコレクションをもっと頻繁に実行させる。
そして、この変数の値を自由に変えて他の設定で実行することももちろんできる。
まとめ
だが、残念なことにHerokuでやろうとするとエラーが発生する。これじゃあ、実際にウェブ上にプログラムをアップロードした際にどうなるのかわからない。明日はがんばってここを何とかしようと思う。
ご精読ありがとうございました。では、また次回まで✌
難易度と対象者の設定について
こんにちは、皆さん!
この記事では、僕のブログで紹介するチュートリアルの難易度と対象者の表記の詳細について説明していきます。
難易度について
- 難易度1★☆☆☆☆: (とてもかんたん)移動時間に見ればわかるような内容
- 難易度2★★☆☆☆: (かんたん)記事通りにやれば30分ほどで終わる内容
- 難易度3★★★☆☆: (ふつう)記事通りにやれば1時間ほどで終わる内容
- 難易度4★★★★☆: (むずかしい)自分で使えるくらいに理解もしようとすると3時間から1日はかかる内容
- 難易度5★★★★★: (おに)記事を読んだだけじゃあ、まだちんぷんかんぷんで理解するのに数日かかる場合もある内容
おそらく難易度5のものはなかなかないかと思う...
対象者について
- ド初心者: code>rails new myappが理解できてるレベル
- 初心者: RailsのコマンドでMVCを構築できるレベル
- 中級者: フォームを作り、ユーザーの情報をデータベースに保存できるレベル
- 上級者: APIなども駆使し、ウェブアプリを作れるレベル
- エキスパート: 実務経験豊富でRailsの使い方についてほぼ網羅しているレベル
できれば、ド初心者の方でも楽しめる内容も作りたいなと思っているところ...
まとめ
質問のある方はコメント、ツイッターなどで連絡ください!!
Ruby on Rails開発のインターン (Day 9)
こんにちは、皆さん!
2回目の月曜日がやってきた。いい週末だった。ゆっくり休みをとって後はリラックスしてって感じ。
今週から勤務時間がもとの6時間に戻るから、楽になる。
今日はTwilioで利用したアプリケーションのテストと例の困ったメモリリークの続き。
- トピック:
- 疑問:
- 問題:
- データベースがめちゃくちゃに (解決)
- 学習した内容:
heroku logs -t
でライブのHerokuログが見れる- Memory bloatたるものが存在する
- 今後やりたいこと:
- Twilioについてもっと勉強する
- リソース:
Herokuのデータベースを確認する方法
heroku run
をつければ、ほとんどHeroku上でも使える。こうやって、一つのコマンドの意味と本当に正しい使い方を知ると一層プログラミングが楽しくなるものだ。で、これがどうやって利用できるかというと、データベースがめちゃくちゃになっちゃった僕のデータベースにはいったい何があるのか気になったのでローカルでよくやるRailsのコンソールを以下のようにHerokuで実行した。
heroku run rails c
その後、User.all
でデータベースのUser
の部分にアクセス。それで、空集合が返ってきたのでデータベースに,User
が何もないことを知った。
結局、以下のように以前に取っておいたバックアップでデータベースを復帰させた。(もちろんいくつかのデータは失った)
$ heroku pg:backups restore [id of backups]
僕は同じHerokuアプリで複数の異なるコードをテストしていたので、これからこれにって感じで移動したときにデータベースの内容が混ぜったのが原因。みなさんは絶対に混ぜないでね(笑)
新しいマイグレーションを追加したときなどはちゃんと以下のコマンドでテーブルを更新しよう。
$ heroku run rake db:migrate
Memory Bloat vs Memory Leak
個人的にこのサイト(Debugging memory bloat)の以下の写真が一番2つの違いを理解しやすくしてくれるだろう。
見ての通り、memory bloatでは短い期間にメモリの使用量が急増している。しかし、そのメモリの使用量も最終的にはある一定の範囲内に落ち着く。これはメモリの使用量がどんどん上昇するだけではないことを示している。
一方で、memory leakは少しだが、ずっとメモリの使用量が上昇し続けている。よって、最終的にはメモリを使い切ってしまうのだ。
よって、memory bloat はmemory leakよりも安全であり、必ずしもプログラムをクラッシュさせるとは限らない。しかし、memory leakはそのまま放っておくとあっという間にプログラムをクラッシュさせる要因となりうる!!
まとめ
それと、memory leakだと思っていたものが単なるmemory bloatである可能性が高くなってきた。少し安心した。今のプログラムでそれのせいでクラッシュしない可能性があるからね。
ご精読ありがとうございました。では、また次回まで✌
Ruby on Rails開発のインターン (Day 8)
こんにちは、皆さん!
今日は急用があって、1時間遅刻し、さすがの優しいマネージャーも今日は一言ありましたね...次は気をつけます(笑)
今日の業務内容は引き続きメモリリークとその傍ら小さなバグの修正もって感じかな
- トピック:
- 疑問:
- 問題:
- プログラム内にメモリリークがある可能性がある
- 学習した内容:
- コントローラー内の定数はメモリリークを引き起こす原因になる
- 今後やりたいこと:
- リソース:
class MyController < ApplicationController FOO = [] def index FOO << "haha" end end
ここのFOO
はグローバル変数のように存在し、そのせいでindex
ページから離れてもガベージコレクションが起こらず、FOO
はその分のメモリを取り続ける。よって、メモリリーク発生!!
実際にメモリリークを発生させてみた
class PagesController < ApplicationController FOO = [] def index 1000000.times do FOO << "hello" end @size = FOO.length end end
まあ、わかっての通り、絶対やらないと思うけど、index
ページを訪れるたびにFOO
に1000000の"hello"を追加し、巨大な配列を構築する。
コードが書けたので、実践!!
1回実行した後の結果(ページ内の数字はFOO
の長さ)
その後、5回ページをリフレッシュした結果
もう明らかに赤線で引っ張ったところが上昇していて、これがメモリの使用状況を表している。そして、原因はFOO
配列がどんどん膨張し、同時になにもその存在をどける処理がないためである。
***僕みたいに馬鹿なことをする人はいないと思うけど、代わりになにもメモリを取らないputs
をFOO
に"hello"を追加するところにおいたら、コンピューターがクラッシュして電源を切ることになった。文字をプリントすることは時に危険なのだ(笑)***
まとめ
まずは週末を楽しむぜ!!
ご精読ありがとうございました。では、また次回まで✌