Categories
open all | close allTags
Aptana | テスト | 認証 | RESTful | スキンエンジン | nextlink | CSRF | 名称 | モデル | カテゴリ | タグ | 抽象化 | Migration | フォーム | アクセス制御 | rake | パソコン | デュアル・コア | OpenID | プラグインSearch
OpenIDの使い方
最近,実験的なものが中心だとは思いますがOpenIDで認証可能なサービスがいくつか出てきました。今のところFoodynは自前の認証しかしていませんが,プラグインで拡張可能な形にはする予定です。そんなに難しくなくて,自前の認証の前にプラグイン用のイベントを用意しておき,そこで認証が行われたときは自前の認証はしない,というだけで済むはず。とはいってもまだOpenID自体生半可にしか理解していません。例えばYahoo!ジャパンのOpenIDにだけ対応して,そのサイトにユーザーがアクセスしにくると,Yahoo!でログインしているかどうかを調べて,自動的に自分のところもログインするなんてことはできるのでしょうか。
なんでそんなことを考えているのかというと,今プライベートでYahoo!グループ(昔のeGroups)を使っているのですが,これだけだと機能が低いので,自サイトのサービスを使って拡張できないか,ただそのときに新たに認証登録などはしないで済ませられないかと思っているのです。コンピュータ・リテラシがあまり高くない人も結構いるので,今のOpenIDのサイトみたいにギークでないと使えないようなものは無理。なるべく自動的にしてあげないといけないのです。
テンプレート表示
前回書いたようなモデル化までが済んでいれば,テンプレートでマルチカテゴリをサポートするのは簡単です。とりあえずテンプレートにと書いたときに展開するというだけのものをあげておきます。これをテンプレートのパースのクラスに置くだけでOKです。
def parse_multiplecategories params
temp = ""
separator = nil
item.categories.each do |cat|
temp += separator.to_s
separator ||= ','
temp += link_to( cat.cname, {:controller=>'categories', :catid=>cat.id.to_s, :action=>'show'})
end
return temp
end
カテゴリとタグのリレーション設定
Foodynではタグとカテゴリは1テーブルで管理し,どのアイテムがどのカテゴリ,あるいはタグに属しているかを中間テーブルを使って記す方法を取っています。Ruby on Railsではこれはhabtn(has and belongs to many)あるいはhas_many throughという方法で取り扱います。ここでは中間テーブルも明示的にいじれるように後者の実装を採用します。中間テーブルのTagCategoryでは次のように取り扱います。
class TagCategory < ActiveRecord::Base
set_base_name 'tag_category'
belongs_to :categories, :class_name=>'Category', :foreign_key=>'category_id'
belongs_to :items, :class_name=>'Item', :foreign_key=>'item_id'
endItem側ではitemオブジェクトに対してitem.categoriesとすればカテゴリ一覧を,item.tagsとすればタグ一覧を表示するために条件を加えてやります。
has_many :categories, :through => :tag_category, :conditions=>"cleft is not null"
has_many :tags, :through => :tag_category, :source=>:categories, :conditions=>"caliasid is not null"
has_many :tag_category
2行目で:source=>:categoriesとしているのはTagCategoryの belongs_to:categoiesを参照しなさいという意味。
これで :conditionsのところの条件でカテゴリとタグを分けます。
マルチカテゴリのテンプレート指定
マルチカテゴリを標準機能として採用すると,Nucleusのテンプレート・モデルと合わない部分が出てきます。具体的には<%catname%>や<%catlink%>といったテンプレート変数は意味がなくなります。例えばdefault/indexのテンプレート中における<a href="<%categorylink%>" title="Category: <%category%>"><%category%></a>
という部分です。どうしても上位互換にするなら,これらのテンプレート変数が来たときは,検索してトップに来たカテゴリーを代表とするとかってことにする手もありますが,どうですかねえ(こうすればシングル・カテゴリーで使っている人の互換性は一応保たれます)。昔考えたときはitemテーブル内のicatをデフォルト・カテゴリという扱いにする,といった実装も考慮していたと思いますが,あまり前向きでないので,それは避けたいところ。
とりあえず,MultipleCategories使っている人はこの部分をそのままにしておくはずはないだろうから,MultipleCategoriesというテンプレート変数をそのまま使ってしまって,というのが当面の実装になりそうです。
で,肝心なことは,複数カテゴリが標準のときのテンプレートにおけるカテゴリー指定はどう書くのがいいか,ということ。<%categories%>とかってテンプレート変数を作って,それが呼ばれたときにテンプレート内の専用の項目を見に行くとかっていうのがNucleusの今の仕様に一番近い形ですが,セパレータの指定をどう書くかなど,ちょっと悩ましい部分があります。
あとは,これまで使用を封印してきたネスト付きパーサで,テンプレート内テンプレートをやらせてしまう,というのもあるけど,やっぱり今のモデルと極端に違うものを加えるのは良くないだろうなあ。
Aptanaのデバッグ問題ようやく解決
めんどくさがらずに早くフォーラムで聞けばよかった。http://forums.aptana.com/viewtopic.php?p=20870#20870
DreamHostでpassenger(mod_rails)サポート
米国の有名なホスティング・サービスDreamHostで,passenger(aka mod_rails)がサポートされたそうです(ブログ・エントリ)。これがあるとRailsアプリをホスティングで動かすのがPHP並みに簡単になるとか。使ってみたいですねえ。といってもまだ今のホスティングでもRailsアプリ動かしていないのですが(今のところ実験はローカルだけ)。このホスティングではまだアナウンスがありません。多分テストはしているのでしょうけど。
DreamHostは年間100ドル近い割引のクーポンが出回っているので,1年だけテスト用に借りるというのはあるでしょうね。悪評も多いところなのでメインに使うのはちょっと不安ですが。
設計とメソッド名と内部構造
どうも頭がまだ手続き型言語から抜けていないようで,メソッド名を付けるときに,ついつい「get~~」みたいに動詞を入れてしまいがちです。ということに気付いたのは,あるブログに属するカテゴリー一覧を取得するとき。実はこれまでCategoryクラスの方でget_listというメソッドを作ってブログオブジェクトをパラメータに取得するようにしていました。こうしておくと,ブログが指定されないときの一覧やブログが複数あるときの一覧とかも同じメソッドで取れるというのがメリットなのですが,見直してみるとCategory.get_list ... と入るのはあまりきれいじゃないです。やはり blog.categories と書いた方がスマート。
これだと順序付けができないのかと思って,この記述を使っていなかったというのもあるのですが,APIを見たら has_many のリレーション指定の中で :order を使って指定できることが分かったので,今回はそちらに切り替えました。
ただ,しっくりこない面がないわけではありません。これだとBlogクラスの中でCategoryのテーブルの内部情報を使って :order のところを書くことになるため,Categoryの実装に完全に依存してしまいます。Categoryの内部構造が変わったらBlogクラスも変えなければいけないのでメンテナンス性が悪くなります。
どうするのがベストなんでしょう。
週末に
タグとカテゴリーは表示系まで終わらせるつもりだったのですが,意外とデータ移行に手間取り,表示系に行きつきませんでした。残念!タグとカテゴリーのサポートについて
Foodyn CMSではツリー型のマルチカテゴリーとタグを標準でサポートします。機能的にはNucleusのMultipleCategoriesとTagEXと同等以上のものになるでしょう。詳しくは後日説明しますが,大部分は2年前にNucleusにこれらの機能を入れようとしたときのものをベースにしています(コードそのものはもう忘れたので別物ですが,考え方など)。
カテゴリー・テーブルを拡張してツリー型の管理およびタグの管理ができるようにします。ツリー管理ではNested Setと呼ばれる,SQL1回の呼び出しで子ツリーを全部取り出せる方法を取ります(説明はこちらの方が分かりやすいかも)。
ツリー構造はブログごとに持ちます。また,タグもブログごとに持ちます。これはタグからカテゴリーへの変換やその逆が楽にできるようにするためです。
タグの場合はブログ横断で検索したいケースもあると思うので,複数のタグが共通の「親タグ」(あるいは「別名タグ」)を参照するようにします。例えばブログ1に「Rails」というタグがあって,IDが10だとします。ブログ2にも「Rails」というタグがあってIDが20だとします。このときにaliasidというフィールドはどちらも10になります(別にどちらも20にしても構いません。共通であればいいだけなので)。このaliasidのフィールドを使うとブログを串刺しにしたタグ検索が可能です。
アイテムとタグ,カテゴリーを紐付けるために新しいテーブルを作ります。ここにはアイテムのIDとタグ・カテゴリーのIDがカテゴリーやタグの数だけ入ります。このテーブル上ではタグとカテゴリーの区別はなく,あくまでもカテゴリー・テーブルにおける違いだけになります。
RailsのActiveRecordにおいては,このテーブルを介してアイテムと,タグ・カテゴリーが多対多のリレーションを持つことになります。このとき「has and belongs to many(HABTM)」あるいは「has_many :through」という二つの方法があり,前者では中間テーブルはRailsが管理し,ActiveRecordで直接いじることはできません。ここでは自由度が高い後者の方法を使っています。
思ったより大変でない
前の記事で書いたTagEXデータのコンバートについてですが,どちらにしてもモデルで,そのタグがそのブログで新規かどうかのチェックなどをしないといけないので,コンバート自体についてはあまり深く考えなくてもそのメソッドを呼び出すだけでできそうです。裏方仕事は多少ありますが,それは当然のこと。
MultipleCategoriesのコンバート部分も基本的にはできたはず。両方できてからじゃないとチェックするのが面倒なのでまだ動かしていませんが。