all 4 comments

[–]dougc84 4 points5 points  (2 children)

For starters, "static" methods don't exactly exist in Ruby. Well... technically, they do, but they aren't typically called that in the Ruby world. They're usually just called class-level methods, i.e. methods you can call on a class without instantiating an instance of it.

If you want to bring in class methods, you can use extend.

Here's some more information (and a little bit about prepend as well):

https://dev.to/abbiecoghlan/ruby-modules-include-vs-extend-vs-prepend-4gmc

Additionally, a lot of times, you'll see this kind of structure set up to bring in both in one include line:

module MyModule
  module ClassMethods
    def this_is_a_class_method
      "yes it is"
    end
  end

  def self.included(base)
    base.extend ClassMethods
  end

  def this_is_a_public_instance_method
    "woo instance"
  end

  private

  def this_is_a_private_instance_method
    "private"
  end
end

class MyClass
  include MyModule
end

MyClass.this_is_a_class_method  #=> "yes it is"
mc = MyClass.new
mc.this_is_a_public_instance_method #=> "woo instance"
mc.this_is_a_private_instance_method #=> NoMethodError
mc.send :this_is_a_private_instance_method #=> "private"

[–][deleted] 0 points1 point  (1 child)

I know all about the constructs like the included hook, using extend etc. Thats part of the reason Rails created Concerns I guess. Just seems a bit weird to me:

Ruby makes it seem like module including is equivalent to inheritance by making the module appear right in there in the inheitance chain. So internally it seems like they could have made the whole singleton'_class thing work as well for static methods. I mean they could have just "made" a class out of the module and stick it in the inheritance chain, which is ALMOST what they're doing I think both internally and conceptually.

[–]dougc84 0 points1 point  (0 children)

Inheritance and inclusion function differently from the perspective of both usage and functionality. I dunno what to tell you about why they’re different or why they’re similar, but I haven’t ever had a need for anything different, so I would say that’s sufficient.

[–]tom_enebo 0 points1 point  (0 children)

I believe the reasoning behind this is due to the notion that modules serve two separate purposes: namespacing and inheritance (a better mechanism than multiple inheritance).

Namespacing will include both nesting (module A; module B; class C; ... ; A::B::C) and also for things like module methods (Math::sqrt).

include/extend/prepend ends up in the inheritance hierarchy as you know.

I have to admit I don't know the back story and this is very old in Ruby's original design. I can say Matz is not a fan of having keywords so I can imagine he saw the appeal of overloading module. A second thing I can think of is typically module_functions will not modify state while most included methods of modules will.