Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community!
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trial
Andrew Stelmach
12,583 PointsHow to create a custom 'NoMethodError' message?
This is from an Extra Credit exercise.
Create a protected method and create a custom message if it's called incorrectly.
class BankAccount
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
@balance = 0
end
def public_deposit(amount)
@balance += amount
end
def protected_deposit(amount)
@balance += amount
end
protected :protected_deposit
def private_deposit(amount)
@balance += amount
end
private :private_deposit
def call_private_deposit(amount)
private_deposit(amount)
end
def call_protected_deposit(amount)
protected_deposit(amount)
end
#To show that you can't call a private method with a different instance of the same class.
def private_add_to_different_account(account, amount)
account.private_deposit(amount)
end
#To show that you can call a protected method with a different instance of the same class.
def protected_add_to_different_account(account, amount)
account.protected_deposit(amount)
end
end
There's a lot of chaff in there that you don't need to see, but what I do with this is load it into irb, then: one_instance = BankAccount.new("Something", "Something")
Then do: one_instance.protected_deposit(500)
And you get a NoMethodError, as expected.
I need to make the program return a custom message, like "This is a custom NoMethodError message." instead.
I've found various bits and bobs on the internet, but it's a nightmare. I've looked at using a rescue block, but I can't get this to work, probably because the NoMethodError is raised before the protected_deposit method is even executed, so putting a rescue block inside that doesn't achieve anything.
Help?! I don't want a full answer though, good hints and pointers are better for learning.
5 Answers

Geoff Parsons
11,679 PointsMy suggestion would be to define method_missing which will get called for any method that that someone attempts to call on the object that isn't defined. You can print out a custom message, raise further exceptions, or whatever else you're looking to do there.
class BankAccount
def method_missing(method)
puts "You tried to call #{method}, don't do that!"
end
end
Hope that helps!

Andrew Stelmach
12,583 PointsBit disappointed with the lack of help I'm receiving here. I even posted up on Stackoverflow and no response there either.

Andrew Stelmach
12,583 PointsWell, time is pressing on, so I've resorted to taking the easy way out, which is saving a bunch of code and just running it i.e. "ruby mycode.rb".
class BankAccount
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
@balance = 0
end
def protected_deposit(amount)
@balance += amount
end
protected :protected_deposit
def call_protected_deposit(amount)
protected_deposit(amount)
end
end
an_instance = BankAccount.new("Andrew", "Stelmach")
puts "Your BankAccount instance: #{an_instance.inspect}"
puts "How much money would you like to deposit?"
first_deposit = gets.to_i
puts "Depositing #{first_deposit} into your account..."
an_instance.call_protected_deposit(first_deposit)
puts "Your BankAccount instance now: #{an_instance.inspect}"
puts "How much money would you like to deposit by calling the protected method?"
second_deposit = gets.to_i
puts "Trying to deposit money using the protected method..."
begin
an_instance.protected_deposit(second_deposit)
rescue StandardError
puts "Failed."
end
This works, and yes, I achieved the extra credit objective of "try writing a program with a protected method. Have that method raise a specific custom error if it's called inappropriately."
....kind of...
The wording of this task, to me, sounds like I should create the conditions within my code so that, "WhenEVER a protected method is called inappropriately, a custom error message appears."
I don't think I've achieved that. Please see my original post at the top of this thread.
I DO feel really let down by Treehouse on this occasion. Up til now, my requests for help have always been answered well and promptly. On this occasion, apart from a reply that wasn't particularly helpful, it's been nothing but tumbleweeds. I even posted the problem up on stackoverflow and I've had no reply there, either.
I understand that the easier problems get more attention by fellow students, but I would expect harder problems like this to attract the assistance of treehouse mods and staff.
I spent five hours last night experimenting and scouring the internet trying to solve this problem. Now, fair enough, I guess if I could work this out for myself... eventually... but the process would be greatly eased by the assistance of some treehouse mods or staff.
It would be really really useful for me if someone could help me with the original problem here (at the top of this thread). I do feel quite let down by what has been, up til now, a stellar service.

Jason Seifer
Treehouse Guest TeacherHey Andrew Stelmach I took a look another look at that extra credit and it's worded very poorly to the point of being misleading. I've updated the extra credit so it's easier to understand. You're just meant to rescue a NoMethodError gracefully. Sorry about that! Let me know if that helps clear things up.

Unsubscribed User
3,309 PointsI also struggled wildly with this Extra Credit. It says, I quote:
Attempt to instantiate and call that method, then rescue the exception.
The wording still leads you to use rescue without (in my case, never having heard of) method_missing. As Andrew points out, rescue won't work with a protected method.
/cc Jason Seifer
Andrew Stelmach
12,583 PointsAndrew Stelmach
12,583 PointsBut that method wouldn't get called unless I called it. It doesn't get called when I do
an_instance.protected_deposit(1000)
Geoff Parsons
11,679 PointsGeoff Parsons
11,679 Pointsmethod_missing
is a special method in ruby that is called when the interpreter can't find the method you called. For example with the following code:Running in IRB you would get this:
This will allow you to print out custom messages when someone tries to call a method that isn't defined or is protected.
If you want a custom message for your
NoMethodError
instead you can just pass a string as an argument:Is this what you're looking for or am I misunderstanding your original post?