diff --git a/Gemfile.lock b/Gemfile.lock index 7963560..edef289 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - rails-graphql (1.0.5) + rails-graphql (1.0.6) rails (>= 6.0) GEM diff --git a/lib/rails/graphql/request/strategy.rb b/lib/rails/graphql/request/strategy.rb index ed13ed0..556e8ce 100644 --- a/lib/rails/graphql/request/strategy.rb +++ b/lib/rails/graphql/request/strategy.rb @@ -131,8 +131,9 @@ def resolve_data_for(field, args) return unless args.size.zero? if field.try(:dynamic_resolver?) - prepared = prepared_data_for(field) - args << Event.trigger(:resolve, field, self, prepared_data: prepared, &field.resolver) + extra = prepared_data_for(field, with_null: true) + extra = extra === PreparedData::NULL ? EMPTY_HASH : { prepared: extra } + args << Event.trigger(:resolve, field, self, **extra, &field.resolver) elsif field.prepared_data? args << prepared_data_for(field) else @@ -206,11 +207,14 @@ def safe_store_data(field, value = nil) # Get the prepared data for the given +field+, getting ready for # resolve, while ensuring to check prepared data on request - def prepared_data_for(field) - return @data_pool[field] unless field.prepared_data? - - prepared = request.prepared_data_for(field).next - prepared unless prepared === PreparedData::NULL + def prepared_data_for(field, with_null: false) + if field.prepared_data? + request.prepared_data_for(field).next + elsif @data_pool.key?(field) + @data_pool[field] + elsif with_null + PreparedData::NULL + end end # Simply run the organize step for compilation diff --git a/lib/rails/graphql/source/active_record_source.rb b/lib/rails/graphql/source/active_record_source.rb index f3dd171..ef7f428 100644 --- a/lib/rails/graphql/source/active_record_source.rb +++ b/lib/rails/graphql/source/active_record_source.rb @@ -256,6 +256,12 @@ def build_association_scope(association) # Once the records are pre-loaded due to +preload_association+, use the # parent value and the preloader result to get the records def parent_owned_records(collection_result = false) + # The absence of the prepared data key means we got to a point that we + # don't know the result of the association, so we simply call it + unless event.data.key?(:prepared_data) + return current_value.public_send(field.method_name) + end + data = event.data[:prepared_data] return collection_result ? [] : nil unless data diff --git a/lib/rails/graphql/version.rb b/lib/rails/graphql/version.rb index ed8ecd8..a757a5f 100644 --- a/lib/rails/graphql/version.rb +++ b/lib/rails/graphql/version.rb @@ -14,7 +14,7 @@ def self.version module VERSION MAJOR = 1 MINOR = 0 - TINY = 5 + TINY = 6 PRE = nil STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.') diff --git a/test/assets/sqlite.gql b/test/assets/sqlite.gql index cd60988..9f8a7e9 100644 --- a/test/assets/sqlite.gql +++ b/test/assets/sqlite.gql @@ -226,6 +226,10 @@ type LiteShip { name: String } +type Sample { + faction: LiteFaction! +} + type _Mutation { createLiteBase(liteBase: LiteBaseInput!): LiteBase! @@ -262,6 +266,8 @@ type _Query { liteShip(id: ID!): LiteShip! liteShips: [LiteShip!]! + + sample: Sample! } """ diff --git a/test/integration/schemas/mysql.rb b/test/integration/schemas/mysql.rb index 3dca27e..4bc4917 100644 --- a/test/integration/schemas/mysql.rb +++ b/test/integration/schemas/mysql.rb @@ -6,7 +6,7 @@ class MySQLRecord < ActiveRecord::Base establish_connection( name: 'mysql', adapter: 'mysql2', - host: ENV.fetch('GQL_MYSQL_HOST', 'localhost'), + host: ENV.fetch('GQL_MYSQL_HOST', '127.0.0.1'), database: ENV.fetch('GQL_MYSQL_DATABASE', 'starwars'), username: ENV.fetch('GQL_MYSQL_USERNAME', 'root'), password: ENV['GQL_MYSQL_PASSWORD'], diff --git a/test/integration/schemas/sqlite.rb b/test/integration/schemas/sqlite.rb index 7a33c44..b7fadc7 100644 --- a/test/integration/schemas/sqlite.rb +++ b/test/integration/schemas/sqlite.rb @@ -95,4 +95,16 @@ def greeting end source LiteShip + + object 'Sample' do + field :faction, 'LiteFaction', null: false + end + + query_fields do + field :sample, 'Sample', null: false + end + + def sample + { faction: LiteFaction.last } + end end diff --git a/test/integration/sqlite/star_wars_query_test.rb b/test/integration/sqlite/star_wars_query_test.rb index 1eb7f6f..068e70d 100644 --- a/test/integration/sqlite/star_wars_query_test.rb +++ b/test/integration/sqlite/star_wars_query_test.rb @@ -88,4 +88,13 @@ def test_query_methods_precedence query EmpireFleet { liteFaction(id: "2") { greeting } } GQL end + + def test_nested_non_prepared_source + bases = named_list('Death Star', 'Shield Generator', 'Headquarters') + sample = { sample: { faction: { name: 'Galactic Empire', bases: bases } } } + + assert_result({ data: sample }, <<~GQL) + query SampleFaction { sample { faction { name bases { name } } } } + GQL + end end