设置变量A,名称存储在变量B中

时间:2011-12-24 20:08:22

标签: ruby metaprogramming

我有以下两个变量:

a = 1;
b = 'a';

我希望能够做到

SOMETYPEOFEVALUATION(b) = 2;

以便变量a的值现在设置为2

a # => 2 

这可能吗?

具体来说,我正在使用Facebook API。每个对象都有各种不同的连接(朋友,喜欢,电影等)。我有一个解析器类,它存储所有这些连接的最后一次调用Facebook API的状态。这些状态都被命名为与您必须调用的GET相对应,以便更新它们。

例如,要更新音乐连接,请使用https://graph.facebook.com/me/music?access_token= ...我将结果存储在名为updated_music的变量中。对于书籍,其更新的书籍。如果我创建了所有这些连接类型名称的列表,我理想地想做这样的事情。

def update_all
  connection_list.each do |connection_name|
    updated_SomeTypeOfEvalAndConcatenation(connection_name) = CallToAPI("https://graph.facebook.com/me/#{connection_name}?access_token=...")
    end
end

Rails和StackOverflow都是新手,所以如果有更好的方法可以遵循任何约定,请告诉我。

尝试以下方法。

class FacebookParser

attr_accessor   :last_albums_json,         

  def update_parser_vars(service)
     handler = FacebookAPIHandler.new
     connections_type_list = ['albums']
     connections_type_list.each do |connection_name|
       eval "self.last_#{connection_name}_json = handler.access_api_by_content_type(service, #{connection_name})['data']"
     end
    #self.last_albums_json = handler.access_api_by_content_type(service, 'albums')['data']
   end


 end

我收到此错误

undefined local variable or method `albums' for #<FacebookParser:0xaa7d12c>

当我使用已注释掉的行时,工作正常。

3 个答案:

答案 0 :(得分:3)

像这样改变一个不相关的变量有点代码味道;当变量神奇地改变值时,大多数程序员都不喜欢它,至少不是在一个封闭的类中。

在这个简单的例子中,更常见的是:

a=something(b)

或者如果a是一个更复杂的东西,那就把它变成一个类:

class Foo
  attr_accessor  :a

  def initialize(value)
    @a = value
  end

  def transform(value)
    @a = "new value: #{value}"
  end
end

baz = "something"
bar = Foo.new(2)
bar.a
=> 2
bar.transform(baz)
bar.a
=> "new value: something"

因此,虽然第二个示例更改了内部变量但未通过访问器更改,但至少它是具有有限API的封装对象的一部分。

更新啊,我认为问题是如何处理php的variable variables。正如穆建议的那样,如果你想这样做,你可能做错了事......这是一个永远不应该被想到的概念。使用类或哈希或其他东西。

答案 1 :(得分:1)

怎么样

eval "#{b}=2"

使用实例变量,您也可以执行instance_variable_set("@name", value)

编辑:

如果你定义了一个setter(你有),你也可以使用send方法,试试这个:

class FacebookParser
  attr_accessor   :last_albums_json,         

  def update_parser_vars(service)
    handler = FacebookAPIHandler.new
     connections_type_list = ['albums']
     connections_type_list.each do |connection_name|
       send("last_#{connection_name}_json=", 
         handler.access_api_by_content_type(
           service, connection_name)['data']))
     end
  end
end

原始代码的问题是

eval ".... handler.access_api_by_content_type(service, #{connection_name})"

将执行

... handler.access_api_by_content_type(service, albums)
# instead of
... handler.access_api_by_content_type(service, 'albums')

所以你必须写

eval ".... handler.access_api_by_content_type(service, '#{connection_name}')" <- the quotes!

这就是人们通常避免使用eval的原因 - 很容易犯这种错误

答案 2 :(得分:0)

这些事情通常不是使用Ruby中的局部变量及其名称来完成的。通常的方法可能包括哈希和符号:

data = Hash.new
data[:a] = 1 # a = 1
b = :a       # b = 'a'

然后,稍后

data[b] = 2  # SOMETYPEOFEVALUATION(b) = 2
data[:a]     # => 2