我想在ruby中进行紧凑的错误检查分配。
class User
attr_accessor :x
end
user = User.new
user.x = 5
a = b || user.x
我想弄清楚哪些是第一个有效属性并分配它,类似于javascript如何处理不同的API,即:
var AudioContext = window.AudioContext||window.webkitAudioContext;
audioContext = new AudioContext();
并找出哪些是有效的。
但是,对于ruby,当我引用一个未定义的变量时,类似的语法会出错。即:
a = 10
b = 7
c = a || b
c # => 10
VS
a = 10
c = b || a # => Error: b is undefined
有干净的方法吗?或者至少,最好的方法是什么?
我正在使用我尚未创建的大型代码,我不允许更改它。
更新: 我认为真正的用例与这个问题有关,所以我会解释它。
我有一个模块,每次更新rails中的模型时都会向DB保存一些内容,此更新需要一个id字段,此id字段位于包含我的模块的模型中,但并非每个模型都保持相同的命名约定为了这个id。三元运算符相当于我想要做的是
id = defined?(self.id) ? self.id : defined?(self.game_id) ? self.game_id : defined?(self.app_id) ? self.app_id : nil
与js等效
相比,难以读写答案 0 :(得分:3)
您可以使用defined?
来测试名称是否指当前范围内可识别的内容(方法,局部变量等):
c = defined?(b) ? b : a # of course this assumes that 'a' is defined
虽然你从未定义的局部变量中分配是非常不确定的 - 这是怎么出现的?
或者您是否总是在测试物业?在这种情况下,respond_do?
可能是更好的选择。
我使用三元运算符作为示例,当然可以使用if / elsif / else块。
由于您只是测试方法,respond_to?
比defined?
更方便,因为它可以使用符号而不是表达式来应用您想要的任何逻辑:
def invoke_first *names
names.each do |name|
if respond_to? name
return send name
end
end
return nil # or, more likely, raise something
end
或更简洁:
def invoke_first *names
send names.find(lambda {raise 'no method'}){|n| respond_to?(n)}
end
包含在您的模型中并用作:
invoke_first(:foo_id, :bar_id, :baz_id)
答案 1 :(得分:0)
好的,有一个更简洁的方法来做到这一点,但它有一个副作用,分配给undefined var的东西。
这打破了
a = 1
c = b || a # => b is undefined
这有效
a = 1
c = b ||= a # => c == 1, b == 1
如果b有效,上面将b分配给c,然后再回到a。如果b未定义/无效,则仅将a分配给b(和c)。