2015/07/11

epgのデータベース登録

シンプルなサーバーアプリが出来たところで番組データを取り込んで、リストアップするところまで。

以前は素のRubyスクリプトでActiveRecordを直接使う流れでしたが、今回はRailsのタスクで用意してみる。

lib/tasks/epg.rakeファイルを作成。以下の様な感じになった。

タスクからタスクを呼ぶのは、executeとinvokeがあるが、invokeは処理中に1度しか呼ばないという仕様がある。チャンネル分回すので、今回はexecuteにした。

タスク引数は、Rake::TaskArgumentsを使うことになるが、executeの場合シンプルに渡すだけらしいので、execute(ch)ってやれば、|task,arg|のargに直接chが入るので、スッキリはする。
ただし、executeからしか呼べなくなるという制約がつく。外から引数付きのタスクとして呼べなくなる。

それから、:updateはただ呼ぶだけのタスクだから :environment は不要だろうと思ったが、親タスクも必要だった。因みに、 :environment はActiveRecordでのレコードクラスインスタンス作成などをやってくれるところらしい。詳しくは知らないっすが・・

後は、んん?というところは無いはず。ごく自然な流れ。


namespace :epg do

  EPG_PATH = Rails.root.join('tmp').join('epg')
  Chs = [27,26,25,24,23,22,21,16]
#  Chs = [27]

  desc "EPG 更新"
  task :update => :environment do
    Chs.each do |ch|
      arg = Rake::TaskArguments.new([:ch],[ch])
      Rake::Task['epg:get'].execute(arg)
      Rake::Task['epg:put'].execute(arg)
#      Rake::Task['epg:get'].execute(ch) ##1 個別に呼ぶのを諦めれば、こっちでもいける.
    end
  end

  desc "EPG 取得"
#  task :get do |t,arg| ##1
  task :get,[:ch] do |t,arg|
    `recfsusb2n -b -i epg #{arg.ch} 10 #{EPG_PATH}/#{arg.ch}.ts`
    `epgdump json #{EPG_PATH}/#{arg.ch}.ts #{EPG_PATH}/#{arg.ch}.json`
  end

  desc "EPG 登録"
  task :put,[:ch] => :environment do |t,arg|
    json = open("#{EPG_PATH}/#{arg.ch}.json").read
    data = ActiveSupport::JSON.decode(json)

    if data.present?
      # Channelレコード 登録
      Channel.create( ch: arg.ch,
                      name: data[0]['name'],
                      code: data[0]['id']) if Channel.where(ch: arg.ch).empty?

      # 過去のプログラムを削除
      Program.destroy_all ["end_at < ?",Time.now]

      # 登録
      data[0]['programs'].each do |prog|
        set_program( prog )
      end
    end
  end

  # レコード 登録
  def set_program( prog )
    if Program.where(event_id: prog['event_id']).empty?

      # category
      category = prog['category']
      if category.present?
        cate = Category.where(name:
                              [category[0]['large']['ja_JP'],' (',category[0]['middle']['ja_JP\
'],') '].join
                              ).first_or_create
      end

      # program
      Program.create( channel_id: Channel.where(code: prog['channel']).first.id,
                      event_id: prog['event_id'],
                      title: prog['title'],
                      detail: prog['detail'],
                      start_at: Time.at(prog['start']/10000),
                      end_at: Time.at(prog['end']/10000),
                      duration: prog['duration'],
                      category_id: cate.try(:id) )
    end
  end
end

0 件のコメント:

コメントを投稿