In Ruby, an API-docs generator must list only the public methods Widget itself defines — which call gives that, and what does it leave out?
answer
- the false argument
- public_ vs plain instance_methods
- mixins count as ancestors
- accessors and aliases included
- ghost methods never listed
basics
~10 sWidget.public_instance_methods(false) lists the public instance methods defined in Widget itself. It leaves out superclass and mixin methods, private and protected ones, class methods, and names served only by method_missing.
solid answer
~40 s`Module#instance_methods` returns public and protected instance method names from the whole ancestor chain; passing `false` limits it to the receiver, and `public_instance_methods(false)` also drops protected ones, which is what public API docs want. Methods from included modules are excluded, because a mixed-in module is an ancestor, so document each module separately with its own `instance_methods(false)`. Methods generated in the class body count as the class's own: `attr_accessor` readers and writers, `define_method` results, aliases, and methods whose visibility the class changed. Class methods are not instance methods and need a separate listing, and names handled by `method_missing` appear nowhere. Sort the result for stable output.
code
ruby · 21 linesmodule Exportable
def to_csv = "..."
end
class Widget
include Exportable
attr_reader :name
alias_method :label, :name
def render = "<widget>"
def self.build = new
protected def weight = 1
private def cache_key = "w"
end
Widget.public_instance_methods(false).sort # => [:label, :name, :render]
Widget.instance_methods(false).sort # => [:label, :name, :render, :weight]
Widget.private_instance_methods(false) # => [:cache_key]
Exportable.instance_methods(false) # => [:to_csv]
Widget.instance_methods.include?(:to_csv) # => true (ancestors included)go deeper
Recall that passing false to instance_methods keeps only the methods the class itself defines, dropping everything inherited.
Explain why mixin methods disappear with false, why accessors and aliases stay, and why public_instance_methods fits public docs better than instance_methods.
Design the generator's walk: one page per class and module, sorted output, source links from instance_method(name).source_location, and class methods listed separately.
Decide what the generated docs promise as public API, since visibility and mixin boundaries in the code become the contract readers rely on.
## The call for the job A documentation generator that walks classes wants, for each class, *the public methods that class itself declares*. Ruby's answer is: ```ruby Widget.public_instance_methods(false) ``` The **argument** decides the scope. `instance_methods(include_super = true)` and its visibility-specific siblings look through every ancestor by default; passing `false` restricts the listing to the receiver's own method table. The **method name** decides the visibility: | Call | Visibility | Scope | |---|---|---| | `Widget.instance_methods` | public + protected | Widget and all ancestors | | `Widget.instance_methods(false)` | public + protected | Widget only | | `Widget.public_instance_methods(false)` | public | Widget only | | `Widget.protected_instance_methods(false)` | protected | Widget only | | `Widget.private_instance_methods(false)` | private | Widget only | `instance_methods(false)` is the one interviewers usually name; for *public* docs, `public_instance_methods(false)` is the exact fit, because protected methods are callable only from other instances and are not public API. ## What counts as defined in the class The method table of a class holds every method **added while that class was open or reopened**, however it got there: - methods written with `def`, including those added by reopening the class in another file; - readers and writers created by `attr_reader`, `attr_writer` and `attr_accessor`; - methods created with `define_method`; - aliases created in the class, and methods whose visibility the class changed — the `instance_methods` rdoc notes both are *considered as methods of the current class*. That last point surprises people: if `Widget` says `protected :render` for a method it inherited, `render` now appears in `Widget.instance_methods(false)`. ## What the listing leaves out 1. **Superclass methods.** They belong to the superclass's own listing. 2. **Mixin methods.** An included or prepended module is an ancestor with its own table, so `false` excludes it. A docs generator should list modules as separate entries and note which classes include them. 3. **Private and protected methods**, when you use `public_instance_methods`. 4. **Class methods.** `def self.build` lives on the class's singleton class, not in its instance method table, and needs its own listing. 5. **Ghost methods.** Names served by `method_missing` are not in any table. ## Ordering and stability The result is an `Array` of `Symbol`s. Nothing in its documentation promises an order, so a generator should `sort` it before rendering, so that two runs over the same code produce identical output and clean diffs. ## Walking a whole namespace A generator rarely starts from one class. It starts from a namespace and discovers what is inside it: ```ruby Billing.constants.sort.each do |const| value = Billing.const_get(const) next unless value.is_a?(Module) puts value.name value.public_instance_methods(false).sort.each { puts " ##{it}" } end ``` `constants` returns the constant names reachable in the module, `const_get` turns each name into its value, and the `is_a?(Module)` check skips plain values such as version strings. `Module#name` gives the fully qualified title for each page. Because each class and module is visited separately and asked only for its own methods, every method is documented exactly once, under the code that defines it. ## Linking each entry to its source For each name, `Widget.instance_method(name)` returns an `UnboundMethod` whose `source_location` gives the file and line of the definition (or `nil` for a method implemented in C), which a generator can turn into a "view source" link. ## Mistakes to avoid - Calling `Widget.instance_methods` without `false` and documenting all of `Object` and `Kernel` under `Widget`. - Expecting mixin methods to appear under the class that includes them. - Using `instance_methods(false)` for public docs and publishing protected methods. - Forgetting that accessors, aliases and `define_method` results are listed, which is usually what docs want. - Relying on the array's order. ## The takeaway `public_instance_methods(false)` answers "what public instance API does this class body add?" Everything else — superclasses, modules, class methods — is documented by asking the owner of that code the same question.
- A class inherits render and then writes protected :render. Does render appear in its instance_methods(false)?Yes. Changing an inherited method's visibility stores an entry for it in the class's own method table, and the `instance_methods` documentation says such methods, like aliases, count as methods of the current class. It appears in `instance_methods(false)` and `protected_instance_methods(false)`, not in `public_instance_methods(false)`.
- How would the generator document a module's methods separately?Call `Exportable.instance_methods(false)` (or `public_instance_methods(false)`) on the module itself. A module is an ancestor with its own method table, so its methods belong to its own page, with a note listing the classes that include it.
saying these in an interview costs you the question
- instance_methods(false) still includes methods from included modules
- Widget.instance_methods lists only what Widget defines
- attr_accessor methods are hidden from instance_methods(false)
- instance_methods(false) returns only public methods
- Class methods such as Widget.build appear in public_instance_methods(false)