这是错误的,但为什么(以及如何让它更好地流动)?

时间:2012-03-01 22:49:51

标签: ruby hash optional-parameters

所以我正在弄清楚如何为课程设置一些选项。 'options'是一个哈希。我想

1)过滤掉我不想要或不需要的选项

2)将一些实例变量设置为在别处使用

3)并设置另一个哈希,处理后的选项为@current_options。

def initialize_options(options)
  @whitelisted_options, @current_options  = [:timestamps_offset, :destructive, :minimal_author], {}
  n_options = options.select { |k,v| @whitelisted_options.include?(k) }
  @current_options[:timestamps_offset] = @timestamp_offset = n_options.fetch(:timestamps_offset, 0)*(60*60*24)
  @current_options[:destructive] = @destructive = n_options.fetch(:destructive, false)
  @current_options[:minimal_author] = @minimal_author = n_options.fetch(:minimal_author, false)
end

我猜这有点多,不管我传给的是什么:

{:timestamps_offset=>0, :destructive=>false, :minimal_author=>false}

当我从命令行逐行执行此操作时,它可以按照我的要求工作,但不能在我的课程中工作。那么是怎么回事以及如何清理它?

编辑:这实际上是从我正在使用它的类中脱离出来的,但在它内部并不是这样,现实正在发生,我现在还不知道。

attr_reader:current_options是如何在类上设置的,可能需要一些修改。

EDIT2:该方法的第2行应该从@whitelisted_options

中选择

EDIT3:实际上原来是我没想到的东西......“选项”来自yaml文件解析为字符串....我正在取符号,改变周围有所不同之前的地方该方法寻找符号并找不到,例如“破坏性”vs:破坏性,所以总是默认为默认值。简而言之,我只需要在导入选项时对哈希键进行符号化。

2 个答案:

答案 0 :(得分:1)

您的@current_options被初始化为空哈希。当您过滤options作为参数传递时,@current_options中不会出现任何键,因此n_options将结束为空。

然后,当您在以下行中设置@current_options时,它将始终获取默认值(0, false, false),这就是您的输出始终相同的原因。

您可以通过有条件地初始化@current_options来解决此问题,以便它只设置为{}一次:

@current_options || = {}

OP后编辑:

你的问题是options.select - 在Ruby 1.8中,它不会返回哈希,而是返回一个数组。您对fetch的调用总是失败(因为符号不能是数组索引),所以总是返回默认值。

相反,请尝试:

n_options = options.inject({}) {|h, p| h[p[0]] = p[1] if @whitelisted_options.include? p[0]; h } 

其中p是包含每个键/值对的数组。

在Ruby 1.9.2中,Hash.select的行为方式符合您的预期。

编辑2:这是我接近它的方式:

class Foo
  @@whitelisted_options= {:timestamps_offset => 0, :destructive => false, :minimal_author =>false}

  @@whitelisted_options.keys.each do |option|
    define_method(option) { return @current_options[option] rescue nil}
  end

  def initialize_options(options)
    @current_options = {}
    @@whitelisted_options.each {|k, v| @current_options[k] = options[k] || v}
    @current_options
  end
end

使用中:

f = Foo.new
f.destructive #=> nil
f.initialize_options(:minimal_author => true, :ignore => :lol)
f.destructive #=> false
f.minimal_author #=> true
f.timestamps_offset #=> 0

答案 1 :(得分:0)

  1. 什么是@whitelisted_options
  2. 如果:destructive不是options中的关键字,您希望发生什么?您想要:destructive => false,还是希望@current_options根本不提及:destructive