CookPadのchanko勉強会に行ってきたのでサンプルを作ってみた(View編)
6/8(金)にCookPadで開催された「chanko勉強会」に行ってきました。
chankoとはCookPadが開発したrails用のライブラリで、chankoを使うと
プロトタイプで作成した機能を素早くかつ安全にプロダクション環境で
実際のユーザーに使ってもらう事が出来ます。
https://github.com/cookpad/chanko
プロトタイプを実験的に特定のユーザーにのみ機能を公開することが出来るので、
自社のスタッフのみに公開したり、ある属性を持ったユーザーに対してのみ公開して
反応を見たりすることが出来るため、開発した機能を全体に公開する前に実際のユーザーからの
フィードバックを得られるというメリットがあります。
リーンスタートアップでいう「仮説と検証」のループを素早く回せるという事ですね。
以前、別のアジャイル系のイベントでchankoを使ったCookPadの取り組みを聞いていて
興味があったので申し込んでみたものの、落選…orz
と思ったら後日欠席者が出たとのことで、繰り上げ当選になりました(∩´∀`)∩ワーイ
勉強会の内容についてはid:antipopさんが詳しく書いてましたのでこちらで
http://kentaro.hatenablog.com/entry/2012/06/08/231419
せっかくなので忘れないうちに簡単なサンプルを作ってみようと思います。
chankoのサンプルプロジェクトの作成
rails new chanko_test
必要なgemの設定。chanko以外に、今回はtwitter-bootstrapとdeviseも入れておきます。
vi Gemfile gem 'chanko', :git => 'git://github.com/cookpad/chanko.git' gem 'twitter-bootstrap-rails' gem 'devise' bundle install
chankoのインストール
rails generate chanko:install
moduleのinclude
vi app/helpers/application_helper.rb module ApplicationHelper include Chanko::Invoker include Chanko::Helper end
chankoは「Unit」という単位で機能を作成します。
Unitはrails generateで生成出来るようになっています。
rails generate chanko deco create app/units/deco/deco.rb create app/units/deco/views/_show.html.haml create app/units/deco/specs/controllers/deco_controller_spec.rb create app/units/deco/specs/models/deco_model_spec.rb create app/units/deco/specs/helpers/deco_helper_spec.rb create app/units/deco/stylesheets/deco.scss create app/assets/stylesheets/units/deco create app/units/deco/javascripts/deco.js create app/assets/javascripts/units/deco create app/units/deco/images/logo.png create app/assets/images/units/deco
生成されたUnitを見てみましょう。
コメントアウトされたサンプルソースが記述されています。
vi app/units/deco/deco.rb module Deco include Chanko::Unit =begin active_if :always_true do |context, options| # "context' is invoking context such as controller true end scope(:controller) do function(:show) do end end scope(:view) do function(:show) do render :partial => "/show" end end models do expand("Recipe") do def your_method end class_methods do def your_class_method end end end end shared("your_shared_method") do 'hello' end helpers do def your_helper_method end end =end end
chankoで作った機能を載せるためのアプリケーションを作ります。
rails g scaffold blog title:string content:text rake db:migrate
デフォルトだと見た目が悪すぎるので、twitter bootstrapを入れます
rails g bootstrap:install rails g bootstrap:layout application fixed
tableの見た目を少しいじりましたが省略します。
この状態でwebrickを起動するとこんな感じ。
ボタンはtwitter bootstrapのclassを使っていないので、chankoを使って少し見た目を変えてみます。
vi app/units/deco/deco.rb module Deco include Chanko::Unit active_if :always_true do |context, options| # "context' is invoking context such as controller true end scope(:view) do function(:show_button) do link_to :show, blog_path(blog), :method => :get, :class => 'btn' end end
先程生成されたUnitを編集しました。
active_ifの戻り値がtrueの場合にこのUnitで定義した機能が公開されます。
scope(:view)はViewに機能を追加する際に使用します。
渡すブロックの中でtwitter bootstrapのclassを設定したリンクを表示するようにしています。
次にアプリケーションから先ほど作成した機能を呼び出します。
vi app/views/blogs/index.html.erb
でViewのファイルを開いて
<td><%= link_to 'Show', blog %></td>
の行を以下のように変更します。
<td><%= invoke(:deco, :show_button, :locals => {:blog => blog}) %></td>
機能の呼び出しは
invoke(ユニット名, function名)
のように書きます。 :localsにはローカルスコープの変数を渡す事が出来ます。
この状態でアプリケーションを見てみると
おぉ、リンクがボタンに変わっていますね!
chankoのUnitで追加した機能が実行されてtwitter bootstrapのclassが反映されています。
では次に特定のユーザーだけにこの機能を見せるようにしましょう。
今のアプリケーションにdeviseをinstallしてユーザー管理の機能の追加します。
※deviseの手順は省略
表示の切り替えは app/units/deco/deco.rb の active_if で行います。
ユーザー名が"siso9to"の場合だけボタンが表示され、それ以外はテキストのリンクが
表示されるようにします。
active_if :always_true do |context, options| if context.current_user.username == "siso9to" true end end
contextにはアプリケーションのコンテキストが渡されるので、ヘルパーなども使えるそうです。
画面の方はどうなったか見てみましょう。
ユーザー siso8toの場合
おぉ、ちゃんと指定したユーザー以外ではデフォルトの挙動をしました(テキストリンクを表示)。
※デフォルトの挙動については後述
今回は単純な例でしたが、例えば男性ユーザーのみに表示したい場合や、20代以上のみに
表示したい場合など、ユーザーのセグメントごとに表示を切り替えて様々な実験をすることが
出来そうです。
ちなみにUnitの方でエラーが発生した場合はどうなるのでしょうか?
chankoのUnitの中で発生したエラーはchankoの中で処理されます。
また、以下のように記述すると、Unitが無効の場合やエラーが発生した場合はデフォルトの
処理が実行されます。
invoke(ユニット名, function名) do #デフォルトの処理 end
この機能のおかげで、開発者は障害を恐れずにプロトタイプをプロダクション環境に
どんどんリリース出来ます。
もしエラーが発生した場合でも、プロトタイプの機能が表示されないだけでユーザーは
既存のアプリケーションを使用することが出来ます。
追加機能のリリースに失敗してアプリケーションが全て真っ白な画面に・・・という悲劇は
かなり回避できそうです。
デフォルトでは開発環境ではこの機能は無効になっている(例外がアプリケーション本体までthrowされる)
ので、もし開発環境でも本番環境と同じ振る舞いを確認したい場合は、
config/initializers/chanko_initializer.rb を開き、
Chanko.config.raise = true if Rails.env.development?
のtrueの部分をfalseにします。
Chanko.config.raise = false if Rails.env.development?
こうしておくと、先程追加した :show_buttonの中でraiseしても
scope(:view) do function(:show_button) do raise link_to :show, blog_path(blog), :method => :get, :class => 'btn' end end
画面にはエラーが表示されません(ログにはraiseの結果が出力されます)
これは便利ですね!
ここまでのソースはこちらにUPしておきました。
(大した事してないので公式のサンプル見たほうがいいですが・・・)
https://github.com/siso9to/chanko_test.git
今回はviewだけ記事に書きましたが、controllerやmodelも試してみたので、
整理して次回以降に書きたいと思います。