マイペースなRailsおじさん

Ruby、Ruby on Rails、オブジェクト指向設計を主なテーマとして扱います。だんだん大きくなっていくRuby on Rails製プロダクトのメンテナンス性を損なわない方法を考えたり考えなかったりしている人のブログです。

やりたいことに気がついたかもしれない

なんか今日仕事していたら、ふと、自分が心からやりたいことに気づいたような気がするので、忘れないうちに今の思いを綴っておく。

今、やりたいこと

大規模だったり、やりたいことが複雑だったり、パフォーマンスが必要だったりして、技術的に困難なシステムを、堅牢に、またスピーディに作りたい。 言い換えると、「私は、大規模で多機能で高性能で、なおかつ安全かつスピーディな拡張が可能なソフトウェアを作るソフトウェアエンジニアです」と言える人間になっていたい。

今まで目指してきたもの

技術のスペシャリストを目指していたが、だんだんとものを作れる・形にできるエンジニアを目指すようになっていった。

学生時代~社会人1年目: 様々な技術を使いこなす、幅広い要素技術にめっちゃ詳しい人

とにかくコンピュータが好きで、コンピュータでできることには何でも興味を持った。特に、コンピュータ・ネットワークは本当に面白くて、最高だった。 コンピュータなんて一台でも面白いのに、通信して複数台で情報がやり取りできるなんて面白いに決まってる。分散コンピューティングを学んで、コンピュータを協調動作させるためには堅牢な仕組みづくりが不可欠であることを学んだ。 古典かもしれないが、GoogleSearchやGoogleFileSystem、BitTorrentの仕組みには本当に胸が踊るような思いだった。

技術に詳しい=優秀なエンジニアという図式が私の中でできていた。今になって、いや違うだろ…って思うけど、当時は本気でそう思っていた。

優秀なエンジニアになるために、私はいろいろなスキルや知識を身に着けた。

こうやって振り返ってみると、「これってなんのために身に着けたの?」って感じるスキルセットだ。 なんかくくりが全然違くて妙に散らかってるかと思えば、同じ用途のフレームワークを複数学んだり、プログラミング言語だって多すぎる。

まあそれもそのはずで、特にやりたいことっていうのはなかった。 新しいことを覚えて、それをつかってなんか小さいものを作って満足するっていうのを繰り返していた。

社会人一年目は実務でプログラミングをしなかったので、暇な時間を使ってScalaで遊んでいた。

社会人2年目: 作れるエンジニア

そんな調子でいたら、ようやく実務でプログラミングをする機会を得た。

プログラミングはずっとやってきたから余裕やろ(^^) 研修でも優秀な成績を収めてたし、とか思ってたら、ここでとても大事なことに気づく。

「おれ、ちっちゃいものしかつくったことねーわ」

業務で作るプログラムは、当然のように規模が大きいシステムの一部だ。 全体はでかいけど自分の作る範囲は小さいので、コードを大量に書くわけではない。 それでも、全体の規模が大きいということはコードの書きやすさに大きな影響を与える。

すでに既存のコードがあるということは、すでに作られている仕組みに則って作るということだが、規模が大きすぎて何をやっているシステムなのか、どこにルールがあるのかさっぱりわからなかった。 また、自分の書く部分でも、このクラスはどんな使われ方をされるだろう、読む人は何がどこに書いてあれば読みやすいだろう、ということを考えながら書くのも初めてだった。

また、システムがどんな仕様を持っていればよいのか?を考えるのも非常に苦手だった。ということにも気がついた。 どんなフローでユーザーを誘導するのか?どんなエラーが起こりうるか?こういったシステム設計の言わば基本みたいなところが、ぜんぜん身についていなかったことに気づいた。

そんな体験を通して私は気づいた。

「おれなんもつくれねーじゃん」

焦った。クリエイターであるはずの私が、何も作れないのである。 この頃から「作れるエンジニア」を志すようになる。 何のために作るのか?今一番作るべきものは何なのか?つくったものをどのように使ってもらうべきか? そんなことを考えるようになっていった。 サービス・ビジネスのことも考えなければということを、誰の受け売りかはわからないが、思っていた。

同時に、システム設計の方法を学んでいくようになる。

これらの知識は、「作る」ために私に足りていなかった部分を大きく補ってくれたように思う。

そして、「作れるエンジニア」になるために、まあいろいろあって転職をした。 今は転職して1ヶ月経ったところ。当初の望み通り、存分に作る仕事をやらせてもらっている。

本当にやりたかったことと、目指してきたもののギャップに気がついた

私が本当にやりたかったことは、技術を駆使して自分にしか解けないような難しい問題を解く、ということなんだと思う。

社会人として生きているうち(環境が大きいと思う)、お金になるものを作らなければ行けない、という考えが芽生えていった気がする。だから、ビジネスの視点を持ったエンジニアに~とか、Webサービスで世の中にイノベーションを起こして~とか、全然思っていなかったけど、そういう方向を目指していた。

自分で自分に目隠しをして、大きな音の鳴っている方向に進んでいたような、そんな気がする。

目指したい方向性が見えてくると、やらなくちゃいけないことの方向性もだんだん見えてくる。 それで、今思いついているやらなくちゃいけないことっていうのが、もう本当にびっくりするくらい、楽しそう、やりたいことなんだよね。多分今度こそ、自分の気持ちに気がついた気がしています。

大きなタスクを細分化して立ち向かう

大きなタスクをもらいました。 そしてその大きなタスクは、さらにどんどん大きくなっていきます。

タスクをちぎるといいよ、という話をツイッターで見かけたので実践してみた。

計画

〇〇機能を実装する

という、大きなタスクを30~60分程度でこなせる大きさにの小さなタスクに分割していく。

大まかにわける

まずは時間のことは気にせず、この作業が完了しているということはつまり、これが終わっているはずだというざっくりとした工程に分ける。この時点では、かかる時間はは気にしない。

細かく分ける

60分以上掛かりそうなものは、複数に分割する。 ここまでできていれば半分くらいいっているはずだ、という感じの大体の目安は見えるはずなので、その目安を基準に分割する。 それぞれの目安が、60分以内になるように分割する。

もし、そのような目安さえも見えないと言うなら、そのタスクは自分の手には負えないものだということだ。 60分でたどり着く場所の想像さえもつかないと言うなら、そのタスクがどれだけの時間があれば終わるか想像もつかないということだ。 この時点で、周りに助けを求めよう。

小さすぎて30分以内に終わってしまうものについては、他のタスクに混ぜて大きさが揃うようにしよう。 この段階では、大きさを揃えることが目的なので、全く性質の違うタスクが一緒になっていても構わない。 ただし、無理に一つのことばで表したりするのはやめよう。

さあ、ここまでくると、あなたがやらなければならないことの全体像と、その量が見えてくる。 かかる時間を揃えたおかげて、全部で何時間かかるかは明確だ。

取り組む

あとは、作ったタスクリストにしたがって作業しよう。 それぞれのタスクにどれくらいの時間がかかったのか記録してあると、あとで振り返りがやりやすくなる。

たいていは予想どおりには進まない。一つのタスクに5時間かかってしまう、なんてこともざらにあるだろう。 それはそれで構わない。あなたは、どうして1時間で終わるはずの仕事が5時間もかかってしまったのか、自然と考えるだろう。その分析は必ず次の計画に役立つはずだ。もしかしたら、上司への言い訳にも使えるかもしれない。

振り返る

仕事を終えたら、計画通りに行ったのか振り返ってみよう。

時間が大幅に遅れたタスクの原因は何だったのだろう?

  • やることが予想以上に多かったから?
  • やることが予想難しかったから?
  • 邪魔が入ったから?
  • 全然やる気が出なくて、実際の作業時間が短かったから?
  • 社内ツールの使い勝手が予想よりも残念だったから?

これらを解決する方法はないか考えてみよう。

所感

タスクの粒度を時間で分けてみると、自分の進捗がとてもわかりやすい。 そうなると、チームのメンバーへの報告もしやすい。 自分がただ頭を抱えているだけではなく、確実に歩を進めているという実感を得やすい。

しばらくはこれを続けたいと思う。

OCS(Open Collaboration Services)

nextCloudにrubyからファイルをアップロードしようとしたら、OCSを使う必要があった。OCSってなんやねん&日本語の情報少ないねんな状態だったので概要書く。英語版wikipediaの日本語訳。

Open Collaboration Services

Open Collaboration Service(OCS)は、デスクトップ及びモバイル・アプリケーション上でウェブコミュニティとウェブベースのサービスの統合を行うための、オープンかつ特定のベンダーから独立した現代的なRESTベースのAPIです。ソーシャルネットワークとサイトやクライアント、例えば別のサイトやユーザーの端末でローカルに動作するアプリケーションやウィジェットの間での関連データの交換が行えるようにします。このプロトコルは、すべてのアプリケーションがOCS APIを提供するすべてのアプリケーションにアクセスできるように設計されました。

このAPIはソーシャルデスクトップ、特にクロスデスクトップなバックエンドの提供者としてのopenDesktop.orgによって設計されました。

このAPIを過去に利用した非KDEの環境はMaemoダウンロードアプリケーションストアやMeeGoのAppsがあります。

モジュール

OCSは複数のモジュールから構成されていて、いずれもサーバーとクライアントの両者がどれを実装するかは自由です。 1.6では、以下のモジュールがあります。

  • Person - user data
  • Friend - social graph
  • Message - in-site messaging between users
  • Activity - activity streaming
  • Content - downloadable content
  • Fan - content favoriting
  • Knowledgebase - access to FAQ items
  • Event - calendaring
  • Comments - content commenting
  • Private data - private key-value store
  • Forum - discussion topic structure
  • Buildservice - application software building

RubyXLを使ってExcelを編集してクライアントに返す

railsでエクセルを編集してクライアントに返そうとしたときのやり方を残しておきます。

作るもの

  1. クライアントがエクセルファイルをアップロードする
  2. サーバが受け取ったエクセルに何かしらの変更を加える
  3. クライアントが変更されたファイルをダウンロードする

といった動きになる機能をRailsで作ります。 出来上がったソースコードはこちら。

GitHub - ytnk531/excel-example: rails excel example

Excelの編集

RubyXLというgemを使います。

github.com

他にもエクセルを開けるgemはあるのですが、

  • Roo: 読み込みのみ
  • AXSLX: 新規作成のみ

という感じで用途が絞られています。 今回は、編集ができるRubyXLを使います。

単体だと、以下のような感じで使えます。

require 'rubyXL'

# ファイルを読み込んでRubyXL::Workbookにデシリアライズ
workbook = RubyXL::Parser.parse("path/to/Excel/file.xlsx")
# ブック→シート→行→セルという構造になっている
worksheet1 = workbook[0]
row1 = worksheet1[0]
cell1 = row1[0]
# 書き込むときはWorksheetのメソッドが使える
worksheet1.add_cell 0, 0, 'changed'
# 保存
workbook.save

rails new

railsプロジェクトを作ります。 今回は横着してモデルを作らないので、ActiveRecordなどいらないモジュールを生成しないようオプションを付けます。

rails new -MOCJ

ルーティング

excelリソースへのルートを作ります。 加えて、ルートをexcelsにします。

下記とおりルーティングされます

  • GET / -> ExcelsController#show
  • GET /excels -> ExcelsController#show
  • POST /excels -> ExcelsController#create

GET /excelsでファイルを受け取るフォームを表示し、POST /excelsでサーバへのファイルアップロードと編集後ファイルの送信を行います。

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  root to: "excels#show"
  resource :excel, only: [:show, :create]
end

excel-example/routes.rb at master · ytnk531/excel-example · GitHub

コントローラ

showメソッドでは何もせず、ページを表示するだけです。 createにはエクセルファイルが送られて来るので、ファイルの編集とクライアントへの送信を行います。

class ExcelsController < ApplicationController
 def show
 end

 def create
   file = params[:file]
   # ファイルを開く
   workbook = RubyXL::Parser.parse file.path
   # 編集する
   workbook[0].add_cell 0, 0, 'changed'
   # 編集したファイルを送る
   send_data workbook.stream.string, type: file.content_type, filename: 'modified.xlsx'
 end
end

アップロードされたファイルはActionDispatch::Http::UploadedFileオブジェクトとして受け取ることができます。 tempfileに受け取ったファイルそのものが入っているので、RubyXLオブジェクトに変換します。

編集したファイルは、send_dataメソッドを使って送信します。

データとして渡すのは、Workbook#streamで取得できるバイナリのストリームを、Stream#stringで文字列にしたものです。 コンテントタイプを指定する必要がありますが、UploadedFileは受信したときのContent-Typeを記録しているので、同じものを指定しておけばいいでしょう。

excel-example/excels_controller.rb at master · ytnk531/excel-example · GitHub

ビュー

エクセルファイルをアップロードするためのビューを作ります。

<%= form_tag({action: :create}, multipart: true) do %>
  <div>
  <%= file_field_tag :file %>
  </div>
  <div>
  <%= submit_tag "Send" %>
  </div>
<% end %>

https://github.com/ytnk531/excel-example/blob/master/app/views/excels/show.html.erb

ファイル選択と送信ができます。 送信したファイルはExcelsController#createで処理します。

f:id:ytnk531:20190302133745p:plain

試してみる

このようなファイルを用意し、

f:id:ytnk531:20190302031633p:plain

送ってみます。

f:id:ytnk531:20190302140054p:plain

編集されたファイルのダウンロードが始まります。

f:id:ytnk531:20190302135833p:plain

開いてみます。期待通り編集されたエクセルをダウンロードできました。

f:id:ytnk531:20190302135554p:plain

まとめ

  • RubyXLでエクセルの編集ができる
  • アップロードされたファイルはUploadedFileオブジェクトに記録される
  • RubyXLで保存したワークブックは、保存しなくてもデータ送信できる

UploadedFileの存在を知らなかったので、うまくいくかわからなかったのですが、うまくrailsと一緒に使うことができました。

Rails6.0リリースまでの予定

weblog.rubyonrails.org の非公式な日本語訳です。

Timeline for the release of Rails 6.0 Posted by dhh, December 20, 2018 @ 12:00 am in News

Rails6.0に向けて、我々がリリースまでの「楽観的な」予定を公開するのに十分な進捗がありました。リリースよりも「楽観的な」がキーワードです 😄。ソフトウェアが予定通りに公開されるのはまれで、今までたくさんの予定通りに行かなかった野心的なリリース予定日がありました。とはいえ、楽観主義がオープンソースの面白いところとして許容されなければ、我々はどうすればいいでしょう?

というわけで、これが我々が現在それぞれのバージョンについての予定です。

  • 1月15日: Beta 1
    • Action MailboxとAction Textという2つの新しいフレームワークをマージする予定です。
  • 2月1日: Beta2
    • 他にも大きな改善が含まれる予定です。
  • 3月1日: リリース候補版1
    • 新機能はここまでで出揃います。
  • 4月1日: リリース候補版2
    • ほぼリリース直前の状態です。バグ修正だけを行います。
  • 4月30日: 最終リリース
    • RailsConf 2019で、Rails6.0のリリースを祝いましょう!

こうやって並べてみると、すてきできれいに見えますよね?真面目なエンジニアがこれを理解するのに真面目にエンジニアリングをしたように。夢と希望を描いたソフトウェア作家も少なくありません。しかしながら、これが私達がやってきたエンジニアリングの部分なのです。

(訳注:ここぜんぜんわかりませんでした。) 原文:It always looks so nice and neat when laid out like that, right? Like some serious engineers did some serious engineering to figure this out. And not just a bunch of software writers plotting down their hopes and dreams. But yeah, it’s really the engineering part we went for (no it wasn’t).

Rails 6.0にはRuby 2.5が必要です!このバージョンを実行できることを確認して準備できます。また、Rails 6.0のリリースのあとは、 Rails Coreチームによるメジャー、マイナー両方のセキュリティ修正を受けられることが保証されているとはRails 6.x.yとRails5.2.xのみであることに注意してください。(いつものことですが、我々はもっと前のバージョンにも修正版を提供する選択をするかもしれませんが、保証はありません。)

いつものように、もしあなたが新規アプリや既存のアプリをrailsリポジトリのマスターブランチのrailsで動かすという大冒険の遺伝子に突き動かされるなら、(または、バグを踏んでも解雇される恐れがないのなら)、この方針を実現するのを手助けしてください。Basecamp 3はすでに本番環境でrails/masterを可動させているので、このメインブランチはすくなくともとてもよく作業されていということです!

Rails6.0のリリースマネージャは、Kasper Timm Hansenの支援のもと、Rafael Françaとなるでしょう。🙏

To Rails Six Oh And Beyond! 🚀🚂

Ruby on Rails 6.0 beta2がリリースされました

リリースされました

weblog.rubyonrails.org

このベータ第2版のリリースで、Rails6の最終リリースに向けて、また一歩近づきました。我々は、多くの問題を修正し、いくつかのマイナーな機能の追加を行いましたが、大きな変更としては、オートロードの処理をXavierの新しいWeirwerkライブラリに切り替えたことです。これは我々が実行時に依存を要求する方法の大きく、また構造的な変更です。この変更はレガシーな見苦しい機能やおかしな挙動を取り除くはずです。Xavierさんは、あなたが確認するに値する大きな変更を加えました。

それ以外の点は、Beta第1版とほとんど同じです。リリースノートを読んで、6.0の全体像を理解することをおすすめします。

beta 1.0以降追加された532のコミットをより深く確認することもできます。

6.0の最終版について公開したスケジュールに向けて今の所順調に進んでいるので、あなたのアプリケーションの移行計画はその計画を参考にしてください。とはいえ、どうかbeta 2をあなたのアプリケーションでテストして我々を援助してください。中レベル程度のRailsの経験を方なら誰でも、Rails 5.2.xシリーズよりもむしろbeta 2を使って新規のアプリケーションを作ることをおすすめします。BasecampとShopifyはすでにRails 6.0.0 beta2を実稼働させています。

このリリースとRails 6.0最終版までの全てのリリースは、Kasper Timm Hansenの支援のもと、リリースマネージャーであるRafael Françaによって手動されています。

Railsの改善に向けて貢献し続けてくださる全ての方々に、重ねてお礼申し上げます。

とのことです。

Masonry Layoutを使いたい

masonry layout

pinterestみたいなレイアウトを、Masonry(石積み) Layoutと言うらしい。

pin.it

デモ

www.erikjo.com

こんな特性のものをmasonryと呼んでる気がします。

  • サイズの違う要素を並べられる
  • 表示領域のサイズが変わると並べ直す(これがおしゃれ)

二番目は副産物で、masonryのことではないかも?

使いたい

masonryが実装できて、SSR(next.js)対応で、速くて、コンポーネントライブラリを使いたい。

初めてコンポーネントを探した。 まずやりたいことがmasonryだってわかるまでが長かった。 わかってしまえば、githubで「masonry component」とおもむろに調べる。

github.com

でてきた。 Masonryにしたいところをで囲むだけでできる。 reactすごいさすが。

しかし初期表示とウィンドウサイズを変えたときの動きが結構もたつく。

hackernoon.com

この記事の筆者はIsotope · Filter & sort magical layoutsというJSライブラリで、どうして遅いか調べたそうだ。

だいたいこんなかんじ

  • フレキシブルにするための機能が重い
    • 様々なサイズの画像に対応している
    • サイズ変更の再描画に時間がかかる
    • 数百の要素のサイズを取得取得しなければいけない
    • 見えていないところの画像も再描画している

ので、

  • ページが大きくなるにつれて指数関数的に計算が増える。

のだそうです。

で、固定サイズの画像にだけ対応するなど機能を絞ってレイアウトエンジンを実装するくらいしか解決策がないと。

そもそも本当にMasonryにしないと行けないのかっていうのはちゃんと考えたほうが良さそうですね。