api.rubyonrails.org is a ghetto

Quoting Mr Shaw should evoke some passion, no doubt.

Here to talk to you today about a problem that’s bugged me personally for quite a long time: api.rubyonrails.org does not reflect the awesome of the Ruby on Rails framework or community. It’s built on what is effectively a documentation system that was crafted by Java programmers and written in Ruby. Frankly: it looks like shit.

Also: it has no searching functionality, making people looking through it resort to their in-browser searching functionality to find the methods or classes they are attempting to locate. Furthermore, there is no commenting functionality on the API entries, which I feel would be beneficial as people could provide useful examples or discuss certain methods in the API.

And then there’s YARD: http://rdoc.info/github/rails/rails/master/frames. It’s clean, has searching and commenting and has, in my opinion, a better user interaction experience than the current http://api.rubyonrails.org.

I propose that we scrap the RDoc api.rubyonrails.org site and replace it with a YARD equivalent, as this is a more modern solution to documenting and allows for better documentation, such as documenting what types of objects the arguments for a method would take (although, I have not checked if RDoc supports this). I think YARD is a better solution to this problem than RDoc and it would make me very, very happy to see it used for Rails.

Thanks.

I’m here today to concur with Radar about the state of api.rubyonrails.org and edgeapi.rubyonrails.org

Besides, yard is just damn sexy.

~Spaceghost

Agreed.

While the *content* of the API has improved vastly since docrails was
created (and content is key), and guides have provided a previously
non-existent top-down introduction to how to use things, I agree that
the API is not on par with the framework, and wrote an email about
that some months ago suggesting different ways this could be improved:

    "Taking the API to the next level"
    http://groups.google.com/group/rubyonrails-core/browse_thread/thread/d8187a0de0e10312/554fc910fb77c178

The template has changed in Rails 3 only to match the color palette of
guides, which is the one theme theme being pursued.

The API needs a better template, and needs a search box. There was
some work being done in that direction that never saw the light of the
day (guess it didn't finish). But I have not pushed too hard there
because I think the solution is not only a better template. That's not
enough.

I am totally convinced we need to create a new API generation tool,
perhaps ad-hoc for Rails, perhaps based on YARD I don't know, that
evaluates the entire source tree with some exceptions. We need to have
all the concerns executed, and as much dynamic stuff as possible.

As a user, I want to go to AR::Base and see the API of a model, I
don't give a shit about the internal organization and partitioning in
a myriad modules of its API. It is OK to mention them: "this method is
defined in module M", but I want it there in AR::Base. And same thing
for everything.

So, execute the tree, and introspect as reflexive does
(https://github.com/dolzenko/reflexive). Use a static parser to
extract the doc snippets per method or whatever, and mix them
together.

That would be a real improvement.

Regarding YARD annotations... I am personally not convinced about
them. On one hand they emphasize types to the writer and programmer,
while Ruby is about being able to respond to methods (I know you can
express duck typing with them). I have mixed feelings about putting
types so prominently everywhere. On the other hand, I am afraid that
in practice they may give place to too terse APIs.

But anyway, for me this is not RDoc vs YARD, this is about doing
bringing the documentation to the next level, and that means more
profound changes from my point of view.

While I still find yard not so intuitive to use, its infinitely more
useful than the API docs.

I am +1 on this. YARD is currently intensively developed, so we can expect even
more profit moving from Rails API to YARD.

Any news on topic?

I love the presentation and speed of this:

http://railsapi.com/doc/rails-v3.0.8rc1/

If you can combine that with a better parser, it would be a big improvement.

I’d like to move this forward for 3.2.

I don’t know what’s going to be the future. As I have said, I think we need a new generation tool. That’s the real step forward.

For me the choice of YARD vs RDoc basically goes down to: if someone implements a doc generator based on source execution and introspection in tool T, then T wins.

If T is YARD, adopting it wouldn’t imply necessarily we also adopt annotations. That would be a different discussion.

In the meantime, I am evaluating sdoc. With sdoc we would get a better template and a search box with little changes.

El 04/06/2011, a les 16:22, Eugene Pirogov iamexile@gmail.com va escriure:

I’m ok with yard, but if sdoc provides both a nice template and searching without a lot of change, that sounds good, too.

I also want to mention railsapi.com. I use it more than the official API site because of its textmate-like searchbox. For example typing “acm” will quickly narrow down the list to activemodel, actionmailer, etc. Any idea if sdoc allows searching like that?

Thanks

Jeff

Unless I’m mistaken, railsapi.com is using sdoc:

https://github.com/voloko/sdoc

railsapi.com is generated with sdoc :slight_smile:

SDoc is one of the possibilties, yes, but I think we should see if Yard can do what is required as that seems to be (currently) the more popular of the two tools.

Plus, Loren is a switched on kind of guy.

Hi Xavier,

I'd like to move this forward for 3.2.

For me the choice of YARD vs RDoc basically goes down to: if someone implements a doc generator based on source execution and introspection in tool T, then T wins.

What do you mean by "source execution and introspection", exactly?
YARD already has more powerful support for documenting metaprogrammed
methods, but doesn't use "source execution" to do so. I'm not sure
it's necessary to eval the codebase to document it. In the end, it
doesn't *really* make things easier. The "eval" approach to generating
docs has actually been looked at pretty thoroughly when architecting
YARD-- we found that in practice you don't actually gain very much
that can't be done with standard source parsing. If you can list
specific examples of where YARD's support for metaprogrammed code is
not sufficient, I'll be glad to look at them and make some concrete
suggestions on how those situations can be dealt with.

If T is YARD, adopting it wouldn't imply necessarily we also adopt annotations. That would be a different discussion.

I think the annotation discussion is inherently integral in adopting
YARD; it should at least be mentioned here in brief. YARD not only
allows you to improve the generated HTML, but the annotations would
allow you to significantly clean up the existing documentation all
while improving output. I noticed you mentioned that you don't like
how YARD emphasizes types, and I find that odd, since Rails API docs
(and all good docs, really) already emphasize types; they just don't
do it in a consistent fashion. Here is the first random result I found
of such documentation practices:
https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal.rb#L114
-- this syntax can be cleaned up significantly by using a single
"@return [String]" annotation, and it would no longer be coupled to
your output/templates, allowing you to change the styling of the
template without worrying about what the documentation markup looks
like. Same goes for the copious usage of the "=== Examples" and "===
Options" headers in the Rails docs, which can be cleaned up and
decoupled from presentation using YARD tags. I actually think
annotations have more to do with improving the "look and feel" than
you think, since it allows you to improve the presentation using CSS
styling in the HTML rather than manually inserting tags/headers in the
source code. There are certainly more benefits to annotations than
just this, but like I said, I only want to mention the benefits in
brief. I agree that a full discussion should probably be had if YARD
is considered.

Finally, I want to point out that YARD's search is probably the only
thing lacking versus sdoc (though AFAIK search is the only thing sdoc
really offers). We've wanted to add fuzzy search in YARD for a while,
so it's certainly on the table, and we would love to have help on this
front if anyone is willing to contribute patches. If that's the only
blocker, we can certainly work on the search side of things.

Regards,

Loren Segal

Hi Loren, thanks for joining the thread :).

I'd like to move this forward for 3.2.

For me the choice of YARD vs RDoc basically goes down to: if someone implements a doc generator based on source execution and introspection in tool T, then T wins.

What do you mean by "source execution and introspection", exactly?
YARD already has more powerful support for documenting metaprogrammed
methods, but doesn't use "source execution" to do so. I'm not sure
it's necessary to eval the codebase to document it. In the end, it
doesn't *really* make things easier. The "eval" approach to generating
docs has actually been looked at pretty thoroughly when architecting
YARD-- we found that in practice you don't actually gain very much
that can't be done with standard source parsing. If you can list
specific examples of where YARD's support for metaprogrammed code is
not sufficient, I'll be glad to look at them and make some concrete
suggestions on how those situations can be dealt with.

Let me put an example: the Rails API should give the user a clear idea
of the methods a model responds to. Today it offers this raquitic

     http://api.rubyonrails.org/classes/ActiveRecord/Base.html

Where is #valid? Missing. As a user of Active Record I want to be able
to open the API of AR::Base and find #valid? and everything there.

We should rather provide something closer to this:

     http://reflexive-demo.heroku.com/reflexive/constants/ActiveRecord::Base

with better usability (and that's a problem to solve in the design).

In my view, a project like Rails has so much separation between its
internal organization and its public interface, that I think executing
and introspecting is the most effective approach to building its API:

    1. executing the source tree except for a list of exceptions is easy
    2. inspecting classes and modules with introspection is easy
    3. we get something much more comprehensive

This might not be the best approach for a generic documentation tool,
but I think it is the best approach for a project like Rails.

The user does not care about the internal organization of the code.
The user does not care about InstanceMethods and ClassMethods. The
user cares about what's the API available for a given class, and we do
not have a good answer to that as of today.

So, in particular, I want all the Ruby hooks like included or
inherited run, all the AS::Concern side-effects in place (AS::Concern
is used in more than a hundred places), I want

    MODULES.each do |mod|
      include mod
    end

in AC::Base to be executed. And we could start looking at the Rails
source code and list more and more examples.

The result won't be perfect, of course, but 1 and 2 are so *trivial in
comparison to a parser*, and you get so much better content to build
your docs from for such a cheap price, that for me this approach _for
Rails_ is a no-brainer (modulus it has not been implemented, it will
have its own issues I am sure.)

A parser would still be needed to extract doc strings, so the tool I
have in mind mixes both things.

If T is YARD, adopting it wouldn't imply necessarily we also adopt annotations. That would be a different discussion.

I think the annotation discussion is inherently integral in adopting
YARD; it should at least be mentioned here in brief.

Thanks for these thoughts on annotations. This is a topic where I have
not yet an actual opinion, only a priori mixed feelings (let me not
elaborate now). So I am personally open to this and interested in
discussing it.

But if you don't mind I'd like first to focus on the problem above,
because I see it as key for the evolution of the Rails API, and its
implementation, if it ever happens, may indirectly select a tool (or
create a new one).

I am considering sdoc as a very easy way to add the number one
requested feature, which is search. It has also a nice template. If
you are using RDoc, I think sdoc is really nice.

But integrating sdoc is very transparent. In particular, if we switch
to YARD someday and it has search by then, the fact that the API uses
sdoc won't be an obstacle. We are essentially at the same distance
from YARD + search today than today + sdoc.

In my view, a project like Rails has so much separation between its
internal organization and its public interface, that I think executing
and introspecting is the most effective approach to building its API:

1\. executing the source tree except for a list of exceptions is easy
2\. inspecting classes and modules with introspection is easy
3\. we get something much more comprehensive

1,2&3 are true, but I think you're focusing too much on "the last 20%"
of the Rails codebase and ignoring the first 80%. Specifically, what
you're worried about supporting is really just some isolated cases of
"extra-dynamic" behaviour. I don't think you necessarily need to throw
away a working documentation tool just to get that last 20%. YARD can
certainly be augmented to deal with these scenarios on a case by case
basis. If you use a tool like Reflexive, you will ultimately need to
implement a full lexical parser on top of it. YARD, on the other hand,
could still quite easily be used with little modification. I show
below how to deal with one of the cases.

The user does not care about the internal organization of the code.
The user does not care about InstanceMethods and ClassMethods. The
user cares about what's the API available for a given class, and we do
not have a good answer to that as of today.

If the mixins were recognized during parsing (see below), YARD has a
simple solution for this already. In fact, YARD already shows
"inherited methods" from ancestor classes/modules in the docs:
http://rubydoc.info/github/rails/rails/ActionController/Base -- it
would be a trivial change to the template to just show these methods
inline instead of linking to them; one that has been feature suggested
before, and something we'd be up for making part of YARD's core
functionality as an option.

So, in particular, I want all the Ruby hooks like included or
inherited run, all the AS::Concern side-effects in place (AS::Concern
is used in more than a hundred places), I want

MODULES\.each do |mod|
  include mod
end

in AC::Base to be executed. And we could start looking at the Rails
source code and list more and more examples.

To give you a practical solution: YARD allows the installation of post-
parsing hooks that can perform final modifications to the raw YARD
object database that's generated for usage in templates. Basically,
you could handle cases like AC::Base individually in such a post-parse
hook, manually adding the necessary mixins to the class. It might look
something like:

    require 'actionpack/action_controller/base'
    include YARD
    SourceParser.after_parse_list do
      obj = Registry.at('ActionController::Base')
      ActionController::Base::MODULES.each do |mod|
        obj.mixins(:instance).unshift P(mod.name)
      end
    end

You would put this in some yard/ac_hooks.rb and run yard with -e yard/
ac_hooks.rb-- then the appropriate mixins will be added to the
AC::Base class as if they were defined statically. You could even grab
the names right out of obj.children('MODULES').value directly, and
never have to eval anything, but YMMV on that.

You'd basically handle the edge cases on an individual basis in this
fashion, and you should be able to get full documentation coverage.
With the "embed included modules" template customizations I talked
about above, you'd get exactly what you want from YARD with only a
handful of lines of extra code.

The result won't be perfect, of course, but 1 and 2 are so *trivial in
comparison to a parser*, and you get so much better content to build
your docs from for such a cheap price, that for me this approach _for
Rails_ is a no-brainer (modulus it has not been implemented, it will
have its own issues I am sure.)

Again, you're de-emphasizing the difficulty of the parsing side of
things. Extracting docs is not all that the parser will need to do
(and is not as simple as you think). If you're interested in
extracting source code, your parser *must* be a full Ruby parser, even
if just to extract constant values. It's easy to just focus on the
runtime / object model side of things and say that "this is much
easier, now we just need to extract the comments"-- trust me, we
looked at this kind of solution in YARD many times before. It really
doesn't work that way in practice. Extracting docstrings from classes/
modules, for instance, will be well-nigh impossible without full
parsing, because unlike methods, you can't get source_location on
these objects from the runtime. I'll point you to the Pry project, who
were recently doing things exactly how you just suggested, until they
realized there was no way for them to pull out docs for classes/
modules without full parsing either. Last I heard they also started
using YARD for their docs parsing.

Yes, the reflection part *is* trivial-- but it's trivial because it's
only a small portion of what needs to be done. The reflection is
something you've better off tacking on top of a working doc tool like
YARD, not the other way around.

- Loren

Oh yes, extracting docstrings and source code is hard. I didn't
emphasize that because existing tools solve it and in my view the most
natural thing to try first is to inject an alternative ancestry chain
into RDoc or YARD somehow before generation.

For example, would it be technically possible to have a YARD after
hook that performs the evaluation of the source tree, rewrites
ancestries in YARD's database according to the ones available at
runtime via introspection, and then lets YARD continue?

Yes-- the example above does this, at least for AC::Base. As I said,
this is something you should use in isolated cases, since, in most
cases YARD does it right the first time. You can handle each isolated
case as it comes up.

Also, I realized the example needs one minor modification:
"Parser::SourceParser" instead of just SourceParser. Also you may not
be able to just require 'action_controller/base', you might have to
pull in more of Rails. I tested the above example out myself but
parsed out the constant value text manually (rather than evaling
runtime stuff) and got the output you were looking for.

- Loren

For example, would it be technically possible to have a YARD after
hook that performs the evaluation of the source tree, rewrites
ancestries in YARD's database according to the ones available at
runtime via introspection, and then lets YARD continue?

Yes-- the example above does this, at least for AC::Base.

That's good news :).

As I said,
this is something you should use in isolated cases, since, in most
cases YARD does it right the first time.

But do you realize that a lot of includes/extends are implicit/dynamic
and happen when the class definition is executed? There's no way a
parser can build an ancestor chain for most Rails classes that matches
the one in runtime, notably for the most important ones. For starters
there are more than one hundred uses of AS::Concern.

You can handle each isolated
case as it comes up.

Well, we differ in that approach, though that is not important. The
number of cases to catch is so numerous and variable over the
evolution of the project that executing everything except for a list
of files maintained by hand seems more robust to me. Does YARD care if
the after hook rewrites most of the ancestry chain in its database?
Can it break something?

Also, I realized the example needs one minor modification:
"Parser::SourceParser" instead of just SourceParser. Also you may not
be able to just require 'action_controller/base', you might have to
pull in more of Rails. I tested the above example out myself but
parsed out the constant value text manually (rather than evaling
runtime stuff) and got the output you were looking for.

OK, I will definitely investigate this path. Looks really
cost-effective and promising.

Nope, it shouldn't break anything.

- Loren

So it’s two months since the last message here. Any progress on this? Is Rails core team still against the migration to YARDoc?

I would really like to see some sort of movement on this before Rails 3.1 comes out. Even just switching the current system over to YARDoc would be a great start. We can then progressively change more details after that point.

Right now, the current system as it stands is still balls ugly and reflects poorly on the high standard of the Rails community.