如何为此自定义方法延迟作业?

时间:2013-01-12 20:39:22

标签: ruby-on-rails postgresql delayed-job

这是我的课程模型:

#encoding: utf-8

class Lesson < ActiveRecord::Base
    attr_accessible :content, :title, :parsed_content, :html_content, :user_id

    serialize :parsed_content, Array
    serialize :html_content, Array
    serialize :pinyin_content, Array
    serialize :defined_content, Array
    serialize :literal_content, Array

    validates :title, :presence => true
    validates :content, :presence => true

    belongs_to :user

    before_update do |lesson|
        lesson.makesandwich
    end

    before_save do |lesson|
        lesson.delay.makesandwich
    end

    def makesandwich

        require 'rmmseg'
                                                          #require 'to_lang'
        require 'bing_translator'
        require 'ruby-pinyin'

        self.parsed_content = []

        RMMSeg::Dictionary.load_dictionaries

        content               = self.content
        paragraphs            = content.split(/\r\n\r\n/) #convert to array of paragraphs
        self.parsed_content = paragraphs
        paragraphs.each_with_index do |text, ti|

            text = text.gsub("。", "^^.")
            text = text.gsub("?", "~~?")
            text = text.gsub("!", "||!")
            text = text.gsub(":", ":")  #fix missing colons

            text = text.split(/[.?!]/u) #convert to an array
            text.each do |s|
                s.gsub!("^^", "。")
                s.gsub!("~~", "?")
                s.gsub!("||", "!")
                #s.gsub!("———————————",":")
            end

            text.each_with_index do |val, index|
                algor     = RMMSeg::Algorithm.new(text[index])
                splittext = []
                loop do
                    tok = algor.next_token
                    break if tok.nil?
                    tex = tok.text.force_encoding('UTF-8')
                    splittext << tex
                    text[index] = splittext
                end
                paragraphs[ti] = text
            end
        end
        bing                   = BingTranslator.new(BING_API)
        self.parsed_content  = paragraphs
        textarray              = Marshal.load(Marshal.dump(paragraphs))
        self.defined_content = Marshal.load(Marshal.dump(paragraphs))
        self.literal_content = Marshal.load(Marshal.dump(paragraphs))
        self.pinyin_content  = Marshal.load(Marshal.dump(paragraphs))
        textarray.each_with_index do |paragraph, pi|
            paragraph.each_with_index do |sentence, si|
                sentence.each_with_index do |word, wi|
                    if DictionaryEntry.find_by_simplified(word) != nil
                        self.defined_content[pi][si][wi] = DictionaryEntry.find_by_simplified(word).definition
                        #self.literal_content is down below
                        self.pinyin_content[pi][si][wi]  = DictionaryEntry.find_by_simplified(word).pinyin
                    else
                        self.defined_content[pi][si][wi] = bing.translate(word, :from => 'zh-CHS', :to => 'en')
                        #self.defined_content[pi][si][wi] = word
                        #self.literal_content is down below
                        if PinYin.of_string(word, true).length > 1 #for punctuation
                            self.pinyin_content[pi][si][wi] = PinYin.of_string(word, true).join(" ").downcase
                        else
                            self.pinyin_content[pi][si][wi] = word
                        end
                    end
                end
            end
        end

        #Literal
        literalarray = Marshal.load(Marshal.dump(paragraphs))
        literalarray.each_with_index do |paragraph, pi|
            paragraph.each_with_index do |sentence, si| #iterate array of sentence
                literalarray[pi][si] = []
                sentence.each_with_index do |word, wi| #iterate sentence's array of words
                    entrytobesliced = DictionaryEntry.find_by_simplified(word)
                    slicedentry     = []

                    if entrytobesliced == nil
                        if word.length > 1 && word !~ /\w/ #/^\s*\w\d+\s*$/ #number regex  #for cases where there is no DictionaryEntry
                            split     = []
                            wordarray = word.split("").each_with_index() do |ws, wsi|
                                split << [DictionaryEntry.find_by_simplified(ws).definition]
                            end
                            literalarray[pi][si] << split
                        else
                            literalarray[pi][si] << [word] #in case none of the above work
                        end
                    else
                        entrytobesliced.simplified.each_char do |w|
                            singlechar = DictionaryEntry.find_by_simplified(w)
                            slicedentry << singlechar.definition.split("\", \"")
                        end
                        literalarray[pi][si] << slicedentry
                    end
                    self.literal_content = literalarray #slicedentry #literalarray
                end
            end


        end
    end
end

当我尝试创建新课程时,会出现以下错误:Jobs cannot be created for records before they've been persisted

但如果我将其更改为after_save而不是before_save,那么我可以看到工作正在运行,但它不会更新数据库中的序列化数组。

有人可以帮我实现delayed_jobs吗?当我有时,它正在工作:

    before_save do |lesson|
        lesson.makesandwich #no delay
    end

1 个答案:

答案 0 :(得分:2)

我认为你得到了这些错误:

  

在记录保留之前无法为记录创建作业

因为您的Lesson个实例在保存并且没有id之前不会有id,因此DJ无法知道它应该使用哪个实例。因此,您必须使用after_save,以便Lesson拥有id,并且可以进行唯一标识。但是,延迟作业的更新将不会被保存,因为没有任何东西要求保存它们。您应该只需在self.save末尾添加self.save!makesandwich来电即可解决此问题。