Skip to content
This repository

Extract an overridable PageFinder class #42

Closed
wants to merge 2 commits into from

2 participants

Mike Burns Joe Ferris
Mike Burns
Owner

Some extra flexibility, per a discussion on #38.

Mike Burns mike-burns referenced this pull request
Closed

Fallback to index #38

lib/high_voltage/page_finder.rb
... ... @@ -0,0 +1,32 @@
  1 +module HighVoltage
  2 + class PageFinder
1
Joe Ferris Owner

A class-level comment on this fella would be nice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Joe Ferris
Owner

I had one minor comment. This is good to merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
30 README.md
Source Rendered
@@ -115,6 +115,36 @@ Then modify it to subclass from High Voltage, adding whatever you need:
115 115 end
116 116 end
117 117
  118 +Custom finding
  119 +--------------
  120 +
  121 +You can further control the algorithm used to find pages by overriding
  122 +the `page_finder_factory` method:
  123 +
  124 + class PagesController < HighVoltage::PagesController
  125 + private
  126 +
  127 + def page_finder_factory
  128 + Rot13PageFinder
  129 + end
  130 + end
  131 +
  132 +The easiest thing is to subclass `HighVoltage::PageFinder`, which
  133 +provides you with `page_id`:
  134 +
  135 + class Rot13PageFinder < HighVoltage::PageFinder
  136 + def find
  137 + paths = super.split('/')
  138 + directory = paths[0..-2]
  139 + filename = paths[-1].tr('a-z','n-za-m')
  140 +
  141 + File.join(*directory, filename)
  142 + end
  143 + end
  144 +
  145 +Use this to create a custom file mapping, clean filenames for your file
  146 +system, A/B test, and so on.
  147 +
118 148 Testing
119 149 -------
120 150
31 app/controllers/high_voltage/pages_controller.rb
... ... @@ -1,11 +1,11 @@
1   -class HighVoltage::PagesController < ApplicationController
2   - VALID_CHARACTERS = "a-zA-Z0-9~!@$%^&*()#`_+-=<>\"{}|[];',?".freeze
  1 +require 'high_voltage/page_finder'
3 2
  3 +class HighVoltage::PagesController < ApplicationController
4 4 unloadable
5 5 layout Proc.new { |_| HighVoltage.layout }
6 6
7 7 rescue_from ActionView::MissingTemplate do |exception|
8   - if exception.message =~ %r{Missing template #{content_path}}
  8 + if exception.message =~ %r{Missing template #{page_finder.content_path}}
9 9 raise ActionController::RoutingError, "No such page: #{params[:id]}"
10 10 else
11 11 raise exception
@@ -16,22 +16,17 @@ def show
16 16 render :template => current_page
17 17 end
18 18
19   - protected
  19 + private
20 20
21   - def current_page
22   - "#{content_path}#{clean_path}"
23   - end
24   -
25   - def clean_path
26   - path = Pathname.new("/#{clean_id}")
27   - path.cleanpath.to_s[1..-1]
28   - end
  21 + def current_page
  22 + page_finder.find
  23 + end
29 24
30   - def content_path
31   - HighVoltage.content_path
32   - end
  25 + def page_finder
  26 + page_finder_factory.new(params[:id])
  27 + end
33 28
34   - def clean_id
35   - params[:id].tr("^#{VALID_CHARACTERS}", '')
36   - end
  29 + def page_finder_factory
  30 + HighVoltage::PageFinder
  31 + end
37 32 end
37 lib/high_voltage/page_finder.rb
... ... @@ -0,0 +1,37 @@
  1 +module HighVoltage
  2 + # A command for finding pages by id. This encapsulates the concepts of
  3 + # mapping page names to file names.
  4 + class PageFinder
  5 + VALID_CHARACTERS = "a-zA-Z0-9~!@$%^&*()#`_+-=<>\"{}|[];',?".freeze
  6 +
  7 + def initialize(page_id)
  8 + @page_id = page_id
  9 + end
  10 +
  11 + # Produce a template path to the page, in a format understood by
  12 + # `render :template => find`
  13 + def find
  14 + "#{content_path}#{clean_path}"
  15 + end
  16 +
  17 + def content_path
  18 + HighVoltage.content_path
  19 + end
  20 +
  21 + protected
  22 +
  23 + # The raw page id passed in by the user
  24 + attr_reader :page_id
  25 +
  26 + private
  27 +
  28 + def clean_path
  29 + path = Pathname.new("/#{clean_id}")
  30 + path.cleanpath.to_s[1..-1]
  31 + end
  32 +
  33 + def clean_id
  34 + @page_id.tr("^#{VALID_CHARACTERS}", '')
  35 + end
  36 + end
  37 +end
13 spec/controllers/alternative_finder_controller_spec.rb
... ... @@ -0,0 +1,13 @@
  1 +require 'spec_helper'
  2 +
  3 +describe AlternativeFinderController do
  4 +
  5 + render_views
  6 +
  7 + it 'renders the file from the alternative directory' do
  8 + get :show, :id => 'ebg13'
  9 +
  10 + response.should be_success
  11 + response.should render_template('rot13')
  12 + end
  13 +end
9 spec/controllers/subclassed_pages_controller_spec.rb
@@ -18,15 +18,6 @@
18 18 end
19 19 end
20 20
21   - describe "on GET to /subclassed_pages/also_dir/nested" do
22   - before { get :show, :id => 'also_dir/also_nested' }
23   -
24   - it "should respond with success and render template" do
25   - response.should be_success
26   - response.should render_template('other_pages/also_dir/also_nested')
27   - end
28   - end
29   -
30 21 it "should raise a routing error for an invalid page" do
31 22 lambda { get :show, :id => "invalid" }.should raise_error(ActionController::RoutingError)
32 23 end
14 spec/dummy/app/controllers/alternative_finder_controller.rb
... ... @@ -0,0 +1,14 @@
  1 +class AlternativeFinderController < HighVoltage::PagesController
  2 + private
  3 +
  4 + def page_finder_factory
  5 + Rot13PageFinder
  6 + end
  7 +
  8 + class Rot13PageFinder < HighVoltage::PageFinder
  9 + def find
  10 + paths = super.split('/')
  11 + "#{paths[0..-2].join('/')}/#{paths[-1].tr('a-z','n-za-m')}"
  12 + end
  13 + end
  14 +end
4 spec/dummy/app/controllers/subclassed_pages_controller.rb
... ... @@ -1,7 +1,3 @@
1 1 class SubclassedPagesController < HighVoltage::PagesController
2 2 layout 'alternate'
3   -
4   - def content_path
5   - 'other_pages/'
6   - end
7 3 end
1  spec/dummy/app/views/pages/also_dir/also_nested.html.erb
... ... @@ -0,0 +1 @@
  1 +hello <%= 'world' %> from a nested dir
1  spec/dummy/app/views/pages/also_exists.html.erb
... ... @@ -0,0 +1 @@
  1 +hello <%= 'world' %>
2  spec/dummy/app/views/pages/also_exists_but_references_nonexistent_partial.html.erb
... ... @@ -0,0 +1,2 @@
  1 +hello <%= 'world' %>
  2 +<%= render 'nonexistent' %>
1  spec/dummy/app/views/pages/rot13.html.erb
... ... @@ -0,0 +1 @@
  1 +alternative
1  spec/dummy/config/routes.rb
... ... @@ -1,3 +1,4 @@
1 1 Dummy::Application.routes.draw do
2 2 match "/subclassed_pages/*id" => 'subclassed_pages#show', :format => false
  3 + match "/alternative_finder/*id" => 'alternative_finder#show', :format => false
3 4 end
53 spec/high_voltage/page_finder_spec.rb
... ... @@ -0,0 +1,53 @@
  1 +require 'spec_helper'
  2 +require 'high_voltage/page_finder'
  3 +
  4 +describe HighVoltage::PageFinder do
  5 + it 'produces the name of an existing template' do
  6 + find('existing').should == 'pages/existing'
  7 + end
  8 +
  9 + it 'produces the name of a nested template' do
  10 + find('dir/nested').should == 'pages/dir/nested'
  11 + end
  12 +
  13 + it 'uses a custom content path' do
  14 + with_content_path('other_pages/') do
  15 + find('also_exists').should == 'other_pages/also_exists'
  16 + end
  17 + end
  18 +
  19 + it 'exposes the content path' do
  20 + with_content_path('another_thing/') do
  21 + page_finder.content_path.should == 'another_thing/'
  22 + end
  23 + end
  24 +
  25 + it 'provides the page_id' do
  26 + subclass = Class.new(HighVoltage::PageFinder) do
  27 + def page_name
  28 + "the page is #{page_id}"
  29 + end
  30 + end
  31 +
  32 + subclass.new('sweet page').page_name.should == 'the page is sweet page'
  33 + end
  34 +
  35 + private
  36 +
  37 + def find(page_id)
  38 + page_finder(page_id).find
  39 + end
  40 +
  41 + def page_finder(page_id = 'whatever')
  42 + HighVoltage::PageFinder.new(page_id)
  43 + end
  44 +
  45 + def with_content_path(path)
  46 + original_content_path = HighVoltage.content_path
  47 + HighVoltage.content_path = path
  48 +
  49 + yield
  50 +
  51 + HighVoltage.content_path = original_content_path
  52 + end
  53 +end

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.