Rails HTTP - POST - ruby-on-rails

I am sending HTTP POST request:
data = { id: 1, name: 'ABC' }
uri = URI.parse('http://localhost:3000/events')
http = Net::HTTP.new(uri.host, uri.port)
http.post(uri, data.to_json)
My routes file:
Rails.application.routes.draw do
post '/events' => 'receiver#create'
end
Whereas create methods looks like:
def create
package = {
id: ,
name:
}
end
How can I get access to data values passing via request? My goal is to assign it to new hash within create method

You should set Content-Type header in your request as well:
http.post(uri, data.to_json, {"Content-Type" => "application/json", "Accept" => "application/json"})
Then you can use params[:id] and params[:data] in your controller.
def create
#package = {id: params.require(:id), data: params.require(:data)}
head :no_content
end
head :no_content will render empty reply (so you can create view later). And params.require will ensure that your parameters is provided (otherwise controller will return 400 Bad Request response) – so you won't receive some strange undefined method ... of nil errors later in case you missed params in your request.

Related

How to check if HTTP request status is 200 OK in Rails

I want to do something like this post but in the actual Rails app, not the testing.
I want to see if the HTTP request was successful or not. If it's not successful (aka 404 Not Found), then I want to render a different HTML. But I can't figure out the syntax to compare.
Currently, I have:
def videos
# get current_user's wistia_project_id & authorization token
#current_user = current_user
project_id = #current_user.wistia_project_id
auth_token = "blah"
request = "https://api.wistia.com/v1/projects/#{project_id}.json?api_password=#{auth_token}"
#response = HTTP.get(request).body
puts HTTP.get(request).status
# handle errors: not 200 OK
if !HTTP.get(request).status:
render "/errors.html.erb/"
end
# get embed code for each video using the hashed_id, put in list
#video_iframe_urls = JSON.parse(#response)['medias'].map do |p|
"https://fast.wistia.com/embed/iframe/#{p["hashed_id"]}?version=v1&controlsVisibleOnLoad=true&playerColor=aae3d8"
end
end
require 'net/http'
uri = URI("https://api.wistia.com/v1/projects/#{project_id}.json?api_password=#{auth_token}")
res = Net::HTTP.get_response(uri)
# Status
puts res.code # => '200'
puts res.message # => 'OK'
puts res.class.name # => 'HTTPOK'
# Body
puts res.body if res.response_body_permitted?

NoMethodError: undefined method `submission' for HTTParty

I'm currently working on a Rails application where I am trying to submit a form to the FormStack API. The request look as follows.
This is what the requests looks like:
POST /api/v2/form/12345/submission.json HTTP/1.1
Host: www.formstack.com
Authorization: Bearer YOUR_APP_OAUTH_TOKEN
Accept: application/json
Content-Type: application/json
field_12345=Example&field_12346=Answer
I'm trying to implement that using Httparty on the library I created to make the requests to this API service.
module FormStack
class Form
include HTTParty
attr_reader :form_id
base_uri "https://www.formstack.com/api/v2"
def initialize
#access_token = ENV.fetch('FORMSTACK_ACCESS_TOKEN')
#form_id = ENV.fetch('FORMSTACK_FORM_ID')
end
def create_form
self.class.get(relative_uri, headers: headers)
end
def submission
self.class.post(create_submission_uri, headers: headers, query: query)
end
private
def relative_uri
"/form/#{#form_id}/field.json"
end
def create_submission_uri
"form/#{#form_id}/submission.json"
end
def headers
{
"Accept" => "application/json",
"Content-Type" => "application/json",
"Authorization" => "Bearer #{#access_token}"
}
end
def query
{
"field_66563890" => "blah",
"field_66563757" => "something"
}
end
end
end
controller
class FormsController < ApplicationController
def display_form
#form = FormStack::Form.new().create_form
end
def create
#form.submission
redirect_to 'localhost:3000'
end
end
This are the routes
get '/forms/display_form', to: 'forms#display_form'
post '/forms/submit', to: "forms#create"
First of all, I've got a couple general ruby things for you:
When you call FormStack::Form.new().create_form you actually don't need the () after .new -- ruby knows to call the method with no arguments even if you exclude the parens.
I'm not quite sure how you're calling FormsController::display_form from FormsController::create, but for now I'll just assume that you're using magic.
Anyways, on to my answer. As your error message states, the error is related to you calling submission on something which does not have a submission method. With that knowledge, we can look at what Object you're calling submission on in this line:
#form.submission
It looks like you're calling submission on #form. Well, let's go and look at where you declare #form:
#form = FormStack::Form.new().create_form
Let's break that declaration down into its parts. First, with FormStack::Form.new(), you're creating a new instance of FormStack::Form. So far so good. FormStack::Form has a submission method defined on it. But then, you call create_form on it. So, let's look at what create_form does:
def create_form
self.class.get(relative_uri, headers: headers)
end
create_form calls a method provided by HTTParty, get. The get method returns a HTTParty::Response Object. So, let's parse through the line where you set #form again. Broken down, what you're doing is this:
#form = FormStack::Form # This line sets the variable to a constant
#form = #form.new # This line sets the variable to be an instance of FormStack::Form
#form = #form.create_form # This line sets #form to be an instance of HTTParty::Reponse
As you can see, at the end we've set #form to an instance of HTTParty::Reponse instead of FormStack::Form, and since there's not submission method for HTTParty::Response that's why you get the error.
Based on this exploration, we can see that the fix would be to set #form to a FormStack::Form object instead, which we can do by changing the display_form action to be:
def display_form
#form = FormStack::Form.new
#form.create_form
end

WebMock model's function when called via controller

I have existing functionality, where specs calls HTTP PUT method of a controller, which in-turn calls model's method to get some JSON data via. API.
class SomeModel
def GetData()
uri = URI.parse('http://api.mydomain.com/getmydata/123/ohmyurl')
Net::HTTP.start(uri.host, uri.port, :read_timeout => 200) do |http|
request = Net::HTTP::Get.new(uri.request_uri)
response = http.request(request)
unless response.body == "null"
return JSON.parse(response.body)
end
#......
end
end
end
class SomeController < ApplicationController
def update
#...
#model.GetData()
#...
end
end
#......specs............
put :update
I need to mock the API in SomeModel. So far I have tried:
#......specs............
before do
stub_request(:get, /api.mydomain.com/)
.with(headers: {'Accept'=>'application/json' })
.to_return(status: 200, body: {id: 1, secondParam: '324'}.to_json, headers: {})
end
#.......
put :update
result = JSON.load response.body
expect(result['secondParam']).to eq("324")
Which is not able to mock the API call and actual API is called.
kindly ignore syntax errors

Any alternative to redirect_to in rails api only application?

I would like to redirect to another url in rails controller action. like
def action_name
redirect_to url
end
I know i can do it simply using the above method. But i want to redirect in only one action in all my application. because of this i don't want to include this in controller.
include ActionController::Redirecting
is there any other way to redirect to a uri in api only applications. Thanks.
You can use respond_with which will respond with a appropriate response depending on the request type and the status of the model you pass to respond_with.
def create
#thing = Thing.create(thing_params)
respond_with(#thing)
end
This will give 201 - Created status and a location header if the the request is successful and a 422 - Unprocessable Entity if the validations fail.
Alternativly you can use head to send a header only response with no body.
def action_name
head :not_found, location: url
end
Note that :not_found could be any appropriate HTTP status.
If your using Rails API:
Route your path, and take the params, and return:
redirect_to controller: "client", action: "get_name", params: request.query_parameters and return

Rails controller is returning escaped JSON

def show
#find parent call_flow
#call_flow = CallFlow.where('dnis' => params[:dnis]).first
if #call_flow.nil?
#response = ["no result"]
else
#find first routable options (should be a message)
#call_flow_options = #call_flow.routable_type.constantize.find(#call_flow.routable_id).options
#if there is a route after the first route, find it
unless #call_flow_options.first.target_routable_type.nil?
#target_routable = #call_flow_options.first.target_routable_type.constantize.find(#call_flow_options.first.target_routable_id).options
#call_flow_options.to_a.push(#target_routable.to_a)
end
#response = #call_flow.to_a.push(#call_flow_options)
end
respond_with #response
end
I get the data back but the browser doesn't recognize it as JSON because all the " double quotes are replaced with ".
If you're looking to have the entire response be JSON (rather than HTML/JavaScript that uses JSON) you can do:
render :json => #response

Resources