Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Ruby_Kaigi_slides.pdf

shawneegao
April 18, 2019

 Ruby_Kaigi_slides.pdf

I will start with some GraphQL basics, then dig into process of metaprogramming a GraphQL layer from a demo ruby server. I will explain the benefits of using this design pattern and how it improves developer experience.

shawneegao

April 18, 2019
Tweet

Other Decks in Technology

Transcript

  1. wagashi wagashi wagashi Lake Ashi ft. Mt. Fuji (a.k.a. shy

    Fuji-san as he’s often covered by fog).
  2. Inventory Price per Unit Restock Date Units Sold Cuban Links

    (Sets) $14,000 3/10/2014 23 Diamond Custom Cuts $200,000 3/10/2014 43 Classic Open Face $230,000 3/10/2014 12 Solid Classics $9,000 3/10/2014 11 Promo Duration Promo Details # Promos used Breezey Promo 3/21/2014 - Forever xx off Loyalty 22 Full Set Discount 3/21/2014 - 4/12/2014 xx% off full set 12 Deposits Pending: $XX Devices: XX # Employees: XX Gift Cards Has Loans Subscriptions # Payments Received Marketing Plans Appointments Chargebacks And So Much More … # Refunds Grillz by Nelly en-US St. Louis, MO Freeze Deactivate Audit Actions: Resolve Unfreeze Payments Graph
  3. Locations Promo Appointments Seller Service Inventory Chargebacks Capital Employees Deposits

    Marketing Hardware Dashboard’s Write Paths Payments Subscriptions
  4. { “data” : [ payment: { “id”: “4567”, “amount”: “300”,

    “merchant”: “1234”, “card: “7890” } ] }
  5. Underfetched! Date Amount Status Merchant Method 3/10/19 $900 Success Grillz

    by Nelly Debit { “data” : [ payment: { “id”: “4567”, “amount”: “300”, “merchant”: “1234”, “card: “7890” } ] }
  6. Road Map • Existing Model Architecture • Write a GraphQL

    Ruby API • Add metaprogramming to our API • Add/Change Business Object • Testing
  7. 1 class TargetBase 2 include TargetMethods 3 extend ModuleHelper 4

    5 def self._fetch_target_data(_token) 6 raise NotImplementedError 7 end 8 9 def self.lookup(token) 10 target_data = _fetch_target_data(token) 11 new(target_data: target_data) 12 end 13 14 def id 15 target_data.id 16 end 17 end
  8. 1 class TargetBase 2 include TargetMethods 3 extend ModuleHelper 4

    5 def self._fetch_target_data(_id) 6 raise NotImplementedError 7 end 8 9 def self.lookup(id) 10 target_data = _fetch_target_data(id) 11 new(target_data: target_data) 12 end 13 14 def id 15 target_data.id 16 end 17 end
  9. 1 class TargetBase 2 include TargetMethods 3 extend ModuleHelper 4

    5 def self._fetch_target_data(_id) 6 raise NotImplementedError 7 end 8 9 def self.lookup(id) 10 target_data = _fetch_target_data(id) 11 new(target_data: target_data) 12 end 13 14 def id 15 target_data.id 16 end 17 end
  10. 1 class TargetBase 2 include TargetMethods 3 extend ModuleHelper 4

    5 def self._fetch_target_data(_id) 6 raise NotImplementedError 7 end 8 9 def self.lookup(id) 10 target_data = _fetch_target_data(id) 11 new(target_data: target_data) 12 end 13 14 def id 15 target_data.id 16 end 17 end
  11. Payment - id - amount - merchant_id Merchant - id

    - store_name Is associated through merchant_id Today’s Data Model
  12. app/models/merchant.rb 4 class Merchant < TargetBase 5 stub_target_data( 6 resource:

    'merchant', 7 id: 4567, 8 response_body: { 9 id: 4567, 10 store_name: 'Grillz by Nelly' 11 } 12 ) 13 14 def self._fetch_target_data(merchant_id) 15 target_data = 16 MerchantClient.get_by_id(merchant_id) 18 19 OpenStruct.new(target_data) 20 end 21 22 def store_name 23 target_data.store_name 24 end 25 end
  13. 4 class Merchant < TargetBase 5 stub_target_data( 6 resource: 'merchant',

    7 id: 4567, 8 response_body: { 9 id: 4567, 10 store_name: 'Grillz by Nelly' 11 } 12 ) 13 14 def self._fetch_target_data(merchant_id) 15 target_data = 16 MerchantClient.get_by_id(merchant_id) 18 19 OpenStruct.new(target_data) 20 end 21 22 def store_name 23 target_data.store_name 24 end 25 end
  14. 4 class Merchant < TargetBase 5 stub_target_data( 6 resource: 'merchant',

    7 id: 4567, 8 response_body: { 9 id: 4567, 10 store_name: 'Grillz by Nelly' 11 } 12 ) 13 14 def self._fetch_target_data(merchant_id) 15 target_data = 16 MerchantClient.get_by_id(merchant_id) 18 19 OpenStruct.new(target_data) 20 end 21 22 def store_name 23 target_data.store_name 24 end 25 end
  15. 4 class Merchant < TargetBase 5 stub_target_data( 6 resource: 'merchant',

    7 id: 4567, 8 response_body: { 9 id: 4567, 10 store_name: 'Grillz by Nelly' 11 } 12 ) 13 14 def self._fetch_target_data(merchant_id) 15 target_data = 16 MerchantClient.get_by_id(merchant_id) 17 .parsed_response 18 19 OpenStruct.new(target_data) 20 end 21 22 def store_name 23 target_data.store_name 24 end 25 end
  16. 4 class Payment < TargetBase 5 stub_target_data( 6 resource: 'payment',

    7 id: 1234, 8 response_body: { 9 id: 1234, 10 amount: 100, 11 merchant_id: 4567 12 } 13 ) 14 15 def self._fetch_target_data(payment_id) 17 target_data = 18 PaymentClient.get_by_id(payment_id) 20 21 OpenStruct.new(target_data) 22 end 23 24 def amount 25 target_data.amount 26 end 29 30 def merchant_id 31 target_data.merchant_id 32 end 33 34 def merchant 35 @merchant ||= Merchant.lookup(merchant_id) 37 end 38 end
  17. 4 class Payment < TargetBase 5 stub_target_data( 6 resource: 'payment',

    7 id: 1234, 8 response_body: { 9 id: 1234, 10 amount: 100, 11 merchant_id: 4567 12 } 13 ) 14 15 def self._fetch_target_data(payment_id) 17 target_data = 18 PaymentClient.get_by_id(payment_id) 20 21 OpenStruct.new(target_data) 22 end 23 24 def amount 25 target_data.amount 26 end 29 30 def merchant_id 31 target_data.merchant_id 32 end 33 34 def merchant 35 @merchant ||= Merchant.lookup(merchant_id) 37 end 38 end
  18. 4 class Payment < TargetBase 5 stub_target_data( 6 resource: 'payment',

    7 id: 1234, 8 response_body: { 9 id: 1234, 10 amount: 100, 11 merchant_id: 4567 12 } 13 ) 14 15 def self._fetch_target_data(payment_id) 17 target_data = 18 PaymentClient.get_by_id(payment_id) 20 21 OpenStruct.new(target_data) 22 end 23 24 def amount 25 target_data.amount 26 end 29 30 def merchant_id 31 target_data.merchant_id 32 end 33 34 def merchant 35 @merchant ||= Merchant.lookup(merchant_id) 37 end 38 end
  19. 4 class Payment < TargetBase 5 stub_target_data( 6 resource: 'payment',

    7 id: 1234, 8 response_body: { 9 id: 1234, 10 amount: 100, 11 merchant_id: 4567 12 } 13 ) 14 15 def self._fetch_target_data(payment_id) 17 target_data = 18 PaymentClient.get_by_id(payment_id) 20 21 OpenStruct.new(target_data) 22 end 23 24 def amount 25 target_data.amount 26 end 29 30 def merchant_id 31 target_data.merchant_id 32 end 33 34 def merchant 35 @merchant ||= Merchant.lookup(merchant_id) 37 end 38 end
  20. 4 class Payment < TargetBase 5 stub_target_data( 6 resource: 'payment',

    7 id: 1234, 8 response_body: { 9 id: 1234, 10 amount: 100, 11 merchant_id: 4567 12 } 13 ) 14 15 def self._fetch_target_data(payment_id) 17 target_data = 18 PaymentClient.get_by_id(payment_id) 20 21 OpenStruct.new(target_data) 22 end 23 24 def amount 25 target_data.amount 26 end 29 30 def merchant_id 31 target_data.merchant_id 32 end 33 34 def merchant 35 @merchant ||= Merchant.lookup(merchant_id) 37 end 38 end
  21. => Payment Payment p = Payment.lookup(1234) => #<Payment id=“1234”> p.amount

    => 100 p.merchant => #<Merchant id=“4567” > p.merchant.store_name => “Grillz by Nelly” Merchant => Merchant m = Merchant.lookup(4567) m.store_name => “Grillz by Nelly” => #<Merchant id=“4567”>
  22. Payment - id - amount - merchant_id Merchant - id

    - store_name Is associated through merchant_id Today’s Data Model
  23. Graphql Controller DemoSchema Mutation Type Query Type Payment Type Merchant

    Type id amount merchant id store_name Some Mutation Merchant Type id store_name
  24. Graphql Controller DemoSchema Mutation Type Query Type Payment Type Merchant

    Type id amount merchant id store_name Some Mutation Merchant Type id store_name Bank Accounts Controller Hardware Controller
  25. Graphql Controller DemoSchema Mutation Type Query Type Payment Type Merchant

    Type id amount merchant id store_name Some Mutation Merchant Type id store_name
  26. query($paymentId: ID!){ payment(id: $paymentId) { id amount merchant { id

    storeName } } } variables{ “paymentId”: 1234 }
  27. 1 class GraphqlController < ApplicationController 2 def execute 3 .....

    4 result = 5 DemoSchema.execute( 6 query, 7 variables: variables, 9 ... 10 ) 11 render json: result 12 rescue => e 13 raise e 14 end query($paymentId: ID!){ payment(id: $paymentId) { id amount merchant { id storeName } } } variables{ “paymentId”: 1234 } app/controllers/graphql_controller.rb
  28. 1 class GraphqlController < ApplicationController 2 def execute 3 .....

    4 result = 5 DemoSchema.execute( 6 query, 7 variables: variables, 9 ... 10 ) 11 render json: result 12 rescue => e 13 raise e 14 end query($paymentId: ID!){ payment(id: $paymentId) { id amount merchant { id storeName } } } variables{ “paymentId”: 1234 } app/controllers/graphql_controller.rb
  29. 1 class GraphqlController < ApplicationController 2 def execute 3 .....

    4 result = 5 DemoSchema.execute( 6 query, 7 variables: variables, 9 ... 10 ) 11 render json: result 12 rescue => e 13 raise e 14 end query($paymentId: ID!){ payment(id: $paymentId) { id amount merchant { id storeName } } } variables{ “paymentId”: 1234 } app/controllers/graphql_controller.rb
  30. 1 class GraphqlController < ApplicationController 2 def execute 3 .....

    4 result = 5 DemoSchema.execute( 6 query, 7 variables: variables, 9 ... 10 ) 11 render json: result 12 rescue => e 13 raise e 14 end query($paymentId: ID!){ payment(id: $paymentId) { id amount merchant { id storeName } } } variables{ “paymentId”: 1234 } app/controllers/graphql_controller.rb
  31. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 class DemoSchema < GraphQL::Schema 2 query(Types::QueryType) 3 query(Types::MutationType) 4 end app/graphql/demo_schema.rb
  32. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 class DemoSchema < GraphQL::Schema 2 query(Types::QueryType) 3 query(Types::MutationType) 4 end app/graphql/demo_schema.rb
  33. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 module Types 2 class QueryType < Types::BaseObject 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 app/graphql/type/query_type.rb
  34. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 module Types 2 class QueryType < Types::BaseObject 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 app/graphql/type/query_type.rb
  35. payment(id: $paymentId) 3 field :payment, Types::PaymentType, null: false do 4

    argument :id, ID, required: true 5 end “paymentId”: 1234
  36. payment(id: $paymentId) 3 field :payment, Types::PaymentType, null: false do 4

    argument :id, ID, required: true 5 end “paymentId”: 1234
  37. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 module Types 2 class QueryType < Types::BaseObject 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 app/graphql/type/query_type.rb
  38. 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null:

    false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end app/graphql/type/payment_type.rb query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName } } } variables{ “paymentId”: 1234 }
  39. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end app/graphql/type/payment_type.rb
  40. payment(id: $paymentId){ id amount merchant { id storeName } }

    1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  41. payment(id: $paymentId){ id amount merchant { id storeName } }

    1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  42. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } app/graphql/type/merchant_type.rb 1 class Types::MerchantType < Types::BaseObject 2 field :id, ID, null: false 3 field :storeName, String, null: false 4 end
  43. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } app/graphql/type/merchant_type.rb 1 class Types::MerchantType < Types::BaseObject 2 field :id, ID, null: false 3 field :storeName, String, null: false 4 end
  44. merchant { id storeName } app/graphql/type/merchant_type.rb 1 class Types::MerchantType <

    Types::BaseObject 2 field :id, ID, null: false 3 field :storeName, String, null: false 4 end
  45. merchant { id storeName } app/graphql/type/merchant_type.rb 1 class Types::MerchantType <

    Types::BaseObject 2 field :id, ID, null: false 3 field :storeName, String, null: false 4 end
  46. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 module Types 2 class QueryType < Types::BaseObject 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 app/graphql/type/query_type.rb
  47. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 module Types 2 class QueryType < Types::BaseObject 3 field :payment, Types::PaymentType, null: false d 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 app/graphql/type/query_type.rb
  48. query($paymentId: ID!){ payment(id: $paymentId){ id amount merchant { id storeName

    } } } variables{ “paymentId”: 1234 } 1 module Types 2 class QueryType < Types::BaseObject 3 field :payment, Types::PaymentType, null: false d 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 app/graphql/type/query_type.rb
  49. Payment.lookup(1234) { "data": { "payment": { "id": "1234", "amount": 100,

    "merchant": { "id": “4567", "storeName": “Grillz by Nelly” } } } }
  50. GraphQL Controller DemoSchema Types::QueryType Root Types Root Type Resolvers field

    :payment … field :merchant … def payment … def merchant … validates Types::PaymentType Types::MerchantType GQL Type Classes Payment Merchant Target Classes
  51. GraphQL Controller DemoSchema Types::QueryType Root Types Root Type Resolvers field

    :payment … field :merchant … def payment … def merchant … validates Types::PaymentType Types::MerchantType GQL Type Classes Payment Merchant Target Classes
  52. Types::QueryType Root Types Root Type Resolvers field :payment … field

    :merchant … def payment … def merchant … Types::PaymentType Types::MerchantType GQL Type Classes
  53. Types::QueryType Root Types Root Type Resolvers field :payment … field

    :merchant … def payment … def merchant … Types::PaymentType Types::MerchantType GQL Type Classes
  54. Payment - id - amount - merchant_id Merchant - id

    - store_name Is associated through merchant_id Today’s Data Model
  55. Payment - id - amount - merchant_id Merchant - id

    - store_name Is associated through merchant_id Today’s Data Model gql_field_annotations gql_field_annotations
  56. Payment.gql_field_annotations => { amount: {type: "Integer", null: false}, id: {type:

    "Types::BaseObject::ID", null: false}, merchant: {type: "Types::MerchantType", null: false} }
  57. Payment.gql_field_annotations => { amount: {type: "Integer", null: false}, id: {type:

    "Types::BaseObject::ID", null: false}, merchant: {type: "Types::MerchantType", null: false} }
  58. 4 class Payment < TargetBase 33 def amount 34 target_data.amount

    35 end 36 38 def token 39 target_data.token 40 end 41 42 def merchant_token 43 target_data.merchant_token 44 end 45 47 def merchant 48 @merchant ||= Merchant.lookup(merchant_token) 49 end 50 end
  59. 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6

    {} 7 end 9 . . . 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end 36 37 annotate_field "Types::BaseObject::ID", null: false, definition: 38 def token 39 target_data.token 40 end 41 42 def merchant_id 43 target_data.merchant_id 44 end 45 46 annotate_field "Types::MerchantType", null: false, definition: 47 def merchant 48 @merchant ||= Merchant.lookup(merchant_id) 49 end 50 end
  60. 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6

    {} 7 end 9 . . . 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end 36 37 annotate_field "Types::BaseObject::ID", null: false, definition: 38 def token 39 target_data.token 40 end 41 42 def merchant_id 43 target_data.merchant_id 44 end 45 46 annotate_field "Types::MerchantType", null: false, definition: 47 def merchant 48 @merchant ||= Merchant.lookup(merchant_id) 49 end 50 end
  61. 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6

    {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  62. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  63. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  64. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  65. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  66. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end :amount
  67. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  68. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  69. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end :amount
  70. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  71. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  72. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  73. 1 module TargetAnnotation 2 def annotate_field(type, null: false, definition:) 5

    self.gql_field_annotations[definition] = { 6 type: type, 7 null: null 8 } 9 10 orig_method = instance_method(definition) 11 define_method(definition) do 12 orig_method.bind(self).call 13 end 14 end 15 end 4 class Payment < TargetBase 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 32 annotate_field "Integer", null: false, definition: 33 def amount 34 target_data.amount 35 end
  74. gql_type_generator = GqlTypeGenerator.new(all_target_classes) => { Payment: Types::PaymentType, Merchant: Types::MerchantType }

    => #<GqlTypeGenerator:0x00007faadc4fff40 @target_to_gql_class_mapping={Payment: Types::PaymentType, Merchant: Types::MerchantType}> gql_type_generator.target_to_gql_class_mapping gql_type_generator.target_to_gql_class_mapping[Payment] => Types::PaymentType gql_type_generator.target_to_gql_class_mapping[Merchant] => Types::MerchantType
  75. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    5 @target_to_gql_class_mapping = {} 6 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class.to_s}Type" 9 10 @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) do end 16 ) 17 end 18 end 19 end
  76. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    5 @target_to_gql_class_mapping = {} 6 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class.to_s}Type" 9 10 @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) do end 16 ) 17 end 18 end 19 end
  77. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    5 @target_to_gql_class_mapping = {} 6 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class.to_s}Type" 9 10 @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) do end 16 ) 17 end 18 end 19 end
  78. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    5 @target_to_gql_class_mapping = {} 6 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class.to_s}Type" 9 10 @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) do end 16 ) 17 end 18 end 19 end
  79. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    5 @target_to_gql_class_mapping = {} 6 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class}Type" 9 10 @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) do end 16 ) 17 end 18 end 19 end
  80. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    5 @target_to_gql_class_mapping = {} 6 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class}Type" 9 10 @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) do end 16 ) 17 end 18 end 19 end
  81. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    5 @target_to_gql_class_mapping = {} 6 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class}Type" 9 10 @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) 16 ) 17 end 18 end 19 end
  82. 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class}Type" 9 10

    @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) 16 ) 17 end 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  83. 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class}Type" 9 10

    @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) 16 ) 17 end 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  84. 7 target_classes.each do |target_class| 8 gql_type_class_name = "#{target_class}Type" 9 10

    @target_to_gql_class_mapping[target_class] = 11 Types.const_set( 12 gql_type_class_name, 13 Class.new(Types::BaseObject) 16 ) 17 end 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  85. 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null:

    false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  86. Types::PaymentType => Types::PaymentType Types::PaymentType.own_fields.keys => [“id”, “amount”, “merchant”] Types::PaymentType.own_fields[“id"].class =>

    GraphQL::Schema::Field Types::MerchantType.own_fields[“id"] => #<GraphQL::Schema::Field:0x00007fdbffbd51e0 @original_name=:id, @underscored_name="id", @name="id", @description=nil, @field=nil, @function=nil . . .>
  87. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    . . . 19 20 def self.add_fields_to_gql_type(target_class, gql_type_class) 22 target_class.gql_field_annotations.each do |field, def_hash| 23 fieldType = field_definition_hash[:type].constantize 24 nullable = field_definition_hash[:null] 25 field field_name, fieldType, null: nullable 26 end 28 end 29 end 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  88. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    . . . 19 20 def self.add_fields_to_gql_type(target_class, gql_type_class) 22 target_class.gql_field_annotations.each do |field, def_hash| 23 fieldType = field_definition_hash[:type].constantize 24 nullable = field_definition_hash[:null] 25 field field_name, fieldType, null: nullable 26 end 28 end 29 end 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  89. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    . . . 19 20 def self.add_fields_to_gql_type(target_class, gql_type_class) 22 target_class.gql_field_annotations.each do |field, def_hash| 23 fieldType = field_definition_hash[:type].constantize 24 nullable = field_definition_hash[:null] 25 field field_name, fieldType, null: nullable 26 end 28 end 29 end 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  90. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    . . . 19 20 def self.add_fields_to_gql_type(target_class, gql_type_class) 22 target_class.gql_field_annotations.each do |field, def_hash| 23 fieldType = field_definition_hash[:type].constantize 24 nullable = field_definition_hash[:null] 25 field field_name, fieldType, null: nullable 26 end 28 end 29 end 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  91. 1 class GqlTypeGenerator 2 attr_accessor :target_to_gql_class_mapping 3 4 def initialize(target_classes)

    . . . 19 20 def self.add_fields_to_gql_type(target_class, gql_type_class) 22 target_class.gql_field_annotations.each do |field, def_hash| 23 fieldType = field_definition_hash[:type].constantize 24 nullable = field_definition_hash[:null] 25 graph_type_class.field field_name, fieldType, null: nullable 26 end 28 end 29 end 1 class Types::PaymentType < Types::BaseObject 2 field :id, ID, null: false 3 field :amount, Int, null: false 4 field :merchant, Types::MerchantType, null: false 5 end
  92. Types::QueryType Root Types Root Type Resolvers field :payment … field

    :merchant … def payment … def merchant … Types::PaymentType Types::MerchantType GQL Type Classes
  93. 1 module Types 2 class QueryType < Types::BaseObject 3 field

    :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20
  94. 1 module Types 2 class QueryType < Types::BaseObject 3 field

    :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20
  95. 1 module Types 2 class QueryType < Types::BaseObject 3 field

    :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end
  96. 1 module Types 2 class QueryType < Types::BaseObject . .

    . 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym 16 field field_name, gql_type, null: false do 17 argument :id, ID, required: true 18 end 24 end 25 end 26 end 27 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end
  97. 1 module Types 2 class QueryType < Types::BaseObject . .

    . 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym 16 field field_name, gql_type, null: false do 17 argument :id, ID, required: true 18 end 24 end 25 end 26 end 27 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end
  98. 1 module Types 2 class QueryType < Types::BaseObject . .

    . 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym 16 field field_name, gql_type, null: false do 17 argument :id, ID, required: true 18 end 24 end 25 end 26 end 27 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end
  99. 1 module Types 2 class QueryType < Types::BaseObject . .

    . 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym 16 field field_name, gql_type, null: false do 17 argument :id, ID, required: true 18 end 24 end 25 end 26 end 27 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end
  100. 3 field :payment, Types::PaymentType, null: false do 4 argument :id,

    ID, required: true 5 end 1 module Types 2 class QueryType < Types::BaseObject 3 field :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end
  101. 1 module Types 2 class QueryType < Types::BaseObject 3 field

    :payment, Types::PaymentType, null: false do 4 argument :id, ID, required: true 5 end 6 7 field :merchant, Types::MerchantType, null: false do 8 argument :id, ID, required: true 9 end 10 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 14 15 def merchant(params) 16 Merchant.lookup(params[:id]) 17 end 18 end 19 end 20 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end
  102. 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 1 module Types

    2 class QueryType < Types::BaseObject 12 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym . . . 20 define_method(field_name) do |params| 21 targetClass = Object.const_get(field_name.capitalize) 22 targetClass.lookup(params[:id]) 23 end 24 end 25 end 26 end 27
  103. 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 1 module Types

    2 class QueryType < Types::BaseObject 12 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym . . . 20 define_method(field_name) do |params| 21 targetClass = Object.const_get(field_name.capitalize) 22 targetClass.lookup(params[:id]) 23 end 24 end 25 end 26 end 27
  104. 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 1 module Types

    2 class QueryType < Types::BaseObject 12 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym . . . 20 define_method(field_name) do |params| 21 targetClass = Object.const_get(field_name.capitalize) 22 targetClass.lookup(params[:id]) 23 end 24 end 25 end 26 end 27
  105. 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 1 module Types

    2 class QueryType < Types::BaseObject 12 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym . . . 20 define_method(field_name) do |params| 21 targetClass = Object.const_get(field_name.capitalize) 22 targetClass.lookup(params[:id]) 23 end 24 end 25 end 26 end 27
  106. 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 1 module Types

    2 class QueryType < Types::BaseObject 12 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym . . . 20 define_method(field_name) do |params| 21 target_class = Object.const_get(field_name.capitalize) 23 end 24 end 25 end 26 end 27
  107. 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 1 module Types

    2 class QueryType < Types::BaseObject 12 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym . . . 20 define_method(field_name) do |params| 21 target_class = Object.const_get(field_name.capitalize) 22 target_class.lookup(params[:id]) 23 end 24 end 25 end 26 end 27
  108. 11 def payment(params) 12 Payment.lookup(params[:id]) 13 end 1 module Types

    2 class QueryType < Types::BaseObject 12 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym . . . 20 define_method(field_name) do |params| 21 target_class = Object.const_get(field_name.capitalize) 22 target_class.lookup(params[:id]) 23 end 24 end 25 end 26 end 27
  109. Payment - id - amount - merchant_id Merchant - id

    - store_name Is associated through merchant_id Today’s Data Model
  110. Payment - id - amount - merchant_id Merchant - id

    - store_name Today’s Data Model Card - id - name_on_card - bin - payment_id
  111. 4 class Card < TargetBase 5 mattr_accessor :gql_field_annotations do 6

    {} 7 end 8 9 stub_target_data( 10 resource: 'card', 11 id: 7890, 12 response_body: { 13 id: 7890, 14 bin: 1111, 15 names_on_card:'Shawnee Gao', 16 postal_code: 94114, 17 payment_id: 1234 18 } 19 ) 20 21 def self._fetch_target_data(id) 22 target_data = CardClient.get_by_id(id) 23 OpenStruct.new(target_data) 24 end . . . 40 41 def payment_id 42 target_data.payment_id 43 end 44 45 annotate_field "Types::PaymentType", null: false, definition: 46 def payment 47 @payment ||= Payment.lookup(payment_id) 48 end 49 end
  112. 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 8 9

    stub_target_data( 10 resource: 'card', 11 id: 7890, 12 response_body: { 13 id: 7890, 14 bin: 1111, 15 names_on_card:'Shawnee Gao', 16 postal_code: 94114, 17 payment_id: 1234 18 } 19 ) 20 21 def self._fetch_target_data(id) 22 target_data = CardClient.get_by_id(id) 23 OpenStruct.new(target_data) 24 end . . . 40 41 def payment_id 42 target_data.payment_id 43 end 44 45 annotate_field "Types::PaymentType", null: false, definition: 46 def payment 47 @payment ||= Payment.lookup(payment_id) 48 end
  113. 5 mattr_accessor :gql_field_annotations do 6 {} 7 end 8 9

    stub_target_data( 10 resource: 'card', 11 id: 7890, 12 response_body: { 13 id: 7890, 14 bin: 1111, 15 names_on_card:'Shawnee Gao', 16 postal_code: 94114, 17 payment_id: 1234 18 } 19 ) 20 21 def self._fetch_target_data(id) 22 target_data = CardClient.get_by_id(id) 23 OpenStruct.new(target_data) 24 end . . . 40 41 def payment_id 42 target_data.payment_id 43 end 44 45 annotate_field "Types::PaymentType", null: false, definition: 46 def payment 47 @payment ||= Payment.lookup(payment_id) 48 end 49 end
  114. Payment - id - amount - merchant_id Merchant - id

    - store_name Today’s Data Model Card - id - name_on_card - bin - payment_id
  115. Payment - id - amount - merchant_id - card_id Merchant

    - id - store_name Today’s Data Model Is associated through merchant_id Card - id - name_on_card - bin associated through payment_id
  116. 1 module Types 2 class QueryType < Types::BaseObject 4 gql_type_generator

    = GqlTypeGenerator.new(Target.all_target_classes) . . . 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym 16 field field_name, gql_type, null: false do 17 argument :id, ID, required: true 18 end 24 end 25 end 26 end 27
  117. 1 module Types 2 class QueryType < Types::BaseObject 4 gql_type_generator

    = GqlTypeGenerator.new(Target.all_target_classes) . . . 12 valid_root_types_target_classes = [Payment, Merchant] 13 gql_type_generator 14 .target_to_gql_class_mapping.each do |target, gql_type| 15 field_name = target.to_s.downcase.to_sym 16 field field_name, gql_type, null: false do 17 argument :id, ID, required: true 18 end 24 end 25 end 26 end 27
  118. 1 module Types 2 class QueryType < Types::BaseObject 4 gql_type_generator

    = GqlTypeGenerator.new(Target.all_target_classes) . . . 12 valid_root_type_targets = [Payment, Merchant] 13 valid_root_type_targets.each do |target| 14 gql_type_class = gql_type_generator.target_to_gql_class_mapping[target] 15 field_name = target.to_s.downcase.to_sym 16 field field_name, gql_type, null: false do 17 argument :id, ID, required: true 18 end 24 end 25 end 26 end 27
  119. 1 require 'spec_helper' 2 3 describe "GqlTypeGenerator#initialize" do 4 it

    'creates a Target Class to GqlType Class mapping' do 5 all_target_classes = Target.all_target_classes 6 all_target_classes.each do |target_class| 7 expect{ "Types::#{target_class.to_s}Type".constantize }.to raise_error(NameError) 8 end 9 10 util = GqlTypeGenerator.new(all_target_classes) 11 12 all_target_classes.each do |target_class| 13 gql_type_class_name = "Types::#{target_class.to_s}Type".constantize 14 expect(gql_type_class_name).to be_instance_of Class 15 util.target_to_gql_class_mapping[target_class] = gql_type_class_name 16 end 17 end 18 end
  120. 1 require 'spec_helper' 2 3 describe "GqlTypeGenerator#initialize" do 4 it

    'creates a Target Class to GqlType Class mapping' do 5 all_target_classes = Target.all_target_classes 6 all_target_classes.each do |target_class| expect{ "Types::#{target_class.to_s}Type".constantize }.to raise_error(NameError) 8 end 9 10 util = GqlTypeGenerator.new(all_target_classes) 11 12 all_target_classes.each do |target_class| 13 gql_type_class_name = "Types::#{target_class.to_s}Type".constantize 14 expect(gql_type_class_name).to be_instance_of Class 15 util.target_to_gql_class_mapping[target_class] = gql_type_class_name 16 end 17 end 18 end
  121. 1 require 'spec_helper' 2 3 describe "GqlTypeGenerator#initialize" do 4 it

    'creates a Target Class to GqlType Class mapping' do 5 all_target_classes = Target.all_target_classes 6 all_target_classes.each do |target_class| 7 expect{ "Types::#{target_class.to_s}Type".constantize }.to raise_error(NameError) 8 end 9 10 util = GqlTypeGenerator.new(all_target_classes) 11 12 all_target_classes.each do |target_class| 13 gql_type_class_name = "Types::#{target_class.to_s}Type".constantize 14 expect(gql_type_class_name).to be_instance_of Class 15 util.target_to_gql_class_mapping[target_class] = gql_type_class_name 16 end 17 end 18 end
  122. 1 require 'spec_helper' 2 3 describe "GqlTypeGenerator#initialize" do 4 it

    'creates a Target Class to GqlType Class mapping' do 5 all_target_classes = Target.all_target_classes 6 all_target_classes.each do |target_class| 7 expect{ "Types::#{target_class.to_s}Type".constantize }.to raise_error(NameError) 8 end 9 10 gql_type_generator = GqlTypeGenerator.new(all_target_classes) 11 12 all_target_classes.each do |target_class| 13 gql_type_class_name = "Types::#{target_class.to_s}Type".constantize 14 expect(gql_type_class_name).to be_instance_of Class 15 util.target_to_gql_class_mapping[target_class] = gql_type_class_name 16 end 17 end 18 end
  123. 1 require 'spec_helper' 2 3 describe "GqlTypeGenerator#initialize" do 4 it

    'creates a Target Class to GqlType Class mapping' do 5 all_target_classes = Target.all_target_classes 6 all_target_classes.each do |target_class| 7 expect{ "Types::#{target_class.to_s}Type".constantize }.to raise_error(NameError) 8 end 9 gql_type_generator = GqlTypeGenerator.new(all_target_classes) 11 12 all_target_classes.each do |target_class| 13 gql_type_class_name = "Types::#{target_class.to_s}Type".constantize 14 expect(gql_type_class_name).to be_instance_of Class 15 util.target_to_gql_class_mapping[target_class] = gql_type_class_name 16 end 17 end 18 end
  124. 1 require 'spec_helper' 2 3 describe "GqlTypeGenerator#initialize" do 4 it

    'creates a Target Class to GqlType Class mapping' do 5 all_target_classes = Target.all_target_classes 6 all_target_classes.each do |target_class| 7 expect{ "Types::#{target_class.to_s}Type".constantize }.to raise_error(NameError) 8 end 9 10 gql_type_generator = GqlTypeGenerator.new(all_target_classes) 11 12 all_target_classes.each do |target_class| 13 gql_type_class_name = "Types::#{target_class.to_s}Type".constantize 14 expect(gql_type_class_name).to be_instance_of Class 15 util.target_to_gql_class_mapping[target_class] = gql_type_class_name 16 end 17 end 18 end
  125. 1 require 'spec_helper' 2 3 describe "GqlTypeGenerator#initialize" do 4 it

    'creates a Target Class to GqlType Class mapping' do 5 all_target_classes = Target.all_target_classes 6 all_target_classes.each do |target_class| 7 expect{ "Types::#{target_class.to_s}Type".constantize }.to raise_error(NameError) 8 end 9 10 gql_type_generator = GqlTypeGenerator.new(all_target_classes) 11 12 all_target_classes.each do |target_class| 13 gql_type_class_name = "Types::#{target_class.to_s}Type".constantize 14 expect(gql_type_class_name).to be_instance_of Class 15 gql_type_generator.target_to_gql_class_mapping[target_class] = gql_type_class_name 16 end 17 end 18 end
  126. 1 require 'spec_helper' 2 3 describe "GqlTypeGenerator#initialize" do 4 it

    'creates a Target Class to GqlType Class mapping' do 5 all_target_classes = Target.all_target_classes 6 all_target_classes.each do |target_class| 7 expect{ "Types::#{target_class.to_s}Type".constantize }.to raise_error(NameError) 8 end 9 10 gql_type_generator = GqlTypeGenerator.new(all_target_classes) 11 12 all_target_classes.each do |target_class| 13 gql_type_class_name = "Types::#{target_class.to_s}Type".constantize expect(gql_type_class_name).to be_instance_of Class gql_type_generator.target_to_gql_class_mapping[target_class] = gql_type_class_name 16 end 17 end 18 end
  127. 1 require 'spec_helper' 2 . . . 19 20 describe

    "GqlTypeGenerator#add_annotated_target_fields_to_gql_type_class" do 21 it 'creates a GqlType Class from Target constant' do 22 Types::PaymentType = Class.new(Types::BaseObject) 26 Types::MerchantType = Class.new(Types::BaseObject) 27 annotated_target_fields_hash = Payment.gql_field_annotations.sort 29 30 GqlTypeGenerator 31 .add_annotated_target_fields_to_gql_type_class( 32 Payment, Types::PaymentType 33 ) 34 35 gql_type_fields_hash = 36 Types::PaymentType.instance_variable_get(:@own_fields) 37 .sort.to_h.symbolize_keys 40 41 annotated_target_fields_hash.each do |field_name, field_definition| 42 expect(gql_type_fields_hash[field_name] 43 .instance_variable_get(:@return_type_expr)) 44 .to eq(field_definition[:type].constantize) 45 46 expect(gql_type_fields_hash[field_name] 47 .instance_variable_get(:@return_type_null)) 48 .to eq(field_definition[:null]) 49 end 50 51 end 52 end
  128. 1 require 'spec_helper' 2 . . . 19 20 describe

    "GqlTypeGenerator#add_annotated_target_fields_to_gql_type_class" do 21 it 'creates a GqlType Class from Target constant' do 22 Types::PaymentType = Class.new(Types::BaseObject) 26 Types::MerchantType = Class.new(Types::BaseObject) 27 annotated_target_fields_hash = Payment.gql_field_annotations.sort 29 30 GqlTypeGenerator 31 .add_annotated_target_fields_to_gql_type_class( 32 Payment, Types::PaymentType 33 ) 34 35 gql_type_fields_hash = 36 Types::PaymentType.instance_variable_get(:@own_fields) 37 .sort.to_h.symbolize_keys 40 41 annotated_target_fields_hash.each do |field_name, field_definition| 42 expect(gql_type_fields_hash[field_name] 43 .instance_variable_get(:@return_type_expr)) 44 .to eq(field_definition[:type].constantize) 45 46 expect(gql_type_fields_hash[field_name] 47 .instance_variable_get(:@return_type_null)) 48 .to eq(field_definition[:null]) 49 end 50 51 end 52 end
  129. 1 require 'spec_helper' 2 . . . 19 20 describe

    "GqlTypeGenerator#add_annotated_target_fields_to_gql_type_class" do 21 it 'creates a GqlType Class from Target constant' do 22 Types::PaymentType = Class.new(Types::BaseObject) 26 Types::MerchantType = Class.new(Types::BaseObject) 27 annotated_target_fields_hash = Payment.gql_field_annotations.sort 29 30 GqlTypeGenerator 31 .add_annotated_target_fields_to_gql_type_class( 32 Payment, Types::PaymentType 33 ) 34 35 gql_type_fields_hash = 36 Types::PaymentType.instance_variable_get(:@own_fields) 37 .sort.to_h.symbolize_keys 40 41 annotated_target_fields_hash.each do |field_name, field_definition| 42 expect(gql_type_fields_hash[field_name] 43 .instance_variable_get(:@return_type_expr)) 44 .to eq(field_definition[:type].constantize) 45 46 expect(gql_type_fields_hash[field_name] 47 .instance_variable_get(:@return_type_null)) 48 .to eq(field_definition[:null]) 49 end 50 51 end 52 end
  130. 1 require 'spec_helper' 2 . . . 19 20 describe

    "GqlTypeGenerator#add_annotated_target_fields_to_gql_type_class" do 21 it 'creates a GqlType Class from Target constant' do 22 Types::PaymentType = Class.new(Types::BaseObject) 26 Types::MerchantType = Class.new(Types::BaseObject) 27 annotated_target_fields_hash = Payment.gql_field_annotations.sort 29 30 GqlTypeGenerator 31 .add_annotated_target_fields_to_gql_type_class( 32 Payment, Types::PaymentType 33 ) 34 35 gql_type_fields_hash = 36 Types::PaymentType.instance_variable_get(:@own_fields) 37 .sort.to_h.symbolize_keys 40 41 annotated_target_fields_hash.each do |field_name, field_definition| 42 expect(gql_type_fields_hash[field_name] 43 .instance_variable_get(:@return_type_expr)) 44 .to eq(field_definition[:type].constantize) 45 46 expect(gql_type_fields_hash[field_name] 47 .instance_variable_get(:@return_type_null)) 48 .to eq(field_definition[:null]) 49 end 50 51 end 52 end