【问题标题】:Ruby: interpolated string to variable name [duplicate]Ruby:将字符串插值到变量名[重复]
【发布时间】:2017-10-22 08:40:23
【问题描述】:

在 Ruby 中,如何插入字符串以生成变量名?

我希望能够像这样设置一个变量:

"post_#{id}" = true

这会返回一个语法错误,很有趣:

syntax error, unexpected '=', expecting keyword_end

【问题讨论】:

  • 一般来说,需要这样做是代码异味,表明数据结构选择不当。与单个变量 post_1post_2post_N 相比,最好(以各种可以想象的方式)拥有例如哈希 post = { 1 => true, 2 => true, ...}
  • @Jörg,OP 没有询问如何动态创建局部变量。他/她可能只想知道如何动态获取或设置现有的局部变量。

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

这涉及局部变量的获取和设置。假设

id = 1
s = "post_#{id}"
  #=> "post_1"

自 Ruby v1.8 起,无法动态创建局部变量。因此,如果局部变量post_1 不存在,唯一的方法是使用赋值语句来创建它:

post_1 = false

如果局部变量post_1存在,你可以使用动态检索其值

b = binding
b.local_variable_get(s)
  #=> false

(或b.local_variable_get(s.to_sym))并使用

动态设置其值
b.local_variable_set(s, true)
  #=> true
post_1
  #=> true

(或b.local_variable_set(s.to_sym, true))。

参见Binding#local_variable_getBinding#local_variable_set

【讨论】:

    【解决方案2】:

    我相信你可以这样做:

      send("post_#{id}=", true)
    

    当然,这需要你有合适的 setter/getter。其中,由于您是动态执行此操作的,因此您可能不会这样做。

    所以,也许你可以这样做:

      instance_variable_set("@post_#{id}",true)
    

    检索变量:

      instance_variable_get("@post_#{id}")
    

    顺便说一句,如果您厌倦了输入 instance_variable_set("@post_#{id}",true),只是为了好玩,您可以执行以下操作:

    class Foo
    
      def dynamic_accessor(name) 
        class_eval do 
          define_method "#{name}" do
            instance_variable_get("@#{name}")
          end
          define_method "#{name}=" do |val|
            instance_variable_set("@#{name}",val)
          end
        end
      end
    
    end
    

    在这种情况下你可以:

    2.3.1 :017 > id = 2
     => 2 
    2.3.1 :018 > f = Foo.new
     => #<Foo:0x00000005436f20> 
    2.3.1 :019 > f.dynamic_accessor("post_#{id}")
     => :post_2= 
    2.3.1 :020 > f.send("post_#{id}=", true)
     => true 
    2.3.1 :021 > f.send("post_#{id}")
     => true 
    2.3.1 :022 > f.send("post_#{id}=", "bar")
     => "bar" 
    2.3.1 :023 > f.send("post_#{id}")
     => "bar" 
    

    【讨论】:

    • 是的,send 出局了,instance_variable_set 运行良好。虽然它需要@ 前缀,但这是一个非常简单的修复方法,并且在给定函数名称的情况下完全有意义。谢谢!
    猜你喜欢
    • 2011-03-22
    • 2020-11-21
    • 2018-12-04
    • 1970-01-01
    • 1970-01-01
    • 2013-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多