LoginSignup
12
12

More than 5 years have passed since last update.

RailsでViewのプロトタイピングを支援するGem ViewDataを作った

Posted at

Github halenohi/view_data
https://github.com/halenohi/view_data

こゆうものです

controllerからviewに渡すインスタンス変数を差し替えて、あたかもモデルが実装済みかのように振る舞います

FactoryGirlライクなDSLでデータを定義するのが特徴です

ただしモデルの attribute に相当する部分の命名とデータ形式に制限はありません
このGemではそれをNode(ノード)と呼んでいます。そしてノードが集まった1つの塊をData (データ)と呼んでいます

app/view_data/posts/_post.rb

ViewData.define do
  data :post do
    title 'Awesome Post'
    body 'far far away long time ago...'
  end
end

app/view_data/posts/index.rb

ViewData.define do
  data :posts do
    collection :post, length: 3
  end
end

postデータにはtitleノードとbodyノードを定義しました。
postsデータにはpostデータを配列で3つ内包するように定義しました。

このようにapp/view_data/posts/index.rbapp/view_data/posts/_post.rbというファイルを作成しておくと、app/views/posts/index.html.erbをrenderする際に @posts を定義したデータで差し替えることができます。

差し替えると言ってもcontrollerで先に @posts をセットしていなくても大丈夫です

view内ではモデルのインスタンスのように扱えます

app/views/posts/index.html.erb

<% @posts.each do |post| %>
    <div>
        <h1><%= post.title %></h1>
        <p><%= post.body %></p>
    </div>
<% end %>

関連オブジェクトをシミュレートすることもできます

例えば Post が has_many :comments な関連を持つような場合このように定義します

app/view_data/posts/_post.rb

ViewData.define do
  data :post do
    title 'Awesome Post'
    body 'far far away long time ago...'

    comments do
      collection :comment, length: 3
    end
  end
end

app/view_data/comments/_comment.rb

ViewData.define do
  data :comment do
    body 'StarWars is my favorite movie!'
  end
end

先述にも出てきましたがノードのブロック内で collection というメソッドを使うと指定した名前からデータファイルを探してデータを拾ってきてくれます

データ名に :comment を指定すると自動で app/view_data/comments/_comment.rb を探すようになっています

もちろんview側では関連モデルのように扱えます

<% @posts.each do |post| %>
    <div>
        <h1><%= post.title %></h1>
        <p><%= post.body %></p>

       <div>
         <% post.comments.each do |comment| %>
           <p><%= comment.body %></p>
         <% end %>
       </div>
    </div>
<% end %>

メソッドチェーンでも問題ありません

画像のアップロード等をしている場合 image.url(:thumb) といった感じでメソッドをチェーンして値を取り出す場合もありますよね。
その場合は以下のように定義します

ViewData.define do
  data :post do
    title 'Awesome Post'
    body 'far far away long time ago...'

    image.url 'http://sample.com/example-default.jpg'
    image.url(:thumb) do
      image.url.sub(/default/, 'thumb')
    end
  end
end

割とそのまま書けるといった感じです。
ノードの定義でブロックを使うとそれ以前に定義したノードの値を取り出すことができます。
上記の場合、画像名のdefaultthumb置き換えるだけで先に定義したimage.urlノードの値を再利用しています

またお気づきかもしれませんが、引数によって返す値を切り替えることも可能です。

なぜ作ったか

サーバーサイドとクライアントサイドの作業が分担されていて、別々のコンテキストで作業が進む場合の問題を解決したいと思いました

rubyでWebフロントエンドのプロトタイピングといえば Middleman が主流かと思いますが、出来上がったコードをviewテンプレート化する際にミスったりする可能性はゼロではありません

また、単純に テンプレート化 という作業がDRYではありません。

「プロトタイピングして作ったviewがそのまま実際のモデルで動く」というのがコンセプトです

※ 注)僕はMiddleman好きです :)

あとはシングルページなアプリケーションを作る際にjbuilderとこのgemを組み合わせれば簡単にダミーjson apiが作れると思います。

例えばデザイナーさんでも積極的にRailsの開発に参加していければいいですね!

まだ開発中

とりあえずGemfileにgithub指定してインスコすれば動きますが、いろいろ機能が足りていない(Configurationが無い)とかバグも沢山あるし、ドキュメントも無いしテストも不完全です

「エイやっ!」で作って「動いた!」という段階です

もし興味持って頂ける人がいたらダメ出しとかもらえるととても嬉しいです

12
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
12