graphiti-api / graphiti

Stylish Graph APIs
https://www.graphiti.dev/
MIT License
974 stars 139 forks source link

Is it possible to get a list of all Resource class names? #417

Closed Ben-Fenner closed 2 years ago

Ben-Fenner commented 2 years ago

I'm trying to write our own API documentation but also automate it as much as possible. Is there a way to get a list of all Resources sort of like Graphiti::Resource.all?

Then I could loop over them and their attributes to output if they are sortable, filterable, etc.

Is there anything like that? I don't recall coming across it in the documentation (and I've read it so many times).

I guess worst case scenario I can introspect the resources directory... =/

Ben-Fenner commented 2 years ago

Until I figure out something better, I'm introspecting the resources directory. Here's that code if anyone else wants to use it:

    resource_location   = '/app/app/resources'
    resource_file_names = Dir.entries(resource_location).select{ |entity| File.file?(File.join(resource_location, entity)) && entity.ends_with?('_resource.rb') }
    resource_classes    = resource_file_names.map{ |file_name| file_name.chomp('.rb').camelize.constantize }
    resource_classes    = resource_classes.reject(&:abstract_class?)

I hope to soon be able to avoid this with something much simpler, but here I am for now.

amaierhofer commented 2 years ago

You could query the schema for that i guess ..

[9] pry(main)> Graphiti::Schema.generate.fetch(:resources).collect { |r| r[:name] }
=> ["BugResource",
 "DepartmentResource",
 "EmployeeResource",
 "EpicResource",
 "FeatureResource",
 "MilestoneResource",
 "NoteResource",
 "PositionResource",
 "TaskResource",
 "TeamResource"]
Ben-Fenner commented 2 years ago

That's a bit more like what I was looking for. Thank you so much!

Ben-Fenner commented 2 years ago

Oh boy, crazily enough the Graphiti::Schema.generate technique above ultimately runs ::Rails.application.eager_load! which causes an application-wide class reload (I think) and when combined with the Rails development environment setting config.cache_classes = false causes an issue with the dry-events gem we're using (it throws a PublisherAlreadyRegisteredError error).

So while the technique above is great, I might have to go back to the directory introspection technique until I can figure out a solution for the dry-events problem. I'm discussing the issue on their support forum and will report back if I ever find a solution.

richmolj commented 2 years ago

Maybe give Graphiti.resources a shot - should return the actual classes, though eager loading might still be an issue.

Ben-Fenner commented 2 years ago

Thank you for the suggestion. I'd actually already tried that after looking up the definition for the earlier suggestion: https://github.com/graphiti-api/graphiti/blob/22808b844133ae67d7dc1a877e0ca97979c23701/lib/graphiti/schema.rb#L5

It seems the eager load is required, as running just Graphiti.resources returns an empty set if the eager loading is not performed first. Well, that's the case in the Rails console, let me check the test environment...

Hmmm, it seems to work in testing. So maybe I'll roll with Graphiti.resources.reject(&:abstract_class?) for now and see how that goes. Thanks for making me re-check. :+1:

Ben-Fenner commented 2 years ago

Well, it worked in the test environment, but not in development*. The eager loading seems to be required there.

So I'm back to introspecting the file system until I can hunt down a solution for the dry-events problem. I'd link to that discussion but my post over there hasn't been approved yet (it's been over 24 hours now). :disappointed:

*Edit: Ha! I got things working in development by adding the app/resources path to the config.autoload_paths setting in my applicatoin.rb file. So I think I'm back in business with the Graphiti.resources technique!

Edit 2: Ugh. After some time the Graphiti.resources solution went back to returning an empty set in development even though I am auto-loading the resource directory. It seems I just can't win. I'm going to have to go back to the file system introspection.

Edit 3: It seems the auto loading only requires the files when they are needed, and they are not needed early enough in my code to produce desired results. I looked into manually requiring all of the resources beforehand but this causes them to be loaded twice, with warnings about constants being already declared. So I looked into conditionally requiring them if they weren't already, but I did not find a good way of accomplishing that. Ultimately it all comes back to needing to look at the file system anyway, so I'm going to stick with my initial file system introspection shown in the second post above.

Ben-Fenner commented 2 years ago

I'll reply with a link to the dry-events discussion when I get it, but really this issue is solved from a Graphiti point of view. There are decent techniques listed above for getting a list of all resource names using built-in Graphiti classes/methods. (Then there is the file system introspection technique.)

So I consider this issue closed. Cheers and thanks! :grin:

Ben-Fenner commented 2 years ago

And finally, here is the link to the dry-events issue and discussion: https://discourse.dry-rb.org/t/publisher-already-registered-error-in-dry-events-when-reloading-classes/1473