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:

-- 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

     ActiveRecord::Base

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: Class: ActionController::Base — Documentation for rails/rails (main) -- 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.