Skip to content

Namespaced model support #176

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 7 commits into from

Conversation

rosskevin
Copy link

Solves #175. Provides support through resolved_class_name.

  • tests added/updated
  • reducer added to map type_name => class_name
  • exposed as Schema.resolved_class_names

An accompanying PR from graphql-relay-ruby will be forthcoming that uses Schema.resolved_class_names

@rosskevin
Copy link
Author

rosskevin commented Jul 7, 2016

PS - Sorry for the spacing change, you might add a .editorconfig. I tried putting it back but you can see it remained, therefore you might merge + squash this to avoid the superfluous commit history.

@rosskevin
Copy link
Author

@rmosolgo - regarding the rbx failure, I have no idea why it isn't loading the test model Acme::Post located in the support directory. Evidently semantics of loading are different, but I am unfamiliar.

rosskevin added a commit to rosskevin/graphql-relay-ruby that referenced this pull request Jul 7, 2016
@rmosolgo
Copy link
Owner

rmosolgo commented Jul 7, 2016

I really like this idea -- matching GraphQL object types to "underlying" Ruby classes -- I just need to get a chance to think it through!

# Conflicts:
#	lib/graphql/object_type.rb
#	lib/graphql/schema.rb
@rosskevin
Copy link
Author

rosskevin commented Jul 25, 2016

@rmosolgo - I just re-merged this to resolve conflicts with updated master. The only item that needs your review specifically is accessibility of attributes, I'm not sure how resolved_class_name fits in with the updated code may need to be modified to be inline with your approach: https://github.com/rosskevin/graphql-ruby/blob/namespaced-model-support/lib/graphql/object_type.rb#L25

Local tests succeed, travis seems hung up at this time (builds aren't starting).

Absent other ideas, I'd like to see this get merged before it falls behind again.

@rmosolgo
Copy link
Owner

Thanks! Sorry I haven't looked at it yet. I want to keep an eye out for extensibility for this mechanism, for example, what if a type can be matched to an object by a hash key? or what if it exposes several classes?

I haven't thought through these questions yet but I'd like to get them all at once, if possible!

@rmosolgo
Copy link
Owner

All in all, I like the idea of adding some awareness of "is this an object that belongs to this type?" There are some dubious "defaults" in graphql-ruby like object_from_id (where this feature is applied in https://github.com/rmosolgo/graphql-relay-ruby/pull/56) and resolve_type.

Given my own experience and things I've heard from maintaining this gem, here are the questions we'll have to answer next:

  • "My objects are members of different classes, how can I use this?"
  • "My objects are all hashes, and they're disambiguated by a certain key, how can I use this?"
  • "My objects are members of the same class, but they're disambiguated by a certain method response, how can I use this?"
  • "My objects may be members of different classes, but they're exposed with the same type, how can I use this?"

Can this approach be expanded to handle these different cases?


I think this can be accomplished without library changes, too. Instead of storing the map of class names to types on Schema, store it as a global value in the application:

# Store a map of application object class names => graphql types 
CLASS_NAME_TO_GRAPHQL_TYPE = {} 

module AssignResolvedClassName 
  # Add an entry to the global map of classname => type 
  def self.call(type, resolved_class_name) 
    CLASS_NAME_TO_GRAPHQL_TYPE[resolved_class_name] = type 
  end 
end 

GraphQL::BaseType.accepts_definitions(resolved_class_name: AssignResolvedClassName)

PostType = GraphQL::ObjectType.define do 
  # ... 
  resolved_class_name "Acme::Post" 
end 

NodeIdentification = GraphQL::Relay::GlobalNodeIdentification.define do 
  object_from_id -> (id, ctx) do
    type_name, id = NodeIdentification.from_global_id(id)
    # Get the resolved_class_name for the given type_name
    class_name = CLASS_NAME_TO_GRAPHQL_TYPE[type_name]
    # "Post" -> Post.find(id)
    class_name.constantize.find(id)
  end 
end 

Would that work the same as this library change?

@rosskevin
Copy link
Author

I think this will work for our case. I don't like the idea of global variables in general; it would be nice if weren't adding to the global namespace, but that's not a show-stopper.

While the case for us seems clear now, I don't quite see how you implement different resolvers for the other cases you mention, but again I don't yet have those same issues.

@rmosolgo
Copy link
Owner

rmosolgo commented Aug 7, 2016

Thanks for working through this with me! I pushed a new feature in 0.18.1 that allows types to store arbitrary metadata: https://github.com/rmosolgo/graphql-ruby/blob/master/guides/defining_your_schema.md#extending-type-and-field-definitions

Do you think that would be a good fit for this use case?

@rmosolgo
Copy link
Owner

hope that works, let me know if it doesn't!

@rmosolgo rmosolgo closed this Aug 17, 2016
@bmcdaniel11
Copy link

Thanks @rmosolgo, this pattern works great and has good use for any specific ruby fields you might need. I've tested the change with our code and it was successful.

@rmosolgo
Copy link
Owner

rmosolgo commented Aug 19, 2016

🎉 glad to hear it, and thanks for following up!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants