Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby gsub doesn't change the content while setting the content does

Could someone please explain the difference between the following two lines of code:

1. element.content.gsub!("#{i}", "#{a[i]}")
2. element.content = element.content.gsub("#{i}", "#{a[i]}")

In the following code:

a.each_index do |i|
  @doc.traverse do |element|
    if element.text?
      element.content = element.content.gsub("#{i}", "#{a[i]}")
    end
  end
end
puts @doc

The code as presented above does change @doc. While if I use line 1 with gsub! it doesn't have an effect on @doc. Does this have to do with how blocks handle their parameters? Shouldn't everything be passed by reference in Ruby unless explicitly copied using a method?

like image 806
ismail Avatar asked Oct 09 '22 06:10

ismail


1 Answers

Checking http://nokogiri.org/Nokogiri/XML/Node.html:

static VALUE get_content(VALUE self) {
    xmlNodePtr node;
    xmlChar * content;
    Data_Get_Struct(self, xmlNode, node);
    content = xmlNodeGetContent(node);
    if(content) {
        VALUE rval = NOKOGIRI_STR_NEW2(content);
        xmlFree(content);
        return rval;
    }
    return Qnil;
}

A copy of the content is made, so any changes to it only affect that copy, and not the internal value of the node's contents.

Using 'element.content=' calls a separate method that does modify the internal value:

def content= string
    self.native_content = encode_special_chars(string.to_s)
end
like image 75
fgb Avatar answered Oct 12 '22 10:10

fgb