swiknaba swiknaba - 2 months ago 6
Ruby Question

How do you define & call a "variable.my_function" method in Ruby within a class?

So the basic setting is the following:

in app/services/SomeService/ABC.rb

class SomeService::ABC
FORBIDDEN_CHARS = {" " => "+", "'" => "%27", "/" => "%2F", ":" => "%3A", "&" => "%26"}
def my_function(input)
#now do something fancy with the input
var = .... #a String is created
var.to_linkable
# continue with something fancy
end

def to_linkable
FORBIDDEN_CHARS.each{|key,value| self.gsub!(key,value)}
end
end


This results in the error: undefined method `to_linkable' for "bla bla":String

However in this way it works:

def to_linkable(link)
FORBIDDEN_CHARS.each{|key,value| link.gsub!(key,value)}
end


but I have to call it with 'to_linkable(link)' instead of just putting 'link.to_linkable'. If I copy paste my code in the Terminal the first way, there is no errors when calling 'link.to_linkable'.

So my question is: How (and where?) do I properly create such a to_linkable method? I might want to use it later on so that's why I want it to be an easy to use method. Thanks very much :)
And yes, I am a Ruby newbie, coming over from Matlab :D

Answer

First of all, don't reinvent the wheel. Use URI.escape, instead of trying to manually define which characters to replace.

However, for the sake of learning, if we go with your implementation...

var is a string. If you wish to call a method on the string, then it must be defined in the String class. It is usually not advised to add methods to core classes like this, but the following would work:

class String
  FORBIDDEN_LINK_CHARS = {" " => "+", ...}
  def to_linkable
    FORBIDDEN_LINK_CHARS.each{|key,value| self.gsub!(key,value)}
    self
  end
end

"hello world".to_linkable # => "hello+world"

Alternatively, if you don't want to extend the String class, but still wish to call an instance method without passing the variable, then you need to somewhere set var as an instance variable in the class. This may or may not be a good idea, depending on the structure of the class.

For example, the following works:

class SomeService::ABC 
  FORBIDDEN_CHARS = {" " => "+", ...}
  def my_function(input)
    @var = .... #a String is created
    make_var_linkable
  end

  def make_var_linkable
    FORBIDDEN_CHARS.each{|key,value| @var.gsub!(key,value)}
  end
end

...However, going back to my original point, the actual implementation I'd recommend is neither of the above. Just do:

require 'uri'

class SomeService::ABC 
  def my_function(input)
    var = URI.escape(....)
  end
end
Comments