"懒"需要红宝石

时间:2012-08-21 16:11:32

标签: sql ruby require lazy-evaluation

我有一个ruby脚本(相当大),使用SQL更新几个dbs。 大多数sql查询(甚至是表名)都是常量,看起来像:

MONTH = 8
SOME_TABLE = "the_table_name_" + MONTH + SOME_SUFFIX
SOME_QUERY = "CREATE TEMPORARY TABLE #{SOME_TABLE} SELECT yada, yada2 FROM #{SOME_OTHER_TABLE} WHERE yada=1 AND MONTH=#{MONTH};"

有数百个类似的查询和表,它们都互相使用。 我做了一个最近的更改,从命令行将“月”作为参数而不是命令行中的常量,所以在cron管理系统中运行此脚本。

我的第一个问题是我无法将MONTH设置为const。首先,我使用类似的东西来解决这个问题:

eval("MONTH=%d" % options[:month])

稍后我将MONTH更改为@month(全局)并修复了该问题。

第二个主要问题是我的main.rb有那条线

require("queries.rb")

在开始时,因此ruby尝试在需要时扩展var MONTH(或@month),在我的主要甚至运行之前! 我使用该代码解决了这个问题:

def run_lazy_loaded_work
    require './queries.rb'
    run_work
end

并删除文件开头的require当然。 该解决方案完美运行,因为在设置@month之后,在需要时,query.rb中的扩展会发生。

然而, 它听起来不像正确的解决方案,感觉就像一个讨厌的补丁,当其他开发者将获得该代码的所有权时,这可能不是防弹。

我尝试初始化配置类中的所有查询,初始化实例初始化中的所有查询,并具有访问权限,但由于这是数百行,以及所有使用它们的行,它变为甚至更糟糕。

我很想知道是否有人能想到更优雅的解决方案。

谢谢! :)

*更新** 我已经编辑了一下,目前它看起来像那样:

main.rb的:

require './work.rb'
def main
    run_work(options)
end

work.rb:

def run_work(options)
    @month=options[:month]
    load 'queries.rb'
    run_query(SOME_QUERY, SOME_TABLE, SOME_INDEX)
end

queries.rb:

SOME_TABLE = "table_name_#{@month}"
SOME_QUERY = "SELECT * FROM #{SOME_TABLE} WHERE month=#{month}"

2 个答案:

答案 0 :(得分:3)

一种可能的解决方案是更改queries.rb,以便昂贵的属性实际上是方法而不是“假”常量。然后要求queries.rb并不昂贵,并且您将代码更改为:

require queries.rb

#...

def run_lazy_loaded_work
    run_work(Queries.some_query())
end

我知道更改一个包含“数百”属性的文件可能看起来有些可怕,但看起来像一个常数但实际上对我来说似乎并不可怕。

答案 1 :(得分:0)

我会试着给我2美分。

您可以使用方法,而不是使用常量和实例变量。

第一次调用该方法时,它会定义内部帮助器实例变量的值。因此,只有在需要时才会扩展月份。

例:

def month
  # set @month at first time; or return it in further calls
  @month ||= $options[:month]     # here I'm using a global $options
end

(...)

# will get the month (will define it at first call)
SOME_TABLE = "the_table_name_" + month + SOME_SUFFIX