Lokkathon #1でプラグインで管理画面を作れるようにしました。

サンプルとしてGoogle Analyticsのプラグインを作りました。

管理画面の作り方

komagata [p0t] - Lokka

管理画面からIDともしあれば、サブドメインを入力できます。(@nkmrshnさん作)

module Lokka
module GoogleAnalytics
def self.registered(app)
app.get '/admin/plugins/google_analytics' do
haml :"plugin/lokka-google_analytics/views/index", :layout => :"admin/layout"
end

app.put '/admin/plugins/google_analytics' do
Option.tracker = params['tracker']
Option.tracker_dn = params['tracker_dn']
flash[:notice] = 'Updated.'
redirect '/admin/plugins/google_analytics'
end

app.before do
tracker = Option.tracker
if !tracker.blank? and ENV['RACK_ENV'] == 'production' and !logged_in?
dn = Option.tracker_dn
tracker_script = ""
(snip...)
content_for :header do
tracker_script
end
end
end
end
end
end

管理画面を作るプラグインのコードはこんな感じです。管理画面のURLを '/admin/plugins/プラグイン名' にすると、プラグイン一覧のプラグイン名から自動的にリンクが張られます。

komagata [p0t] - Lokka

/admin/〜というURLには自動的に認証が係るので、プラグイン内で認証を気にする必要はありません。

テンプレートへの挿入

テンプレートの中にはheader, footerという外部から何かを挿入できるポイントがあります。(テーマ側でこのheader, footerが無い場合は何も起きません)

要はyieldなので、プラグインの中からそれぞれの場所にcontent_forしてあげればプラグインからテンプレートにタグを挿し込むことができます。

content_for :footer do
'<p>created by unk</p>'
end

この仕組を使えばjavascriptを使ったプラグインなどが簡単に作れそうです。

Lokkathon #1でLokkaをgem化しました。

$ gem install lokka

lokkaコマンドが入ります。

$ lokka
== Sinatra/1.1.0 has taken the stage on 9646 for development with backup from WEBrick
[2010-11-22 17:19:23] INFO WEBrick 1.3.1
[2010-11-22 17:19:23] INFO ruby 1.8.7 (2010-08-16) [i686-darwin10.4.3]
[2010-11-22 17:19:23] INFO WEBrick::HTTPServer#start: pid=8950 port=9646

デフォルトのポートは9646(苦しむ)番になりました。

あくまでプラグインデベロッパーのテストを書くのを簡単にするためと、プラグイン同士の依存関係解決のためにgem化しただけで、ユーザーのインストール方法は変わりません。(zip解凍する)

明日土曜日・日曜、待ちに待った大イベント、Lokkathon #1が開催されます。気になる開催概要は下記です。

Lokkathon #1

  • 日時 / DATE: 2010/11/20 10:00 to 19:00
  • 定員 / LIMIT: 俺
  • 会場 / PLACE: FJORD, LLC
  • URL / URL: http://fjord.jp/
  • 内容 / DESCRIPTION: Lokka本体・プラグイン・テーマを作る。

ああ、そうだよ。思いつきだよ。ダジャレだよ。

プラグインの管理画面へのリンク

Lokkaでプラグインで管理画面を持った時にプラグイン一覧からリンクしてくれるようにしました。

Test Site - Lokka

最初はプラグイン内でhave_admin_page(acts_as_fooみたいなの)を宣言するようにしてたんですが、頑張って、

Lokka側から "/admin/plugins/#{プラグイン名}"のページがプラグインに存在したらリンクを貼る。

というようにしました。

管理画面左メニューへの追加

また、管理画面の左メニューの一番下にyield_content :admin_menuというプラグインから挿入できるポイントを入れときました。複数回呼べるみたいなので、色んなプラグインから挿入されても大丈夫ですね。(順番はプラグインの読み込まれる順)

まだ、プラグイン内で管理画面作った場合の認証入れてないんですが、sinatra1.1のパス指定beforeを使えるようにしてからの方がいいかなと・・・。

テーマの方にもheader, footerという挿入できるポイントを入れようと思ってます。(全テーマ修正がだるい・・・)

僕の中で曖昧だったので、ユーザー分類を元にLokkaの開発方針をまとめてみました。

ユーザー分類

  • 閲覧者(visiter)
    • ブログを見に来る人
  • 投稿者(author)
    • ブログにエントリーを投稿する人
  • 管理者(administrator)
    • ブログを設置し、管理する人
  • 開発者(developer/designer)
    • プラグイン・テーマを作る人
  • コミッタ(commiter)
    • 本体を作る人

上(人数が多い)、下(人数が少ない)

上(影響が少ない)、下(影響が大きい)

ユーザー分類補足

  • 閲覧者
    • fc2とwordpressの見た目が殆ど付かない現状、閲覧者にとってはどのツールも違いがない。
  • 投稿者
    • ブログの体裁を取っていれば殆どの投稿者にとっては最低限投稿することは出来る模様。UI改善の余地は多少あり
  • 管理者
    • インストールの敷居がまだ高い
    • 職業Webデザイナーが多い
    • ローカルで開発するデザイナーは殆どいないらしい
      (Apache + MySQL or XAMPが必要等、敷居が高いため)
    • CMS/Blogツール導入の権限はココに該当する人にある
    • どれだけ管理者に好かれるツールであるかが最も重要。
  • 開発者
    • 上記管理者に好かれるツールになるかどうかは開発者の充実にかかっている。
    • テーマはデザイナー、プラグインはプログラマーが主に作ることを意識する必要がある。
  • コミッタ
    • コア内部よりも上記開発者に触れる部分をどれだけ簡単でクリーンに出来るかが重要だと思われる。コミッタはそれ程大勢になるわけではないので開発者への奉仕に注力する必要がある。
    • フルタイムのコミッタがいるプロジェクトは成功率が高いらしい

どんなソフトウェアを目指すのか?(スローガン)

  • CMS for Cloud
    • クラウド環境で良く動く
  • 打倒WordPress
    • 協調や補完では無く打倒。
    • WordPressを置き換えるモノで無くてはならない。つまり現状のWordPressユーザーが置き換えたくなる機能が必要。

必ず実現したいこと

  • デフォルトでHeroku(or GAE)で良く動くこと
    • ファイルのWriteや大量DB消費があってはならない
  • Windows, Mac, Linuxでzipを解凍すれば動くこと
    • デザイナーがローカル環境で作業するのに必須
  • zipを解凍してフォルダに置くだけでプラグインが動くこと
    • WordPressユーザーにとって必須
  • 少なくとも1つ、現実的な分散環境で簡単に動くこと
    • プライベートクラウドで簡単に動くようにするということ
    • mongodbとかkumofsとかromaとかそういうの。

できれば実現したいこと

  • 本体とプラグインがgem
  • プラグインが単体でテストし易い
    • 本体のgem化が出来ればこれもできることになる

要は?

  1. ファイルのWriteしない(=クラウド対応)
  2. RDB, KVS, Document指向DBに対応
  3. zip解凍で動く
今のところこれがこのソフトの存在意義。これが出来なければ作る意味が無いので気をつけていきたい。

@nkmrshnさんの素晴らしいまとめ。Optionを使ってるコードとかまだ他で見たことないので素敵ですw

作成したLokkaプラグインのまとめ - nkmrshnの日記

  1. プラグインで使用するgemを、Gemfileと別にプラグイン側で管理する方法。(現状:Lokka本体のGemfileに書くしかない。)
  2. プラグインで使用するi18nのen/ja.yml。(現状:Lokka保体のen/ja.ymlに追記するしかない。)
  3. プラグインの読み込む順番。(現状:読み込む順番を設定できない。)
  4. プラグインの有効・無効。(現状:public/plugin/lokka-<プラグイン名>は全部有効。)
  5. プラグインのアップロード・削除機能。(現状:ターミナルのコマンドなどでプラグインファイルを追加・削除する必要がある。)
  6. public/admin/layout.hamlのdiv#aside(左側サイドメニュー)にプラグインのメニュー項目を追加。(現状:layout.hamlに追記するしかない。)

コメント欄に書いたらエラー?が出たのでココに書きます。(以下俺)

おおお、すばらしいまとめありがとうございます!

最後の6点は僕もどう本体を実装すべきか悩んでおります。

  1. C拡張を含むメジャーなgemは本体に同伴し、pluginで必要な(Pure Rubyの)gemはpluginに同伴してもらう?
  2. 頑張ればplugin毎のi18nを読み込める?拙作のdm-validations-i18nとあわせて対応できるか?r18nの利用を継続するか?
  3. railsのようにルールさえ明確ならば指定出来る必要は無い?
  4. DBで管理すれば可能だがWordPressであんまり必要性を感じてないので検討中。
  5. 実装方法が思いつかない・・・(基本WRITE出来ない環境を想定してるので現状でいいかも?)
  6. やり方を決めればいいだけなんですが、選択肢が有り過ぎてしっくりくる方法を思いついていない。文字列とリンクURLの構造体を持つ?xxxxx.{erb,haml,erubis}があったらそれを表示する?

という感じです。

やっぱりプラグインを書いてみた人本人でないとわからない点が沢山あるとおもいますので、「こうしたほうがいい」というところがあればお教えいただけると嬉しいです!

LokkaにWordPressでいうwp_options的なサイト固有で何でも入れとける場所を作りました。(Lokkaではscript/console的なのは irb -r init.rbで出来ます)

% irb -r init.rb
>> Option.aksmet_key
=> nil
>> Option.aksmet_key = 'hoge'
=> "hoge"
>> Option.aksmet_key
=> "hoge"
>> Option.all
=> [#<Option @name="aksmet_key" @value=<not loaded> @created_at=Sun, 31 Oct 2010 00:01:02 +0900 @updated_at=Sun, 31 Oct 2010 00:01:02 +0900>]

lib/lokka/option.rb from komagata's lokka - GitHub

ソースは上記の通りです。name / valueしか持たないテーブルにmethod_missingでいれているだけです。

上の例の様にプラグインで値を保存したい時に、プラグイン毎にイチイチテーブルを作るまでもないもの(akismetのkeyとか)を保存する場所として用意しました。

% irb -r init.rb
>> @site = Site.first
=> #<Site @id=1 @title="Test Site" @description="description..." @theme="default" @created_at=Sun, 31 Oct 2010 00:06:39 +0900 @updated_at=Sun, 31 Oct 2010 00:06:39 +0900>
>> @site.akismet_key
=> "hoge"

また、Siteクラスのインスタンスから代入以外はOptionにproxyするようにしました。

追記:optionsテーブルが増えたので最新にした方は $ bundle exec rake db:migrate お願いします。

Lokkaのプラグインの機能を修正しました。

komagata's lokka at master - GitHub

修正点

  • プラグインのフォルダ名規則を変更(foo -> lokka-foo)
  • プラグインフォルダを移動(/plugin -> /public/plugin)

フォルダ名はそもそもlokka/foo.rbだったのでオートロードの命名に従えばlokka-fooのハズ、というのと、プラグインをgemにするときのためです。(sinatra-logger, rack-flashみたいに。)

プラグイン命名規則は要は下記。

Dir["public/plugin/lokka-*/lib/lokka/*.rb"]

フォルダ移動はプラグイン内にcssや画像を置けるようにです。WordPress的に。

RbConfig Plugin - Lokka

これはrbconfigというプラグインを試しに作ってみて、問題が出たところを修正した感じです。rbconfigプラグインは単にrubyインタプリタの情報を表示するrbconfigを出すだけのプラグインです。

# lokka-rbconfig/lib/lokka/rbconfig.rb
require 'rbconfig'

module Lokka
module Rbconfig
def self.registered(app)
app.get '/admin/plugins/rbconfig' do
haml :"plugin/lokka-rbconfig/views/index", :layout => :"admin/layout"
end
end
end
end
# lokka-rbconfig/views/index.haml
- content_for :head_last do
%link{:rel => 'stylesheet', :href => '/plugin/lokka-rbconfig/views/style.css', :type => 'text/css'}
%h2 RbConfig
%dl.rbconfigs
- Config::CONFIG.each do |key, value|
%dt= key
%dd= value

中身はこんな感じです。

問題点

作ってみてプラグイン機能の課題がいくつかできました。

  • テンプレートの指定が冗長
  • 管理画面や他のテーマのlayoutを利用する場合はテンプレート言語が同じである必要がある。(管理画面の場合はhaml限定になる)
  • プラグインがページを持ってない場合もあるのでプラグイン一覧からリンクを貼っていいのか悪いのか、どこに貼ればいいのかわからない。(lokka本体にプラグインのページを知らせる方法が無い)

もしインストールしてみた方で自分用に修正した箇所とかあれば是非、気軽にpatchやpull requestしていただけるとありがたいです!

http://localhost:9393/hello

Commit c6954984dca64cbc02ee28f63ec4f7ce56bec1b4 to komagata's lokka - GitHub

ktkr! 神降臨! > @yagi_

IRC(#lokka-ja)で適当に話してたことが既に実装されとる!

テーマAPIとプラグインAPIは超大切なのでプラグイン規約はちょっと悩みますね。@yagi_さんが書かれている通りですが、現状helloというプラグインを作るとするとこんな感じです

  • plugin/lokka-hello/lib/lokka/hello.rbがあればrequireする。
  • Lokka::Helloがあればregisterする。
  • helperはLokka::Helpersを勝手に再オープンしてメソッド追加すればよろし。

規約とは殆どが配置と命名の事です。配置はこんな感じです。

LOKKA_ROOT/
 plugin/
  lokka-hello/
   lib/
    lokka/
     hello.rb

URLの/helloにアクセスするとhelloと表示し、helloというhelperを追加するhelloプラグインの中身はこんな感じです。

module Lokka
  module Hello
    def self.registered(app)
      app.get '/hello' do
        'hello'
      end
    end
  end

  module Helpers
    def hello
      'hello'
    end
  end
end

簡単なルールでいいかもですね。

Lokkaの@yagi_さんのforkのplugin autoloadを辛抱たまらず勝手にマージしてみた。

$ git fetch git://github.com/yagitoshiro/lokka.git master:plugin-patch
$ git merge plugin-patch

Commit c01380f5d6d5ddf4145fa990c7d3d1ca03ed8bce to komagata's lokka - GitHub

404 not found - Lokka

サンプルのHelloプラグインが動いてないので明日もっとよく見る。今日は寝る。