I have a Team class in my program and I am trying to use method_missing but instead of running the function when the method doesn't exist, it gives me an error:"undefined method `hawks' for Team:Class (NoMethodError)"
My code is as follows:
class Team
attr_accessor :cust_roster, :cust_total_per, :cust_name, :cust_best_player
@@teams = []
def initialize(stats = {})
@cust_roster = stats.fetch(:roster) || []
@cust_total_per = stats.fetch(:per)
@cust_name = stats.fetch(:name)
@cust_best_player = stats.fetch(:best)
@@teams << self
end
def method_missing(methId)
str = methID.id2name
Team.new(roster:[], per: 0, name: str.uppercase, best: 0)
end
class <<self
def all_teams
@@teams
end
end
end
hawks = Team.hawks
There are a number of problems with your code. Let's go through one by one.
From the documentation,
method_missing(*args) private Invoked by Ruby when obj is sent a message it cannot handle.
Here message
refers to the method
. In ruby, whenever you're calling a method on an object, you're actually send
ing a message
to the object
To better understand this, try this in the irb shell.
1+2
=> 3
1.send(:+,2)
=> 3
Here 1 and 2 are objects of Fixnum
class. You can confirm that by using 1.class
. Ok, back to your question. So, a method_missing
method should be called on an instance.
team = Team.new
team.hawks
If you try the above piece of code, you'll get an error saying 'fetch': key not found: :roster (KeyError)
You can get around this by passing a default value
as the second parameter to fetch
method. Replace your initialize
method with
def initialize(stats = {})
@cust_roster = stats.fetch(:roster, [])
@cust_total_per = stats.fetch(:per, 0)
@cust_name = stats.fetch(:name, "anon")
@cust_best_player = stats.fetch(:best, "anon")
@@teams << self
end
If you execute the script, you'll get a stack level too deep (SystemStackError)
because of a small typo in this line.
str = methID.id2name
In the method definition, you're receiving an argument with the name of methId
but inside you're trying to call methID
. Fix it with
str = methId.id2name
If you execute your script, you'll again get an error saying undefined method uppercase for "hawks":String (NoMethodError)
This is because there is no uppercase
method on strings. You should instead use the upcase
method.
Team.new(roster:[], per: 0, name: str.upcase, best: 0)
and you should be good to go.
For more, see http://apidock.com/ruby/BasicObject/method_missing
Hope this helps!