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
end
It 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
end
ActionView::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
end
The 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
I've been interested in abstractions between the controller and view.
Some are:
Learning from Django: slides / video.