I have two rails app, one is a graphql API and the other one is a REST API App as well.
Let's call the graphql app graphi
and the REST app resti
.
graphi sends data to resti.
resti then talk's to an external API, get's a response from that external API, and talks back to graphi with a nice response.
Ok, so graphi has a mutation called vendor. which can look like this:
mutation {
createVendor(
input: {
vendorId: 2,
quoteType: "renter",
renterData: {
firstName: "Tony",
lastName: "Stark",
email: "tony@starkindustries",
phoneType: "mobile",
phone: "6504881234",
requestType: "renter",
address1: "123 Main Street",
addressCity: "Palo Alto",
addressState: "CA",
addressZip: "94301",
dob: "1990-07-22"
}
}
)
}
Then I send this data through httparty like this on the create_vendor.rb (mutation file)
:
class CreateVendor < Mutations::BaseMutation
description 'Create a vendor'
argument :vendor_id, ID, required: false
argument :quote_type, String, required: true
argument :renter_data, Types::RenterVendorType, required: false
field :vendor, Types::VendorType, null: false
def resolve(args)
response = HTTParty.post(
'http://localhost:3001/api/v2/vendor', <-- this sends data to resti
body: JSON.parse(args.to_json),
headers: AUTHORIZATION_HEADERS
)
if response.success?
puts "Cool, I was successfull"
else
puts "I wasn't successful"
end
end
end
Once graphi sends data to resti, resti server looks like this:
Processing by Api::V2::VendorController#create as */*
Parameters: {"vendor_id"=>"2", "quote_type"=>"renter", "renter_data"=>{"first_name"=>"Tony", "last_name"=>"Stark", "email"=>"tony@starkindustries", "phone_type"=>"mobile", "phone"=>"6504881234", "request_type"=>"renter", "address1"=>"123 Main Street", "address_city"=>"Palo Alto", "address_state"=>"CA", "address_zip"=>"94301", "dob"=>"1990-07-22"}}
Now, this isn't graphql stuff anymore, this passes to be a hash with one nested parameter.
On resti's controller I have something like to to permit vendor params
def create_vendor_params
params.require(:vendor).permit(
:vendor_id, :quote_type, renter_data: %i[first_name last_name email phone_type phone request_type address1 address_city address_state address_zip DOB]
)
end
THE PROBLEM
When I go through this flow I recieve this issue on the resti server:
ActionController::ParameterMissing (param is missing or the value is empty: vendor
Did you mean? vendor_id
renter_data
action
quote_type):
And when I test this exact same thing on Postman using this data structure:
{ "vendor": {
"vendor_id": 2,
"quote_type": "renter",
"renter_data": {
"first_name":"Tony",
"last_name":"Stark",
"email":"[email protected]",
"phone_type":"mobile",
"phone":"6504881234",
"request_type":"renter",
"address1":"123 Main Street",
"address_city":"Palo Alto",
"address_state":"CA",
"address_zip":"94301",
"DOB":"1990-07-22"
}
}
}
I recieve this below:
#<ActionController::Parameters {"vendor"=>#<ActionController::Parameters (#<ActionController::Parameters this piece of code is ruining everything,) {"_id"=>2, "quote_type"=>"renter", "renter_data"=>{"first_name"=>"Tony", "last_name"=>"Stark", "email"=>"[email protected]", "phone_type"=>"mobile", "phone"=>"6504881234", "request_type"=>"renter", "address1"=>"123 Main Street", "address_city"=>"Palo Alto", "address_state"=>"CA", "address_zip"=>"94301", "DOB"=>"1990-07-22"}} permitted: false>, "controller"=>"api/v2/vendor", "action"=>"create"} permitted: false>
Now there's something I can't understand why this happens. When I byebug
on this piece of code:
def create_vendor_params
params.require(:vendor).permit(
:vendor_id, :quote_type, renter_data: %i[first_name last_name email phone_type phone request_type address1 address_city address_state address_zip DOB]
)
byebug
end
And I manually do this:
(byebug) params.require(:vendor).permit(
:vendor_id, :quote_type, renter_data: %i[first_name last_name email phone_type phone request_type address1 address_city address_state address_zip DOB]
)
it prints out this:
#<ActionController::Parameters {"vendor_id"=>2, "quote_type"=>"renter", "renter_data"=>#<ActionController::Parameters {"first_name"=>"Tony", "last_name"=>"Stark", "email"=>"[email protected]", "phone_type"=>"mobile", "phone"=>"6504881234", "request_type"=>"renter", "address1"=>"123 Main Street", "address_city"=>"Palo Alto", "address_state"=>"CA", "address_zip"=>"94301", "DOB"=>"1990-07-22"} permitted: true>} permitted: true>
It get's permitted!!
Why is this happening? How does graphql structure data? I will really appreciate your help!
CodePudding user response:
The params you sent to resti
don't have the right shape. If you look closely the params aren't nested under a vendor
as they were when you sent them through Postman.
Your mutation should have the following structure mutation
createVendor(
input: {
vendor: {
vendorId: 2,
quoteType: "renter",
renterData: {
firstName: "Tony",
lastName: "Stark",
email: "tony@starkindustries",
phoneType: "mobile",
phone: "6504881234",
requestType: "renter",
address1: "123 Main Street",
addressCity: "Palo Alto",
addressState: "CA",
addressZip: "94301",
dob: "1990-07-22"
}
}
}
)