ytnk531の日記

日々調べたことを書きます。

"Ask Me Anything" by DHH での質問と答え part2

ここにいる全員にあなたのようにStimulusとturbolinksを使うことを薦めますか?

まず第一に、ブログ、カンファレンスあるいはtwitterで人気のあるものと、実際に作られているアプリケーションで人気のあるものには違いがあります。 私は、それらの間には大きな違いがあるということに気が付きました。 今のところのブログ、カンファレンス、Twitterで人気のあるものは、react.jsやvue.jsあるいは他のツールを使ってたくさんのJavaScriptを記述するものです。 これらは、私には人気があるわけではなくとても誇張されているようにみえるのです。

私はそういったことの見極めについておそらくエキスパートです。 なぜなら、かつてRubyRailsの利用についてまた誇張されていたからです。 2000年台中期に、RubyRailsが人気になったとき、みんながそれについて語っていました。 しかし、実際に書いていたのは一部の人々だけです。

たくさんの人と話をしてみて、turbolinksやstimulusや少ないJavaScriptのアプローチが好きな人がたくさんいるということに気がついたんです。 そういった人々はあまり声を大にして主張しません。 皆さんは彼らの主張を、重厚なJavaScriptフレームワークを使っている人たち程は聞かないでしょう。 ときどき人々は、声を大にして主張されているものが人気のあるものだと誤解してしまいます。 もう一つ言いたいことは、ほとんどのアプリケーションはturbolinksやstimulusのみを使ってシンプルにスタートし、必要性が高まったとき、より洗練された、あるいは複雑なフレームワークに移行したほうがいいということです。

たくさんのアプリケーションがごく僅かなフォームを扱うだけであっても、とても洗練されていて複雑なJavaScriptを備えてスタートしてしまっていることは残念に思います。 ほとんどのアプリケーションの基本的な要求は、10年前と変わっていません。すなわちデータベースを扱うCRUDアプリケーションを作ることです。 そう言うと、それは良くない、もっと洗練されたアプリケーションを作ろうという野望を持つべきだと考える人がいます。 私はそれはくだらないことだと思います。

我々が今日作っているような情報技術における大多数は、良い方法に向かっているとは言えません。 なぜなら、我々は良くしているのではなく、たくさんのアプリケーションにJavaScriptフレームワークを導入するなどの理由で複雑にしてしまっているからです。 多くのアプリケーションは、よりシンプルな方法で開発することで少数の開発者でのデリバリーを高速化した場合などは、良くなったと言っていいでしょう。

BaseCampでの経験で言えば、我々が作ったすべての要素の中で極稀にそういった種類のフレームワークを必要とします。 BaseCampはどちらかといえば、react.js, vue.jsのようなフロントエンドフレームワークを使いサーバがJSONだけを返すようなスタイルが完璧にはフィットしない大規模アプリケーションの典型です。 私は、そのようなスタイルがフィットするアプリケーションは人々が思っているよりも一般的でないと考えています。

あなたはajaxやcoffee scriptを広めました。それって過ちだったのでは?

そうですね。私の失敗です。

それは当初からの計画でしたか?(この辺質問よくわからない)

もっと簡単にしようという思いがありました。 そして、多くのWebアプリケーション、ほとんどのWebアプリケーションは、JavaScriptを使うことで改善できるということに気づきました。もしJavaScriptを全く使えないなら、アプリケーションは良くないものになってしまいます。ただ、どれくらい多く使うかについては選択の余地があります。私はJavaScriptは少量のふりかけとして使うなら、うまく作用すると思います。少しの塩が(料理の)うえに乗っているだけなら風味を与えてくれますが、もしお皿が塩でいっぱいになってしまったら美味しくありません。これは現実にいつも起こっていることです。

人々は、新しいアイディアや進歩を手にしたとき、そのアイディアでどこまでもやって行きたいと思ってしまいます。だってこんなに素晴らしいアイディアなんだから、もしこれをすべてのことに使ったらどうだろうかと考えてしまうのです。そして、すべてのことに使おうと試行錯誤したあとで、悪いアイディアだったということに気づくのです。

今朝、yamlと、yamlXMLと同じ轍を踏んで悪いプログラミング言語として使い始めてしまうかについての記事を読みました。 初めは設定ファイルとして使いますが、次第に条件分岐や変数をはじめプログラミング言語で使える要素を使おうとし、それにもかかわらず設定ファイルとして扱おうとしてしまうために巨大な化け物に変貌してしまうのです。 これは、一度良いと思ったものを使い始めてしまうときの状態とすこし似ています。

良いものは、限られた範囲での特定の運用ではうまくいきます。しかし、詰め込みすぎてしまうと途端に破綻します。

RubyRailsについても、同じようなことが言えます。 これは最高だ!と思うと、適していないことであっても全て同じものを使ってしまうのです。 もともと考えられていたよりも、Rubyrailsの適用範囲は広がっているように思います。 一部はアーキテクチャの優先事項の問題です。

必ずしもいつも正しい方法があるとは考えないほうが良いでしょう。 Webの美しさは、バックエンドでどんなプログラミング言語でも利用できる多様性にあるのです。 私がWebアプリケーションをRubyで書く一方で、他の人はPythonで、また他の人はGoでもJavaでも書くことができて、その上ユーザーはそんなことを気にしないのです。これはwebの固有かつとても特別な特徴です。ほとんどのソフトウェア開発プラットフォームは、特定の開発環境に大きく依存します。iosのアプリを作りたいならばswiftを使わなければならないし、 Androidのアプリを作ろうと思ったらJava を勉強しなければなりません。Web ならそんなことは気にしません。C でもBASICでも、HTMLを生成できる言語なら何でも使うことができます。だから、どれぐらいのJavaScript が使われていればいいのかっていうことだってユーザーは気にしません。シンプルに作ろうが複雑に作ろうが素早く作ろうがユーザは気にしません。Web の素晴らしいところはそういった多様性を許容できるところです。他の開発プラットフォームと違って、人が違えばアイディアも違います。そういったところが Web の本当に美しいところだったと考えています。

"Ask Me Anything" by DHH での質問と答え part1

www.youtube.com

これの質疑応答を日本語にしようとしましたが、ボリュームがすごくて全然ゴールが見えません。多分part5くらいまで行きます。

多分50%くらいは間違ってるんだと思います! 編集リクエスト、指摘、訂正お待ちしてます!!

誰か同じようなもの作ってないかなーとビビりつつ書いてます。 Youtubeの自動文字起こしを参考に書いてます。 日本語字幕つけたかったけど、あれって動画投稿者からのリクエストが必要なんですな~。

Railsdm運営の皆さん、素晴らしい動画を短期間で公開してくださり大変助かっています。本当にありがとうございます!

質問と答え

あなたは今どこにいて、そこは今何時ですか?

カリフォルニア州のマリブにいて、夕方のちょうど6時半です。

簡単に自己紹介をお願いします

私の名前はデイヴィッド・ハイネマイヤー・ハンソンです。Railsの作者で、2003年からRubyで仕事をしておりRailsにも同じ時期から取り組んでいます。Basecamp社の共同創業者で共同出資者で共同経営者です。

Basecampはrailsアプリケーションの起源です。 私はrailsをBasecampの外に持ち出して2004年にリリースし、それ以来ずっとrailsに取り組んできました。

私はRubyの大ファンです。Rubyは私をプログラマーになりたいと思わせ、またプログラマーであり続けたいと感じさせてくれるプログラミング言語です。長い年数経っても未だにRubyでプログラミングをし、楽しめていることをとても誇らしく思います。

2006年のRubyKaigiにRubyプログラマーとして来日したときの思い出を教えてください

とてもよいカンファレンスだったと記憶しています。 日本のRubyカンファレンスに行ったのはその時が初めてで、何に期待すればいいのかもよくわかりませんでしたが、ただただ素晴らしかったです。 とてもたくさんの幸せそうなプログラマーたちがいた事を思い出します。彼らのことを私は知らないのに、彼らはrailsを使っていたんです。 私はときどきオープンソースの開発者として、間違いなく自分のためにrailsをプログラミングしていると思います。私はただ家で座ってrailsを作っていて、私が作ったものを使っているプログラマーが何千人もいることなんて本当に気づいていないんです。 みなさんも、自分が作ったものを知らない誰かが仕事で使っていて、最終的にカンファレンスでそういう人たちに個人的に会ったときはちょっとした衝撃ですよね。信じられないことです。

私は日本でのRubyカンファレンスに行ってからだいぶ時間が経っていると言いましたが、実はプログラミングではなくてレーシングで日本にはほぼ毎年行っています。 だから、東京には10月にしばしば行って、富士スピードウェイでレースをしています。 私はRubyで仕事をし始める前から日本と日本の文化の大ファンなので、ほぼ毎年行けていることが嬉しいです。 いつかRubyKaigiに戻ってきます

一日の中でどれくらいRubyを書いていますか?

週によりますね。 本当に良い週は、ほとんどの時間をRubyを書いて過ごします。 あまり良くない週は、ほとんどプログラミングをしません。 大抵はひどく悪い週です。

少なくとも多くの時間をRubyを書くのに費やす機会を得たときは最高に良い週です。 BaseCampで新しいプロジェクトを動かしているときには、Rubyコードを書くたくさんの機会がありますし、Railsのために働くことにもなります。 Railsの新しいバージョン6のフレームワークであるaction textとaction mailboxは、新しいプロジェクトの成果から展開したものです。

そういった理由で、私は新しいプロジェクトで働くのが大好きです。 私はまっさらな状態からrailsアプリケーションを構築する機会を得ると、新しいアプリケーションで使うときどのようになるか見ます。過去のアプリケーションから新しいアプリケーションで再利用したいアイディアを展開して、railsがもっとできることを探します。 それがたくさんのRubyコードを書くきっかけになります。そういうときはいつもいい日ですね。

実際のところ、JavaScriptは自分で書いていますか?

かなり書いています。 私はここ何年かで、JavaScriptを書くことに前向きになりました。 私が2005年から2006年にJavaScriptを書かなければならなかったとき、たぶん私はあまりハッピーではありませんでした。 JavaScriptはかなり良くなったと思います。 私はJacvaScriptフレームワークの大ファンというわけではありませんが、モダンなツールや私の大好きなJavaScriptのエコシステムは言語自体態を良くしていっています。

Basecampでは、最近自分たちのためのJavaScriptフレームワークを作りました。 とてもミニマルなフレームワークで、Stimulusと呼んでいます。 だいたい2年位前だったと思いますが、クリスマス中座り込んで、我々がBaseCampで書いてきたすべてのJavaScriptコードをみて、どのようにするのか、いくつかの意味と順序を見つけようとしました。

Basecampでは、JavaScriptを書いていますが、モダンJavaScriptと呼ばれるようなものではありません。react.jsやvue.js、それらに類するフロントエンドのフレームワークを使いません。 我々はturbolinksをすべての基本として、たくさんのsprinkleを使い、それらを呼び出すのを好みます。すべてのHTMLで、殆どの場合はサーバーサイドでレンダリングされ、クライアントに送られると、少しの動的な魔法をふりかけます。

最近では、Stimulusを使ってそれらのsprinkleをカプセル化します。 これは、私がJavaScriptを書くのが好きではないということではありません。ただ、ほとんどのアプリケーションが最近他の界隈で考えられているほど大量のJavaScriptを必要としているとは思わないということです。もし、もう少し少ないJavaScriptともう少し多くのRubyで書けるなら、多くのアプリケーションはもっと速く、もっと弾力がある状態で、かつプログラマーがハッピーに作ることができるはずです。

勉強会レポート UIT#6 進化する React.js

UIT#6

フロントエンド開発の勉強会。LINE株式会社が運営していて、1クォーターに1回のペースで開催している。

  • テーマ: 進化する React.js
  • 場所: LINE本社 カフェテラス(新宿ミライナタワー23階)
  • 参加費: 0円
  • 参加人数: 100人
  • 参加方法: connpassで抽選

https://uit.connpass.com/event/119594/

Hooks で作る React.FC

Takepepe / DeNA/デザイン本部・デザインエンジニアリンググループ

https://speakerdeck.com/takefumiyoshii/hooks-tezuo-ru-react-dot-fc

Hooksというreactの新機能を使ってアニメーションを実装できますよという話。 従来はFunction Componentに実装しなければ行けなくて、それが結構辛かったけど、Hooksならもう少しきれいに書けるみたい。 そもそもなんでアニメーションにそこまでこだわって実装するの?に対して深い考察がされていた。要は、コンテキストによってアニメーションが重要となる場合があり、場所を見極めて適切に使うことで機能価値を高められるかもしれませんよ、という話だった。詳細はスライドを見てくださいぜひ。

Page Stack again in React

sunderls / LINE株式会社 - フィナンシャル開発室

https://speakerdeck.com/sunderls/pagestack-in-react-again

  • ユーザーはweb(ブラウザ)よりnative(アプリ)を好む傾向にある
    • そもそもサービス提供者側がアプリ推し
    • とはいえ起動速度、新規ページのロード速度はあまり変わらない
    • ページ繊維時のサクサク感、特に前画面への戻りは圧倒的にnativeのほうが良い
  • nativeのサクサク感をwebに取り入れるために、Page Stackを開発した
    • 表示したのページのDOMをページごとに記録するスタックを持つReactComponentを作った
    • 戻るときはスタックから取り出すのでサクサク!
    • 画面遷移が多いとスタックが多くなりすぎて重たくなってしまうので、アプリの性質によって使えたり使えなかったりする
    • スタックのサイズは設定できる

native > webの構図に対して一石投じたい!という取り組みでした。どうしてそんな構図になってるか?に対する考察が大変興味深かったです。 nativeとwebでページロードがそんなに変わらないっていうのが、動画で比較されててめちゃくちゃわかりやすかったです。

現場から届けるReactの悩みと改善

sakito / ヤフー株式会社 https://speakerdeck.com/mukai21/xian-chang-karajie-kerureactpuroziekutofalsenao-mitogai-shan

開発していく中で、UIまわりのコードが複雑になりすぎて開発スピードが落ちてきていたので、いろいろ技術を導入して解決しようと奮闘した話。 - TypeScript - Emotion - Formik - Re-ducks - Immer

アプリに対して適切な技術を取り入れて改善していくの、かなり大変だと思うけど、どんどんやっていけるのはsakitoさんのパワーかなと思った。すごい。 導入する前の準備を他のエンジニアを巻き込んで丁寧にやっていたみたいなので、そのへんの根回しというか技術からちょっと外れてるけどすごく大事なノウハウを聞けたのすごく良かった。もうすこし踏み込んで話し聞ければよかったな(質問すればよかった)

所感

どの発表も、なぜそれをやるのか、どんな価値があるのかというところを丁寧に説明していたのが印象的だった。UIに対してどんな貢献があるのか、UIが変わるとユーザーがどう嬉しいのかという点について発表者の考察が聞けたのでわかりやすかった。今回はreact.jsが副題に入ってはいるが、そこまでreact.jsに特化した話でもなかった(ように聞けるプレゼンだった)。

懇親会への参加は20名程度。ピザとかオードブルがたくさん出てきてとても豪華でした。

potato4dさんが司会なさってました。司会上手でした。すごい。

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

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

今、やりたいこと

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

今まで目指してきたもの

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

学生時代~社会人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と一緒に使うことができました。