views:

137

answers:

2

I am using the acts_as_taggable_on gem and would like to add a method to one of the gem source files (tag.rb), but I do not want to change the gem source in any way.

I have tried creating my own tag.rb file to in the /app/models directory or in the /lib directory, and then adding the desired method to that file expecting that ruby will merge the two tag.rb files

But when I do I get a NoMethodError: undefined method ...

What am I missing?

+2  A: 

I think you're right that reopening the Tag class is the way to go. I wouldn't introduce another level of inheritance unless it really made sense for your code.

I'm not sure, off the top of my head, why reopening the Tag class didn't work. A few thoughts:

1 - When you wrote your own Tag class, did it descend from ActiveRecord::Base? The Tag class in acts as taggable on does, and I could see how neglecting that might mess things up.

2 - If I needed a place to put code that reopened a plugin class for a single method, I'd probably put it in an initializer file (such as config/initializers/tag_patch.rb). Just to keep things clean.

3 - If all else fails and you still can't get the Tag class reopened properly (for whatever reason) there are other metaprogramming techniques you might try to add the method. For example:

Tag.send(:define_method, “method_name”) do 
  #code for your method
end
PreciousBodilyFluids
This seems to work. I'm guessing your point #2 was the magic. Getting the code into the initializers was likely what I needed (though I thought I could put my tag.rb in /lib also).
rswolff
What's wrong with class_eval, seems a better and clearer way of reopening a class.
railsninja
I think railsninja is right, Tag.class_eval is probably the clearest way to go. It didn't occur to me when I was writing out the define_method example.
PreciousBodilyFluids
+1  A: 

Wait, you shouldn't be adding method to the file, but to the class instead. Are you familiar with the concept of reopening the class? You can't add a method just by naming your file same as the one which original class is defined in. Fortunately. :)

Mladen Jablanović