简体   繁体   English

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

[英]Replace word using gsub function in ruby

i am trying to replace some word from a string with gsub function in ruby, but sometimes that works fine and in some cases giving this error? 我试图用ruby中的gsub函数替换字符串中的某些单词,但有时这样可以正常工作并且在某些情况下会出现此错误? is there any issues with this format 这种格式有什么问题吗?

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

model.rb 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 another_model.rb

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

Ah, I found it! 啊,我找到了! gsub! is a very weird method. 是一个非常奇怪的方法。 Firstly, it replaces the string in place, so it actually modifies your string. 首先,它替换了字符串,因此它实际上修改了你的字符串。 Secondly, it returns nil when no substitution has been made. 其次,当没有替换时它返回nil This all sums up to the error you're getting. 这一切都归结为你得到的错误。

The first time you execute that call, it modifies the string assigned to a constant, so it reads as "replace this 3 and name" . 第一次执行该调用时,它会修改分配给常量的字符串,因此它将显示为"replace this 3 and name" When you try to run it for a second time, the first gsub will fail to find a string it is looking for so will return nil . 当您尝试再次运行它时,第一个gsub将无法找到它正在查找的字符串,因此将返回nil The second gsub is then executed on the nil. 然后在nil上执行第二个gsub

On how to solve it - it all depends on what you're trying to achieve. 关于如何解决它 - 这一切都取决于你想要实现的目标。 For me, it is somewhat risky to change other class constants (breaks encapsulation). 对我来说,改变其他类常量(打破封装)有些冒险。 If you just want to get the result without modifying the original string, use gsub (no bang). 如果您只想在不修改原始字符串的情况下获得结果,请使用gsub (no bang)。 Or even better, convert those string into a method and use interpolation instead of substitution. 或者甚至更好,将这些字符串转换为方法并使用插值而不是替换。

If the strings are just patterns, that should be replaced before get used. 如果字符串只是模式,那么在使用之前应该替换它们。 A better way would be string Interpolation. 更好的方法是字符串插值。

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

this will change every apearance of the hash keys in the string 这将改变字符串中散列键的每个外观

for example: 例如:

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

And like @BroiSatse said, you should not change constants of other classes or within the same class itself, at the end they are constants. 就像@BroiSatse所说的那样,你不应该改变其他类的常量或者在同一个类本身内,最后它们是常量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM