#inherited
is called right after the class Foo
statement. I want something that'll run only after the end
statement that closes the class declaration.
Here's some code to exemplify what I need:
class Class
def inherited m
puts "In #inherited for #{m}"
end
end
class Foo
puts "In Foo"
end
puts "I really wanted to have #inherited tiggered here."
### Output:
# In #inherited for Foo
# In Foo
# I really wanted to have #inherited tiggered here.
Does anything like that exist? Can it be created? Am I totally out of luck?
Take a look at
defined
gem. You can do like this:Output:
However
self.defined
will be fired after each class definition. So if you add the following codeYou will see
There are ways to avoid that which I can explain to you if you want.
However, as said there are probably better ways to solve your problem.
Rails has a
subclasses
method, it might be worth looking at the implementation:I had the same question when trying to automatically add generic validations to all models. The problem was that if the model used #set_table_name then my code that added added the validations based on the DB data-types would blow up because it was guessing at the table name based on the name of the model (because #inherited was getting called BEFORE #set_table_name).
So just like you, I was really looking for a way to get #inherited to fire AFTER everything in the model had already been loaded. But I didn't really need to take it that far, all I needed was something that fired AFTER #set_table_name. So it turned out to be a simple as aliasing the method. You can see an example of what I did here: https://gist.github.com/1019294
In a comment above you stated "I'm trying to add behavior to activerecord models, but I need all the model customizations to go through before I mess with it". So my question to you is if there are specific model customizations you care about, if so then maybe you could use an aliasing approach to achieve your desired result.
No, there no such a hook to my knowledge, but the good thing is you can kind of do it yourself. Here is a possible implementation:
Is not super clean, but it works:
Output:
So this is obviously not as clean as a hook, but I think at the end we have a pretty good result.
If we had tried to do the same with :inherited sadly is not possible, because :inherited is called even before the execution entoer in the body of the class:
Output:
You may be out of luck. But that's only a warning, not a definitive answer.
Ruby hooks the beginning of the class definition, rather than the end, for
Class#inherited
b/c ruby class definitions don't have a real end. They can be reopened any time.There was some talk a couple years ago about adding a const_added trigger, but it hasn't gone through yet. From Matz:
So this might handle your case - but I'm not sure (it may trigger on the start too, when it's eventually implemented).
What are you trying to do with this trigger? There may be another way to do it.
If you are willing to assume your Ruby implements ObjectSpaces, you could could look up all model instances after the fact, and then modify them appropriately. Google suggests http://phrogz.net/ProgrammingRuby/ospace.html