在ruby中使用gsub函数替换单词

时间:2015-02-06 10:29:44

标签: ruby-on-rails ruby gsub

我试图用ruby中的gsub函数替换字符串中的某些单词,但有时这样可以正常工作并且在某些情况下会出现此错误?这种格式是否存在任何问题

NoMethodError (undefined method `gsub!' for nil:NilClass):   

model.rb

class Test < ActiveRecord::Base
  NEW = 1
  WAY = 2
  DELTA = 3

  BODY = {

    NEW => "replace this ID1",
    WAY => "replace this ID2 and ID3",
    DELTA => "replace this ID4"
  }
end

another_model.rb

class Check < ActiveRecord::Base
  Test::BODY[2].gsub!("ID2", self.id).gsub!("ID3", self.name)
end

2 个答案:

答案 0 :(得分:6)

啊,我找到了! gsub!是一种非常奇怪的方法。首先,它替换了字符串,因此它实际上修改了你的字符串。其次,当没有进行替换时,它返回nil。这一切都归结为您所得到的错误。

第一次执行该调用时,它会修改分配给常量的字符串,因此它将显示为"replace this 3 and name"。当您尝试再次运行它时,第一个gsub将无法找到它正在查找的字符串,因此将返回nil。然后在nil上执行第二个gsub

关于如何解决它 - 一切都取决于你想要实现的目标。对我来说,改变其他类常量(打破封装)有些冒险。如果您只想在不修改原始字符串的情况下获得结果,请使用gsub(无爆炸)。或者甚至更好,将这些字符串转换为方法并使用插值而不是替换。

答案 1 :(得分:2)

如果字符串只是模式,那么在使用之前应该替换它们。更好的方法是字符串插值。

class Test < ActiveRecord::Base
  # Here use symbols instead, because symbols themselfs are immutable
  # so :way will always equal :way
  BODY = {
    :new => "replace this %{ID1}",
    :way => "replace this %{ID2} and %{ID3}",
    :delta => "replace this %{ID4}"
  }    
end
# HERE you should create another constant based on the 
# Test class constants
class Check < ActiveRecord::Base
  BODY = {
         :way => Test::BODY[:way] % {ID2: self.id, ID3: self.name}
  }

 # Or you can make it a method
 def self.body
   Test::BODY[:way] % {ID2: self.id, ID3: self.name}
 end
end

这将改变字符串

中散列键的每个外观

例如:

str = "%{num1} / %{num1} = 1"
str % {num1: 3} # 3 / 3 = 1

和@BroiSatse一样,你不应该改变其他类的常量或者在同一个类本身内,最后它们是常量。