Add support for view classes

234 views
Skip to first unread message

gliga....@gmail.com

unread,
Apr 15, 2013, 2:34:29 AM4/15/13
to rubyonra...@googlegroups.com
Hi,

My name is Andrei and I'm a student at Polytechnics University of Bucharest in the 3rd year at the Computer Science department.
I have experience developing Ruby and Ruby on Rails apps for almost one year and I can say that Ruby is my primary developing language. It really makes the developer happy.

I am interested in participating this year's GSOC with the "Add support for view classes" project.
I really like the idea of having some of the code into a class only for the View. Sometimes you don't want part of the code to be in the Controller and the Helpers makes your code available to all the Controllers actions, not just for the one you need it and it's really ugly to write the code into the view. In my little experience with Rails I've had this problem once or twice and I've ended writing the code into the Controller.

I really like the way the Cells gem is solving this problem, classes not colliding with other views, being the controllers for their own views and calling the partial with a simple render :cell.
 Maybe I'm missing something from the picture. I've never worked before with Cells, I'm now playing with it for the first time :D

This is what I've understand about this project, creating some mini-controller to handle their own actions without colliding with other things. Did I understand it right? Maybe there are a few more things that I'm missing.

As for the implementation part, I've never fixed a bug or done something with the ActionPack code but as the skills requirement says I just need to know Ruby and RoR.

You can see some of my projects on my Github account [1].
[1] - https://github.com/otzy007

Andrew White

unread,
Apr 16, 2013, 7:27:08 AM4/16/13
to gliga....@gmail.com
On 15 Apr 2013, at 07:34, gliga....@gmail.com wrote:

> This is what I've understand about this project, creating some mini-controller to handle their own actions without colliding with other things. Did I understand it right? Maybe there are a few more things that I'm missing.

Early versions of Rails had a feature called components which had their own controllers, models, views, etc. Cells is somewhat similar to that and we explicitly don't want to re-introduce this kind of functionality.

What it is more about is encapsulation - eliminating the global helper & instance variable soup. This could be joint project with the Action View / Action Controller split - there's probably a lot of common ground.


Andrew White
Ruby on Rails GSoC Administrator

apot...@gmail.com

unread,
Apr 18, 2013, 1:13:41 AM4/18/13
to rubyonra...@googlegroups.com, gliga....@gmail.com
A first step/thought could be to make ActionView's rendering engine replaceable by something like tilt. I did that years ago and in the end there was no coupling anymore between the view and the controller. It also helps to establish a strong interface. Using tilt's render interface made it really easy to have a view model-like behavior. Just an idea.

Guillermo Iguaran

unread,
Apr 18, 2013, 2:01:22 AM4/18/13
to rubyonra...@googlegroups.com, gliga....@gmail.com, apot...@gmail.com
@apotonick, maybe you want to be mentor for this idea? ;)

iirc, we still waiting for https://github.com/rtomayko/tilt/pull/107 to adopt Tilt in Rails, maybe fine add this as another idea for GSoC?

-- 
Guillermo Iguaran

Nick Sutterer

unread,
Apr 18, 2013, 2:40:20 AM4/18/13
to rubyonra...@googlegroups.com
On Thu, Apr 18, 2013 at 4:01 PM, Guillermo Iguaran <guille...@gmail.com> wrote:
@apotonick, maybe you want to be mentor for this idea? ;)

Ha- I'm definitely up for that. I will do my best to support people who are willing to clean up ActionView.
 
iirc, we still waiting for https://github.com/rtomayko/tilt/pull/107 to adopt Tilt in Rails, maybe fine add this as another idea for GSoC?

Yepp, tilt as an AV replacement would be a nice GSoC task!!!

Regarding the view model concept, there should be more discussion on
* replacing helpers and instance variables (by changing/extending the ViewContext, etc)
* making view inheritance more useful with partials (as it is already done in cells)
* conventions


Ferris Tseng

unread,
Apr 18, 2013, 3:06:37 PM4/18/13
to rubyonra...@googlegroups.com
Hi, my name is Ferris, I'm a student at the University of Virginia. I'm interested in contributing to cleaning up ActionView. I have never worked with the rails source code (though, I have made application using rails), so is there anything I should read to better understand what is going on in the background? Can you also explain the ViewContext and how it relates to helpers and instance variables?
Thanks! 

Andrew White

unread,
Apr 19, 2013, 4:58:47 AM4/19/13
to rubyonra...@googlegroups.com
On 18 Apr 2013, at 20:06, Ferris Tseng <ferri...@gmail.com> wrote:

> Hi, my name is Ferris, I'm a student at the University of Virginia. I'm interested in contributing to cleaning up ActionView. I have never worked with the rails source code (though, I have made application using rails), so is there anything I should read to better understand what is going on in the background?

Reading this is a good start to understand the Action Controller / Action View interface:

http://yehudakatz.com/2009/07/19/rails-3-the-great-decoupling/


> Can you also explain the ViewContext and how it relates to helpers and instance variables?

The view context is an anonymous class created by Action Controller inheriting from ActionView::Base that has the route helpers and view helpers mixed into it. It provides the context for rendering the templates and is where the instance variable you assign in the controller are copied to. So for example when the ERb code <%= @product.name %> is executed, self is an instance of this anonymous class.

Andrew White

unread,
Apr 19, 2013, 6:43:18 AM4/19/13
to rubyonra...@googlegroups.com
On 18 Apr 2013, at 07:40, Nick Sutterer <apot...@gmail.com> wrote:

> Regarding the view model concept, there should be more discussion on
> * replacing helpers and instance variables (by changing/extending the ViewContext, etc)
> * making view inheritance more useful with partials (as it is already done in cells)
> * conventions

I know that the instance variable interface between controllers and views has it's detractors but I don't think there's any consensus in the Core Team that this needs to be changed. However I'm sure that there would be agreement that we should be able to support a variety of interfaces.

Please feel free put forward any ideas you have, Nick :-)

Ferris Tseng

unread,
Apr 20, 2013, 6:48:11 PM4/20/13
to rubyonra...@googlegroups.com
Ok, so as I understand it the objective would be to remove "the interface between ActionController and ActionView" (the article provides 4 points on how this interface is defined). Removing this interface would allow you to support multiple interfaces to generate views with instead of being forced to use ActionView with ActionController. Did I understand that correctly?

John Wang

unread,
Apr 21, 2013, 8:12:45 PM4/21/13
to rubyonra...@googlegroups.com
I have a couple of ideas for how views could be improved. Talking with Nick Sutterer, however, it seems that a lot of what I'm proposing overlaps with the functionality of cells. Here's my proposal: https://gist.github.com/wangjohn/09f054c15d777997242a. I'm still thinking of ideas and trying to flesh out more thoughts.

apot...@gmail.com

unread,
Apr 21, 2013, 8:14:42 PM4/21/13
to rubyonra...@googlegroups.com


On Sunday, April 21, 2013 8:48:11 AM UTC+10, Ferris Tseng wrote:
Ok, so as I understand it the objective would be to remove "the interface between ActionController and ActionView" (the article provides 4 points on how this interface is defined). Removing this interface would allow you to support multiple interfaces to generate views with instead of being forced to use ActionView with ActionController. Did I understand that correctly?

Well, actually one task could be introducing an interface between AV and AC. Currently, there's still a coupling between those two, but it would be cool (eh, that's my opinion, btw), if the interface would look like this.

in controller:
  av.render("path/to/template", locals, context)

the AV instance used here shouldn't know anything about AC internals so the actual rendering implementation (av.render) could also be done by tilt:

  rails_tilt_instance.render("path/to/template", locals, context)

This change wouldn't have any benefit for the end user but would improve the architecture and make us think about what is needed where.

Note that this task wouldn't be directly associated with the original view class task. :-)

Ferris Tseng

unread,
Apr 21, 2013, 9:30:20 PM4/21/13
to rubyonra...@googlegroups.com
Would that task be essentially the same thing as / could it be done simultaneously with removing ActionView from ActionPack? 

av.render("path/to/template", locals, context)
 
 rails_tilt_instance.render("path/to/template", locals, context)

I also like the interface that you suggested. In this interface, what would the context be if it the view context currently must include ActionView::Context? Would you still want the ActionController to know anything about AV or just make it assume nothing about which rendering implementation to use?

Also, should I start a new thread if our discussion is deviating from the original task described here?

apot...@gmail.com

unread,
Apr 21, 2013, 11:53:43 PM4/21/13
to rubyonra...@googlegroups.com
I'm fine with discussing all our ideas in this thread for now and I'm very glad to see people are actually interested in improving Rails views!


Extracting AV from ActionPack + making AV replaceable (by introducing the discussed API) would imo be the same task.

The context in my example could be anything as long as it would respond to the "helper" methods used in view template (that's what a "view context" is all about). I just stole this from tilt btw since I do like it very much.

Currently, you can still find coupling of AV and AC in the core code, e.g. daching logic does know about both view internals and controller privates, which is simply making things harder to maintain.

apot...@gmail.com

unread,
Apr 22, 2013, 12:02:02 AM4/22/13
to rubyonra...@googlegroups.com
On Monday, April 22, 2013 10:12:45 AM UTC+10, John Wang wrote:
I have a couple of ideas for how views could be improved. Talking with Nick Sutterer, however, it seems that a lot of what I'm proposing overlaps with the functionality of cells. Here's my proposal: https://gist.github.com/wangjohn/09f054c15d777997242a. I'm still thinking of ideas and trying to flesh out more thoughts.

Here's a brief overview of what John proposes (if I understood the gist correctly, of course):

* He introduces a concept called "landscapes" which is kindof a view context.
* landscapes contain "helper" methods
* still using normal partials
* when rendering a landscape partial, you have to provide the landscape instance

render partial: :comment, landscape: CommentLandscape.new(@comment)

class CommentLandscape < AV::Landscape
  ...
  def from
    @comment.created_at.human_readable
  end
end

His main intend seems to be to move helper/decorator logic into a separate asset, the landscape. That is a good thing.

John: what would make a landscape different to a, say, Draper decorator?




Andrew White

unread,
Apr 22, 2013, 6:19:51 AM4/22/13
to rubyonra...@googlegroups.com
On 22 Apr 2013, at 04:53, apot...@gmail.com wrote:

> I'm fine with discussing all our ideas in this thread for now and I'm very glad to see people are actually interested in improving Rails views!

Whilst I'm fine with discussing the ideas in the one thread since there's a lot of overlap I'd say it still needs to be treated as two separate projects when applications are submitted - otherwise it's a lot of work for one student.

Andrew White

unread,
Apr 22, 2013, 6:41:37 AM4/22/13
to rubyonra...@googlegroups.com
On 22 Apr 2013, at 05:02, apot...@gmail.com wrote:

> His main intend seems to be to move helper/decorator logic into a separate asset, the landscape. That is a good thing.

Agree with being able to move helper/decorator logic into a separate file is a good thing but not keen on John's ideas in his gist - sorry John! I think it needs to be an opt-in solution that can be done progressively through an application. There's currently an anonymous view context class being generated - I think we can layer the concrete view classes on top of this. Unfortunately the app/views path is already taken and I'd be wary of using app/decorators since there's a big likelihood we will break existing apps.

> John: what would make a landscape different to a, say, Draper decorator?

The obvious difference at the moment is that a Landscape is for a whole view whereas a Draper decorator is model-based (I know that Steve Klabnik wants to remove this limitation in the future). I think any solution we adopt must not be model-based.

Andrew White

unread,
Apr 22, 2013, 6:41:45 AM4/22/13
to rubyonra...@googlegroups.com
On 22 Apr 2013, at 04:53, apot...@gmail.com wrote:

> Currently, you can still find coupling of AV and AC in the core code, e.g. daching logic does know about both view internals and controller privates, which is simply making things harder to maintain.

The hardest problem to solve is how to deal with view paths. Logically you should just pass the template path to the renderer and then it should find the template that best matches that path. This means moving a bunch of code dealing with layout/template inheritance into Action View which is likely to be very messy.

The current API should be able to be tweaked quite easily - you have view_renderer, view_context_class and view_context which is an instance of view_context_class. There should be a configuration mechanism which allows a gem's Railtie to setup these values and then it's just a case of the view_renderer supporting `render(view_context, options)`. The view_context_class needs to accept the view_renderer, view_assigns and controller instance in its initialize method. The ActionController::Renderers code would also need to be moved to Action View so that it's responsible for handling the `render :xml => @model` options.

This would allow the Rails API project to cleanly add Active Model Serializers as a replacement renderer for Action View without having to monkey patch _handle_render_options.

José Valim

unread,
Apr 22, 2013, 5:49:10 PM4/22/13
to rubyonra...@googlegroups.com

The hardest problem to solve is how to deal with view paths. Logically you should just pass the template path to the renderer and then it should find the template that best matches that path. This means moving a bunch of code dealing with layout/template inheritance into Action View which is likely to be very messy.

I agree with this. This is one of the responsibilities shared by both controllers and views. Views need to look for templates to render them (for example, a partial, or any kind of rendering, really). Controllers needs to look for templates too, in order to set the proper response content type.

To complicate matters, Rails considers many factors when looking up for a template:

* The view paths registered in the controller
* The request format and locale
* The controller prefixes (like users for UsersController)

Therefore the API previously proposed  (av.render("path/to/template", locals, context) considers just one third of the actual information required to lookup a template. Maybe we need to compile all those requirements in a template query so we can pass to AV (which is pretty much what the lookup context is).
  
The ActionController::Renderers code would also need to be moved to Action View so that it's responsible for handling the `render :xml => @model` options.

I disagree actually. Those renderers are actually the only rendering code in Rails controllers that doesn't depend on AV. :)

We should maybe provide an option to extend an existing renderer, which is pretty much what Active Model Serializers need.

apot...@gmail.com

unread,
Apr 22, 2013, 10:04:34 PM4/22/13
to rubyonra...@googlegroups.com


On Tuesday, April 23, 2013 7:49:10 AM UTC+10, José Valim wrote:

The hardest problem to solve is how to deal with view paths. Logically you should just pass the template path to the renderer and then it should find the template that best matches that path. This means moving a bunch of code dealing with layout/template inheritance into Action View which is likely to be very messy.

I agree with this. This is one of the responsibilities shared by both controllers and views. Views need to look for templates to render them (for example, a partial, or any kind of rendering, really). Controllers needs to look for templates too, in order to set the proper response content type.

To complicate matters, Rails considers many factors when looking up for a template:

* The view paths registered in the controller
* The request format and locale
* The controller prefixes (like users for UsersController)
Well, shouldn't the whole lookup happen in the controller, which knows best about view paths, inheritance and request formats? It would just pass this information to AV which can still provide the rendering by exposing the proposed #render API?!?!

apot...@gmail.com

unread,
Apr 22, 2013, 10:06:49 PM4/22/13
to rubyonra...@googlegroups.com

Well, shouldn't the whole lookup happen in the controller, which knows best about view paths, inheritance and request formats? It would just pass this information to AV which can still provide the rendering by exposing the proposed #render API?!?!

I meant to say: the lookups can happen in AV as well but the informations needed (suffixes, pathes, inheritance, prefixes) should be passed from the controller which knows best about these things.

Nick Sutterer

unread,
Apr 22, 2013, 10:11:49 PM4/22/13
to rubyonra...@googlegroups.com
Aaaaaaaaaaah I mean a something like this

AV.new(suffixes, prefixes, pathes).render(template_name, locals)

:-)

José Valim

unread,
Apr 22, 2013, 10:18:39 PM4/22/13
to rubyonra...@googlegroups.com
On Mon, Apr 22, 2013 at 8:06 PM, <apot...@gmail.com> wrote:

Well, shouldn't the whole lookup happen in the controller, which knows best about view paths, inheritance and request formats? It would just pass this information to AV which can still provide the rendering by exposing the proposed #render API?!?!

I meant to say: the lookups can happen in AV as well but the informations needed (suffixes, paths, inheritance, prefixes) should be passed from the controller which knows best about these things.

This is exactly what happens today. My point is exactly that there are a bunch of objects inherently shared by both the controller and view, which makes this harder. We already delegate most of it to the view anyway, the controller just gathers information (lookup context), builds the view context and send it all to the view renderer.

AV.new(suffixes, prefixes, paths).render(template_name, locals)

Well, this is pretty much what we have today:

ViewRenderer.new(lookup_context).render(view_context, options)

The information is in the lookup context (prefixes, formats and what not), the rendering context in view_context (an instance of AV::Base) and the template name and locals inside options. You have all the information, it is just passed down differently.

apot...@gmail.com

unread,
Apr 23, 2013, 1:57:36 AM4/23/13
to rubyonra...@googlegroups.com, jose....@plataformatec.com.br

Well, this is pretty much what we have today:

ViewRenderer.new(lookup_context).render(view_context, options)


I do like how Renderer, LookupContext and ViewPaths are designed with decoupling in mind.

To boil it down, what happens after the lookup is the following (in pseudo code):

Template.new("path/we/just/figured/out").render(..)

It'll be cool to have this "layer" being replaceable, so Template and everything below would come from tilt. So when I was talking about #render it referred to Template#render, sorry for that (I was confused myself). What do you think of that?

Ferris Tseng

unread,
Apr 23, 2013, 5:54:54 PM4/23/13
to rubyonra...@googlegroups.com, jose....@plataformatec.com.br

The current API should be able to be tweaked quite easily - you have view_renderer, view_context_class and view_context which is an instance of view_context_class. There should be a configuration mechanism which allows a gem's Railtie to setup these values and then it's just a case of the view_renderer supporting `render(view_context, options)`. The view_context_class needs to accept the view_renderer, view_assigns and controller instance in its initialize method. The ActionController::Renderers code would also need to be moved to Action View so that it's responsible for handling the `render :xml => @model` options. 

To me this solution makes a lot of sense, and is very flexible as well. This solution also seems to have the added benefit of being able to eventually remove ActionView into a separate gem (another proposed task), with the only requirement being the Railtie to set up the proper configuration.

Andrew White

unread,
Apr 24, 2013, 5:11:18 AM4/24/13
to rubyonra...@googlegroups.com
On 23 Apr 2013, at 22:54, Ferris Tseng <ferri...@gmail.com> wrote:

>> The ActionController::Renderers code would also need to be moved to Action View so that it's responsible for handling the `render :xml => @model` options.
>
> To me this solution makes a lot of sense, and is very flexible as well. This solution also seems to have the added benefit of being able to eventually remove ActionView into a separate gem (another proposed task), with the only requirement being the Railtie to set up the proper configuration.

I know José doesn't agree with me here but just to make it clear is that I think that the view renderer should be responsible for handling render options - that's more than just moving the ActionController::Renderers into Action View. By doing this we make the render interface as abstract as possible so that alternative view engines can support whatever is appropriate, e.g:

def render(*args)
renderer.render(*args, self)
end

with the renderer creating the view context, lookup context, merging helpers, etc. This would allow API applications to bypass most of the context initialization process that ends up being irrelevant (locale, formats, etc.) if all you're pushing out is JSON.

Łukasz Strzałkowski

unread,
Apr 27, 2013, 11:04:00 AM4/27/13
to rubyonra...@googlegroups.com
Hey guys,

I ask this question here as it's general thread about AP & AV.

I would like to send proposal with the idea of splitting out AV from AP. It's basically one week of work more or less. It's a matter of finishing the work which was already done by @drogus. Thus I thought that adding tilt to this idea would good in terms of extending scope, but Jose warned me that there's no consensus on integrating tilt with Rails.

Also, because splitting AV from AP and tilt thing (not that much of work as well imo) are relativel small tasks I think that idea of one GSoC project composed of:

* Splitting out AV
* Integrating with tilt
* Adding support for view classes

If absolutely valid and doable in my eyes, and hell yeah, I'd love to work on this during summer.

What do you think? What's the core team opinion on tilt?

José Valim

unread,
Apr 28, 2013, 12:40:40 AM4/28/13
to rubyonra...@googlegroups.com, Konstantin Haase
I am copying Konstantin because I think he tweeted Sinatra is moving away from Tilt and if this is the case, we should understand why and discuss if it would still be beneficial to Rails.

José Valim
Skype: jv.ptec
Founder and Lead Developer

Nick Sutterer

unread,
Apr 28, 2013, 3:59:54 AM4/28/13
to rubyonra...@googlegroups.com
Sorry that whole tilt-thing was my idea - I am not saying we need tilt in Rails, I just would love to "evaluate" how much core-code we could save by using a template gem. Is there anything else worth looking into tpl-wise?

Andrew White

unread,
Apr 28, 2013, 4:01:17 AM4/28/13
to rubyonra...@googlegroups.com
> On Sat, Apr 27, 2013 at 9:04 AM, Łukasz Strzałkowski <strz...@gmail.com> wrote:
>
> * Integrating with tilt

On 28 Apr 2013, at 05:40, José Valim <jose....@plataformatec.com.br> wrote:

> I am copying Konstantin because I think he tweeted Sinatra is moving away from Tilt and if this is the case, we should understand why and discuss if it would still be beneficial to Rails.

Just to be clear, integrating Tilt isn't part of the proposal idea - any Tilt integration with Rails is for either the Tilt team or a third-party to produce. That said if you want to be that third-party it's fine, we just won't be shipping it as part of the core Rails framework. :-)

Łukasz Strzałkowski

unread,
Apr 28, 2013, 5:49:49 AM4/28/13
to rubyonra...@googlegroups.com
Allright, that's clear now. Andrew, what about making one idea out of Spliting AV and Supporting view classes?

--
Łukasz.


2013/4/28 Andrew White <an...@pixeltrix.co.uk>

Andrew White

unread,
Apr 28, 2013, 7:40:07 AM4/28/13
to rubyonra...@googlegroups.com
On 28 Apr 2013, at 10:49, Łukasz Strzałkowski <lukasz.st...@gmail.com> wrote:

> Allright, that's clear now. Andrew, what about making one idea out of Spliting AV and Supporting view classes?


That's something we've discussed internally, whether the splitting of AC of AV was enough work for a full project and whether supporting view classes should be rolled into it. I think probably the best idea is to leave the decision on whether it's too much up to the student applicants themselves - they're in the best position to determine whether they're capable.

So if you want to make a single joint application then please go ahead but you'll need to convince us that you're capable of handling the workload and that you'll be available throughout the summer - no month long hiking trips! :-)
Reply all
Reply to author
Forward
0 new messages