おもしろwebサービス開発日記

Ruby や Rails を中心に、web技術について書いています

Rails::API について発表した

FiNC さんの社内マイクロサービス勉強会と、表参道.rb にて、そろそろリリースされそうな Rails 5 におけるメジャーフィーチャの一つ Rails::API について話しました。

雑感

スライド読むと分かるように、Rails::API は API サーバを作る時の銀の弾丸でもなんでもなくて、条件に合致したときに使うとちょっとだけ速くなりますよ、軽くなりますよという機能なのでした。

Rails::API の機能面としてはそれだけなのだけど、Rails は Rack Middleware や ActionController::Base 内の Module が疎になっていて、着脱が簡単なんですよというのを示す良い例にもなっていると思います。使っていない Middleware や Module を外すことで、手軽にちょっぴり速く/軽くできるので、API サーバに限らず不要なものがある場合は外してみてしまっても良さそう。ただし本当にちょっぴりしか変わらないので、速度を劇的に改善する必要のある場合は別の言語を検討するのが良いのではないでしょうか。

他の言語との比較も時間あったらやりたい*1ですね。

*1:そういうの知りたい会社さんがお仕事依頼してくれたら嬉しいなあ

DroidKaigi2016に参加した

DroidKaigi 2016 に行ってきました。

おそらくブログには書いていなかったのですが、1年ほど前に RubyMotion で Android アプリを開発したことがあります*1。それ以来、あまり Android 開発トレンドのキャッチアップができていなかったので、ここらで遅れを取り戻そうとしたのでした。

個人的には、最近どのようなライブラリが使われているのか、RxJava、テストが気になっていたのでそれらの発表を中心に見て回りました。

Rx系については具体的に何が嬉しいのかよくわかっていなかったのですが、非同期処理をうまく扱えるイメージがついたので今後積極的に使っていきたいです。

テストに関しては Jenkins を使っているところが多いようで、Ruby 界隈とは異なる印象。おそらく(減ってきたとはいえ)機種依存での不具合を発見するために実機を通してテストをせざるをえないのが、一般の CI サービスを使う場合の壁になっているのかなと感じました。

全体通じて、スタッフの方々がとても頑張ってくれていて過ごしやすいKaigiでした。また来年も参加する予定です。

*1:RubyMotion ネタで去年の DroidKaigi に CFP を出したのですがあえなく落選しました><

権限管理のgemで良いのはどれ?

昨日は ginza.rb 31回目のミートアップでした。

Ginza.rb 第31回 ユーザの権限管理どうしてます? - Ginza.rb | Doorkeeper

@kyuden_ さんに、現状の二大認可 gem である cancancan や pundit、それらの問題点を解決するために作った banken について発表してもらいました。

感想

個人的には pundit のリソースベースでの権限管理は悪くないと思っています。ただスライドで書かれているような、Admin::UsersControlller と UsersController で処理を分けたい時などのエッジケースで回避策を模索しなきゃいけないのはだるいですね。banken だと、コントローラベースなのでコード記述量は増えてしまうのですがその分ハマりどころが減るので、そのトレードオフを考慮しつつ案件によって使い分けるのがいいのかなという気持ちです。

rails-assets の調子が悪い時の回避策

皆さん、rails-assets は使っていますか?

rails-assets は、Gemfile で js や css のライブラリを指定して、バージョン管理や依存の解決などをしてくれるとても便利なサービスです。

しかし最近ではその役目を終えたとして、最大で今年末でサポートを終了するとしています。

Future of rails-assets · Issue #291 · rails-assets/rails-assets

そしてもう閉じることが決まったプロジェクトだからなのか、あまり活発にメンテナンスをしていないような印象を受けます。昨年からrails-assets を運営しているサーバが不安定になることが多く、rails-assets に依存しているプロジェクトを持つ会社さんは、bundle update やデプロイに失敗して辛い日々を過ごしたのではないでしょうか。

そんな折、明日 2016/1/19 にサーバのSSL証明書の期限が切れることがわかりました。証明書の期限延長対応がされるまで、困ったことになりますね…><

f:id:willnet:20160118191355p:plain

(追記) 証明書は lets'encrypt を利用しており、(おそらく)自動で更新されるようになっているようです。よかったですね。 SSL certificate for rails-assets.org will expire soon · Issue #306 · rails-assets/rails-assets

僕がお手伝いしているクリニカルプラットフォームさんでも rails-assets を利用しており、昨年 rails-assets が不安定になった際に、非常用として回避策を用意しておきました。

その回避策をシェアしておきますので、僕たち同様に困っている方がいらっしゃったらご利用下さい。以下は クリニカルプラットフォームさんの esa@masa_iwasaki がまとめてくれた記事を改変したものです。

rails-assets.org が不安定な場合

rails-assets.org へ接続ができない場合、 bundle install が終了せず最悪デプロイができない状況に陥ります。

急いでいる場合は、rails-assetsのリポジトリからソースコードを手に入れ、開発環境でgemパッケージをビルドし、外部に公開してそのURLをGemfileで参照するという手段があります。ただし、多少の時間はかかりますので、時間に余裕を持って取り組むのがベストです。

rails-assetsでgem生成

rails-assetsREADMEに従ってセットアップします。redis さえ動いていれば、最後の foreman start は必要ありません。

git clone git@github.com:rails-assets/rails-assets.git && cd rails-assets
bundle install && npm install
cp config/database{.sample,}.yml
cp config/application{.sample,}.yml
# edit config/database.yml and config/application.yml if necessary.
bin/rake db:setup
foreman start

手元でgemを以下のようにビルドします。各assetのバージョンは各プロジェクトのGemfile.lockを参照して取得してください。

bundle exec rake 'component:convert[jquery, 2.1.4]'
bundle exec rake 'component:convert[jquery-ui, 1.11.4]'

↑の作業を楽にするために、Gemfile.lock をパースして、実行すべき rake タスクを出力する簡単なスクリプトを書きましたのでご利用下さい。parse_gemfile_lock.rb のように保存して ruby parse_gemfile_lock.rb Gemfile.lock で実行できます。

files = ARGF.readlines.grep /rails-assets-/
files.map(&:strip!)
files.reject! { |file| file[-1] == '!' || file.match(/[>=<]/) }
files.each do |file|
  name, version = file.split(' ')
  name.gsub!(/rails-assets-/, '')
  version.gsub!(/[\(\)]/, '')
  puts "bundle exec rake 'component:convert[#{name}, #{version}]'"
end

外部への公開

rails-assetsのワーキングコピー直下にあるpublicディレクトリ以下をrsync等を使って外部に公開します(public以下のファイルさえあれば、gem serverとして機能します)。公開先はどこでもいいですが、最も簡単なのはAWS S3を利用することでしょう。

gem sourceの変更

プロジェクトのルートディレクトリに移動し、Gemfile 中の https://rails-assets.orghttp://公開URL に変更して、bundle install を走らせれば終了です。

ローカル環境で確認したい場合

localにgemがすでにインストールされている場合、公開URLのものは当然インストールしてくれません。もし、ちゃんとインストールが出来ることをローカル環境で確認したい場合は、インストール済みのrails-assets-*系gemを削除してください。ざっくりと全部抜くのであれば、以下のようなコマンドで削除できます。

$ gem list --no-version | grep rails-assets- | xargs gem uninstall

最後に

役に立った!と思ったら下記エントリの応援や応募などをお願いします (\( ⁰⊖⁰)/)

犬の手も借りたい!ヘルスケアITのスタートアップがRubyエンジニア募集! - クリニカル・プラットフォーム株式会社の求人 - Wantedly

合わせて読みたい

最近のお仕事について - おもしろwebサービス開発日記

Lotus についての雑感

今回の ginza.rb ミートアップで、Lotus と呼ばれる、Ruby製フレームワークについて学びました。

ginzarb.doorkeeper.jp

@y_yagi さんが概要を資料にまとめてくれたので、それに沿って特徴や機能について理解を深めつつ、気になることについてワイワイ話しました。

感想

Lotus は、Rails とは異なる明確なポリシーで設計されており好感が持てます。Rails は少人数、短期間で素早くサービスを作るのに向いているフレームワークだと思いますが、最近はある程度大規模な開発にも使われているはずです。その時に開発メンバーの習熟度にばらつきがあると、例えばコントローラに不必要なインスタンス変数が定義されたり、ActiveRecord を継承したモデルにビジネスロジックが書かれすぎてモデルが肥大化したりします。こうしたことは少しなら問題ないのですが、開発が進むにつれ徐々にビジネスロジックの実装を難しくし、バグが入り込みやすくなり、さらにコードを読み書きする楽しさを奪っていきます。Lotus は、そのようなことが(比較的)起こりにくい設計になっています。

機能的に足りていない部分(関連やi18n)があるので、どんどん使いましょう!とは言えないのですが、Rails で消耗した人向けのもう一つの選択肢になればいいなあ。

最近のお仕事について

ここ半年ほど、Clinical Platform さんのお手伝いをしています。最近エンジニア募集を開始したので、どんな感じでお仕事を進めているかを簡単に紹介しようと思います。

作っているもの

クリニック向けのクラウド電子カルテです。

Ruby や Rails のバージョン

Railsエンジニアが会社を選ぶときは使っているRubyとRailsのバージョンで決めるらしいので一応。

  • Rails 4.2.4
  • Ruby 2.2.2
  • PostgreSQL 9.3.6

Ruby と PostgreSQL のバージョンが少し古いのは、本番環境である Engine Yard のバージョンに合わせているためです。gem 類は、週に一回自動で bundle update のプルリクエストが生成される仕組みが作られているためほぼ全て最新バージョンです。

(2015/11/09追記)Engin Yard が Ruby 2.2.3 に対応したので、現時点では 2.2.3 になっています。

フロントエンドは vue.js を使っています。特にカルテ内では多くの情報を素早く編集、閲覧する必要があるので多用しています。 今のエンジニアは僕含めサーバサイドが得意なメンバーが多いので、苦手なフロントエンド成分を補充するために週1で社内勉強会を開催しています。現在のテーマは React です(今の所 React に書き換える予定はありません)。

開発の進め方

普通のことを普通に進めています。Railsでウェブサービスを開発する、といったときにみなさんが想像するようなことは大体やってるはずです。これ不便だな、こうやったら便利になるのでは?と思ったら10分後にはpivotalでチケット化されていて、誰かがカッとなったときに導入されます。

  • Pivotal Tracker でチケット駆動開発
  • esa でドキュメント管理&日報管理
  • GitHub でソースコードレビュー
  • 通知類とチャットは Idobata に集約
  • CircleCI で CI まわす
    • 自動で rubocop, simplecov, brakeman などを動かして GitHub にコメントをつける
  • 朝会
  • 週一の全体ミーティング&KPT

ただ、技術的にチャレンジングなことをしている!エッジな技術をどんどん採用している!…というわけではなくて、どうやったらユーザである医療従事者の方々にとって便利なサービスになるか、を一番重視しています。

クリニックによってカルテの使い方は全然異なるので、それらを置き換える電子カルテの仕様を決めることは難しく、トライアンドエラーの連続になります。最初から決まったものを作るのではなくて、小さく作って様子を見てから大きく育てていく。当然、仕様も降って湧いてくるというより、みんなで考えて決めていく感じです。

エッジな技術に囲まれて仕事をしたい!という人よりは、チームで楽しく開発したいとか、ユーザに価値を届けるために知恵を絞るのが好きとかいう人が向いてると思います。

もちろん、新技術を採用する明確なメリットがあるなら、躊躇なく採用していくつもりです!

雰囲気

楽しくやっています。個人的にはもともとの知り合いばかり周りにいるのでやりやすいという面もありますが、それを差し引いても良い雰囲気で開発できていると思います。

チームがどんな雰囲気で開発をしているか、チームメイトである @tatsuoSakurai のエントリも参考になると思います。

カッとなるチーム - 開発チームのモチベーションをチョットあげる工夫のお話 - tatsuo.sakurai's blog

最後に

興味ある方は、Wantedly 経由、もしくは @netwillnet、その他関係者っぽい人に声かけてください!採用決まったら一緒にペアプロしましょう (\( ⁰⊖⁰)/)

医療界にインパクトを与えるクラウドサービスを一緒に開発しませんか? - クリニカル・プラットフォーム株式会社の求人 - Wantedly

Rails 4.2 で postgresql を使う場合の注意事項

Rails 4.2 では、DB の string 型が255文字制限ではなくなりました。もともとあまり意味がなかったらしいです(詳しい人補足求む)。対象は postgresql と sqlite で、mysql は対象外です。

PostgreSQL, remove varchar limit. by senny · Pull Request #14579 · rails/rails

Rails 4.2 以降は、string は文字数制限未指定 の character varying 型に変換されます。ただそれって、text 型と何が違うんでしょうね。

と、調べた限りでは違いはなさそうでした。

string - PostgreSQL: Difference between text and varchar (character varying) - Stack Overflow

ちなみに Rails 4.1 で string 型のカラムに256文字以上の文字列を入れて保存するとこのようになります(PostgreSQLは 9.4.1 でためしてます)。Rails 4.2 だとエラーにならず普通に保存されます。

ActiveRecord::StatementInvalid: PG::StringDataRightTruncation: ERROR:  value too long for type character varying(255)

この挙動を頼りにして、これまで string 型に validation をかけてこなかったみなさん、ちゃんと validation かけていきましょうね(\( ⁰⊖⁰)/)

補足 character varying(n) の挙動について

上記では制限している文字数以上の文字を入れようとするとエラーと書きましたが、例外があります。超過分の文字列が空白の場合はそれが切り詰められて格納され、エラーにはならないようです。SQL標準の仕様らしいけど変な挙動ですね…。

SQL defines two primary character types: character varying(n) and character(n), where n is a positive integer. Both of these types can store strings up to n characters (not bytes) in length. An attempt to store a longer string into a column of these types will result in an error, unless the excess characters are all spaces, in which case the string will be truncated to the maximum length. (This somewhat bizarre exception is required by the SQL standard.)

PostgreSQL: Documentation: 9.4: Character Types

mysql の場合

mysql は特に挙動は変わっていません。mysql 5.6 のデフォルトである STRICT_ALL_TABLES が有効になっていると次のようなエラーになります。無効だとエラーにはならず、256文字以降が自動でカットされて格納されます

ActiveRecord::StatementInvalid: Mysql::Error: Data too long for column 'name' at row 1: INSERT INTO `users` (`created_at`, `name`, `updated_at`) VALUES (?, ?, ?)