helper functions permanently altering variables


I'm not sure if I'm maybe not understanding the helper functions correctly, but I'm having a weird problem that seems like it shouldn't be. I'm sanitizing some book names for url's using my application helper:

-- application helper

def format_url(url)     title = url     clean_string(title)     truncate(@title, 100, "")     return title end

def clean_string(str)     str.gsub!(/\W+/, ' ') # all non-word chars to spaces     str.strip! # ohh la la     str.downcase! #     str.gsub!(/\ +/, '-') # spaces to dashes, preferred separator char everywhere end

-- view showing the books

book.product_name #returns "a name with a lot of spaces and characters in it"

link_to(image_tag(book.image_url_small), :controller => "book", :action => "detail", :book_url => format_url(book.product_name), :key => book.isbn)

book.product_name #returns "a-name-with-a-lot-of-spaces-and-characters-in-it"

so the problem is I want a function that formats just the path, but what I have here alters book.product name permanently, so that when I want to write it as text to the screen after using format_url, it-has-the-escape-dashes-everywhere-in-it. how come it alters this when I pass it as a param, and then variable assign it to "title" and do all the alterations on the "title" variable?



by the way I notice that the above code is wrong - assume that title and @title are consistent throughout the function.

The easy answer is that in ruby, everything is an object and objects get passed by reference, not by value. So when you pass in url to a method, and then assign it to another variable (title), that new variable is just a pointer to the same memory location as what was passed in. The solution is to clone or dup:

Ahhh, ok thanks Phillip! Explanation was good and understood.

I actually solved the problem just recently by doing thus:

title = url + ""

which seems to work and force title not to just remain as a pointer to url.



Jason Pfeifer wrote:

I actually solved the problem just recently by doing thus:

title = url + ""

And if I had to guess (which I do because I don't feel like digging through source), I'd say that under the hood the equivalent of

title = url.clone + ""

is happening. So you could save the one or two processor cycles by doing the clone yourself and not worrying about the concatenation.

Peace, Phillip

Great thanks for the explanation. Processing cycles saved.