Lazy Loading and Object Proxying Shenangians

1,206 views

Published on

A presentation delivered to the Ruby on Rails Oceania Melbourne group's October meet up.

Covers how to cleaning organise controller code with object proxying to play well with fragment caching in the views

Published in: Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,206
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
6
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Lazy Loading and Object Proxying Shenangians

  1. 1. Lazy Loading ..and object proxying shenanigans
  2. 2. John Barton www.whoisjohnbarton.com @johnbarton
  3. 3. we’re often* hiring * a month or two ago, right now, a couple of months from now
  4. 4. The Problem:
  5. 5. To handle ever increasing page load through the judicious application of view fragment caching...
  6. 6. ... without resorting to downright ugly code
  7. 7. For Example:
  8. 8. class PostController < ApplicationController def index @posts = Post.all end end
  9. 9. <% @posts.each do |post| %> <%= post.title %> <% end %>
  10. 10. Make it fast:
  11. 11. <% cache 'slow_posts' do %> <% @posts.each do |post| %> <%= post.title %> <% end %> <% end %>
  12. 12. What now?
  13. 13. class PostController < ApplicationController def index @posts = Post.all end end @posts = Post.all is still evaluated ... and it’s expensive
  14. 14. What about? <% cache 'slow_posts' do %> <% Post.all.each do |post| %> <%= post.title %> <% end %> <% end %>
  15. 15. Separation of concerns?
  16. 16. What about? class PostController < ApplicationController def index unless fragment_exist? 'slow_posts' @posts = Post.all end end end
  17. 17. Separation of concerns?
  18. 18. What About? class PostController < ApplicationController def index @posts = lazy_load { Post.all } end end
  19. 19. Still not perfect ... but fuck it ... I’ve got a job to get on with
  20. 20. How?
  21. 21. def lazy_load(&block) LazyLoader.new(&block) end
  22. 22. class LazyLoader instance_methods.each { |m| undef_method m unless m =~ /^__/ } def initialize(&block) @_initializer = block end protected # pass everything to _target def method_missing(method, *args, &block) _target.send method, *args, &block end private # on first call will instantiate itself with _initializer block def _target @_target ||= @_initializer.call end end
  23. 23. Gotchas:
  24. 24. ... or when I realised I wanted to be a Smalltalk programmer
  25. 25. class PostController < ApplicationController def show @post = Post.find(params[:id]) end end <% if @post %> <%= @post.title %> <% end %>
  26. 26. class PostController < ApplicationController def show @post = lazy_load { Post.find(params[:id]) } end end <% cache 'slow_post' do %> <% if @post %> <%= @post.title %> <% end %> <% end %>
  27. 27. NoMethodError: undefined method `title' for nil:NilClass
  28. 28. wtf?
  29. 29. Ruby’s boolean operators don’t ask the objects for their truthyness Word on the street is Smalltalk has that covered* * I don’t know Smalltalk so hopefully I’m not full of shit right here
  30. 30. a = lazy_load { nil } # this is fine nil.nil? # => true a.nil? # => true # this is broken but..... # i can fix it by opening up NilClass a == nil # => true nil == a # => false # but what do i do about these? !!nil # => false !!a # => true if a puts "blah!" end # => "blah!"
  31. 31. Two Solutions:
  32. 32. <% cache 'slow_post' do %> <% unless @post.nil? %> <%= @post.title %> <% end %> <% end %> OR Learn Smalltalk
  33. 33. http://github.com/joho/lazy-loader we’re pretty frickin rad, come work for us

×