Actually, the assigns didn't seem to be a major issue. I'm struggling a bit with the output buffering though.
Can I start a Work In Progress PR on GitHub? I have a few ideas for how to proceed, but I'd like to get some feedback soon :-) On Wednesday, May 29, 2013 8:17:31 PM UTC+2, Daniel Schierbeck wrote: > > That's my biggest worry as well. I'll give it a shot - I have an idea for > how I can cut the problem into smaller steps. > > On Wednesday, May 29, 2013 7:38:13 PM UTC+2, Jeremy Kemper wrote: >> >> Go for it, Daniel! >> >> I think you'll find that handling references to local & instance vars is >> the fly in the ointment. Method-missing doesn't cut it since it's very low >> precedence compared to a real local var. >> >> >> On Wed, May 29, 2013 at 7:41 AM, Daniel Schierbeck <[email protected] >> > wrote: >> >>> Hi guys, >>> >>> I think this may be too daunting a task, but I'd like to propose a >>> change to the way views are rendered in Rails. >>> >>> Currently, a template handler converts a template to a string containing >>> Ruby code, which then gets evaluated in a context that has certain >>> variables present. The code is actually stored as a method on a module as >>> far as I can see. >>> >>> This is all well and good, but I'm interested in using multi-gets to >>> efficiently cache the rendering of a collection of objects. Right now I see >>> no easy way to do it in PartialRenderer, since the state of the rendering >>> is shared between each render. The current code is something like this: >>> >>> collection.map do |object| >>> locals[as] = object >>> template.render(view, locals) # returns a string. >>> end >>> >>> I think the code would be more robust, maintainable, and generally just >>> easier to work with if the compiled views were instead classes that looked >>> like this: >>> >>> class SomeAnonymousCompiledView >>> def initialize(context, locals = {}) >>> @context, @locals = context, locals >>> end >>> >>> def render >>> output_buffer = "" >>> output_buffer << "<h1>I was rendered by ERB!</h1>" >>> output_buffer << some_local >>> output_buffer >>> end >>> >>> # Template handlers can optionally define a cache_key method. This >>> could e.g. >>> # encapsulate the stuff currently handled by Cache Digests, but >>> could also use >>> # the locals. >>> def cache_key >>> @locals[:fiddle] >>> end >>> >>> def method_missing(*args) >>> # This could be a way to handle local lookups. >>> end >>> end >>> >>> The project I'm working on, Curly, is a template handler that has a >>> built-in concept of presenters. Say there's a template >>> "posts/show.html.curly" containing the following: >>> >>> <h1>{{title}}</h1> >>> >>> It would have a matching presenter in >>> "app/presenters/posts/show_presenter.rb": >>> >>> class Posts::ShowPresenter < Curly::Presenter >>> presents :post # the controller would assign @post >>> >>> def title # the return value is inserted in the template when >>> rendered >>> post.title >>> end >>> >>> # Right now Curly generates code that checks the cache key and uses >>> # Action View's existing cache system with the given key. This >>> cannot work >>> # when rendering a collection, unfortunately. >>> def cache_key >>> post >>> end >>> end >>> >>> I'd love to have my template handler generate the following class: >>> >>> class CompiledPostsShowView >>> def initialize(context, locals = {}) >>> @context, @locals = context, locals >>> end >>> >>> def render >>> @rendered ||= "<h1>#{presenter.title}</h1>" >>> end >>> >>> # This would be used automatically by Rails if defined. >>> def cache_key >>> presenter.cache_key >>> end >>> >>> private >>> >>> def presenter >>> @presenter ||= >>> Curly.presenter_for_path(@context.virtual_path).new(@context, @locals) >>> end >>> end >>> >>> By wrapping each instance of a rendering in an object, we can >>> encapsulate and carry around the state, reusing the cache key in multiple >>> locations. >>> >>> I'm not sure how easy it would be to retrofit this on top of ERB, but it >>> should be possible. >>> >>> I'd be willing to put in the work, I just want to know if this is >>> something Core is interested in. >>> >>> Cheers, >>> Daniel (@dasch) >>> >>> -- >>> You received this message because you are subscribed to the Google >>> Groups "Ruby on Rails: Core" group. >>> To unsubscribe from this group and stop receiving emails from it, send >>> an email to [email protected]. >>> To post to this group, send email to [email protected]. >>> Visit this group at >>> http://groups.google.com/group/rubyonrails-core?hl=en. >>> For more options, visit https://groups.google.com/groups/opt_out. >>> >>> >>> >> >> -- You received this message because you are subscribed to the Google Groups "Ruby on Rails: Core" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/rubyonrails-core?hl=en. For more options, visit https://groups.google.com/groups/opt_out.
