Shoken Startup Blog

KitchHike Founder/CTO

Trailblazer勉強会に参加してきた #trbtky

Trailblazer::Tokyo #1@クラスメソッドに参加してきました。

connpass.com

発表者

  • @kbaba1001
  • @yuukigoodman

Trailblazerとは

A new architecture for Rails.
apotonick先生の考えた最強のRails.

github

github.com

Trailblazer は Rails に新しいアーキテクチャを提供する gem です。 Rails のメンテナンスしづらさや複雑さはビジネスロジックMVC に混ざっていることにあります。 Trailblazer ではビジネスロジックMVC から分離することで Rails のメンテナンス性を向上します。

引用 http://connpass.com/event/20137/

READMEが充実しているので、読むだけでも概要はつかめる。ソースコードでの例も多く、コード例を眺めるだけでもなんとなくならわかる。サンプルアプリもあるので、そのソースを使い方はわかる。

発表者の@kbaba1001さんいわく、Trailblazerは、開発者であるapotonick先生が業務で多くのレガシーコードと向き合う中で見つけた解決策の集大成なのだとか。思想が先にあって、それをRailsに落とし込んだものではない。なので、机上の理想論ではなく、実現性の高い現実解となっているのがステキなところ。自分で苦労しながら導きだした一つの現実解を汎用的に再構築し、Githubで公開してメンテナンスしている開発者のapotonick先生はエラい。

apotonick先生は充実したREADMEだけではなく、Trailblazerに関する本も執筆している。

leanpub.com

プロジェクトに導入する際には、この教科書が唯一指針となる。英語で200ページ以上。学習コストとしては低くはないが、指針があるのでメンバー間のブレが出にくいのは大きい。

以下は勉強会中にとったメモです。

Trailblazer の紹介 (@kbaba1001)

Trailblazerが解決する課題

Railsは規模が大きくなるとメンテナンスしづらい

  • ビジネスロジックのあるController、再利用しづらい
  • partialがたくさんあって、変更による影響が追いにくい
  • default_scopeを付けている時、外す時が大変。リレーション側からのアクセスだとunscopeで外せない
  • accepts_nested_attributes_for。いっしょに関連するモデルを作る機能。モデルとモデルが密接な結合になってしまってメンテナンスがしづらくなる。
  • validationをifオプションで切り替えをすると、メンテナンスしづらくなる。例: Amazonの買い物かごのウィザード。テストで再現が難しい。後でAPIで登録する場合は書き直しになる。
  • Rails Engineを使うgemの拡張。DeviceやRails adminでcontrollerを上書きすると後々のメンテナンスが大変。gemごとに上書き方法が違う。
  • fat model, fat controller
  • 遅いテスト

課題に対するフォース

apotonick先生の考えた最強のRails

Trailblazerとは、A new architecture for Rails.
cells, reformなどapotonick先生が開発したgemを多く取り入れている。

具体的には、app/conceptsというディレクトリを作って、その配下に機能ごとにディレクトリ作成する。

  • ビジネスロジックMVCから分離してconcepts以下にまとめる
  • MVC疎結合にしてメンテナンス性の向上
  • Model: associationとscopeだけを書く
  • View: concepts毎にViewModelとして分割
  • Controller: オペレーションに対するHTTPエンドポイントのみを提供。Strong Params、Modelをfindしない。

ビジネスロジック

  • CRUD
  • validation/callback
  • Viewのためのロジック
  • Worker

一言でいうとMVC + Operation + Cell

サンプルアプリ
https://github.com/apotonick/gemgem-trbrb

Operationとは

Modelのラップ

ビジネスロジックを書く、CRUD, validation, callback

Controllerからのrunメソッドで、processメソッドが呼ばれる

Cellとは

ViewModel

メソッドとassetsのあるpartial

concepts/{機能ディレクトリ}/以下のcell.rbに定義されているメソッドを呼べる

テスト

Operation, cellのテストを行うことで、featureテストやrequestテストを減らすことができる。

partialだけのテストは書かないが、cellのテストができる。細かい単位でテストができるメリット。

Trailblazerと自動テスト (@yuukigoodman)

  • なぜTrailblazerか
  • 電子書籍について
  • とりあえずやってみた前後のdiff
  • Tarilblazerの情報源とか

情報源

DDDの知識は必須では無いが、fat modelに苦しんだ経験から良い設計を勉強する過程で勉強することになるだろう。

以下が揃ったプロジェクトなら、導入できるかも。

  • メンバーがfat modelに苦しんだ経験、良い設計への興味
  • テスト重視
  • Version 2.0が計画されていること。長期メンテナンスが予定されていること。

apotonic先生の教科書が唯一指針になっているので、学習コストは多いが指針はぶれなさそう。

Trailblazer を業務で使ってみた話 (@kbaba1001)

iOSのバックエンドAPI開発でTrailblazer(reform)を使ってみた

解決したかったこと

  • APIリクエストの妥当性検証
  • モデルとリクエストパラメータの疎結合

Grapeは未使用

コントローラ、モデルでをやりたくなかったので、フォームオブジェクトを作った

reform

modelを継承して、propertyとvalidationを書ける。modelとformを分離するためのgem。

ActiveRecordは入れ子のパラメーターが扱いにくい。reformで解決する。

  • バリデーション、massassignment対策
  • 入れ子パラメータが使える
  • 項目が任意に増えるフォームで、配列を受け取ることができる
  • 複数モデルにパラメータを分配できる
  • モデルに定義されていないカラムをpropertyに書いてvirtual: trueで書ける
  • モデルに書かれていたvalidationのifを無くすことができる。コンテキストによる混乱が無くなる。

コントローラのテストはしにくい。model.saveをコントローラでやっているが、saveメソッドを上書きすることで対応。request specに書かれていたものがservice specに移る。

service層でmodel層をラップしているイメージ

  • ビジネスロジックをサービス層に封じ込めた
  • サービス層でテストするので速い。serviceでcreateして、saveするテストを書けば良い。

Trailblazerが提供するもの => Operation層

  • RailsにもMVC以外の層を作ってもよい
  • Trailblazerのgemは小さい
  • 小さなgemを組み合わせる導入の柔軟さ
  • テストしやすさを重視

apotonick先生が仕事の過程で見つけた現実解。思想が先にあってそれをRailsに合わせたわけでは無いので、現実的である。

勉強会で仕入れた新しい情報メモ

YAPC::Asia 2015のスライド #yapcasia

公式サイトのリンクまとめページ

トークリスト: しばらく経てばここに資料へのリンクが張られるはず。
Talks - YAPC::Asia Tokyo 2015

発表者や参加者のブログエントリまとめ。発表者のブログに行くとスライドと発表の補足があったりする。
【随時更新中】YAPC::Asia Tokyo 2015 感想エントリまとめ | YAPC::Asia Tokyo 2015

外部サイト

SSSSLIDE
「yapc」タグの付いたスライド - SSSSLIDE

Togetterまとめ
YAPC::Asia Tokyo 2015 #yapcasia 全セッション総まとめ - Togetterまとめ

gihyo.jpのレポート 発表内容がレポートされている。このレポートを読むと発表の概要がつかめる。
YAPC::Asia Tokyo 2015 スペシャルレポート:レポート|gihyo.jp … 技術評論社

読んだスライド

我々にできるOSSとそのコミュニティの育てかた

OSS開発とコミュニティに関する興味深いテーマ。@t_wadaさんの関連エントリと合わせて読むべし。

@tagomoris

@t_wadaさんの関連エントリ
OSS開発の活発さの維持と良いソフトウェア設計の間には緊張関係があるのだろうか? - t-wadaのブログ

どうしてこうなった? Node.jsとio.jsの分裂と統合の行方。これからどう進化していくのか?

Node.jsの開発がスタートした2009年から、Ryan -> Isaac -> TJへとリーダーの移り変わり、BDFLモデルからの脱却、io.jsのforkが時系列にまとめられている。

@Yosuke Furukawa

Docker3兄弟

先週、Docker速習会で触ったばかりなので理解を深めることができた。

@toritori0318

発表者のエントリ
YAPC::Asia 2015で「Docker3兄弟」というお話をしました+QA補足 #yapcasia - アルパカDiary

Perlの上にも三年 〜 ずっとイケてるサービスを作り続ける技術

YAPC 2015のベストトーク賞!

@hitode909

発表者のエントリ
YAPCでベストトーク賞いただきました #yapcasia - hitode909の日記

Podcastを支える技術、エンジニアのためのWebメディア、そしてCPAN

2008年からYAPC::Asiaに関わっている@yusukebe氏の発表。エンジニアがコンテンツを発信するための1例として、Podcastを使った配信の具体的な話。

@yusukebe

発表者のエントリ
ありがとう! #yapcasia - ゆーすけべー日記

Perlでゼロから作るコンテナ

@nukamu, @maokt
Perlでゼロから作るコンテナ - YAPC::Asia Tokyo 2015

この発表の資料をどうしても見たかったので図々しくも@nukamuさんに連絡したところ、公開予定があるそうです。
Togetterはこちら
Dockerの振る舞いを知るためにPerlを使ってゼロからコンテナシステムを作ってみよう!Linux基礎講座付き #yapcasia #yapcasiaC - Togetterまとめ

他に公開されているスライド

Ginza.rb 第25回 RailsConf2015の資料をみんなで読もうに参加してきた

7/21にRubyの勉強会、Ginza.rbに行ってきました。ブログ書こう書こうとしていてずっと書いてなくて、ついに第26回Ginza.rbが明日になったので書きます。

やったこと

  • RailsConf2015の資料や動画を見た
  • Rails Weeklyで直近のコミット内容を追った
  • Rails5での新機能、主にAction Cableについて

RailsConf2015の資料や動画

公式サイトにアップされているDHH氏の基調講演や、各発表のスライドを流し読み。

Confreaks TV | railsconf2015

Slide decks from RailsConf 2015 | Eventifier

Rails Weekly

This week in Rails

RailsConfの資料を見終わると、話題はRails Weeklyに上がってくる直近の動きへ。実際にコミットしている方も主催者側として勉強会に参加されていて詳しい説明を聞くことができた。

ちなみにGinza.rbの主催者/参加者には、パーフェクト Ruby on Railsの共著者である@willnet氏と@joker1007氏がいる。さらに@a_matsuda氏もフラッと参加するなどハイレベル。Ginza.rbほんとすごい。

Rails5の新機能

3つ大きな変更が予定されている。

  1. Action Cable
  2. Rails API
  3. Turbolinks3

ここの勉強会がきっかけで、次の週に行った開発合宿でAction Cableを使うことになった。Ginza.rbほんとすごい。

rails/actioncable

rails/actioncable-examples

[Rails5]Action Cableのサンプルを読み解いてみる - Qiita

Turbolinks 3こそRailsの未来 - Qiita

Rails 5 の足音 - Misoca開発ブログ

(翻訳) Ruby 2.2 のシンボル GC | FIVETEESIXONE

次回の勉強会

次回(といっても明日だけど)は@kyannyさんがBackbone, Chaplin, Marionette そして React - Quipper における Single Page Application 開発の変遷 - YAPC::Asia Tokyo 2015をベースにJavaScriptフレームワークに関する発表をされる予定。

イベントページ Ginza.rb 第26回 シングルページアプリケーションのためのRailsとJavaScript フレームワーク - Ginza.rb | Doorkeeper

Doorkeeperからメール来てすぐに予約したつもりだったけど、キャンセル7人待ちだったorz。Ginza.rbほんとすごい。

MongoDB 3.2の新機能を先取りチェック

MongoDB 3.2の新機能について言及している記事を読んだので、簡単に要約を書く。

www.compose.io

MongoDB 3.2の新機能を早送りで見てみよう

MongoDB 3.2は2015年の終わりにリリースされる見込みだということが、MongoDB Worldで報告されました。新機能を見てみますが、開発中なのでリリースまでには変更する可能性があります。

今回はこの3つについて見てみます。

  1. ドキュメント バリデーション
  2. Partial Index
  3. Aggregationでjoin ($lookup)

カンファレンスではスキーマについて多くの話がありました。MongoDBはこれまでスキーマレスを売りにプロモーションされてきたので、スキーマについて言及されることは奇妙に見えます。これは、MongoDB, Incがデータベースに格納された文書への規則的な構造を再評価していることなのでしょうか。

MongoDBのエンタープライズツールではscans collectionsやeverse engineers a schema from the collectionsなど、スキーマについてのものがリリースされています。これらは3.2で、コレクションをより便利で整然とするための新機能への提案になるでしょう。

1. ドキュメント バリデーション

[SERVER-18227] Document Validation - MongoDB
3.1.3でリリース済み

コレクションと条件式を指定するシンプルな形のバリデーションです。バリデーションにパスしなかったら error 121 DocumentValidationFailureを出します。
条件式は、greater than, less than, existsなどの式が使えますが、今のところgeo nearやtext search, whereは使えません。

db.runCommand({"collMod": collName,  
               "validator" : {a: {$exists: true}}})

注意点。すでに存在しているコレクションのvalidateはできない。insert, update時のみ。

2. Partial Indexes

JIRAチケット: System Dashboard - MongoDB
3.1 RequiredでOpenだが、3.1.5で試したところ動いた。

2010年からJIRAに登録されている課題で、スキーマに関する新機能。filter expressionをパスしたドキュメントのみがindexされる仕組み。

db.myusercoll.createIndex({ name: 1 },  
        { partialFilterExpression: { status: { $eq: "active" } } } )

ユーザーをactive, inactiveというステータスで管理している状況を考える。例えばsoft remove実装。 上記のクエリを流すと、activeなユーザーのみがnameでindexされる。

巨大なデータでのパフォーマンス改善になるだろう。filterにマッチしなかったドキュメントはクエリーでスキップされるだけではなく、insert やupdate時のindexingもスキップされる。

3. Aggregationでjoin ($lookup)

JIRAチケット: [SERVER-19095] $lookup - MongoDB
3.1.6でリリース予定

Aggregationフレームワークで、コレクション間のjoinに関する機能。普段の業務でjoinは使わなくても、analyseで使いたくなる時がある。MongoDB, Incはこれまでそのような場合は非正規化をするようにアドバイスしてきた。

これまでのAggregationフレームワークでは、単一のコレクションについてのパイプラインしか実行できなかったが、新機能の$lookupオペレータでは他のコレクションのデータを取得できるようになる。言い換えると、Aggregationステージでleft outer join機能を提供する。

$lookupは大きなポテンシャルを秘めているだろう。ユーザーはデータを非正規化しなくてもよくなる。ただ、実際にどのくらい使える機能なのかはalpha/beta版のリリースを待たなければならない。

まとめ

これらの3つの新機能は、サーバーサイドのMongoDBアーキテクチャにとって課題だった点への取り組みである。MongoDB 3.2 alpha/betaがリリースされた時、その改善を目に出来るだろう。3.2での他の変更点のほとんどはストレージエンジン、認証、他ツールとの連携とレプリケーションである。今後、残りの新機能についても取り上げていく。

ActiveRecord4, Rails4のinverse_ofについて理解したメモ

MongoDB(mongoid)でも使える。

inverse_ofとは

inverse_ofを指定したリレーションのある2つのモデルでは、双方から同一のインスタンスを参照できるようになる。両者ともメモリ上で同一のインスタンスとして扱われる。
逆に、inverse_ofの設定が無いと同一として扱われず、一方からの変更がもう一方から参照しても変更されていない。

具体例

UserモデルとMenuモデルが1対多でリレーションしている状況を考える。Userが複数のMenuを登録できるWebサービスのイメージ。

f:id:sfujisak:20150714093037j:plain

ソースコード

class User < ActiveRecord::Base
  has_many :menus
end

class Menu < ActiveRecord::Base
  belongs_to :user
end

inverse_ofが無かったら

Userのフィールドnameの変更が、Menuからたどった場合に変更が参照できない。メモリ上で別インスタンスとして扱われているから。

user = User.first
menu = user.menus.first
user.name == menu.user.name # => true
user.name = "change"
user.name == menu.user.name # => false

inverse_ofを指定すると

class User < ActiveRecord::Base
  has_many :menus, inverse_of: :user
end

class Menu < ActiveRecord::Base
  belongs_to :user, inverse_of: :menus
end

メモリ上で同一インスタンスとして扱われるようになり、userもしくはuser.menuからnameを変更しても、常にuser.name == menu.user.nameがtrueを返すようになる。

ドキュメント

Active Record の関連付け (アソシエーション) | Rails ガイド

ActiveRecord::Associations::ClassMethods