Why did we use an !omap
in the
source YAML? This Wiki will eventually support any kind of YAML.
Short-term, we only need pages that present lists of test cases, and
!omap
s are the only ordered maps in
YAML. So, short-term, this project will only use !omap
nodes containing !omap
and !str
nodes. Future iterations can easily add
other types. This Short Cut focuses on Ajax, not elaborate HTML, and if we
can convert two YAML types then the rest will be easy.
This new code passes those tests:
class YarWiki def initialize(page_name = 'FrontPage') @page_name = page_name.to_s end attr_reader :page_name def wiki_path wp = File.expand_path(File.join(RAILS_ROOT, 'wiki')) Dir.mkdir(wp) rescue nil return wp end def yaml_path File.join(wiki_path, page_name + '.yaml') end def save_page(contents) File.open(yaml_path, 'w'){|f| f.write(contents) } end def format_yaml(x) return unless File.exist?(yaml_path) seq = YAML::parse_file(yaml_path) x.ul do seq.children.each do |kid| x.li do hash = kid.value x.strong( hash.keys.first.value ) x.text! ': ' + hash.values.first.value end end end end end
YAML::Syck
expresses an !omap
as a Seq
object containing a list of Map
objects, so the method format_yaml
works in two phases. We grab the
Seq
and iterate through its children;
each one is a Map
with only one key and
one value. We print the key in strong
markup, and we print the value after a colon.
Both the key and the value are Scalar
objects, and we get their raw data from
their .value
members. Our preliminary
formatting is soon to upgrade.
The new tests force edits inside index.rhtml
. It fetches the current page name
from the params
data block into the
YarWiki
object, to render the page. I
mark the relevant changes in bold, and
hide the irrelevant code with ellipses:
x.tr do
x.td :id => 'wiki_panel',
...
yar.format_yaml(x)
end
The line File.join(RAILS_ROOT,
'wiki')
points to a new subfolder of RAILS_ROOT
called wiki/
. We will stash our pages there, because
our Wiki is an addition to Rails, outside its other systems. If you need
different concepts, put your Wiki pages somewhere else.
Our Wiki's path is disturbing:
http://localhost:3000/wiki/index/WikiTestPage
It neglects the Web 2.0 ideal of "Pretty URIs." Fixing it allows us to briefly demonstrate another nonheinous Rails assertion:
def test_clean_uri assert_routing '/wiki/WikiTestPage', :controller => 'wiki', :id => 'WikiTestPage' end
That new test with assert_routing
fails, inspiring us to go into
config/routes.rb
and add this
line:
map.connect 'wiki/*id', :controller => 'wiki', :action => 'index'
That line works, but it breaks any old-fashioned actions. Our Wiki
will need those to serve Ajax hits. If all our Wiki pages use WikiName
format, and all our actions are
rails_style
, we can restrict our
routing table to distinguish them. Hence:
def test_dont_route_actions assert_routing '/wiki/action', :controller => 'wiki', :action => 'action' end
And:
map.connect 'wiki/*id', :controller => 'wiki', :action => 'index',
:requirements => { :id => /(?:[A-Z][a-z]+)+/ }
Now we can take the redundant "index/
" out of our URI. A public Wiki would
also take out the word "wiki
". Our
goal is a private administrative Wiki supporting some other web site, so
we'll leave that in. (This Short Cut also leaves securing that Wiki with
a password as an exercise for the reader.)
assert_routing
is a good
example of an assertion that targets semantics instead of just syntax.
The first argument is an example of the URI path that our users should
type, and the optional arguments declare how the routing system should
decompose that URI. So assert_routing
helps us play "what if" with our URIs, and detect how they match users'
guesses and assumptions.
After an excursion into testing semantics, we will now learn a very good way to test more syntax!
3.137.178.133