开放指南
首先,一个免责声明。
我不是一个维基名人。我不适合使用粗体大写。我不属于维基文化——我从未为Ward的Wiki做出贡献,从未使用过TWiki,对MoinMoin感到困惑,每次看到UseMod代码,我的大脑就会变成糊状。大多数维基用户可能都不知道我是谁。
话虽如此,我将用大约2,500字来阐述Ward Cunningham简单而强大的想法的可能性,并解释我和其他几位Perl Mongers是如何将其应用于创建我认为目前最激动人心的Perl应用程序之一——OpenGuides。
起源
OpenGuides的前身grubstreet是在2002年初萌生的,当时我询问Earle Martin是否知道伦敦有维基。
It seems that my friend's Wiki is running UseModWiki; I think I rather
like it. It would be good if there was one of these for info about
London; do you know if anyone's done that? Things like which pubs
serve food and good beer, etc.; which is the best end of the platform
to stand at to get a seat (discussed this kind of thing with blech
recently).
Earle非常热情,并使之成为现实。我们都非常兴奋,并开始填充内容。Wiki使这变得容易!你正在阅读一个网页,发现某个地方有错误或遗漏。点击“编辑”链接,添加你的评论,它就立刻出现了。
持续发展
不久之后,我们开始遇到了usemod
软件的限制。即使抛开它倾向于对其(自定义格式)平面文件数据库进行限制并拒绝任何人编辑访问的趋势,我也发现自己不得不编写大量屏幕抓取器来做简单的事情,比如在Soho找到一个好酒吧。我讨厌屏幕抓取,但我喜欢啤酒。
我们试图修补和改进usemod
。我们非常努力。Ivor Williams,特别是,在它的内部花费了大量的时间。我最终决定编写软件只应该在某些时候让人痛苦,在一夜的几杯啤酒之后,我和Chris Ball达成协议,grubstreet的软件将用真正的Perl重写。Chris坚持我的承诺,并最终产生了CPAN友好的wiki工具包——CGI::Wiki。一旦有了这个工具包作为基础,我们就开始了最终演变成OpenGuides的CGI脚本。
实至名归
OpenGuides是一个完整的网络应用程序,用于管理一个关于城市或城镇的协作编写的指南。
安装OpenGuides,你将得到一个等待你填充内容的空白框架。
这里有一个机会,供任何想要加入项目团队的人。为OpenGuides软件的新安装编写一组页面——如何使用指南、如何格式化你的条目,也许为所有城市都有共通的事物编写一些简短页面,也许为交通页面编写一个分类框架——你肯定能想出比我们这些使用软件多年且对它的困惑之处视而不见的人更好的主意。 |
只是一个骨架,但非常坚固
不,我们并没有只给你一个空目录来存放HTML文件。开始添加页面,你就会看到。
假设我想添加一个关于我当地酒吧的页面。我会点击“创建新页面”,并输入页面名称。我应该叫什么名字?嗯,这是一个新的OpenGuides安装,没有既定的规范,所以我可以叫它“The Drapers Arms”、“Drapers Arms”、“The Drapers Arms (Islington)”或 whatever。我只需要记住名称需要是唯一的,所以如果预计我的城市中会有不止一家Drapers Arms,我真的很应该添加一些其他类型的识别信息。《伦敦开放指南》有一个包括邮编的惯例——因此“Drapers Arms, N1 1ER”。
好的,我已经完成了,现在出现了一个编辑表单,有几个方框让我可以输入。第一个是“内容”,这是一个自由形式的方框,我可以放入任何不适合下面特定方框的信息。
接下来是“地区”和“类别”方框。我可以把任何我喜欢的东西放进去,以后访问这个指南的人也可以。我现在不需要决定如何将我的城市划分为地区;这将从所有贡献者的汇总意见中产生。我可以在几个月后回到我的第一个页面,添加任何后来定义的类别或地区。或者,我可能不需要这么做;也许有人在我之前已经做了。
地区和类别是确保您新添加的内容不会漂移到解耦的炼狱状态(即未链接的页面)的绝佳方式。只需将“酒吧”类别和“伊兹灵顿”地区添加到“德雷珀斯之臂”页面,那么进行搜索的任何人——无论是简单的输入框搜索还是定向的地区或类别搜索——都会找到它。
接下来,我们得到一系列更小的方框,用于输入更详细的位置信息、联系方式和营业时间。这些方框可能对您指南中的许多、大多数或所有页面都完全不相关。没关系。它们是可选的。但如果你真的填了它们,你就可以体验我认为是OpenGuides最创新、最简单的功能之一——在皮卡迪利广场地铁站周围半公里内找到所有事物。请。因为我的脚疼,我想要一杯红酒。
定制和扩展
我说我想找到酒吧是认真的。我想找到所有在诺丁山提供食物和啤酒花园的酒吧。伦敦开放式指南必须有这些信息!虽然直接到达这里没有明显的途径。我可能需要编写一些代码。
鉴于我是管理员之一,我有权访问服务器上的数据库——所以我可以直接调用CGI::Wiki的list_nodes_by_metadata
方法来查找类别为“酒吧”,地区为“诺丁山”,类别为“酒吧食物”的所有页面。
我编写了一个CGI脚本来接收选择酒吧的选项并输出结果。这非常有用,所以将会在下一个官方OpenGuides版本中发布。以下是摘录。请注意,地区和类别只是简单地存储为CGI::Wiki元数据。此外,还使用了CGI::Wiki::Plugin::Locator::UK来允许通过最近的地铁站进行搜索。如果你居住的城市人们以其他类型的地标导航,你可以轻松地对其进行修改。
my %possible_features = (
"beer gardens" => "Has beer garden",
"function room" => "Has function room",
"good beer guide" => "Appears in the CAMRA Good Beer Guide",
"real cider" => "Serves real cider",
"belgian beer" => "Serves Belgian beer",
"pub food" => "Serves food of some kind",
);
if ( $action eq "search" ) {
my @locales = CGI::param( "locale" );
my @features = CGI::param( "feature" );
my @tube_stations = CGI::param( "tube" );
# Ignore the blank "any locales" option.
@locales = grep { $_ } @locales;
# Ensure that we only look for 'allowed' features.
@features = grep { $possible_features{$_} } @features;
# Ensure that we only look for extant Tube stations.
my %is_tube = map { $_ => 1 } list_tube_stations();
@tube_stations = grep { $is_tube{$_} } @tube_stations;
# Grab all the pubs, to start with.
my @pubs = $wiki->list_nodes_by_metadata(
metadata_type => "category",
metadata_value => "pubs",
ignore_case => 1,
);
# Filter by locale if specified.
if ( scalar @locales > 0 ) {
my @in_locale;
foreach my $locale ( @locales ) {
push @in_locale,
$wiki->list_nodes_by_metadata(
metadata_type => "locale",
metadata_value => $locale,
ignore_case => 1,
);
}
my %in_locale_hash = map { $_ => 1 } @in_locale;
@pubs = grep { $in_locale_hash{$_} } @pubs;
}
# Filter by Tube station if specified.
if ( scalar @tube_stations > 0 ) {
my $locator = CGI::Wiki::Plugin::Locator::UK->new;
$wiki->register_plugin( plugin => $locator );
my @near_station;
foreach my $station ( @tube_stations ) {
push @near_station,
$locator->find_within_distance(
node => $station . " Station",
metres => 600,
);
}
my %near_station_hash = map { $_ => 1 } @near_station;
@pubs = grep { $near_station_hash{$_} } @pubs;
}
# Filter by features if specified.
if ( scalar @features > 0 ) {
my %has_feature = map { $_ => [] } @pubs;
foreach my $feature ( @features ) {
my @has_this_feature = $wiki->list_nodes_by_metadata(
metadata_type => "category",
metadata_value => $feature,
ignore_case => 1,
);
foreach my $pub ( @has_this_feature ) {
push @{ $has_feature{$pub} }, $feature;
}
}
# Only keep pubs that have *all* the requested features.
@pubs = grep { scalar @{ $has_feature{$_} } == scalar @features }
@pubs;
}
show_results(
pubs => \@pubs,
locales => \@locales,
tube_stations => \@tube_stations,
features => [ @possible_features{ @features } ],
);
你也可以做到
假设我有了这个定向酒吧搜索的想法,但没有直接访问任何OpenGuides数据存储?没问题——我可以玩RDF接口。大多数OpenGuides页面都有一个链接到RDF版本,这包括自动生成的页面,如地区或类别搜索结果。
我可以发送一个查询,如https://web.archive.org/web/20051104072148/http://london.openguides.org/index.cgi?action=index;index_type=category;index_value=Pubs;format=rdf,然后使用RDF::Core::Parser来解析返回的RDF/XML并获取通常需要CGI::Wiki调用的数据。
RDF接口并没有很好地宣传。一份列出任何缺失到RDF版本链接的地点的列表将非常有用。
鉴于OpenGuides页面简单数据模型,这样的外部插件可以很容易地集成到核心分发中。因此,一旦你编写了一个,请发送给我们。
RDF接口也非常适合对编写IRC机器人感兴趣的人。
15:12 <Kake> grotbot: things in Chinatown
15:12 <grotbot> OK, working on it
<grotbot> Kake: things in Chinatown: Crispy Duck, W1D 6PR; De Hems,
W1D 5BW; Golden Harvest, WC2H 7BE; HK Diner; Hung's, W1D 6PR;
Misato, W1D 6PG; Tai, W1D 4DH; Tokyo Diner; Zipangu, WC2H 7JJ
注意事项
OpenGuides软件仍然很年轻。特别是安装程序需要仔细检查,并且一些位置特性目前仅适用于位于英国的城市指南。
实时OpenGuides安装
类似系统
标签
反馈
这篇文章有什么问题?请在GitHub上打开一个issue或pull request来帮助我们。