LocmareListGroup @ AboutLocmare

モデルに一覧取得SQLを発行するためのクラス。

基本的な考え方

SQLを発行する際に必要となる各種条件とは、次の三つである。

  • where
  • includes
  • order

一つのリストに対し上記の三つの条件を与える機能をモデルに実装することになる。例えば、publicのリストに対して、public_list_where, public_list_includes, public_list_orderの三つのメソッドを実装する。

モデルにこれらのメソッドを実装して、指定したメソッドを呼び出すことで、リストを取得できる。最も確実な方法なので、優先順位としてはこのメソッド呼び出しパターンが最強ではある。しかしながら、正直に実装すると、メンテナンスが大変なことになる。可能な限りは自動で組み立ててくれて、いざとなったらメソッド呼び出しで逃げることができればベストである。そこで自動生成について考えてみる。

自動生成 おおまかな規則

where

取得条件には、モデル単位で共通する条件と、リスト単位で共通する条件がある。この二つをクロスさせることで条件を生成する。リストの中には、どちらか片方の条件しか使わないものもある。

モデル単位で共通する条件

モデル単位で分けられるなら、モデルにメソッドを追加するのが一番早い。このタイプの条件はモデルにメソッドとして現れるので、メソッド名を指定する形となる。

このパターンの典型的な例は、コンテンツと非コンテンツの違いである。

システムリソースなどの非コンテンツは、閲覧制限がかけられていない。一方、コンテンツはオーナーによって閲覧制限をかけられるので、公開フラグを参照する必要がある。この条件文はパラメータを必要としないので、文字列だけで表現できる。

  def self.public_list_where
    'scrolls.visible > 0'
  end

公開フラグはモデルごとにカラム名や数値が変わる{パネルの公開フラグはpublishだったりする… }ので、設定には切り出しにくく、必ずメソッド呼び出しの形になる。

リスト単位で共通する条件

リストごとにクラスを定義して、抽象化する。

結合方法も必要なパラメータもリストタイプごとに違うので、結合処理はリスト側で行わなければならない。

フィルターの条件はパラメータを必要とするので、配列を使った条件となる。配列タイプの条件に別の条件を結合するには骨が折れるが、幸いにも文字列を配列タイプに重ねるので、楽に済む。ただし、これは現在の構成に限った話なので、いずれ例外が出るかもしれない。

includes

まず大前提として、リストにインクルードするべきモデルパターンは千差万別。最適なSQLを判別するのは簡単ではない。それでも、大抵の場合は、従属しているモデルを組み込むだけで良いので、そこを足がかりに生成する。

モデルのマニフェストにはツリー構造を設定できる。これは本来、エレメントのツリー構造を解析するための設定だが、includesを生成する要望とぴったり一致するので便乗することにする。

サンプルとしてスクロールとスクコマの関係を見てみる。

  scroll: {
    tree: {
      scroll_owner: 'author',
    },
  },
  scroll_panel: {
    tree: {
      owner: 'scroll',
      scroll_owner: 'scroll',
    },
  },

公開されているスクコマをリストアップ(public list )するには、公開フラグを参照しなければならない。フラグはスクロールモデルにあるので、スクロールを組み込みたい。そのため、ownerという名前のツリーを設定し、スクコマからスクロールを組み込めるようにしている。また、自分が作成したスクコマをリストアップ(外部フィルタリスト)するには、スクロールモデルをさらに遡って作家モデルも組み込まなければならない。そのため、scroll_ownerという名前のツリーを設定し、スクコマからスクロールを経由して作家を組み込めるようにしている。

なお、ツリー設定は親のモデルを探すためのものなので、子供のモデルをincludesに組み込む事は考慮していない。

WhereMethod

WhereAuto

統一条件のメソッド名を文字列設定する。省略したときは、アイテムの種別によって適切な文字列が補充される。

  • コンテンツの時 : 'public_list_where'
  • 非コンテンツの時 : 'list_where'

これらのメソッドは、アイテムやコンテンツの標準メソッドとして定義されているので、コーディングなしでもこけることはない。

コンテンツと非コンテンツに条件の違いなんてあるか?と思わないでもないが、システムリソースの中には無効なアイテムがあるかもしれないし、アカウントを(削除ではなく)停止することもあるかもしれないので、念のために用意しておく。そもそも、閲覧制限の有無で機能が違うのに名前が同じになると混乱の元になるので、明確に分けておく。

システムリソースのとき'enable_list'を補充したくなる。これによって、待機状態のリソースをリストから除外することができるが、ユーザに活用されてしまったリソースを管理者の都合で後から利用不可にされたものをオーナーが見れないのはいかがなものかと思うので、ここでは条件に組み込まない。

IncludeMethod

IncludeAuto

PublicList

PrivateList

FilterList

ThroughFilterList

ForeignFilterList

PlayList