島根県CMS

「島根県CMS」は、Ruby on Railsで作られた行政機関向けのCMSである。 オープンソースソフトウェア(ライセンスはGPL)であり、無償で利用できる。

  • 島根県CMSを参考にスクラッチから開発。GalateaTalkも使用「徳島県がRubyの独自開発CMS「Joruri」でサイトを刷新,OSSとして公開へ」 http://bit.ly/6KugCP

音声合成エンジン (gtalk) の利用

GalateaTalk (gtalk) 関連の利用状況を確認する。 作業環境は Ubuntu Linux 9.04 である。日常的に Galatea Toolkit や Ruby on Rails の開発に使っている環境。

2009年8月8日現在の最新版である 1.1.0 のソースを確認してみる。

$ tar xvfz pref-shimane-cms-1.1.0.tar.gz
$ cd pref-shimane-cms-1.1.0

音声合成関連は tool/gtalk/ にある。

$ ls -1 tool/gtalk/
gtalk/
morph/
rubi-adder/
speakers/
voice-synthesis/

rubi-adder は gtalk と直接関係ないと思われるが、テキスト解析を伴うので この場所に置かれている模様。

tool/gtalk/gtalk/README.ipadic には西本が書いた ipadic 対応化のドキュメントがある。 かつて unidic の辞書は非常に語彙サイズが小さく、ipadic を使うことは現実的な利用の手段として 検討に値するものだった。また、現時点でも unidic のライセンスはフリーではなく、 島根県CMSでは「GPL 互換」にするために ipadic が選択されたと考えられる。

$ head -15 tool/gtalk/gtalk/ssm.conf 
# configuratiuon file for gtalk (GalateaTalk)

# path name of 'chasen'
CHASEN: /usr/bin/chasen

# configuration file for 'chasen'
CHASEN-RC: ./chasenrc

# command of running 'chaone'
#CHAONE: ../morph/chaone-1.2.0/chaone
CHAONE: ../voice-synthesis/chaone-filter.rb

# path name of 'chaone.xsl' (only for library-based version)
#CHAONE-XSL-FILE: ../chaone-1.2.0/chaone_t_EUC-JP.xsl

voice-synthesis ディレクトリには、Ruby から音声合成を呼び出すラッパーなどがあるようだ。

$ ls -1 tool/gtalk/voice-synthesis/
chaone-filter.rb*
speak.rb*
speakout.cgi*
tests/
voice_synthesis.cgi*
voice_synthesis.html
voice_synthesis.rb

CGIファイルはデバッグ用であるらしく、このままでは動かない。

$ ruby tool/gtalk/voice-synthesis/speakout.cgi 
tool/gtalk/voice-synthesis/speakout.cgi:7:in `chdir': No such file or directory - /home/kouji/work/pref-shimane-cms/gtalk/gtalk (Errno::ENOENT)
	from tool/gtalk/voice-synthesis/speakout.cgi:7

いろいろいじる前に git で commit しておこう。

$ git init
$ git add .
$ git commit -m "initial" -a

下記のように直した。

diff --git a/tool/gtalk/voice-synthesis/speakout.cgi b/tool/gtalk/voice-synthesis/speakout.cgi
index ddc106a..5ecf456 100755
--- a/tool/gtalk/voice-synthesis/speakout.cgi
+++ b/tool/gtalk/voice-synthesis/speakout.cgi
@@ -4,7 +4,7 @@ require 'cgi'
 
 text = 'こんにちは、赤ちゃん。'
 
-Dir.chdir('/home/kouji/work/pref-shimane-cms/gtalk/gtalk') do
+Dir.chdir(File.join(File.dirname(__FILE__), "../gtalk")) do
   ENV['LANG'] = 'ja_JP.EUC-JP'
   IO.popen("./gtalk -C ssm.conf > /var/tmp/log", "w") do |f|
     f.puts("set Text = #{text}")

再度実行。gtalk がコンパイルされていないことに気づく。

$ ruby tool/gtalk/voice-synthesis/speakout.cgi 
sh: ./gtalk: not found

doc/INSTALL を見てみると。。

==== 音声合成プログラムの設定
   音声合成プログラムgtalk, chaoneをコンパイルします。

    $ cd /var/share/cms/tool/gtalk/gtalk
    $ sudo -u www-data ./configure
    $ sudo -u www-data make
    $ cd /var/share/cms/tool/gtalk/morph/chaone-1.2.0
    $ sudo -u www-data ./configure
    $ sudo -u www-data make

いまはTTS単体での動作確認が目的なので、横着して sudo しないでコンパイルしておく。

$ pushd tool/gtalk/gtalk/
$ ./configure ; make
$ popd

実行すると今度は kakasi と ipadic がないと怒られる。

$ ruby tool/gtalk/voice-synthesis/speakout.cgi 
../voice-synthesis/chaone-filter.rb:3:in `require': no such file to load -- kakasi (LoadError)
	from ../voice-synthesis/chaone-filter.rb:3
/usr/bin/chasen: /usr/share/chasen/dic/ipadic/user.da: No such file or directory
(offline mode: enter name=value pairs on standard input)

いままで doc/INSTALL の手順を完全に無視していたので当たり前なのだが、 あえて TTS が依存しているパッケージを確認したかったのだ。

そもそも kakasi が必要なのはなぜだろう。

tool/gtalk/voice-synthesis/chaone-filter.rb を見てみる。

  def to_katakana(str)
    return Kakasi.kakasi('-JK -HK', str).gsub(/[,.]/e, '')
  end

chasen+ipadic での解析では不十分な変換を補っているらしい。

$ sudo apt-get install kakasi libkakasi-ruby1.8

kakasi を長い間使っていないのでオプションの意味を忘れてしまった。確認しておこう。 gnome-terminal で EUC-JP に設定しておく。

$ LANG=ja_jp.euc-jp;echo "今日はいい天気。ヤッホー" | kakasi -HK
今日ハイイ天気。ヤッホー
$ LANG=ja_jp.euc-jp;echo "今日はいい天気。ヤッホー" | kakasi -JK
コンニチハいいテンキ。ヤッホー
$ LANG=ja_jp.euc-jp;echo "今日はいい天気。ヤッホー" | kakasi -JK -HK
コンニチハイイテンキ。ヤッホー

気を取り直して。chasen と ipadic はすでに入っている。

$ ruby tool/gtalk/voice-synthesis/speakout.cgi
/usr/bin/chasen: /usr/share/chasen/dic/ipadic/user.da: No such file or directory
(offline mode: enter name=value pairs on standard input)

どうやらユーザ辞書を使うことが前提になっている。 でもこれは chasenrc で指定されているので、とりあえず外しておこう。

--- a/tool/gtalk/gtalk/chasenrc
+++ b/tool/gtalk/gtalk/chasenrc
@@ -12,7 +12,7 @@
 ;;;
 ;;;  dictionary /辞書
 ;;;
-(DADIC        chadic user)
+(DADIC        chadic) ; user
 
 ;;;

lame を入れる。doc/INSTALL では make install することになっているが、 Ubuntu のパッケージを使おう。

$ sudo apt-get install lame
$ echo "" | ruby tool/gtalk/voice-synthesis/speakout.cgi > /mnt/hgfs/work/_out.mp3

仮想マシンのホスト環境である Windows で聴いてみる。 http サーバの応答なので先頭にテキストが2行くっついているが、それを取り除いても音がおかしい。

$ play -r 16000 -t sw /var/tmp/14765.raw

エンコードする前の音は問題ないようだ。バイトオーダーが逆?

speakout.cgiを見てみよう。

system("lame -r -s 16 -m m -x -S --silent -b 32 --cbr /var/tmp/#{$$}.raw /var/tmp/#{$$}.mp3")

doc/INSTALL では lame 3.97 を入れているが、apt-get で入れたのは 3.98 である。

$ lame -v
LAME 32bits version 3.98 (http://www.mp3dev.org/)

usage: lame [options] <infile> [outfile]

    <infile> and/or <outfile> can be "-", which means stdin/stdout.

Try:
     "lame --help"           for general usage information
 or:
     "lame --preset help"    for information on suggested predefined settings
 or:
     "lame --longhelp"
  or "lame -?"              for a complete options list

気を取り直して、もう一つのデモらしいスクリプトを試そう。

$ ruby tool/gtalk/voice-synthesis/voice_synthesis.rb 
tool/gtalk/voice-synthesis/voice_synthesis.rb:136:in `write': Broken pipe (Errno::EPIPE)
	from tool/gtalk/voice-synthesis/voice_synthesis.rb:136:in `synthesize'

けっきょく「lameのパスを正しく与える」「lameの-xオプションを外す」の2つで、音が出るようになった。

--- a/tool/gtalk/voice-synthesis/voice_synthesis.rb
+++ b/tool/gtalk/voice-synthesis/voice_synthesis.rb
@@ -80,9 +80,10 @@ class VoiceSynthesis
     @gtalk_path =
       File.expand_path('../gtalk/gtalk', File.dirname(__FILE__))
     @gtalk_options = ['-C', 'ssm.conf', '2>', '/dev/null']
-    @lame_path = '/usr/local/bin/lame'
+    @lame_path = `which lame`.chomp # '/usr/local/bin/lame'
     @lame_options =
-      ['-r', '-s', '16', '-m', 'm', '-x', '-S', '-b', '32', '--cbr',
+      ['-r', '-s', '16', '-m', 'm', # '-x', 
+       '-S', '-b', '32', '--cbr',
        '--scale', '1.5', '-', '-', '2>', '/dev/null']
     @max_part_length = 1000
     @logger = nil
$ ruby tool/gtalk/voice-synthesis/voice_synthesis.rb > /var/tmp/_hoge.mp3
$ play /var/tmp/_hoge.mp3

で、この VoiceSynthesis クラスは本当に使われているのか?

$ find -name *.rb | xargs grep VoiceSynthesis
./tool/gtalk/voice-synthesis/tests/voice_synthesis_test.rb:class VoiceSynthesisTest < Test::Unit::TestCase
./tool/gtalk/voice-synthesis/tests/voice_synthesis_test.rb:    res = VoiceSynthesis.replace_phone_number('(090)1234-5678') { |s|
./tool/gtalk/voice-synthesis/tests/voice_synthesis_test.rb:    res = VoiceSynthesis.replace_phone_number('[(090)1234-5678]') { |s|
./tool/gtalk/voice-synthesis/tests/voice_synthesis_test.rb:      res = VoiceSynthesis.replace_phone_number(test_data) { |s|
./tool/gtalk/voice-synthesis/tests/voice_synthesis_test.rb:      VoiceSynthesis.replace_phone_number(test_data) do |s|
./tool/gtalk/voice-synthesis/voice_synthesis.rb:class VoiceSynthesis
./tool/gtalk/voice-synthesis/voice_synthesis.rb:  vs = VoiceSynthesis.new

あれ、使われてない? と焦るが、あった。

$ find . | xargs grep VoiceSynthesis
./tool/export:    vs = VoiceSynthesis.new
...

拡張子なしの tool/export を見てみると CMSExport クラスで create_mp3(arg, tmp_id) というメソッドを発見。 ここで VoiceSynthesis クラスの html2m3u メソッドが使われている。 VoiceSynthesis クラスに戻って確認すると、html2m3u メソッドが synthesize_html メソッドを呼び出し、 ここでさらに synthesize メソッドが呼ばれる。

だいたい GalateaTalk の使われ方に納得できたのだが、VoiceSynthesis クラスから HTML 依存の機能を追い出すように リファクタリングして、VoiceSynthesys クラスを汎用化する(railsプラグインあるいはgemにする) と喜ばれるかも知れない。

そういえば ruby-chasen をインストールしなかったが、問題なかったようだ。

chasen は gtalk のサブプロセスとして呼ばれるだけだから、現段階では、必要なくて当然な気もするが。。

lib/filter.rb

CMSではあらゆるテキストが入力されることを想定しなければならず、 GalateaTalkのような(商用品質とは言い難い)TTSがあらゆる入力に対して 頑健ではないという現実を、「島根県CMS」がどう実装で補っているのだろう?

日本語の encoding の問題、機種依存文字の変換などを担っている箇所を見つけた。 VoiceSynthesys クラスからも使われている Filter モジュール lib/filter.rb である。

if __FILE__ == $0
  a = "\xe3\x81\x82\xe3\x80\x9c\xe2\x91\xa0\xe2\x85\xa0\xe3\x81\x84"; puts a
  puts Filter::convert_non_japanese_chars(a)
end

のように puts a を書き加えて実行してみた。

$ ruby lib/filter.rb 
あ〜①Ⅰい
あ〜<span class="invalid">&#9312;</span>Iい

2文字目は Ubuntu の「端末」では「~」(いわゆる「から」記号)に見えるのだが、 Windowsのブラウザにコピペすると「上下が逆になったチルダ」である。

3~4文字目のWindows依存文字「マル1」「ギリシャ数字の1」を 機種非依存文字に変換している。機種に依存せずブラウザでコンテンツを表示するためには 必要な機能である。ただし音声化を想定した前処理としては機能不足に思える。

postgres を動かす

そろそろシステムを動かしてみよう。 Ubuntu で「できるだけ手抜きをしながら」そして「できるだけ中身を理解しながら」やってみる。 まず postgres だ。 作業マシンではいままで sqlite3 と mysql5 をかじっていたが、この機会に環境設定しておく。

$ sudo apt-get install postgresql

Version: 8.3.7-1 がインストールされた。 doc/INSTALL によれば createuser を使え、とのこと。 /usr/bin/createuser である。postgres-xxx でも pg-xxでもなく、この名前である。

www-data というユーザ名が指定されているのだが、あとで別のシステムの開発に使いたいので、 cms-data にしておこう。

$ sudo -u postgres /usr/bin/createuser cms-data
Shall the new role be a superuser? (y/n) y
createuser: could not connect to database postgres: could not connect to server: No such file or directory
	Is the server running locally and accepting
	connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

怒られてしまった。 多少やり方を変えてみた。

$ sudo -u postgres /usr/lib/postgresql/8.3/bin/createuser -h localhost cms-data
Shall the new role be a superuser? (y/n) y
createuser: could not connect to database postgres: could not connect to server: Connection refused
	Is the server running on host "localhost" and accepting
	TCP/IP connections on port 5432?

たいして変わらない。そういえば initdb しなくてよかったのだろうか、と気になる。

$ sudo -u postgres /usr/lib/postgresql/8.3/bin/initdb -D /var/lib/postgresql/data
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale ja_JP.UTF-8.
The default database encoding has accordingly been set to UTF8.
initdb: could not find suitable text search configuration for locale ja_JP.UTF-8
The default text search configuration will be set to "simple".

...

Success. You can now start the database server using:

    /usr/lib/postgresql/8.3/bin/postgres -D /var/lib/postgresql/data
or
    /usr/lib/postgresql/8.3/bin/pg_ctl -D /var/lib/postgresql/data -l logfile start

後者がデーモン起動っぽいのでやってみる。

$ sudo -u postgres /usr/lib/postgresql/8.3/bin/pg_ctl -D /var/lib/postgresql/data -l logfile start
server starting

これでサーバが動くのではないか? psql というコマンドの存在を思い出した。

$ sudo -u postgres psql -h localhost -l
        List of databases
   Name    |  Owner   | Encoding 
-----------+----------+----------
 postgres  | postgres | UTF8
 template0 | postgres | UTF8
 template1 | postgres | UTF8
(3 rows)

動いたようだ。

$ sudo /etc/init.d/postgresql-8.3 status

/etc/init.d は無反応なのが気になるが。

気を取り直して。

$ sudo -u postgres /usr/lib/postgresql/8.3/bin/createuser -h localhost cms-data
Shall the new role be a superuser? (y/n) y

rails 用のデータベース3兄弟を作る。 doc/INSTALL に書かれている手順と異なり、sudo -u postgres でなくてはならない。 cms-data は Lunux のユーザアカウントではなく、postgres の中のアカウントである。 以前はこのあたりを密に連動させていた気がするが。。

$ sudo -u postgres /usr/bin/createdb -U cms-data cms_test -EUNICODE
$ sudo -u postgres psql -h localhost -l
        List of databases
   Name    |  Owner   | Encoding 
-----------+----------+----------
 cms_test  | cms-data | UTF8
 postgres  | postgres | UTF8
 template0 | postgres | UTF8
 template1 | postgres | UTF8
(4 rows)

引き続き。

$ sudo -u postgres /usr/bin/createdb -U cms-data cms_development -EUNICODE
$ sudo -u postgres /usr/bin/createdb -U cms-data cms_production -EUNICODE
$ sudo -u postgres psql -h localhost -l
           List of databases
      Name       |  Owner   | Encoding 
-----------------+----------+----------
 cms_development | cms-data | UTF8
 cms_production  | cms-data | UTF8
 cms_test        | cms-data | UTF8
 postgres        | postgres | UTF8
 template0       | postgres | UTF8
 template1       | postgres | UTF8
(6 rows)

ここまでやって思い出したが、最近の rails なら rake db:create:all すればいいところだ。。 rails のバージョンアップがどこまで可能かどうかも検討課題ということにしておこう。

script/server で動かしてみる

あらためて rails の作業に取りかかる。

$ cp config/database.yml.example config/database.yml
$ cp config/cms.yml.example config/cms.yml

最近(たぶん1.2以降)の rails なら db:migrate だがここは rails 1.0 あたりの流儀で。。

$ rake migrate
rake aborted!
no such file to load -- postgres

postgres という gem が入ってないようだ。

$ sudo gem install postgres 
Building native extensions.  This could take a while...
ERROR:  Error installing postgres:
	ERROR: Failed to build gem native extension.

/usr/bin/ruby1.8 extconf.rb
extconf.rb:46: command not found: pg_config --includedir
extconf.rb:53: command not found: pg_config --libdir
checking for main() in -lpq... no
*** extconf.rb failed ***

たぶん postgresql の開発パッケージが必要なのだろう。

$ sudo apt-get install libpq-dev

$ sudo gem install postgres 
Building native extensions.  This could take a while...
Successfully installed postgres-0.7.9.2008.01.28
1 gem installed
Installing ri documentation for postgres-0.7.9.2008.01.28...
Installing RDoc documentation for postgres-0.7.9.2008.01.28...

無事に終わったので migrate に戻る。

$ rake migrate
It may take a while. Please wait.
$ rake create_session_table
$ ./script/server 

いまさらだが postgres の動作確認。

$ ps ax | grep postgres
27964 pts/0    S      0:00 /usr/lib/postgresql/8.3/bin/postgres -D /var/lib/postgresql/data
27966 ?        Ss     0:00 postgres: writer process                                        
27967 ?        Ss     0:00 postgres: wal writer process                                    
27968 ?        Ss     0:00 postgres: autovacuum launcher process                           
27969 ?        Ss     0:00 postgres: stats collector process                               
31411 ?        Ss     0:00 postgres: postgres cms_development [local] idle                 
32626 pts/0    S+     0:00 grep postgres

http://localhost:3000/ いってみよう。

MissingSourceFile in <controller not set>#<action not set>

no such file to load -- chasen

RAILS_ROOT: script/../config/..

やっと chasen gem の出番らしい。

ruby-chasen

別のコンソールで。

$ mkdir ruby-chasen ; cd ruby-chasen
$ wget http://raa.ruby-lang.org/cache/ruby-chasen/chasen1.6.tar.gz
$ tar zxvf chasen1.6.tar.gz 
$ cd chasen1.6
$ ruby extconf.rb 
checking for chasen_getopt_argv() in -lchasen... no

うまくいかなそうな予感。

えとブログ https://www.codeblog.org/blog/eto/20060212.html を参考に。

$ sudo apt-get install chasen libchasen-dev chasen-dictutils
$ ruby extconf.rb 
checking for chasen_getopt_argv() in -lchasen... yes
$ make
cc -I. -I. -I/usr/lib/ruby/1.8/i486-linux -I. -D_FILE_OFFSET_BITS=64  -fPIC -fno-strict-aliasing -g -g -O2  -fPIC   -c chasen.c
cc -shared -o chasen.so chasen.o -L. -L/usr/lib -L. -Wl,-Bsymbolic-functions -rdynamic -Wl,-export-dynamic    -lruby1.8 -lchasen  -lpthread -ldl -lcrypt -lm   -lc
$ sudo make install 
mkdir -p /usr/local/lib/site_ruby/1.8/i486-linux
/usr/bin/install -c -m 0755 chasen.so /usr/local/lib/site_ruby/1.8/i486-linux

うまくいった。

ふたたび script/server

島根県CMSのディレクトリに戻る。

$ ./script/server

Ubuntu の中で Firefox から http://localhost:3000 を開く。今度はトップページが表示される。

よく見ると ERROR ThreadError: not owner というエラーがでているのだが。

ブラウザで操作。右上の「ふりがな」ボタンは動作する。

右上の「よみあげ」ボタンを押すと http://localhost:3000/index.m3u

Not Found
The requested URL /index.m3u was not found on this server.

になる。 public ディレクトリにはそもそも index.html らしきものがない。 rake routes も残念ながら使えない。

このまま doc/INSTALL の指示を無視して development 環境ていじることはできるのだろうか。

トップページの表示

config/routes.rb の最後が

  map.connect '*path', :controller => 'visitor', :action => 'view'

になっている。rails のドキュメント http://api.rubyonrails.org/classes/ActionController/Routing.html によれば、

Route globbing
Specifying *[string] as part of a rule like:

  map.connect '*path' , :controller => 'blog' , :action => 'unrecognized?'

will glob all remaining parts of the route that were not recognized earlier. 
The globbed values are in params[:path] as an array of path segments. 

とのこと。ということは http://localhost:3000/ は params[:path] に '/' を入れて、 app/controllers/visitor_controller.rb の view メソッドにルーティングされているはず。

当該メソッドを読んでみると、path = request.path となっているが、まあ同じことなのだろう。 path == '/' の場合に起こりそうな処理は、 「Page クラス(モデルだろう)の genre_id が 1 で name が 'index' であるレコードを find する」 である。nil の場合には top (あるいは mobile_top)アクションを render する。

それって、http://localhost:3000/visitor/top ってこと? 404 Not Found になってしまうから、どうやら違うらしい。

ぐぐってみた。

http://akimichi.homeunix.net/hiki/rails/?render

そうか、render :action はいきなり view にいくのか。

app/views/visitor/top.rhtml

があった。しかし、この top.rhtml は、どうも localhost:3000 と内容がちがう。

もしや、migrate したときにデータを入れてくれている?

$ ./script/console 
Loading development environment.
>> Page.find :all
=> [#<Page:0xb6f8f0c8 @attributes={"name"=>"section", "title"=>"組織別情報", "genre_id"=>"1", "id"=>"4"}>, #<Page:0xb6f8f08c @attributes={"name"=>"page_template1", "title"=>"ページテンプレート1", "genre_id"=>"3", "id"=>"2"}>, #<Page:0xb6f8f050 @attributes={"name"=>"page_template1", "title"=>"ページテンプレート2", "genre_id"=>"3", "id"=>"3"}>, #<Page:0xb6f8f014 @attributes={"name"=>"index", "title"=>"島根県のトップページ", "genre_id"=>"1", "id"=>"1"}>]

>>  page = Page.find(:first, :include => [:contents], :conditions => ['genre_id = ? and name = ?', 1, 'index'])
=> #<Page:0xb6f82c38 @attributes={"name"=>"index", "title"=>"島根県のトップページ", "genre_id"=>"1", "id"=>"1"}, @contents=[#<PageContent:0xb6f8242c @attributes={"top_news"=>"2", "admission"=>"3", "comment"=>nil, "section_news"=>"0", "page_id"=>"1", "id"=>"1", "tel"=>nil, "news_title"=>nil, "mobile"=>nil, "begin_date"=>nil, "content"=>"<div id=\"main\"> <h2 class=\"emg\">緊急情報</h2> <%= plugin('emergency') %> <h2 class=\"news\">新着情報</h2> <div class=\"news\"><%= plugin('news', 10) %></div> <div class=\"right\">[<a href=\"/news.1.html\">履歴一覧</a>]</div> </div>", "user_name"=>nil, "last_modified"=>"2007-02-15 12:40:33", "end_date"=>nil, "email"=>nil}>]>

そういうことだったか。

あらためて確認すると db/migrate の 082_load_pages_data.rb と dev_data/{pages,page_contents}.yml のようだ。

    directory = File.join(File.dirname(__FILE__), "dev_data" )
    Fixtures.create_fixtures(directory, "pages" )

いまどきの作法だと migrate の中でやらないで db:fixtures:load だろう。

そういえば rake default でテストを走らせると

167 tests, 867 assertions, 0 failures, 16 errors
rake aborted!
Test failures

である。migrate でデータを突っ込んでいて test は通るのだろうか。

unfreeze_rails してみる

rails 1.0 からどこまでバージョンアップできるのだろうか。

$ rake unfreeze_rails 
$ ./script/server 
./script/../config/boot.rb:16: undefined method `require_gem' for main:Object (NoMethodError)
	from ./script/server:2:in `require'
	from ./script/server:2

なおす。

--- a/config/boot.rb
+++ b/config/boot.rb
@@ -13,7 +13,7 @@ if File.directory?("#{RAILS_ROOT}/vendor/rails")
   require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
 else
   require 'rubygems'
-  require_gem 'rails', '= 1.0'
+  gem 'rails', '= 1.0'
   require 'initializer'
 end
$ ./script/server 
/usr/local/lib/site_ruby/1.8/rubygems.rb:827:in `report_activate_error': RubyGem version error: rails(2.0.2 not = 1.0) (Gem::LoadError)
	from /usr/local/lib/site_ruby/1.8/rubygems.rb:261:in `activate'
	from /usr/local/lib/site_ruby/1.8/rubygems.rb:68:in `gem'
$ sudo gem install rails -v 1.0
...
Successfully installed activesupport-1.2.5
Successfully installed activerecord-1.13.2
Successfully installed actionpack-1.11.2
Successfully installed actionmailer-1.1.5
Successfully installed actionwebservice-1.0.0
Successfully installed rails-1.0.0
6 gems installed
...
Installing ri documentation for actionpack-1.11.2...
ERROR:  While generating documentation for actionpack-1.11.2
... MESSAGE:   Unhandled special: Special: type=17, text="<!-- The header part of this layout -->"
... RDOC args: --ri --op /usr/lib/ruby/gems/1.8/doc/actionpack-1.11.2/ri --quiet lib --title actionpack-1.11.2 Documentation
(continuing with the rest of the installation)
...

ri でエラーが得たがインストールは終了。 script/server も無事動き、トップページも表示される。

じゃあ boot.rb が 2.0.2 ではどうか。

 gem 'rails', '= 2.0.2'

script/server するがブラウザでエラー。

1.x 系の最終版である rails -v 1.2.6 で試してみたが、やっぱりだめ。

エラーを眺めていて、もしかしたらと思ってやってみた。

--- a/app/controllers/application.rb
+++ b/app/controllers/application.rb
@@ -41,7 +41,8 @@ class ApplicationController < ActionController::Base
   end
 
   def rubi_filter
-    return if @headers['Content-Type'] || !@cookies['ruby'] || @cookies['ruby'].first != 'on'
+    # @cookies['ruby'].first != 'on'
+    return if @headers['Content-Type'] || !@cookies['ruby'] || @cookies['ruby'] != 'on' 
     @response.body = RubiAdder.add(@response.body)
   end

たぶん @cookies[] の結果が array でなくなったのだろう。 これで 1.2.6 対応に(見かけだけは)なった。

なぜ rails をバージョンアップしたかったかというと、

$ script/console
>> app
=> #<ActionController::Integration::Session:0xb6febbe8 @controller=nil, @cookies={}, @headers=nil, @named_routes_configured=true, @remote_addr="127.0.0.1", @host="www.example.com", @path=nil, @response=nil, @https=false, @status=nil, @request=nil, @result=nil, @status_message=nil, @accept="text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5">

などが使えた方が嬉しいと思ったからだ。

rake routes も使えるようになった。

$ rake routes
  /_admin/preview/:id          {:action=>"show", :controller=>"visitor"}
  /_admin/preview_revision/:id {:action=>"show_revision", :controller=>"visitor"}
  /_admin/word/:action/:id     {:controller=>"word"}
  /_admin/:action/:id          {:controller=>"admin"}
  /_help/:action/:id           {:controller=>"help"}
  /_board/:action/:id          {:controller=>"board"}
  /_board_comment/:action/:id  {:controller=>"board_comment"}
  /board/:id/:page             {:action=>"view", :controller=>"board_comment"}
  /_enquete/:action/:id        {:controller=>"enquete"}
  /_statistics/:action/:id     {:controller=>"statistics"}
  /_advertisement/:action/:id  {:controller=>"advertisement"}
  /_mailmagazine/:action/:id   {:controller=>"mailmagazine"}
  /_site/:action               {:controller=>"site"}
  /_web_monitor/:action/:id    {:controller=>"web_monitor"}
  /_qr/:path                   {:action=>"qrcode", :controller=>"visitor"}
  /:path                       {:action=>"view", :controller=>"visitor"}

cron による処理

話を戻して、読み上げ機能の動作を解明したい。

あらためて doc/INSTALL を読む。

「exportの設定」「cronの設定」によると。

var/share/cms に展開されたプログラム一式 (今回の作業ではそのように展開していないが) で tool/export を書き換えて、 「公開サーバのドメイン」 「公開サーバにrsyncするユーザ」 を指定することになっている。

crontab.example を見る。

# htmlページの公開サーバへrsyncするスクリプトの実行スケジュール
*    * * * * if [ -e '/var/share/cms/do_export' ]; then nice /var/share/cms/tool/export; fi
# 音声ファイルを作成するスクリプトの実行スケジュール
*    * * * * if [ -e '/var/share/cms/do_export' ]; then nice /var/share/cms/tool/export_mp3; fi

tool/export は VoiceSynthesis が使われている(唯一の)場所だ。

tool/export_mp3 は tool/export を load している。 Job.next_mp3 がないなあ、と思って探す。

$ find . | xargs grep next_mp3 
./tool/export_mp3:  while job = Job.next_mp3
./app/models/job.rb:  def self.next_mp3

あった。

  def self.next_mp3
    self.find(:first,
              :conditions => ['(datetime <= ? or datetime is null) and action = ?',
                Time.now, 'create_mp3'],
              :order => 'id')
  end

あらためて toos/export を探すと、こんな感じで生成されている。

    Job.create(:action => 'create_mp3',
               :arg1 => arg,
               :arg2 => tmp_id,
               :datetime => Time.now)

Job を生成して DB に入れておき、export の最後にある

    while job = Job.next
      @exporter.run(job)
    end

で実行している。run は CMSExport のメソッドである。 export_mp3 の場合は Job.next ではなく Job.next_mp3 が使われる。 Job の処理は奥深そうだ。

ここまでのまとめ

非常に偏った視点でこのソフトウェアを概観してみた。 島根県公式サイトとしての外部仕様を満たすための苦労(アドホックな部分?)が散見されるが、 そもそもこういう「斜め読み」ができるのは Rails アプリであるおかげだろう。

「漢字に対するルビの自動生成」は JavaScript で実現されている。 「聴覚スタイルシート」は public/stylesheets/aural.css として提供されている。

音声合成だけでなく、このような 「アクセシブルなWebサイト」 を実現する機能がいろいろ盛り込まれていることはやはり興味深い。

これらの技術が独立したパーツとして生かされることで、 高度なWebアクセシビリティ技術が幅広く普及することを望む。

pref_shimane_cms.txt · 最終更新: 2011/03/08 11:28 by Takuya Nishimoto
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0