Best practice: Creating a module with expectation of type its included in?
When defining a module in Ruby, I have seen examples where the module expects the class(es) it is to be included in to have particular definitions and functionality.
For example, the module might call a method that itself doesn't contain expecting that the class its included in contains that method definition.
To me, this is a different paradigm from my background of strongly typed languages lacking the ability to include an arbitrary set of logic (Ruby as a whole is a totally different paradigm for that matter).
Is this an acceptable style per the ruby standards or at least seen often enough in mature code-bases that be considered "ok"?
I realize this is a somewhat subjective question, however I'm looking to see if this is something that occurs often enough that one would be considered within the "norm" if they were to construct a module as such.
Since Ruby is very loosely typed, relying more on the ability to respond to methods, so-called duck typing, than class, it's difficult to take responsibility for these things.
If your module is included in a context that is incompatible, it's not your job as a module to do anything about it. There's no way you can know, in advance, if any given method call will succeed or fail because after your module is included there might be other things that happen that would make doing some kind of validation premature.
Given these limitations, it's important to try and architect things to avoid this sort of ambiguity.
Take Enumerable as an example. In order for it to work correctly when included, a number of methods must be defined in the context to which it's included. If these are not defined, the module will not work, but the responsibility for this failure is not Enumerable, but the module that included it.
Basically, before you include SomeModule you should be certain that the dependencies, if any, for including that module are met. As the includer, you also assume all responsibility for any conflicts this might cause.
Other languages have more rigid methods for validating integrity, like the protocols feature of Objective C or the presence of a base class in C++. As Ruby doesn't have this, to ensure everything is working correctly, automated test suites are employed. You might notice that the Ruby community is very test-oriented, and this sort of ambiguity is one of many reasons why this is the case.