Using Grape to build a Rails API but having issues posting JSON - ruby-on-rails

Here is my API post:
resource :service_requests do
get do
authenticate!
current_company.service_requests
end
params do
requires :service_request, type: Hash do
optional :prefix, type: String
requires :first_name, type: String
requires :last_name, type: String
requires :contact_email, type: String, regexp: User::EMAIL_REGEX
requires :telephone, type: String
end
end
post do
authenticate!
{ service_request: params[:service_request] }
end
end
Here is what my json post looks like:
{
'service_request': {
'first_name': 'Foo',
'last_name': 'Bar',
'contact_email': 'foo#bar.com',
'telephone': '111-111-1111'
}
}
The error I am receiving is:
ActionDispatch::ParamsParser::ParseError (795: unexpected token at '{
'service_request': {
'first_name': 'Foo',
'last_name': 'Bar',
'contact_email': 'foo#bar.com',
'telephone': '111-111-1111'
}
}'):
Not sure what I am doing wrong. Anyone see anything that stands out?

Use double quotes in your json:
{
"service_request": {
"first_name": "Foo",
"last_name": "Bar",
"contact_email": "foo#bar.com",
"telephone": "111-111-1111"
}
}

Related

How create with rswag following the json api specification?

I didn't find any examples of how to use rswag to generate documentation according to json api.
spec/integration/pets_spec.rb
require 'swagger_helper'
It is possible to change the code to generate the format of json api?
describe 'Pets API' do
path '/api/v1/pets' do
post 'Creates a pet' do
tags 'Pets'
consumes 'application/json', 'application/xml'
parameter name: :pet, in: :body, schema: {
type: :object,
properties: {
name: { type: :string },
photo_url: { type: :string },
status: { type: :string }
},
required: [ 'name', 'status' ]
}
response '201', 'pet created' do
let(:pet) { { name: 'Dodo', status: 'available' } }
run_test!
end
response '422', 'invalid request' do
let(:pet) { { name: 'foo' } }
run_test!
end
end
end
path '/api/v1/pets/{id}' do
get 'Retrieves a pet' do
tags 'Pets'
produces 'application/json', 'application/xml'
parameter name: :id, :in => :path, :type => :string
response '200', 'name found' do
schema type: :object,
properties: {
id: { type: :integer, },
name: { type: :string },
photo_url: { type: :string },
status: { type: :string }
},
required: [ 'id', 'name', 'status' ]
let(:id) { Pet.create(name: 'foo', status: 'bar', photo_url: 'http://example.com/avatar.jpg').id }
run_test!
end
response '404', 'pet not found' do
let(:id) { 'invalid' }
run_test!
end
end
end
end
If rswag what tips would you give me?
You need to change the swagger_helper.rb file. Change the file format to JSON. I have attached the screenshot for that one below:
https://i.stack.imgur.com/MzOR9.png

rswag gem does not recognize my parameters in rspec

when running RSpec, in the action of controller,(use byebug or pry)
the specific value like (email or password) did not exist in the request parameters,
and so the result of the test become failed
for more details, see my below code
path '/api/v1/admin/authentications/sign_in' do
post('admin sign_in') do
produces 'application/json'
parameter name: :params, in: :body, schema: {
type: :object,
properties: {
email: { type: :string },
password: { type: :string }
},
required: %w[email password]
}
let(:admin) { create(:admin) }
response('200', 'sign in successfully') do
let(:params) { { email: admin.email, password: '***' } }
run_test!
end
end
end
add consume type for your request:
consumes 'application/json'
I also had the same problem with the latest version of gem rswag. You can change the version of gem to "1.6" to fix it

rails gem rswag custom parameter

How do I add a custom parameter in my rswag-specification?
Rswag seems to consumate only parameters which exists as fields
but I need to add a custom parameter. So whatever I do - I can see in controllers params only fields of my model.
RSpec.describe Api::V1::LogsController, type: :request do
path '/api/v1/logs' do
post 'Create a Log' do
tags 'Logs'
security [ApiKeyAuth: {}]
consumes 'application/json'
produces 'application/json'
parameter name: :log, in: :body, schema: {
type: :object,
properties: {
title: { type: :string },
description: { type: :string },
my_custom_parameter: { type: :string }
},
required: %w(title description user_phone_number),
}
response '200', 'New Log created' do
let(:Authorization) { "Token token=#{company.api_key}" }
run_test!
end
end
end
end
you can add any parameters with any name that you liked,
and then you can give values to those parameters in the response block like below:
parameter name: :params, in: :body, schema: {
type: :object,
properties: {
profile_attributes: {
type: :object,
properties: {
email: { type: :string, example: Faker::Internet.email(Faker::Name.first_name) }
},
required: %w[email]
}
response('201', 'successfully') do
let(:params) do
{
profile_attributes: { email: Faker::Internet.email(Faker::Name.first_name) }
}
end

Ruby JSON API and post request with Postman

I'm using postman to make post request to my rails/grape API
Here is the json object
{
"customer":{
"first_name":"Joe",
"last_name":"Doe",
"email":"test#test.com",
"phone":"999-999-9999",
"addresses_attributes":[{
"address":{
"address1":"123 somewhere st",
"customer_id":"",
"address2":"",
"city":"Moldor",
"state":"CA",
"zip":"99999",
"region_id":"1"
}
}]
}
}
If send this to a api/v1/customers.json
I get the following error message
"error": "first_name is missing, last_name is missing, email is missing, phone is missing",
If I change the JSON format to:
{
"first_name":"Joe",
"last_name":"Doe",
"email":"test#test.com",
"phone":"999-999-9999",
"addresses_attributes":[{
"address":{
"address1":"123 somewhere st",
"customer_id":"",
"address2":"",
"city":"Moldor",
"state":"CA",
"zip":"99999",
"region_id":"1"
}
}]
}
I does creates the customer but it does not creates the address
In my Models I have
#customer.br
has_many :addresses
accepts_nested_attributes_for :addresses, allow_destroy: true
#address.rb
belongs_to :customer
Here is the api/vi/curtomer.rb
desc "Create a Customer"
params do
requires :first_name, type: String, desc: "First Name"
requires :last_name, type: String, desc: "Last Name"
requires :email, type: String, desc: "Email"
requires :phone, type: String, desc: "Phone"
optional :notes, type: String, desc: "Notes"
end
post do
# Tried with new instead of create
# test = Customer.new({
# first_name: params[:first_name],
# last_name: params[:last_name],
# email: params[:email],
# phone: params[:phone],
# notes: params[:notes],
# addresses_attributes: params[:addresses]
# })
Customer.create({
first_name: params[:first_name],
last_name: params[:last_name],
email: params[:email],
phone: params[:phone],
notes: params[:notes]
# addresses_attributes: params[:addresses]
})
end
The address looks pretty much the same as the customers
I'm not using controllers per Grapes Documentation
EDIT: to add customer.rb create code
Think your json data should be:
{ "customer":
{
"first_name":"Joe",
"last_name":"Doe",
"email":"test#test.com",
"phone":"999-999-9999",
"addresses_attributes":[{
"address1":"123 somewhere st",
"customer_id":"",
"address2":"",
"city":"Moldor",
"state":"CA",
"zip":"99999",
"region_id":"1"
}]
}
}
Refer to this example.
If it not works, show your controller code.

Grape API in Rails and issues with Strong Parameters

Here is what my API looks like
resource :service_requests do
before do
error!('Unauthorized. Invalid token', 401) unless current_company
end
get do
current_company.service_requests
end
params do
requires :service_request, type: Hash do
optional :prefix, type: String
requires :first_name, type: String
requires :last_name, type: String
requires :contact_email, type: String, regexp: User::EMAIL_REGEX
requires :phone_number, type: String
requires :address, type: String
optional :address2, type: String
requires :city, type: String
requires :state, type: String
requires :zip_code, type: String
requires :country, type: String
requires :address_type, type: String
requires :troubleshooting_reference, type: String
requires :line_items, type: Array do
requires :type, type: String
requires :model_number, type: String
requires :serial_number, type: String
optional :additional_information, type: String
end
end
end
post do
parameters = ActionController::Parameters.new(params).require(:service_request)
sr = ServiceRequest.new(
parameters.permit(
:troubleshooting_reference,
:rma,
:additional_information
)
)
sr.build_customer(
parameters.permit(
:prefix,
:first_name,
:last_name,
:contact_email,
:phone_number
)
)
#
# shipping_info = customer.build_shipping_information(
# parameters.permit(
# :address,
# :address2,
# :company_name,
# :city,
# :state,
# :zip_code,
# :country,
# :address_type
# )
# )
if sr.save
sr
else
sr.errors.full_messages
end
end
end
The problem I am running into is that when the save method is called, I am getting this error Unpermitted parameters: first_name, last_name, contact_email, phone_number, address, city, state, zip_code, country, address_type, line_items
Here is what my JSON post looks like:
{
"service_request": {
"first_name": "Foo",
"last_name": "Bar",
"contact_email": "foo#bar.com",
"phone_number": "111-111-1111",
"address": "102 foo st",
"city": "Nashville",
"state": "TN",
"zip_code": "23233",
"country": "USA",
"address_type": "Business",
"troubleshooting_reference": "dshjf",
"line_items": [
{
"type": "Unit",
"model_number": "123",
"serial_number": "222"
}
]
}
}
Having tried your code locally, I think what you're seeing is normal behaviour. I, too see the "Unpermitted parameters..." messages logged to the console, but the calls to parameters.permit do succeed and return filtered hashes as you expect. So I think if you check you'll find your code is actually working.
You can silence those messages by adding
ActionController::Parameters.action_on_unpermitted_parameters = false
either at the top of your class or in a file under config/initializers.

Resources