2010-03-14 28 views
1

这是一个Ruby设计问题。如何制作可重复使用的平面文件分析器,以便每次调用都可以执行不同的数据清理操作,将每次清理操作的发出结果返回给调用者并执行批量SQL插入?SQL Bulk Inserter的Ruby设计问题

现在,在任何人得到无耻/关注之前,我已经以非常不流行的方式编写了这些代码。这就是为什么我要求任何Ruby摇滚乐队在那里为我们做点贡献。基本上,每次我想要执行这个逻辑时,我创建了两个嵌套循环,在两者之间进行自定义处理,将每个处理过的行缓存到一个数组,并在达到缓冲区大小限制时将其作为批量插入输出到数据库。

虽然我写了很多帮手,但主要模式是每次都复制粘贴。不是很干!

这是一个Ruby/Pseudo代码,我正在重复的例子。

lines_from_file.each do |line| 

    line.match(/some regex/).each do |sub_str| 
    # Process substring into useful format 
     # EG1: Simple gsub() call 
     # EG2: Custom function call to do complex scrubbing 
     #  and matching, emitting results to array 
     # EG3: Loop to match opening/closing/nested brackets 
     #  or other delimiters and emit results to array 
    end 

    # Add processed lines to a buffer as SQL insert statement 
    @buffer << PREPARED INSERT STATEMENT 

    # Flush buffer when "buffer size limit reached" or "end of file" 
    if sql_buffer_full || last_line_reached 
    @dbc.insert(SQL INSERTS FROM BUFFER) 
    @buffer = nil 
    end 

end 

我熟悉Proc/Lambda函数。但是,因为我想将两个单独的过程传递给一个函数,所以我不知道如何继续。我对如何解决这个问题有一些想法,但我真的很想看看真正的Rubyists建议的是什么?

给你。在此先感谢:D

回答

1

虽然jeem的解决方案可能是您的最佳选择,你甚至可以去一点,并创建两个类,而不是特效,读取器和作者:

class InsertReader 
    def initialize(lines) 
    @lines = lines 
    end 

    def each 
    @lines.each do |line| 
     yield(make_insert(line)) 
    end 
    end 

    def make_insert line 
    # return INSERT created for input line 
    end 
end 

class InsertWriter 
    def initialize 
    @buff = [] 
    @buffsize = 100 
    end 

    def write insert 
    @buff << insert 
    flush if @buff.length > @buffsize 
    end 

    def flush 
    @buff.each do |insert| 
     DbAdapter.insert(insert) 
    end 
    @buff = [] 
    end 
end 

,并使用他们喜欢

reader = InsertReader.new(my_file) 
writer = InsertWriter.new 
reader.each do |insert| 
    writer.write insert 
end 
writer.flush 

然后继承并重新实现您需要覆盖的每个特定案例的适当方法。

+0

感谢Jeem和Mladen。你们两人都得票直接向前解释。在设计方面,我更喜欢Mladen的方法,因为这更符合我的项目需求。 好的工作Rubyistas! :d – pchap10k

2

您可以将任意数量的proc对象传递给一个方法,但它们将成为普通参数,并丢失特殊块语法。例如。

def import(lines_from_file,insert_statment_maker,special_logic) 
    lines_from_file.each do |line|  
    inserts = []  

    line.match(/some regex/).each do |sub_str| 
    inserts << insert_statment_maker.call(sub_str)  
    end 

    inserts = special_logic.call(inserts) if special_logics 

    # Add processed lines to a buffer as SQL insert statement  
    @buffer << inserts 

    # Flush buffer when "buffer size limit reached" or "end of file"  
    if sql_buffer_full || last_line_reached 
    @dbc.insert(SQL INSERTS FROM BUFFER) 
    @buffer = nil  
    end 

end 

要叫你会......

build_m_and_m_insert = Proc.new {|sub_str| ..... } 
take_out_the_brown_ones = Proc.new {|inserts| .... } 

import lines, build_m_and_m_insert, take_out_the_brown_ones