This is a working draft of proposal. Feel free to comment, express your opinions and suggest alternative solutions.
As a second part of my Google Summer of Code, I planned to introduce View Classes to Action View.
There was ongoing discussion about this and extracting AV from AP (which is done already: rails/rails#11396) here: https://groups.google.com/forum/#!topic/rubyonrails-gsoc/N7uDY_6513I
The "problem" is becoming more common and people are looking for solution to ERB view templates bloated with too much logic (http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/#view-objects)
I'd like to propose as simple as possible solution which will introduce context argument to render method like following:
class PagesController < ApplicationController
def index
@post = Post.find(params[:post])
render context: PostsShowViewContext.new(@post)
end
endIt will also work for partials in the same way:
render partial: "page_content", context: PostsShowViewContext.new(@post)The render will expect context class instance as an argument. It'll have reference to controller.
The ViewContext class will look like this:
# app/view_models/posts/show.rb
class PostsShowViewContext
include ActionView::ViewContext # pseudo code, something like this will be including AV's stuff.
attr_reader :post
def initialize(post)
@post = post
end
def title
post.title
end
endActionView::ViewContext module will deliver all boilerplate: view helpers, assigns and route helpers
The whole thing would be implemented somewhere in place where ActionView makes rendering happen
# somewhere in ActionView depths
class ActionView::Rendering
def render(options)
if context = options[:context]
context.controller = self
end
end
endThe intention of this change is to introduce "view classes", the object in which context's template would be evaluted. The way it works in tilt for example: https://github.com/rtomayko/tilt#basic-usage
As we all know, it's hard. For me, the best name for this "feature" would be ViewModel (view_model). However there are other candidates:
- View Context
- View Class
- Context
This gist i just a regular git repo. You can find both solutions under the link I've posted in my comment above: https://gist.github.com/strzalek/6267840/249c76563dfb3d2fcf97c76d7546614dbf84d214. You have "first" and "second" solution in there of which I've picked second one and only this one remained in the document.