ボクココ

サービス開発を成功させるまでの歩み

AppSignal でのサービス管理

ども、@kimihom です。

f:id:cevid_cpp:20210111110041p:plain

今回、エラー通知やサーバー管理のために AppSignal を導入したので記事としてまとめてみる。日本での事例があまりないようなので、今後増えていけばと思う。

利用サービス選定

まず、メインの目的はバグ管理だった。より見やすく管理しやすいようにすることが必要となり、Heroku にある Addons の中から選ぶことにした。以下のような選択肢があった。最終的には AppSignal, Rollbar, BugSnag の3つが候補となった。

AppSignal 無料プランなし。 有料 $12: 7日間,有料 $35: 30日 3,000,000 リクエスト。 Ruby. Elixir, NodeJS。 何が遅いかを監視できる。 フロントエンドのエラーも見れる。 コアRubyデベロッパの言及はあったが利用事例は少ない。

Rollbar 無料プランあり。 有料$39. 月30,000件、180日間。 Slack, BitBucket, Trello連携。 エラーが起きた原因をフロントエンドの状態から送る。

BugSnag 無料プラン ok。 Ruby ok。 有料: $29, 60日, ユーザー5。 日本での利用報告多い。

Sentry 無料プラン ok。 Ruby ok。 有料: $29 月50,000件まで, 90日 メンバー制限なし。 bitbucket, trello, slack 連携。 backend, frontend。 rails 専用ではない。gemの細かい設定が必要で複雑な感じがする。

RuntimeError 無料プランなし。 $4.99 のみ。10万件まで。 Github にエラーを直接送る。github 前提か。

Raygun Crash Reporting 無料プラン ok。 Ruby ok。 有料: $9, 90日分のデータ保存 15,000件まで。 UI みた感じ複雑そう。 日本での利用報告なし。

Honeybadger 無料プラン ok。 Ruby ok。 有料 全機能 $149。 日本での利用例ほとんどなし。

Airbrake Error Monitoring 無料プランあり。 $59 で 100,000件、30日間。 Bitbucket, Trello 連携。 国内の記事だとかなり古いがバズった模様。

利用の決断

色々とある中で、私がなぜ AppSignal を選んだか。それは Heroku Addons にとって、最適化どうかの判断が大きかった。 また、バグの管理だけでなく、統括的にサービスを監視できるサービスとして、NewRelic などのパフォーマンス系サービスを別で入れる必要もなく、AppSignal だけで管理できる魅力があった。

AppSignal は現在 Ruby. Elixir, NodeJS の3つだけのサポートとなっている。これが他の言語に色々と手をつけてカオスになっている監視アドオンや、Heroku では監視できないような項目をたくさん管理しているような 管理アドオンが多かったりする中、シンプルで、Ruby をメインに管理している点も良かった。

あと、ロゴも個人的に Heroku と似たシンプルさが好みである。無料から始められないデメリットはある。ただ今回はお金の面では問題ではなかったので採用となっている。

AppSignal ではフロントエンド JavaScript も同様に管理できるようになっている。まだベータ版ではあるけど、バックエンドとうまく連携しながらフロントエンドの監視ができるサービスとして便利に使えるだろう。

AppSignal

では AppSignal ではどんなことができるのか。簡単に調べたことだけ報告する。

Errors エラーが起きた場所や利用ユーザー情報、対象箇所の Git へのリンクなど、エラーの調査に必要な情報が綺麗にまとまっているページ。 エラーが起きた時の通知に、どの頻度で通知するかを設定できる。

Change notification frequency - Every occurrence: 毎回エラー出るたびに通知 - First in deploy: デプロイしてまたエラーが起きた時 - First after close: Close にした後またエラーが起きた時 - Never notify: 通知しない

上記はデフォルト設定の選択となる。エラーが起きるたびに通知をしたとしても、そのエラーごとに通知止めたりすることもできる。AppSignal のデフォルトはこの First in deploy で推奨のようである。デプロイしたことが Heroku から AppSignal へ情報を渡すようにすれば、"デプロイ後"っていう管理も AppSignal 側でうまく動作する。

Performance 遅い処理があった場合にリスト表示される。もちろんそれが何秒以上の時に通知出すのかっていう設定が可能だ。私のサービスの場合、多くの API 呼び出しがあるため、この Performance で処理が1秒以上かかることも1日数回起きてしまうため、設定の秒数を伸ばすで対応するしかないか。

Anomaly detection サービス全体として何か問題が起きた時に通知を出す。下記が基本のようだが、それ以外にもいくつか通知を出す条件が存在する。

  • エラーの発生率が20%を超えた時
  • 平均リクエスト処理時間が500ms 以上かかった時
  • Swapが利用され始めた時
  • ディスク利用量が90%超えた時 (Heroku 関係なし)

Inspect サービスを改善するための調査ができるページ。通知などは来ず、自分で定期的に見にいく形となる。

  • Actions リクエスト処理の遅い、影響力の高いものリスト
  • Slow events フレームワーク別 遅い処理リスト (ActiveRecord, ActionController, net_http など)
  • Host usage, Host metrics Heroku ではあまり参考ならないので気にせずでok

Improve SQL と API のアクセスに時間のかかっているものを調べられる。

  • Slow queries 遅いSQL文 影響力高い リスト
  • Slow API requests 遅いAPI 呼び出し。AWS Lambda や Twilio, PAYJP の API

終わりに

AppSignal を使い始めているが、現在は満足して利用ができている。

こういったサービスは、「みんなが使うから俺も使お」っていう判断は危険かもしれない。自分にとって不要な機能が大量にあって複雑なサービスもたくさんあるからである。

Ruby on Rails の監視管理サービスとして、AppSignal を使ってみたレポートでした。

Rails で大量のレコードを並列処理する

ども、@kimihom です。

f:id:cevid_cpp:20200119181256j:plain

今回、大量のレコードを一つずつ処理する実装をしたので、その実装方法をまとめておく。

コードの大枠

以下は全ユーザー(User)に紐づいているレコード(Record) に対して処理をするコードとなっている。

User.all.order("id").each do |u|
  r_all = u.records
  r_all.find_in_batches do |records|
    Parallel.each(records, in_threads: 50) do |r|
      begin
        # 処理
        ActiveRecord::Base.connection_pool.with_connection do
          # ActiveRecord を使った処理
        end
      rescue => e
        puts "err #{e}"
      end
    end
  end
  r_all = nil
end

find_in_batches

find_in_batches を使うことで、u.records を一気に処理するのではなく、デフォルトでは1,000件ごとに分けて処理するようになる。これによって、サーバーのメモリ負荷を軽減することができる。 ドキュメントには

To be yielded each record one by one, use #find_each instead.

と書かれている。一つずつレコードを生成するには、#find_each を使うとのこと。

Parallel

大量のレコードを一つ一つ処理していては、日が暮れてしまう。ということでマルチスレッドでコードを実行するには Parallel という Gem が便利に使える。デフォルト Ruby の提供している Threads は、実際にコードを書いてみると複雑になりがちだ。

ActiveRecord で取ってきたデータをスレッドで each させる。この時指定するパラメータ in_threads の数は、実行する環境によって左右される。例えば外部のデータにアクセスする際や、書くコードの重さなどによって低くしないといけないケースが出てくる。まずは少なめの数から実行してみて、最適な数を見つけていく形になるだろう。

ActiveRecord::Base.connection_pool.with_connection

マルチスレッドで処理をすると、ActiveRecord の DB アクセスがスレッドごとに作られてしまい、コネクションの作成に失敗してしまう。

could not obtain a connection from the pool within 5.000 seconds (waited 5.000 seconds);

DB コネクションを使い回すようにするために、この with_connection のブロック内で ActiveRecord の処理を書く必要がある。

終わりに

普段 Rails でコードを書いているだけだと、このような大量の処理というケースはあまり出くわさないんだけど、大量のデータを一括で更新したいといったような運用のケースで並列処理は必要になってくるだろう。

私自身、Web コードばかり書いていた影響で並列処理を熟知しているわけではないんだけど、最終的に今回書いたコードでうまく大量の処理を実行できたので良かった。

こうした大量の処理をする前には、DB のバックアップは取っておいた方が身のためだね。より安全なバッチ処理についても考えていかなければならないと思った。

Ruby on Rails 5.1 から 5.2 へアップデートログ

ども、@kimihom です。

f:id:cevid_cpp:20190301214729j:plain

今回は Ruby と Ruby on Rails をそれぞれバージョンアップさせたので、そのログを記そうと思う。

アップデート概要

Ruby と Ruby on Rails をそれぞれアップデート。そろそろ Rails 6.0 も出そうなタイミングってこともあって、定期的にアップデートしないとすぐに取り残されちゃうね。

  • Ruby 2.5.3 -> 2.6.1
  • Ruby on Rails 5.1.6 -> 5.2.2

Ruby on Rails 5.2 リリースノート - Rails ガイド

関連 Gem のアップデート

Ruby 自体のアップデートは特に問題なく終わった。Rails を 5.2.2 にあげようとした時 Devise が依存関係で引っかかったので先にアップデート。

  • Devise 4.4.1 -> 4.6.1

これで Rails 5.2 へアップグレードできた。いつも通りアップグレードのコマンドを実行。

bundle exec rails app:update

このコマンドで config 等で変わる差分を見ながらやっていく訳だけども、自分のプロジェクトでカスタマイズした config もあったのでひとまず 差分を見てエディタにコピっておいて、あとで一つずつマージする作業をしていった。そのほうが安全だね。

ソースコードの修正

bootsnap っていうアプリ起動を効率化させる Gem を追記。

【アプリ起動時間を50%削減】Rails5.2からデフォルトGemに採用されたBootsnapを検証した · カウル Tech Blog

belongs_to がデフォルトで required: true になったようだ。has_many な関係のモデルがあった時、親要素を指定する必要があるのがデフォルトになった様子。一部、モデルの親子関係で 親_id に nil を許容するものがあったので、そこの部分を修正。

# belongs_to :user
belongs_to :user, optional: true

SQLite を使っていると起動する度に警告が出てきたので、Arel を追記

eager_load(:user).order(Arel.sql("動的な Order 指定")) 

Arel.sqlを付けるだけじゃダメ!? Railsで"Dangerous query method …”の警告が出たときの対応方法 - Qiita

安易に Arel つけて解決するんじゃねーぞという記事。自分の場合は完全にシステム側で文字の出し分けするだけだったので大丈夫だった。ユーザーの投稿内容を Arel 使ったりしたらそりゃあやばいよね。

ActiveStorage は使わない。

# config/application.rb 
+#require "active_storage/engine"
# config/environments/production.rb 
+  #config.active_storage.service = :local

Uglifier がなんかバグったので、ググって解決。

-  config.assets.js_compressor = :uglifier
+  config.assets.js_compressor = Uglifier.new(harmony: true)

form_with がデフォルトで remote: true にならなくなった。ソースコードを読むと、どうやら form_with_generates_remote_forms 設定を読み込んでいるようだ。config/initializers/new_framework_defaults.rb に追記。

+# Make `form_with` generate non-remote forms.
+Rails.application.config.action_view.form_with_generates_remote_forms = true

factory_bot もアップデートしたら、値の指定方法が {} でくくらないといけなくなっていたので対応。

 FactoryBot.define do
   factory :contact do
-    friendly_number "080-5352-3523"
-    name "Test Taro"
+    friendly_number {"080-5352-3523"}
+    name {"Test Taro"}
   end
 end

途中で気づいたこと

先ほど紹介したリリースノートを見ると、Rails 5.2 からRedis Cache Storeが組み込まれるようになったようだ。うちではすでに Redis をキャッシュストアと利用していたから、それがデフォルトで使えるようになった様子。

bin/yarn ってコマンドが出てきて、Heroku のデプロイが簡単になったかなと思ったらそういうわけではなかった。引き続き buildpack に nodejs を追加する必要があった。その方法に関しては既に下記に記してある。

www.bokukoko.info

終わりに

Rails 4 -> 5 のような大きいアップデートとは違うので、ちょっとした修正で無事アップグレードを終えることができた。ちゃんとテストコードを書いて、気になるところは手動でテストもしっかりやったから安心である。

新しいプロジェクトだったら Action Cable とか Active Storage とか使うだろうけど、やっぱ前からあるプロジェクトだとわざわざ同じ機能を作り直したくはないよね。これらの技術に関しても追従できるように、定期的にちょっとしたサンプル Rails プロジェクトを作って遊んでみたいと思う。

今回のアップデートで Ruby の高速化・省メモリや ActiveRecord の高速化などに期待したいところだ。

Rails コントローラ内の define_method 活用例

ども、@kimihom です。

今日はちょっとした Rails の小ネタ。Ruby にはご存知の通りメタプログラミングというトリッキーな開発方法があって、これが良いだ悪いだの議論が絶えないわけだけども、ちょっとしたことで便利に使える時がある。

今回紹介する define_method は、コードでメソッドを定義できる手法だ。以下のような感じで class 内でメソッド定義できる。

class MyClass

  define_method(:say_hello) do
    puts "hello world."
  end

end

MyClass.new.say_hello #=> hello world.

さてこの define_method だけど、 Rails でもそれなりに便利に使える時があるので活用例をご紹介する。

同じ(似た)実行内容のメソッドを一括定義

例えば Rails でランディングページを作っていた場合、大抵は View の表示だけ変わる、至ってシンプルなコントローラができるはずだ。しかし、その中で例えば “og:title などのメタタグなどは layout 内の @og-title をセットしないといけないので、コントローラ内でそれを定義したい” といったことが出てきたとしよう。今回の記事ではこういうニーズが出てきたっていうことにしておいてほしい。

そん時に define_method を使うとこんな感じでかける。

class LandingPagesController < ApplicationController

  [:welcome, :feature, :terms, :privacy].each do |m|
    define_method(m) do
      @og_title = t("landing.#{m}.og_title")
      # ...
    end
  end

end

このサンプルでの"before_action" に書けばよくね?のツッコミはナシでお願いしたい。 わお、これで View に @og_title を渡すことができた!しかもバッチリとアクション別の文言に変えることができている。

このくらいシンプルな共通処理だったら同じようなメソッド定義がつらつらと書かれているよりも、スッキリして見やすくなるかと思う。こんな感じでちょっとした手間を省く上でも、define_method をチョロっと活用してみることからお薦めしたい。

メタプログラミングを学ぶ

Ruby のメタプログラミングといえば、以下の本が有名だ。当然、私も本書を読んで Ruby の魔力に惹かれたものである。

メタプログラミングRuby 第2版

メタプログラミングRuby 第2版

この本を読んだ途端、きっとmethod_missing などの Ruby の魔力を使いたくなるだろう。「オレ、Ruby 使いこなしてるぜ」感が出てくるからだ。しかし、一旦落ち着いてほしい。メタプログラミングを乱用すると、メソッド定義がどうなっているのか、誰も理解することのできない状態 を生みかねない。

Ruby にはインスタンスメソッド一覧を表示してくれる methods という大変便利なメソッドが用意されている。メタプログラミングを乱用すると、methods などの出力にそれらが出てこなくなり、後でどうやって使えば良いのか、そもそもそのメソッドは存在するのかを確認することが困難になる。

なので、メタプログラミングの乱用は自分の趣味の範囲で実験で使ってみて、実際のプロダクションのコードでもちょっとだけ入れてみる程度から始めてみよう。いきなり Rails の Model でメタプログラミングを多用すると確実に痛い目を見ることになる。ここまで言い切れるのはなぜかというと、実際の経験者がここにいるからである。

終わりに

今回は Ruby のメタプログラミングの最初のとっかかりだけ紹介した。

「大いなる力には大いなる責任が伴う」とはよく言ったもので、メタプログラミングを活用すれば一部のコード量が劇的に下げられたり、今まで実現不可能だったほどの柔軟性のあるコードを実現できる。メタプログラミングのトレードオフを理解した上で、確実安全なプログラムを書いていこう。

そしたら、一段階上の Ruby プログラマになることができよう。

ライブラリの利用を減らしていくことの重要性

ども、@kimihom です。

最近の運用フェーズでの開発で意識していることの一つ、「Gem ライブラリの利用を減らす」ことについて思うことを書く。 記事の内容は Ruby 周りに最適化されているけど、他の言語でも同様のことが言えると思うので適宜置き換えて読んでいただきたい。

初期フェーズによるライブラリの利用

新サービスを作る段階では、「いかに早く機能を作り、検証しながら機能を作り直していくか」が大事になってくる。その時にいちいち機能をゼロから自分で作っているようでは時間の無駄だ。第三者が作ってくれた、ライセンス的に問題ないライブラリをシステムに組み込み、作っては壊しての繰り返しで機能検証していくことが大事になってくる。サービス開発初期でライブラリを使う理由は「機能を素早く実現するため」にある。だからちょっとした機能でも Gem で入れまくることになる。

これは全く問題ない。むしろ推奨されることだと思う。開発スピードを強みすることが第三者(特に大企業)と差別化する上で重要になる。小規模チームでの小回りの速さは確実に武器になる。

プロダクトマーケットフィット後のプロダクト

しばらくして見事サービスがプロダクトマーケットフィットの段階になれば、今度はサービスを集中して磨き上げることが大事になってくる。そこではより確実に素早くソースコードを改善していくことが求められる。

わけがわからんが、なんとなく動いている。” そんな状態を少しずつ無くしていこう。例えば以下のような時に役立つ。

サービスの最適化に役立つ

基本的にライブラリは、あらゆる利用を想定した作りになっているため、カスタマイズ項目がたくさんある。そしてそのぶん、ソースコードは Fat になり複雑になる。ライブラリの機能がさほど複雑なロジックを必要としない場合には、自前で実装することで無駄な処理を実行することがなくなる。より速く効率的な実行速度を実現でき、今後の独自の拡張性を見込める機能を実現することができる。

独自の拡張性は、今後のサービスの差別化に役立つ。プロダクトマーケットフィットの段階以降は、サービスに最適化された機能を多く増やしていくことが大事になってくる。競合が出て来ても、簡単には真似できないようなサービスをコツコツ実現していくのだ。

まずはマイナー系のライブラリから最適化することをお勧めする。そのようなライブラリは基本的に自前でも十分実装できるからマイナーなままであるパターンが多いからだ。 ちょっとした実装で実現できそうな Gem ならわざわざ使わずに自分で作った方が適したものになる可能性が高い。

反対に視点を変えるとライブラリを使い続けることで、Gem 自体がコミュニティの力でどんどん進化していくという側面がある。てことでライブラリを使用する/しないの見極めが必要だが、まずはほとんどアップデートの無いライブラリから削除することを検討するようにしている。

起動時の使用メモリを省略できる

起動時に大量のライブラリを読み込むと、そのぶん大量のメモリを必要としてしまい、無駄にサーバーリソースを消耗することになる。ライブラリを減らさずに増やし続けてしまうと、それがいつか限界を迎えて Out of Memory のエラーが発生することがある。

使用メモリを把握するには、Derailed Benchmarks などの Gem をインストールして調査してみよう。あまり使っていない Gem が案外無駄にメモリを消耗していたりする。そういうのは優先的に外していって自前で実装していくようにしよう。

GitHub - schneems/derailed_benchmarks: Go faster, off the Rails - Benchmarks for your whole Rails app

Gem のほとんどの機能は使わないけど、どうしてもその Gem を使わないといけないような場合、 require するものを最小限にとどめることで対応が可能だ。例えば、 rack-cors を入れる時には require で読み込むものを限定している。以下ような書き方で、ライブラリの利用を最小限にとどめることができる。

gem 'rack-cors', :require => 'rack/cors'

こうしてより多くのアクセスを少ないサーバーリソースで運営することもできるようになる。そして何より、自分の理解している範囲でコードが動いているという安心感。問題が起きても自力でデバッグすることができるだろう。

独自実装でオープンソース公開の機運ができる

独自に実装した何かが第三者に公開できるようなものが出てくる場合がある。その時はコミュニティに貢献するチャンスだ。うまくライブラリ化して逆に公開しよう。そしてうまく実装してマーケティングもうまくいけばスター数がつくかもしれない。そのようなライブラリを持つことを増やすことがエンジニアの価値だと考えている方にとってはまさに理想的なオープンソースの公開方法ではないだろうか。

オープンソースで公開すると、どうしてもカスタマイズでオプションをたくさん作るようなことが必要になるかもしれないが、その方針を決めて作るのもコミッタであるあなた次第だ。そんな自由なオープンソース活動を実現することができる。

終わりに

改めて注意書きするけど、最初からライブラリの利用を減らすべきとは書いてはいない。あくまでプロダクトマーケットフィットを達成した後のサービスの最適化の段階でやっていくべきだ。だからサービス初期のエンジニアと、サービス成熟期のエンジニアの求められる役割は違う。

ライブラリの利用を減らして、独自の価値を持つサービスがどんどん増えていくといいなと思っている。

Ruby のバージョンを上げてGuard が動かなくなった時の対応

ども、@kimihom です。

Ruby で開発しているのであれば常に新しいバージョンで開発を続けたいもの。その中で今回は guard が動かなくなったのでその対応メモ。

  • Ruby 2.3.3
  • guard 2.14.1

エラー内容

こんなエラーが出て開発できなかった。

$ bundle exec guard

22:34:15 - INFO - Run all
22:34:15 - INFO - Running all specs
/Users/user/.rbenv/versions/2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- bundler (LoadError)
    from /Users/user/.rbenv/versions/2.3.3/lib/ruby/site_ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
    from /Users/user/dev/rails/rails4.2/myapp/bin/spring:8:in `<top (required)>'
    from bin/rspec:3:in `load'
    from bin/rspec:3:in `<main>'
22:34:15 - ERROR - Failed: "bin/rspec -f progress -r /Users/user/dev/rails/rails4.2/myapp/vendor/bundle/ruby/2.3.0/gems/guard-rspec-4.6.4/lib/guard/rspec_formatter.rb -f Guard::RSpecFormatter --failure-exit-code 2  spec" (exit code: 1)

まぁ Bundler 周りが怪しいよね、ってのはわかる。

対応ログ

Guardfile

- guard :rspec, cmd: "bundle exec rspec" do
+ guard :rspec, cmd: "bin/rspec" do

...

end

これで spring 経由で rspec が走るとのこと。そしたらこんなエラーが次に出た。

22:37:25 - INFO - Run all
22:37:25 - INFO - Running all specs
There is a version mismatch between the spring client and the server.
You should restart the server and make sure to use the same version.

CLIENT: 1.6.1, SERVER: 2.0.1

どうやら spring のバージョンが古いみたいなのでアップデート。

$ bundle update spring

そして…

$ bundle exec guard

22:38:43 - INFO - Run all
22:38:43 - INFO - Running all specs
Running via Spring preloader in process 28169
...............................................................................................................................................................................................................................

Finished in 13.06 seconds (files took 1.62 seconds to load)
XXX examples, 0 failures

よっしゃ!動いた。

得られた教訓

Gem はテストツールも常に最新に更新しておかないとね。それにしても、 bundler、こいつは優秀だな。

独学での Web プログラミング学習まとめ

ども、@kimihom です。

自分で何かサービスを出したいという方は多いかと思う。今回はそんな方へ最低限知らなければならないリストを上げようと思う。ターゲットとしては Web アプリケーションということにしたい。

UNIX コマンド

最初は黒い画面に慣れる必要がある。いつまでも Mac の Finder でダブルクリックしてるようではプログラミングの効率が悪すぎる。UNIX に関してひとまず知らなきゃいけないのはディレクトリ/ファイル操作閲覧やエディタ(Vim or Emacs)、各種プログラミングコードの実行といった基本的なことで十分だ。次第にリダイレクトやパイプとかを知っていくと、より効率的な操作ができるようになる。最初から一気にマスターする必要はないが、シェルスクリプトとかも書けるとさらに良い。興味の度合いに応じて UNIX を学んでみよう。

これらはとても基本となる操作であり、UNIXの基礎を知らないと、これから学ぶことに対してことごとく UNIX コマンドから調べなきゃいけなくなったりと地味にきつく挫折する原因にもなりうるので最初にがっつりやってみよう。

例えば以下のような本。読んでないけどおそらく正しいこと書いてると思う。

MacOS XユーザのためのUNIX入門―ターミナルから覗くUNIXの世界

Ruby

ひとまず Web アプリケーションなら Ruby でいいだろう。なぜならあらゆるドキュメントが整備されていて、いろいろな問題にあたってもネットにたくさん情報があり、そして何より書いていて楽しい言語だからだ。複雑でぐちゃぐちゃになるような言語(何とは言わないが)を使うと、プログラミング自体がつまらないものになってしまう。考えてみてほしい。これからあなたはプログラミングをすることになるが、そのコードと四六時中付き合わないといけない。 楽しく学べる Ruby がいいと私は思う。(ここら辺はいろいろと論争を生むところだからあまり突っ込みはしないでいただければ幸いだ)

Ruby でターミナル上で動く簡単なサンプルプログラムを書けるようになろう。ruby test.rb とかを実行して色々と学んでいくのだ。Ruby と UNIX は当然のことながら深く結びついているので、UNIX を深く知れば知るほど、Ruby とのつながりを感じて感動することもある。

これに関しては 2冊くらい読んでおいたほうがいいと思う。王道がこの2冊。

たのしいRuby 第5版

プログラミングRuby 1.9 −言語編−

後者は Ruby 1.9 とちょっと古いんだけど、Ruby 2.x でも十分動くと思う。ちょっと古くてもお勧めしたい本だ。

HTTP

HTTP プロトコルはあらかじめ知っておいてたほうがいい。これを勉強しないでいると、今後の Rails の勉強の時に意味わからないことがたくさん出てくる。本当に基本だけでいいので、さらっとだけでも本を読んでおくといいだろう。

特に GET/POST などの HTTP メソッド、200, 400 などの レスポンスコード、Cookie、セッション などは知っておいたほうがいい。これはWeb標準なので今後絶対に知らないといけない知識になってくる。

HTTPの教科書

HTML/CSS/JavaScript

Web ならこの基本を押さえておかないといけない。この3つに関してはいろいろな本が出回っているから、自分にあったのを読めばいいと思う。最近は HTML5 とか CSS3とかもでてきて情報が錯乱しつつあるので、ググりながら実力をつけるってのがちょっと難しくなってきてる感じもする。

こういうのは必要な時に必要なコードが書ければいいと思うので、辞典っぽいのを買って一通りさらっと読んで気になるのがあればコード書いてみてブラウザで確認するみたいなことをすればいいんじゃないかな。

例えば好きなサイトの完全コピーを HTML/CSS/JavaScript で作ってみよう。そこで「これどうやってやるんだろう?」ってのが出てくることかと思う。そんな時は Chrome Console を開いて、HTML要素やCSSを見て理解できるようになろう。

詳解HTML&CSS&JavaScript辞典 第6版

Web開発でよく使う、特に使えるChromeデベロッパー・ツールの機能 - Build Insider

jQuery, jQuery プラグイン

今でも大活躍の jQuery。初学者は jQuery を知ることは今でも有効だと思う。 DOM 操作によってページの要素が動的に切りけるような基本を身につけることが重要だ。最初は汚いコードでも構わないので、jQuery で色々と遊べるようになるとサービス作成の幅が広がると思う。また、それにあわせて ajax も早いうちに学んでおくと、なお良い。

jQuery プラグインでさらに自分の欲しい機能を早く実現できるような仕組みも学んでみよう。DOM操作ができれば、そのjQueryプラグインをさらに自分好みにカスタマイズできるようにもなるだろう。大事なのはとにかく自分で書いて JavaScript を好きになること。それこそがさらなる勉強の意欲と成長を生むからね。

jQuery レッスンブック jQuery2.X/1.X対応

データベース

Web アプリケーションを作るなら、データベースの知識は必須だ。今でも現役バリバリのリレーショナルデータベースを理解しよう。テーブル設計を正しく行い、SQL が発行できるようにならないといけない。

これも勉強してみればパズルみたいなもので案外面白いものだ。ビビらずに軽い気持ちでチャレンジしてみてほしい。

【改訂第3版】 SQLポケットリファレンス (POCKET REFERENCE)

まずは最低限の SQL さえかければいいんじゃないかな。今後ゼロからがっつり Web アプリケーションを作るならテーブル設計も正しくできるようにならないといけない。

Git, Github

Git はソースコードを管理するためのバージョン管理システムだ。あなたが書いたコードを前の状態に戻したかったり、他のメンバーと開発したコードを組み合わせたり、そんな作業を Git はしてくれる。これも絶対に学んでおかないといけない技術になってきている。

最初のうちはそこまで詳しく知る必要はない。add, commit, branch, checkout, push, fetch, merge, log, diff くらいで最初は十分だろう。

Gitが、おもしろいほどわかる基本の使い方33

この時点で自分の Github アカウントも作っておこう。

Ruby on Rails

ついにだ。やっとここで Ruby on Rails を学習できるようになる。ここまでの基礎がないと、Rails を学んでも自分の作りたいアプリは作ることはできない。決してここまでの勉強は無駄ではないので安心してほしい。

Ruby on Rails は今までの総まとめみたいなものだ。今まで学んだ知識をうまく組み合わせてくれるのが Ruby on Rails だと思ってもいいかもしれない。ここでも何冊か本を読んでしっかりとマスターしたいところだ。

RailsによるアジャイルWebアプリケーション開発 第4版

パーフェクト Ruby on Rails

Heroku

作ったアプリを公開するときにはサーバーが必要だ。 Heroku。この神がかったサービスをぜひ使おう。あなたの書いた Ruby on Rails コードが数行のコマンドを叩くだけで世界中に公開できる。こんな素晴らしいことが他にあろうか。

ここまでくると Qiita とかでたくさん記事が出回っているので、それらを読んでデプロイしてみよう。なぁに、ここまで勉強してきたあなたなら難しいことは何もない。一番簡単な記事はこれかな。

railsアプリを5分でherokuにデプロイする - Qiita

独自ドメインとか SSL とかそういうのもみんなネット上に情報はたくさんある。問題なくできるはずだ。

終わりに

ここまで学べば、ある程度自分の力で Web アプリケーションが作れるようになるだろう。ここから先の技術は、自分でどんどん作って壁にぶち当たり、その壁を突破していくことで体得し、成長することができる。

そのぶち当たった壁はあなたのブログに書き残していってほしい。あなたの貴重な時間の記録を残すという意味で重要だ。その情報が次なるプログラマーを助けるヒントになるだろう。

本気で Web アプリケーションを作りたいあなたなら、きっとここまで勉強してくれることだろう。ぜひこのレベルにまで来てほしい。そしていつかたくさんの人に使われる Web アプリケーションをあなたの手で作り上げていただきたい。その日が来るのを私は心待ちにしている。

Ruby の メソッドについての解釈 (中級者向け)

本ブログはプログラミング中級者向けのトピックを扱う。

今回はRuby のメソッドについて。インスタンスメソッドやクラスメソッドなどがあるが、プログラミング始めの段階では、基本的にクラスからインスタンス化したのから呼べるのがインスタンスメソッド、クラスから直接呼べるのがクラスメソッド、みたいな区切りで理解している方が多いかと思う。以下のような感じに。

a = A.new
a.instance_method
A.class_method

今回は、クラスメソッドの詳細とインスタンスメソッドの関係について深掘りしてみよう。

メソッドの探索

さて、先ほどのサンプルで、a.instance_methodとしたが、このinstance_methodメソッドはRubyはどのように探してきているのか。例えばこんなコードの時。

class A
  def instance_method
    puts "from a."
  end
end

module B
  def instance_method
    puts "from b."
  end
end

class C < A
  include B

  def instance_method
    puts "from c."
  end
end

c = C.new
c.instance_method # どうなる?

これを見た時、パッと from cと答えられたら正解だ。まずは自分のクラスのメソッドから探索が始まる。もしC内になかった場合は次にモジュールBの中を探しに行く。そこにもなかったら親クラスのAを探しに行く。

これは直感的にわかることだろう。次に行く。

特異クラス

まずはシンプルな以下のコードを見ていただきたい。

class A
  def a
    puts "a called."
  end
  
  def self.b
    puts "b called."
  end
end

obj = A.new

def obj.c
  puts "c called."
end

obj.a 
A.b
obj.c
a called.
b called.
c called.

意図した結果になったことだろう。 aとbについては特筆すべき点はない。cについて見ていただきたい。RubyはCのように、 作ったオブジェクトからしか呼べないメソッドを定義する ことができる。これが特異メソッドと呼ばれる。他のAのインスタンス変数からこのcを呼ぶことはできない。

ここで疑問が起こる。 先ほどの メソッドの探索 で学んだメソッド探索において、このcメソッドはどこから見つけ出しているのか? 自分のクラスにもいないし、モジュールにもいないし、親クラスでもない。だけれども cメソッドを呼ぶことがでいる。

これが隠れている 特異クラス というものの存在だ。obj インスタンスに特異クラスというそのオブジェクトにしかない隠れたクラスを作り、そこにcメソッドを定義しているのである。これがメソッドの探索の最優先で呼ばれる。

クラスメソッドの正体

Ruby初心者の方は、クラスメソッドは A.class_method というような形でクラスから直接メソッドを呼べるもの、という認識だと思う。ただこれもRuby的には オブジェクトからメソッドを呼び出している 、というに過ぎない。ここがRubyにおいて重要な概念なんだけど、 クラスもオブジェクトである ということが言えるのだ。これをぱっとわかる人はまずいないと思う。ということでサンプル。

class A
end

puts A.class
p A.methods

a = A.new
puts A.new.class
p a.methods
Class
[:allocate, :new, :superclass, :freeze.....]

A
[:nil?, :===, :=~, :!~, :eql?, :hash, :<=>, :class, .....]

ということだ。確かにAもオブジェクトっぽく振舞っていることがわかるだろう。AクラスはClassクラスのオブジェクトであることがわかる。

そしてここからが今回の感動ポイント。 Ruby の美しさを知る場面だ。

先ほどのクラスメソッドと特異メソッドの定義をまた挙げる。

class A  
  def self.b # def A.b とも書ける
    puts "b called."
  end
end

obj = A.new

def obj.c
  puts "c called."
end

def obj.cobjに対しての特異クラスであった。ということは、 この def self.b というのは、 Aクラスに対しての特異メソッドになるのだ!だからこそ、A.bと呼ぶことができるのである。

今まで何も考えずに、 def adef self.b のように使い分けていたRubyエンジニアにはこのような違いがあることを知っていただきたい。

Ruby の特異クラス関連のイディオム

さてこれがわかえれば、Ruby のオープンソースによく出てくる以下のような表現も理解することができるようになる。

class << B はBの特異クラスを開いた状態にしてくれる。

obj = A.new

class << obj
  def c
  puts "c called."
  end
end

def obj.c
  puts "c called."
end

この2つの書き方は全く同じだ。特異クラス内で、cを定義するのが def cの書き方である。もう一つサンプル。

class A
  def self.a
    puts "a called."
  end
  
  class << A
    def a
      puts "a called."
    end
  end
end

これも同様で、self.aと同じ書き方になる。

Object#extend も理解できる。 a.extend(b)aの特異クラスとしてbを追加するメソッド だ。

  • インスタンスオブジェクトの場合
module D
  def d
    puts "from d."
  end
end

class A
end

a = A.new
a.extend(D)
a.d # => "from d."
  • クラスオブジェクトの場合
module B
  def b
    puts "from b."
  end
end
class A
  A.extend B # extend B と書いてもok.
end

A.b #=> "from b."

このことからもわかるように、 インスタンスメソッドもクラスメソッドも結局はオブジェクトから呼び出すメソッド 。そんな認識を持っていただけたら今回はいいのではないだろうか。

Ruby の美しさを感じることができたら何よりである。

ブラックリストワードをフィルタリングする Obscenity

今日は便利なGemを紹介。

掲示板システムをアプリとかで運用していると、NGワード連発な方々がどうしても出てきてしまう。そのため彼らの投稿は拒否したり特殊文字で置き換えたりする必要がある。

そんな時に便利な Gem が tjackiw/obscenity · GitHubだ。

Gemfile に obscenity を追加し、bundle install後、以下を追加。

$ cat config/initializers/obscenity.rb

Obscenity.configure do |config|
  config.blacklist   = "config/blacklist.yml"
  config.replacement = :stars
end

ブラックリストを記載したymlファイルを置けば完了だ。

そしたら以下のようにチェックできる基本メソッドがある。

Obscenity.profane?("simple text")
=> false

Obscenity.profane?("text with shit")
=> true

バリデータも ActiveRecord, Mongoid それぞれサポートしている。

CGMを運用しているRailsアプリなら是非導入して安全なサイト運営を心がけたいところだ。ちなみに自分のブラックリスト一覧を置いてみてるので、参考にしていただきたい。

black lists in bss

追記

Obscenity のデフォルトのままだと、スペースに囲まれた単語のblacklistのみがになるため、日本語のようにスペース区切りが無い場合はに変換されない問題がある。そこはソースのbase.rb にある \b を消去しなければならない。

最近の興味

ところで、WordPressホスティングは割と面倒だけど、最近はクラウドで簡単にやってくれるようなサービスが出てきているみたい。設置ってだけで何万とか取ってる会社あるし、こういうので自分でさくっと立てられるようになれれば節約になるんじゃないかな。

Effective Ruby を読んで

以前から気になっていた "Effective Ruby" を読んだ。 Effective シリーズは中級〜上級向けプログラマーの読むべき本として親しまれている。

個人的にもっとも得意な言語はRubyだったので、このシリーズが出るのを楽しみにしていた("得意な"と変換しようとしたら"特異な"と変換されるくらいには使用している)。

中身のネタバレはもったいないので、この本を通じて自分が今まで見落としていた点を挙げてみようと思う。

nil 時の対応

array = hoge()
array.split('/')[1] 

NoMethodError: undefined method hoge for nil:NilClassRubyプログラマーなら何度も遭遇するであろうこのエラー。配列でnilっぽくしたい時は空の配列を用意してあげたいところだが、その変数にnilが返ってきてしまうとこの問題に出くわしてしまう。

例えばある変数があって、それに array.split('/')とさせるとしよう。ここでarray変数がnilなのか、そもそも配列なのか、よくわからない。ちゃんとコードを戻って読まないといけない。

この問題を解決する素晴らしい手段が本書には書かれている。一体何でしょう?

なんでもかんでもHash使いたい

@hash = {}

@hash[:hoge] = hoge
@hash[:fuga] = fuga
...

これはまさしく自分だった。Hashを使えばコードを簡潔に書くことができる。特にRailsアプリなどではViewに渡すインスタンス変数をHashに変換し、View側でそのHashを取得するような処理を書くことは多いのではないだろうか。

しかし、Hashはなんでもかんでもキーとして詰め込むことができるため、このキーが一体どの部分で入れられたものなのか、コードを読み直す必要が出てくる。また、存在しないキーが出てきてもnilを返すだけで、例外を投げないため間違っているかどうかの判断がつかない。

ではどうするのがEffectiveなのか。一体何でしょう?

reduce をマスターせよ

本書で唯一 特定のメソッドに対して複数ページを割いて解説しているメソッドがある。それが reduceだ。これをわかりやすいサンプルとともに、ただ合計値を出すだけでない他のreduceの使い方を示してくれている。これにより、今まで無駄に書いていたあの処理が実はreduceで書き換えられるということを理解できるだろう。

終わりに

ある程度Rubyに慣れ親しんだ方なら、 何かしらのGemを入れ、気になった時はそのGemのソースコードを読む機会が何度かあったと思う。基本的にはそこから学ぶことが大変多いのだけども、この本はそれらの知識・ノウハウをよくまとめられているという印象を受けた。

対象としてはパーフェクトRubyとか読んだ後なら普通に読めると思うけど、Effective Ruby の場合はそれなりにRubyコードを実際に書いて運用した経験をした後によむと、「あ、こういう書き方ができるのか!」という発見があって楽しく読めると思う。

Spree 最新版の日本語国際化ファイルを更新した

さて、前回の記事で CMS とかランディングページは Jekyll で作成できるようになった。次はECサイトもパパッと作れるようになっちゃう。

ECサイトOSS

ECサイトを自作するのに、EC-CUBE や Spree を利用することが多いかと思う。

www.ec-cube.net

spreecommerce.com

まぁ日本じゃ圧倒的にEC-CUBEの利用例が多いんだけど、PHPで書かれているってので即刻アウト。日本製ってのも開発具合に疑問を感じる。 Spree ならHerokuで動かせるし、海外のコミュニティによって激しく改良が続けられている。なんとRails で検索した時にGithubスター数でトップ5だ!!

世界的には Spree の方が標準だけど、 日本じゃEC-CUBE製のECサイトばっかだからここで差別化が狙えるんじゃないか。

Spree のインストール

今回は Spree の 3.0-stable バージョンを利用してECサイトの枠組みだけ軽く作ってみた。導入編。

rails new myec

cd myec

gem install spree_cmd

rbenv rehash

spree install -A

echo "gem 'spree_i18n', :github => 'spree/spree_i18n', branch: '3-0-stable'" >> Gemfile

bundle install

bundle exec rails g spree_i18n:install

vim config/application.rb
//  config.i18n.default_locale = :ja

be rails s

# localhost:3000/admin
# id:   spree@example.com
# pass:   spree123

とりあえずこれでなんとか動くんだけど、 admin 入ってすぐ分かるのは、

全てが i18n 対応してねー!

っていうこと。これ自分だけが使っていくならいいけど、今後誰かに運用お願いしたいときとか致命的すぎる。しゃーないから 3時間くらいかけて全部足りない分翻訳しましたよ。。

英語間違っている部分結構あるかと思うので、参考程度で使いたい方は使ってください。翻訳に自信がないので 本家にプルリクエストは送ってないです。

spree/config/locale/ja.yml

今後

Webpay は正式に Spree のサポートする gem を公開してくれているので、これを使ってみたい。

そして最終的には Heroku デプロイし、 SSL を通して独自ドメインで 試験的なECサイトを運営してみようと思う。そこで得られた知見などは適宜ブログに残していこうと思う。

間違いなく Jekyll より難しい。w

2,3 日でマスターできるようなものじゃないのでじっくり腰を据えてやっていこう。

Jekyll と Github Pages で CMS を構築する

http://jekyllrb.com/img/logo-2x.png

Jekyll の特徴

近頃、 Jekyll という静的サイトジェネレータを利用し始めている。言わばWordPressのようなCMSのような使い方が可能だが、それらとは全く違う点が データベースやプログラムを利用しない というところがある。記事とかは全て静的サイトとして作成するのでDBアクセスが発生しない。

これにより圧倒的なサイトアクセスのスピードと、DBを用意しないことによる運用コスト削減が可能だ。また Ruby で機能拡張もできるし、プラグインが豊富に提供されているので気軽に利用することができる。

さらに、Github Pages のサポートがあるので、 Githubレポジトリと記事を丸々プッシュすることで、それだけでブログが出来上がる! もちろんGithub Pages はカスタムドメインも対応しているので、独自ドメインCMSを構築することが可能だ。

記事作成などは自前で管理ページを持つ必要がない。それらは Web の Github 上で編集し、変更を反映すれば記事が動的に追加される。画像アップロードは Github Issue を使えばアップローダーとして利用することが可能だ。記事を書く人はGithubアカウントを作成してもらい、そのリポジトリにコミッターとして招待すればよい。

ここまで書いておいて恐縮だが、私はWordPressを使ったことがない。 PHPという時点でもう拒絶反応を起こす。代替を探していたら素晴らしいものに出会うことがた。そのためWPとの比較などはこのくらいしかできないし、WPの利点をそこまで理解していないことを承知していただきたい。

Jekyll の学習

以下のサイトだけで大枠は理解できる。大変参考になった。

Jekyllいつやるの?ジキやルの?今でしょ!

Jekyll テンプレート集

Jekyll Themes

Jekyll の使い方を学べば、これらテンプレートをたやすく利用することができるだろう。 Github 上で Fork し、 _config.xml を自分のブログ用に書き換えるだけで良い。

Github Pages での問題点

Github Pages では、 https://{account}.github.io/{repository} というURL構成になっている。Jekyll ではデフォルトではルートのindex.htmlがある想定なので、ローカルではうまくパスやURLが通っていても、Github Pages に上げたらパスが通っていないという現象に遭遇する。

そのため、ローカルでも本番でもどちらでも動くように設定を変える必要がある。

_config.yml の設定

_config.yml に baseurl をセットする。

baseurl: "/myblog"

ローカルではmyblogのようなサブディレクトリがなく、ルートで実行するので、以下のように指定する。

jekyll serve --baseurl ''

そして読み込むJavaScriptCSS、リンクなどを以下のように書き直せば良い。

<link rel="stylesheet" type="text/css" href="{{ site.baseurl }}/css/main.css">
<script type="text/javascript" src='{{ site.baseurl }}/js/jquery.min.js'></script>

~~~

<a href='{{ site.baseurl }}{{post.url}}'><h1 class='post-title'>{{post.title}}</h1></a>

SPIKE API にアクセスする gem を作りました

最近出たSPIKE APIRubyでアクセスするgemを作りました。SPIKE で決済APIの機能を提供してくれたお礼とでも言いましょうか。

Github にソースを上げたので、ご自由にお使いください。今後 SPIKE API に機能追加されていった際のプルリクエスト等大歓迎です。あ、ちなみに Metaps 非公式のgemですのでご注意を。

この gem はコネクシィで利用されています。以下の機能を利用できます。

  • 課金の実行
  • 課金の払い戻し
  • 課金情報の取得
  • 全ての課金情報の取得

ちなみに課金実行の際に必要なカードトークンはSPIKE Checkout で取ってきたものとなります。

アプリエンジニアがインフラに挑戦その4

どーも。

ホストOS側のChef環境がそろったので、いよいよゲストOS(Virtual Machine) に Rails 環境をインストールしていきます。今回は一つのゲストOS にRailsとMongoDB, Nginx 全て入れていきます。

今回のChef Recipes は Github においてますので適宜参照してください。

まずは Berkshelf で入れたCookbook を環境構築に含めます。 nodes 以下に vagrant.json を作り、ここでchef で実行するレシピを指定します。 また、Berkshelf で入れたレシピのそれぞれのドキュメントはOpsCodeから検索して閲覧できます。

nodes/vagrant.json:

{
  "run_list":[
    "simple_iptables",
    "nginx::source",
    "mongodb::10gen_repo",
    "mongodb"
  ]
}

執筆時にはMongodb は build-essential の部分でうまくいかなかったので、いくつかハックします。またiptables などで一部追加が必要なので自分用レシピをちょっと作成します。

bundle exec knife cookbook create myrecipe -o site-cookbooks

これでsite-cookbooks に myrecipe が追加されました。(myrecipe は曖昧なので目的に応じて変えたほうがいいと思うのですが、今回は手っ取り早い方法で。。)

ここで追加するのを一気に記載します。 site-cookbooks/myrecipe/recipes/ にそれぞれ配置します。

### app_env.rb
# this is required for capistrano
directory "/var" do
  owner "root"
  group "root"
  mode "0777"
  action :create
end

### build-essential.rb
#see http://qiita.com/soundTricker/items/f1dca9573323048f3446
file '/etc/yum.conf' do
  _file = Chef::Util::FileEdit.new(path)
  _file.search_file_replace_line('exclude=kernel', "#exclude=kernel\n")
  content _file.send(:contents).join
  action :create
end.run_action(:create)
simple_iptables_policy "INPUT" do
  policy "DROP"
end

### iptables.rb
# Allow all traffic on the loopback device
simple_iptables_rule "system" do
  rule "--in-interface lo"
  jump "ACCEPT"
end

# Allow any established connections to continue, even
# if they would be in violation of other rules.
simple_iptables_rule "system" do
  rule "-m conntrack --ctstate ESTABLISHED,RELATED"
  jump "ACCEPT"
end

# Allow SSH
simple_iptables_rule "system" do
  rule "--proto tcp --dport 22"
  jump "ACCEPT"
end

# Allow HTTP, HTTPS
simple_iptables_rule "http" do
  rule [ "--proto tcp --dport 80",
         "--proto tcp --dport 443" ]
  jump "ACCEPT"
end

simple_iptables_rule "mongodb" do
  rule "--proto tcp --dport 27017"
  jump "ACCEPT"
end

### rbenv.rb
include_recipe "rbenv::default"
include_recipe "rbenv::ruby_build"

rbenv_ruby "2.1.0-rc1"

rbenv_gem "bundler" do
  ruby_version "2.1.0-rc1"
end

そしてnodes/vagrant.json に追加したレシピを適用します。

{
  "run_list":[
    "myrecipe::build-essential",
    "simple_iptables",
    "myrecipe::iptables",
    "nginx::source",
    "myrecipe::rbenv",
    "mongodb::10gen_repo",
    "mongodb",
    "myrecipe::app_env"
  ]
}

これでbundle exec knife solo cook vagrantで環境が構築されていくはずです。 実際に vagrant ssh ではいると Nginx や Mongodb のプロセスが起動されていて、 rbenv コマンドが入っていることが確認できるはずです。

Chef で問題が起きたときに、それらの原因を調査するためにChef の書き方は知っておくべきです。基本的なことさえわかっていれば十分環境は作れるので、定番の入門Chef-solo を読めば十分だと思います。

補足

nginx.conf は Capistrano で更新する

Rails アプリに関わる nginx.conf のため、Chef 側でnginx.conf は修正しないようにしています。次回のRailsデプロイ時に Rails.root/config にあるnginx.conf にシムリンクを張るようになります。

/var は 777 にする

Capistrano デプロイ時にここに /var/www/ というディレクトリを作り、その上でRails アプリを配置していきます。その際デフォルトの権限だと怒られるので o+w な権限にしておく必要があります。

次は

いよいよラスト、 Rails アプリをこのゲスト OS にCapistranoでデプロイしてRails アプリを動かします!

パーフェクト Ruby を読んで

この本が新しく出てます。





僕のスペックとしては、

  • Ruby 歴4年
  • もはや Rails ばかり
  • メタプログラミング Ruby 読んでRubyのコアはそこそこ理解

こんなもんです。
で、実際読んでみたら、最初はものすごいハイスピードで言語仕様だけをさらっと紹介している(知ってることが多かったので、流し読みしてたからという理由もある)。でもその中でも正規表現とスレッド、Process周りは込み入った内容も書いてあって難しいし知らないことが結構あった。
とはいえこの本の神髄は間違いなく「メタプログラミング」の章だと思う。特にClassクラスに関しての説明がすごいわかりやすい。でも、もうちょい実践的なメタプログラミングの例が欲しいから、やっぱりメタプログラミングRubyも読んだ方がいい。
何よりRuby2.0対応ってのがいいね。例えば2.0からの「Module#prepend」とか、こういうのは知る機会がなかったのでこういうので知れて本当に良いと思う。


後半は全てライブラリの説明。まぁだから必要な所だけ読めば良さそうだね。
特にGemのつくりかたとBundler,Pryは参考になった。いつも使ってはいるけれど、あまり細かい使い方とかを認識してなかったから、この本でざっくりと理解する機会ができたのが良かったな。さっそくGemを作りたくなった。

ここまでRubyの詳細が書かれていたのはメタプログラミングRubyくらいしか知らなかったから、今後はこの本はRubyistの必要な本になっていくんじゃないかな。「たのしいRuby」→「プログラミングRuby」→「パーフェクトRuby」→「メタプログラミングRuby」の順番かな。
でも、なんでTestの項目なかったんだろw Rubyなんて言語はテスト書かなきゃ一気にコードが破滅すると思うだけどねぇ。ウフフ