This repository has been archived by the owner. It is now read-only.
Permalink
Browse files

Initial commit

  • Loading branch information...
Joe Ferris and Mike Burns authored and jferris committed Aug 2, 2012
0 parents commit d5bcbca7fff10087545d798ddf94bdb28cccf9e9
@@ -0,0 +1,4 @@
+require 'turning/callbacks'
+
+module Turning
+end
@@ -0,0 +1,6 @@
+module ActiveModel::Callbacks
+ def on(event, &block)
+ new_block = lambda { |instance| block.call(instance) }
+ send(:"after_#{event}", &new_block)
+ end
+end
@@ -0,0 +1,13 @@
+module Turning
+ class Controller
+ def initialize(renderer)
+ @renderer = renderer
+ end
+
+ private
+
+ def render(template_name, assigns = {})
+ @renderer.render_to_file(template_name, assigns)
+ end
+ end
+end
@@ -0,0 +1,51 @@
+module Turning
+ class Renderer
+ def initialize(controller_path)
+ @controller_path = controller_path
+ @renderable = Class.new(AbstractController::Base) {
+ include AbstractController::Rendering
+ include AbstractController::Layouts
+ include ActionController::Helpers
+ include Rails.application.routes.url_helpers
+ attr_accessor :view_assigns
+
+ # Search for views based on the controller name
+ attr_accessor :controller_path
+ self.view_paths = 'app/views'
+
+ # Include all helpers from the application's helper paths
+ def self.helpers_path
+ Rails.application.helpers_paths
+ end
+ helper :all
+
+ # We can't protect against forgery in static HTML, because it requires a session
+ def protect_against_forgery?
+ false
+ end
+ helper_method :protect_against_forgery?
+
+ # Look for a "static" layout by default, but don't fail if it doesn't exist
+ def self.name
+ 'StaticController'
+ end
+ layout nil
+ }.new
+ @renderable.controller_path = @controller_path
+ end
+
+ def render_to_file(template_name, assigns)
+ @renderable.view_assigns = assigns
+ target = target_path.join("#{template_name}.html")
+ contents = @renderable.render_to_string(action: template_name)
+ FileUtils.mkdir_p(target_path)
+ File.open(target, 'w') { |file| file.write(contents) }
+ end
+
+ private
+
+ def target_path
+ Rails.root.join('public', 'cached', @controller_path)
+ end
+ end
+end
@@ -0,0 +1,21 @@
+module Files
+ def create_file(path, content)
+ full_path = Rails.root.join(path)
+ FileUtils.mkdir_p(File.dirname(full_path))
+ File.open(full_path, 'w') { |file| file.write(content) }
+ @files ||= []
+ @files << full_path
+ end
+
+ def cleanup_files
+ (@files || []).each do |file|
+ FileUtils.rm_rf(file)
+ end
+ end
+end
+
+RSpec.configure do |config|
+ config.include Files
+
+ config.after(:each) { cleanup_files }
+end
@@ -0,0 +1,27 @@
+module Views
+ def create_view(path, contents)
+ full_path = Rails.root.join('app', 'views', path)
+ FileUtils.mkdir_p(File.dirname(full_path))
+ File.open(full_path, 'w') { |file| file.write(contents) }
+ @view_files ||= []
+ @view_files << full_path
+ end
+
+ def read_cached_view(path)
+ IO.read(Rails.root.join('public', 'cached', path))
+ end
+
+ def cleanup_views
+ (@view_files || []).each do |view_file|
+ FileUtils.rm_rf(view_file)
+ end
+
+ FileUtils.rm_rf(Rails.root.join('public', 'cached'))
+ end
+end
+
+RSpec.configure do |config|
+ config.include Views
+
+ config.after(:each) { cleanup_views }
+end
@@ -0,0 +1,21 @@
+require 'spec_helper'
+require 'turning/callbacks'
+
+describe Turning, 'callbacks' do
+ it 'runs a callback without mangling self' do
+ model_class = Class.new do
+ extend ActiveModel::Callbacks
+ define_model_callbacks :save
+ end
+ ran_with = nil
+
+ model_class.on(:save) do
+ ran_with = self
+ end
+
+ model = model_class.new
+ model.run_callbacks(:save)
+
+ ran_with.object_id.should == self.object_id
+ end
+end
@@ -0,0 +1,51 @@
+require 'spec_helper'
+require 'turning/controller'
+
+describe Turning::Controller do
+ it 'sets up a listener' do
+ listening = false
+ concrete_controller = Class.new(Turning::Controller) do
+ define_method :listen do
+ listening = true
+ end
+ end
+
+ concrete_controller.new(mock_renderer).listen
+
+ listening.should be
+ end
+
+ it 'renders' do
+ concrete_controller = Class.new(Turning::Controller) do
+ def do_it
+ render 'index', greeting: 'hello'
+ end
+ end
+ renderer = mock_renderer
+
+ concrete_controller.new(renderer).do_it
+
+ renderer.should have_rendered('index', greeting: 'hello')
+ end
+
+ it 'renders without assigns' do
+ concrete_controller = Class.new(Turning::Controller) do
+ def do_it
+ render 'index'
+ end
+ end
+ renderer = mock_renderer
+
+ concrete_controller.new(renderer).do_it
+
+ renderer.should have_rendered('index', {})
+ end
+
+ def mock_renderer
+ stub('mock renderer', render_to_file: nil)
+ end
+
+ def have_rendered(template_name, assigns)
+ have_received(:render_to_file).with(template_name, assigns)
+ end
+end
@@ -0,0 +1,40 @@
+require 'spec_helper'
+require 'turning'
+
+describe Turning do
+ it 'listens to events and renders the view to a static file' do
+ controller_class = Class.new(Turning::Controller) do
+ def initialize(renderer, model)
+ super(renderer)
+ @model = model
+ end
+
+ def listen
+ @model.on_update do
+ render 'index', greeting: 'Hello'
+ end
+ end
+ end
+
+ model_class = Class.new do
+ def on_update(&block)
+ @on_update = block
+ end
+
+ def trigger_update
+ @on_update.call
+ end
+ end
+
+ create_view('examples/index.html.erb', '<%= @greeting %>')
+
+ renderer = Turning::Renderer.new('examples')
+ model = model_class.new
+ controller = controller_class.new(renderer, model)
+
+ controller.listen
+ model.trigger_update
+
+ IO.read('public/examples/index.html').should == 'Hello'
+ end
+end
@@ -0,0 +1,50 @@
+require 'spec_helper'
+require 'turning/renderer'
+
+describe Turning::Renderer do
+ it 'renders to a file' do
+ create_view('examples/say_hello.html.erb', '<%= @greeting %>')
+ renderer = Turning::Renderer.new('examples')
+ renderer.render_to_file('say_hello', greeting: 'Hello')
+
+ read_cached_view('examples/say_hello.html').should include 'Hello'
+ end
+
+ it 'supplies built-in helpers' do
+ create_view('examples/go_home.html.erb', '<%= link_to "go home", root_path %>')
+ renderer = Turning::Renderer.new('examples')
+ renderer.render_to_file('go_home', {})
+
+ read_cached_view('examples/go_home.html').should match(%r{<a href=".*">go home</a>})
+ end
+
+ it 'supplies custom helpers' do
+ create_file('app/helpers/greeting_helper.rb', <<-HELPER)
+ module GreetingHelper
+ def greet
+ 'Hello'
+ end
+ end
+ HELPER
+ create_view('examples/greet_hello.html.erb', '<%= greet %>')
+ renderer = Turning::Renderer.new('examples')
+ renderer.render_to_file('greet_hello', {})
+
+ read_cached_view('examples/greet_hello.html').should include 'Hello'
+ end
+
+ it 'disables forgery protection for static forms' do
+ create_view('examples/form.html.erb', "<%= form_tag '/' do %><% end %>")
+ renderer = Turning::Renderer.new('examples')
+ expect { renderer.render_to_file('form', {}) }.not_to raise_error
+ end
+
+ it 'renders with a layout' do
+ create_view('examples/simple.html.erb', 'Hello')
+ create_view('layouts/static.html.erb', 'Check this: <%= yield %>')
+ renderer = Turning::Renderer.new('examples')
+ renderer.render_to_file('simple', {})
+
+ read_cached_view('examples/simple.html').should == 'Check this: Hello'
+ end
+end

0 comments on commit d5bcbca

Please sign in to comment.