読者です 読者をやめる 読者になる 読者になる

Sequel::ModelでJoinしたテーブルの値をWhere条件にするやりかたとか

泥縄で調べた事なので、このやり方で本当に良いのかわからないけどとりあえずメモ。
先日公開した、http://nbc.skr.jp/なんですが、ModelにSequelを使用しました。で、生放送とコミュニティのデータ管理するためにこんな感じのコードを書いた。

require 'rubygems'
require 'sequel'

Sequel::Model.plugin(:schema)
DB = Sequel.sqlite('kaitemita.sqlite3')

class Live < Sequel::Model
  unless table_exists?
    set_schema do
      primary_key :id
      text :live_id       #生放送ID
      text :name          #番組名
      date :pub_date      #放送開始時間
      text :description   #番組説明
      text :community_id  #放送コミュニティ
    end
    create_table
  end
  many_to_one :community, :key => :community_id, :primary_key => :community_id
end

class Community < Sequel::Model
  unless table_exists?
    set_schema do
      primary_key :id
      text :community_id  #コミュニティID
      text :name          #コミュニティ名
    end
    create_table
  end
  one_to_many :lives, :key => :community_id, :primary_key => :community_id
end

livesとcommunitiesにアクセスするためのLiveとCommunityクラスです。
で、両クラスを使用するこんな感じのプログラムを書くと、最近放送を開始した順番に10件ほど放送の情報を表示してくれる、と。(もちろんDBにデータが入って無いと駄目だけど)

live = Live.
  order(:pub_date.desc).
  limit(10)
puts live.sql

live.all.each do |l|
  puts "#{l.live_id} (#{l.pub_date}開始):#{l.name} (#{l.community.name})"
end

そのまま表示するのも芸がないので、番組名に「絵」という文字が含まれているものだけを抜き出そうとするとfilterメソッドlike使ってこんな感じ。

live = Live.
  filter(:name.like('%絵%')).
  order(:pub_date.desc).
  limit(10)
puts live.sql

live.all.each do |l|
  puts "#{l.live_id} (#{l.pub_date}開始):#{l.name} (#{l.community.name})"
end

同じ事をcommunitiesテーブルに格納されているコミュニティ名でやろうとした場合、単純に:nameをcommunity_name置き換えただけではそんなフィールド無いってエラーになります。
で、ネット上にあるSequelのサンプルを見るとJoinメソッドを使用してテーブルを連結している例があるのでそれに習ってやってみると一応動きました。

live = Live.
  join(:communities, :community_id => :community_id).
  filter(:communities__name.like('%絵%')).
  order(:pub_date.desc).
  limit(10)
puts live.sql

live.all.each do |l|
  puts "#{l.live_id} (#{l.pub_date}開始):#{l.name} (#{l.community.name})"
end

でも、これだとせっかくModelクラスに関係とか定義してるのに使われないし、定義があちこちに有るとか、方やテーブル方やクラスというのはなんか嫌なのでどうにかできないかなーとあれこれ調べたところ、eager_graphというメソッドがありました。

live = Live.
  eager_graph(:community).
  filter(:community__name.like('%絵%')).
  order(:pub_date.desc).
  limit(10)
puts live.sql

live.all.each do |l|
  puts "#{l.live_id} (#{l.pub_date}開始):#{l.name} (#{l.community.name})"
end

一応、Liveクラスのmany_to_oneを使用してSQLを作成してくれる模様。これでいいのかなぁ。