Does anybody know why the included method doesn't work inside a class method?
class MyClass
include ActionView::Helpers::NumberHelper
def test
puts "Uploading #{number_to_human_size 123}"
end
def self.test
puts "Uploading #{number_to_human_size 123}"
end
end
ree-1.8.7-2011.03 :004 > MyClass.new.test
Uploading 123 Bytes
=> nil
ree-1.8.7-2011.03 :005 > MyClass.test
NoMethodError: undefined method `number_to_human_size' for MyClass:Class
from /path/to/my/code.rb:9:in `test'
from (irb):5
ree-1.8.7-2011.03 :006 >
It's hard to tell without seeing your helper code, but include
will insert all of the methods in that module into instances of the class you include into. extend
is used to bring methods into a class. Therefore, if you just have methods defined in NumberHelper, these are being put onto all instances, but not the class, of MyClass.
The way that lots of Rails extensions work is using techniques that have been consolidated into ActiveSupport::Concern. Here is a good overview.
Essentially, extending ActiveSupport::Concern in your modules will allow you to specify, in sub-modules called ClassMethods and InstanceMethods, what functions you want to be added to classes and instances into which you include your module. For example:
module Foo
extend ActiveSupport::Concern
module ClassMethods
def bar
puts "I'm a Bar!"
end
end
module InstanceMethods
def baz
puts "I'm a Baz!"
end
end
end
class Quox
include Foo
end
Quox.bar
=> "I'm a Bar"
Quox.new.baz
=> "I'm a Baz"
I've used this before to do things like define the bar function in ClassMethods, then also make it available to instances by defining a bar method of the same name that just calls this.class.bar, making it callable from both. There are lots of other helpful things that ActiveSupport::Concern does, like allowing you to define blocks that are called back when the module is included.
Now, this is happening here specifically because you're include
ing your helper, which might indicate that this functionality is more general-purpose than a helper - helpers are only automatically included in views, since they are only intended to help with views. If you want to use your helper in a view, you could use the helper_method
macro in your class to make that method visible to your views, or, even better, make a module as above and not think about it as a helper, but use include to mix it in to the classes you want to use it in. I think I would go that route - there's nothing that says you can't make a HumanReadableNumber module and include
it in NumberHelper to make it easily available across your views.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With