Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Initial commit

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

0 notes on commit d5bcbca

Please sign in to comment.
Something went wrong with that request. Please try again.