Jekyllの外の世界からdataを作る準備

※ 実際には外の世界へのアクセスの部分は何も扱ってません。あくまで Reader が仕事する前に data を作ることができた、ってだけ。また Assetを外に置く話 とも別の話。

My first Jekyll GeneratorのためにJekyllを読んでみて分かったんだけど、Jekyll::Hooks を利用すると Jekyll の外からデータを持ってきたあとに reader が仕事するようにすることは割と簡単にできそうだ。

Jekyll 自体はあくまで local の file を相手にする静的サイトジェネレータだが、これを活かして plugin 的なもので外部からデータを持ってきて file を作ってしまえば そのデータはどこからやってくるものであろうと構わない、つまりデータの生成、置き場所は自由ということになる。

ということは Jekyll 以外の何かでコンテンツを作れる、言い換えると Decoupled CMS のできあがりだ。1

とりあえず毎回のprocessのたびに何かする

Jekyll::Site#process をもう一度読むと

   def process
     reset
     read
     generate
     render
     cleanup
     write
     print_stats if config["profile"]
   end

のように毎回 reset が走っているので、適当な plugin を作って2、その最後に

Jekyll::Hooks.register :site, :after_reset do |site|
  MyFirstResetPlugin.new(site)
end

みたいなコードを書いておくと、自動でサイトの内容が空っぽの状態で Plugin が実行されるので、そこで site.config['data_dir'] の中に対してなんらかのデータを吐いてあげれば、Generator からは自動的に site.data として取得できるようになる。

例えばこんな感じ。

class ExternalData < Jekyll::Plugin
  def initialize(site)
    @dir  = File.join(site.config['source'], site.config['data_dir'])
    @file = File.join(@dir, 'external.yml')
  end
  attr_reader :dir, :file

  def fetch_from_api
    FileUtils.mkdir_p(dir)
    open(file, 'w') {|f|
      f.puts YAML.dump(foo: 'bar')
    }
  end
end

Jekyll::Hooks.register :site, :after_reset do |site|
  ExternalData.new(site).fetch_from_api
end

とすると、build のたびに API からデータを取得するような仕組みが可能だ。

※ ここでは API から取得する処理は何も書いてないので data を吐いているだけ。

after_resetなのかafter_initなのかそれとも

ただ上のやり方だとちょっと現実的じゃない。

少なくとも実際に本物の API へアクセスするような仕組みを毎回の process のたびに走らせるのは開発環境では高コストすぎる。だからたぶんこんな感じにして、

Jekyll::Hooks.register :site, :after_init do |site|
  if ENV['FORCE_FETCH']
    ExternalData.new(site).fetch_from_api
  end
end

みたいに環境変数で切り替えて、必要な時にだけ API アクセスするような仕組みがあるとよさそう。3

これを応用して data でも collection でもなんでも作って、その後に Generator に渡してや れば Decoupled CMS への第一歩を踏み出せたと言ってよさそう。

残りはCMSとビルドサーバの連携(例えばWebhook)

CMS を Jekyll や静的サイトジェネレータ側で担わないようになると、

  1. コンテンツの更新
  2. コンテンツの更新から kick されたサイトのビルド
  3. ビルドしたサイトの deploy

の 1 と 2 をどうやって繋ぐのかという問題になる。

例えば CMS が WordPress だったら WordPress の更新を Webhook でビルドサーバに送り、ビルドサーバ上で WP REST API からコンテンツを取得してビルド、といった具合。

これが可能になれば CMS としては WordPress を活かしたまま、表側はエンジニア、デザイナが余計なこと4を気にせずに、かつ存分にモダンな作りで改善するために WordPress から分離するといったことが可能になる。5

感想

今後静的サイトジェネレータを評価する機会があったら、簡単に始めることができることも速さも大事だけど、Asset も Data も分離しやすい、という視点での評価を少なくとも個人的には大事にしいきたいなぁと思いましたとさ。

  1. 実際には site オブジェクトにさえつっこめればいいので、site に ActiveRecord をぶらさげる、みたいなやり方でもいいけど、今回は扱わない。 

  2. plugin でなくてもいいけど、plugins_dir 以下は自動で require されるし、乗っておいた方が混乱がなくてよい。 

  3. 本気でコンテンツの量がすごいことになったらCI的な意味ではなくgenerate用のビルドサーバを用意してそこにストレージも用意して差分でfetchするようなものが必要かもしれないが、その辺は今回の範疇外。 

  4. セキュリティの問題はあるけどバージョンアップでプラグインが動かなくなってしまったらどうしよう?とか 

  5. 「プレビュー」をどのレベルまで求めるのか?といった問題はあるが。 

RubyEnterpriseをsrpmからrebuildしようとしたらspec間違ってるじゃん

※ _prefix 付けるの前提みたい!

Xen + REE の問題を解消するために自前 build

Ruby Enterprise を rebuild しようとしています。以下にあるような Xen + REE の問題を解消するためです。

方法はいくつかあるのですが、全部入りで準備が楽だろうということで

ruby enterprise の srpm を取ってきて rebuild する

ことにしました。で、できあがった rpm を install し直すことにすれば作業的にも楽じゃないかなと予想。

基本手順

で、手順は基本的に以下のようになります。1

  1. https://packages.endpoint.com/rhel/5/ruby-enterprise-opt/SRPMS/ から srpm を取得
  2. ~/rpmbuild/{BUILD, RPMS/i386, SOURCES, SPEC} を作る
  3. rpmbuildree ユーザーを作る
  4. メッセージを抑止する環境変数をセットします
  5. rpmbuild -bb –rebuild –define 'dist #{SUFFIX}' 'srpm file'

rpmbuild は特定のディレクトリ構造を要求します。こんなの rpmbuild init みたいなコマンドで自動で作ってほしいです。rpmbuild は root 権限を使わずに済むように特定のユーザーの作成を推奨します。本気で推奨するなら root になって build を継続しないで STOP してほしいです。とにかく手作業はきらいです。

話が逸れました。

環境変数は以下のようにセットします。

export CFLAGS="-mno-tls-direct-seg-refs"
export CXXFLAGS="-mno-tls-direct-seg-refs"

で、rpmbuild の –define で自分で用意したよーと目印を付けておきます。最終的にパッケージ名に反映されるので、公式に配布されているものと自分で build したものの区別を付けられます。会社名の略称とか付ければいいんじゃないですかね。

cf.

ところが spec が間違っている

上の手順でディレクトリやユーザー名の問題がなくてもやはりうまくいきません。答えは以下にあって、要するに spec ファイルが間違っています。

I need an rpm that includes libruby.so - Ruby Enterprise Edition | Google グループ

こんな感じで直せということですね。

これで今度は spec ファイルを指定して rpmbuild してやると ~/rpmbuild/RPMS 以下に指定のプラットフォームの rpm が生成されます。

もし次回以降がありそうならこの段階で

  • ~/rpmbuild/SRPMS も用意
  • rpmbuild を -ba に変更

してやればいいと思います。spec ファイルに直接環境変数を書くことはできないのかな? できるのならそういう spec を用意しておけばいいと思います!

[2012-01-06 追記] 実は _prefix がないだけ

あとで分かったけど上のやりかたで作った rpm は endpoint の rpm とは異なります。

rpmbuild -bb --rebuild --define 'dist XXX' --define '_prefix /usr/local' \
ruby-enterprise-xxx.srpm

ってやるのが正解みたい。

この _prefix /usr/local がないと rpmbuild 標準の /usr 以下にインストールされて、インストール済みの gem とかとイロイロ合わないのでまともに動きません。


実は入れ直さなきゃねと気づいたのは7月なんだよね…。すぐに取りかかりにくい状況が本当にダメだ。

  1. こういうところに手作業がいっぱいあるのが RHEL 系というか rpm 周りのきらいなところ。 

repository local の設定

とりあえず Git と Mercural だけの話。

 GitMercurial
ユーザー共通の設定~/.gitconfig~/.hgrc
repositoryごとの設定.git/config.hg/hgrc

こんな感じかな。

cf.

nadoka pong 問題よく分からず

X-Chat で PONG が延々表示されるのは困るので追いかけてみた。

--- server.rb   (リビジョン 188)
+++ server.rb   (作業コピー)
@@ -415,6 +415,7 @@
         when 'PING'
           @server << Cmd.pong(q.params[0])
         when 'PONG'
+          @logger.dlog "[<S] #{p q}"
           @pong_recieved = true
         when 'NOTICE'
           @logger.dlog "[<S] #{q}"

X-Chat 上のメッセージがこれ。

[18:57] 	*	PONG LAG3723386795

該当するログがこれ。

07/12/09-18:57:12 [<S] #<RICE::Command::PONG:0x411d056
prefix:irc.nara.wide.ad.jp command:PONG
params:["irc.nara.wide.ad.jp", "irc.nara.wide.ad.jp"]>

LAG なんとかって値はどこにあんだ? この #{p q} で吐いてる q ってのは

   def recv_from_server
     while q = @rq.pop

の q で、@rq ってのは

   def make_server
     host, port, @server_passwd = next_server_info
     server = ::RICE::Connection.new(host, port)
     server.regist{|rq, wq|
       Thread.stop
       @rq = rq

だよな。pop は Array#pop ってことか?(違いました)

んー。つまり単に PONG メッセージがひとかまりとして取れてないのかな? RICE の問題?

ぐーぐるだんす

何があったのか知らないけど「あーありがち」でバッチリ Google 検索に出てくるようになってしまった。そりゃサイトタイトルなんだからキーワードとして十分なんだけど、何もいきなり一位にならなくたっていいっていうか、せっかく潜行できるタイトル思いついたと思ったのになぁ。

ダーツ&ビリヤード入門

NHK趣味悠々『大人の遊びダーツ&ビリヤード入門』

なんてものを見た。基本のフォームの話をしていて、おーなつかしいというかなんというか。しかし「大人の遊び」なのに出演者が妙に若いのはなんでだろう。「大人入門」も兼ねているのか?

次回はイメージボールだそうだ。まだ始まったばかりなのでまだの人(って誰に言ってる)も再放送があるので今からでも遅くない。

日本情報保全協会

http://www.jip.or.jp/

へー。名前がいい感じ。

問題は配列そのものじゃなかった

reset() してなかったので配列をさらなる配列に分割するループに入ってすらおらなんだ。reset() でハマるのは少なくとも Perl にはなさげな挙動なので注意せんとな。 ふぅ。

今年の整理と来年の目標なぞ

PHP ももう少しディープに行きたいが、幅を広げるために mod_perl とか Apache::ASP とか Ruby とか mod_ruby とか eRuby とか erb とかも抑えておきたいところ。それだけできれば Light-weight Language はもういいだろう。(Python はパス。)というかこれだけやるのにどれだけ掛かるんだ。まぁ Ruby そのものの書き方に慣れてしまえばあとはどこでどうやって動くかという問題だから、それほど時間は掛かるまい。環境の構築に関するメモと、動作上のメモがある程度たまればよい。

次は doxygen とか smartdoc なんかのドキュメンテーションツールとか Pdoc, RDoc 辺りのツールのテスト。んで、RDBMS かな。Java はいつやるんだろうか。再来年か? というか DNS は?

PHP の配列はスマートじゃない

というか柔軟じゃない、かなぁ。Perl 流の配列のめちゃくちゃに柔軟な扱いに慣れてしまうと PHP の配列はカタく感じられていけない。配列の配列を扱いたいんだけど、ズバっと扱える Tips がどこにもないじゃないか。

まぁ他にも Perl のようにはスパッと書けない点が多く、ときどきイライラする。こりゃ Java なんか書けと言われたら発狂するかもしれんな。

About

例によって個人のなんちゃらです