-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Release 1.8.0 #1389
Comments
Hey @rmosolgo, first of all, thank you for your work on We're using it in a new project, and I've been wondering: should we start with the current pre-release of 1.8.0 right away, or should we stick to 1.7.x and wait until the first RC or so? Thanks! |
If it were me, I'd start on 1.8. The only big caveat is Interface types -- I might switch up the current implementation so that they're Ruby modules. So you could handle that by either writing them as classes and taking the hit to redo them if they change, or writing them in the old But the usability of the class-based style is so nice, I'd recommend it! |
Our project isn't going to be terribly large, so a certain amount of refactoring to keep up with 1.8's development is perfectly acceptable. Thanks for the heads-up! |
@rmosolgo I'll echo the thanks for all your hard work, the 1.8 changes are really great. I'm starting to migrate a project over to the class-based API, and I'm trying to decide on if/how to change the way we're dynamically generating types. I think there are a number of ways it could be done (including leveraging |
I think it will be Edit: there are some trivial and incomplete examples in the specs, for example: graphql-ruby/spec/graphql/schema/object_spec.rb Lines 17 to 20 in 44e0908
graphql-ruby/spec/graphql/schema/object_spec.rb Lines 34 to 37 in 44e0908
|
Makes sense! We also add fields dynamically, and I initially thought I might be able to use Factory: class Graph::Factories::Metric
def self.define(metric)
if Graph::Objects::Interval.fields[metric.source].nil?
return_type = Graph::Objects::PostSource.create(metric.source)
field = Graph::Fields::PostSource.new(metric.source, return_type,
owner: Graph::Objects::Interval, null: false)
Graph::Objects::Interval.add_field(field)
end
end
end Field: class Graph::Fields::PostSource < Graph::Fields::Base
def initialize(*args, **kwargs, &block)
source = args.first
resolve = -> (obj, args, ctx) { obj.where(source: source) }
super(*args, resolve: resolve, **kwargs, &block)
end
end Return Type: class Graph::Objects::PostSource < Graph::Objects::Base
def self.create(source)
Class.new(self) do
graphql_name "#{source.classify}Posts"
end
end
field :count, Integer, null: false
def count
@object.count
end
end So the one part still relying on the pre-1.8 API is the resolve proc. I suppose I could call |
Could you share an example of how |
Right now I'm just calling it from class Graph::Objects::Interval < Graph::Objects::Base
Metric.all.each do |metric|
Graph::Factories::Metric.define(metric: metric)
end
end Ideally though I think I want to be able to call |
Thanks for sharing. I tried to understand it by inlining a lot of the code. Then I made a few changes:
In my case it turned out looking like this: class Graph::Objects::Interval < Graph::Objects::Base
# Read some objects from the database
Metric.all.each do |metric|
# Generate a field from each object, using `source` as the name
field_name = metric.source
# Don't override an existing field
if fields[field_name].nil?
# Generate a return type for this field. It has a `count` field.
return_type = Class.new(Graph::Objects::Base) do
graphql_name "#{field_name.classify}Posts"
field :count, Integer, null: false
end
# Define a field with the same name, returning the generated return type
field(field_name, return_type, null: false)
# Implement the field with a method
define_method(field_name) do
@object.where(source: field_name)
end
end
end
end Like you said, maybe for your app you want to reorganize it a bit to fit your flow, but I thought it was a fun exercise and maybe a fresh perspective would come in handy! Thanks again for sharing your use case a bit. |
Thanks! The inline approach is pretty much where I started. 😄 I just realized I could use class Graph::Factories::Metric
def self.define(metric:)
field_name = metric.source
if Graph::Objects::Interval.fields[field_name].nil?
return_type = Graph::Objects::PostSource.create(field_name)
Graph::Objects::Interval.field(field_name, return_type, null: false,
method: :resolve_post_source, extras: [:irep_node])
end
end
end
class Graph::Objects::PostSource < Graph::Objects::Base
def self.create(source)
Class.new(self) do
graphql_name "#{source.classify}Posts"
end
end
field :count, Integer, null: false
end
class Graph::Objects::Interval < Graph::Objects::Base
def resolve_post_source(irep_node:)
object.where(source: irep_node.name)
end
end I'm pretty happy with this approach—no need for separate I think the only slight improvement might be a way to get |
Cool! The only thing I would say is to use |
This issue is to track the stable release of 1.8.0
TODO
Roughly in order:
[1.8] Schema classes don't supportfixed by Fix subscriptions for class-based schemas #1391.subscriptions
yet #1388GraphQL-Pro route helpersfixed in 1.7.1ShipI'll release another.rc1
pre
insteadThe text was updated successfully, but these errors were encountered: