Home > Software engineering >  Understanding Rails Params Graphql Mutation interaction
Understanding Rails Params Graphql Mutation interaction

Time:06-04

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.

  1. graphi sends data to resti.

  2. 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"
        }
      }
    }
  )
  • Related