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
Related
I'm new to Ruby, trying to building an API.
I've followed a tutorial and was able to return a JSON response when calling an API endpoint.
In this example, the function called raises an error that I want to pass as a JSON response.
my_controller.rb
class MyController < ApplicationController
def getTracklist
begin
importer = #this raises an error
rescue StandardError => e
#response = {
error: e.message,
}
return #response
end
end
end
my view look like this :
getTracklist.json.jbuilder
json.response #response
thing is,
this works but renders my response as
{"response":{"error":"the error message"}}
while I want it as
{"error":"the error message"}
I made an attempts by changing my view to
json #response
but it fails :
ActionView::Template::Error (undefined method `json' for
<#:0x0000559304675470> Did you mean? JSON):
1: json #response
So how could I render my response "fully" without having to put it in a property ?
I've also seen when reading stuff about ROR that this code is sometimes used, and I was wondering how I could use it in this situation :
render json: { error_code:'not_found', error: e.message }, status: :not_found
Thanks !
There are multiple ways of achieving what you want. You could merge! the response into the jbuilder root.
json.merge! #response
The above merges all key/value-pairs into the jbuilder root. You could also opt to extract! specific attributes.
json.extract! #response, :error
Alternatively you can simply render it in the controller, since you've already composed the structure the following would be enough.
render json: #response
You can do this for jBuilder:
json.merge!(#response)
Source
class MyController < ApplicationController
def getTracklist
begin
# you need to assign something to a variable
rescue StandardError => e
respond_to do |format|
format.any(:json, :js) do
render :json => {:error => e.message}
end
end
end
end
end
Making these changes to your controller can help you with your requirements.
You don't need a view after doing this.
I'm using an ActiveAdmin custom page and httparty to request a json response from a third-party api. I've successfully accessed the json data response, parsed it, set it to a variable, and used puts to see it in my console.
How can I access this variable to view it on an activeadmin page?
Here's my activeadmin page:
ActiveAdmin.register_page "API" do
content do
response = HTTParty.get("http://www.omdbapi.com/?s=war&apikey=#####")
res = response.body
result = JSON.parse res
#title = result["Search"][0]["Title"]
puts #title
end
controller do
# response = HTTParty.get("http://www.omdbapi.com/?s=war&apikey=#####")
# res = response.body
# result = JSON.parse res
# #title = result ["Search"][0]["Title"]
# puts #title
end
end
What I've tried:
*capturing JSON data from api works in either the content or controller block.
using a partial to render embedded ruby: <%= #title %>
capturing json data in controller and display #title in content area
text_node instead of puts should work here, see https://activeadmin.info/12-arbre-components.html
I am trying to set up an example Twilio Rails project that calls a person. I am following the tutorial associated with this repo and have basically a carbon copy of the codebase. I'm getting an error that I think is from this line #validator = Twilio::Util::RequestValidator.new(##twilio_token).
Here's my twilio_controller.rb
class TwilioController < ApplicationController
# Before we allow the incoming request to connect, verify
# that it is a Twilio request
skip_before_action :verify_authenticity_token
before_action :authenticate_twilio_request, :only => [
:connect
]
##twilio_sid = ENV['TWILIO_ACCOUNT_SID']
##twilio_token = ENV['TWILIO_AUTH_TOKEN']
##twilio_number = ENV['TWILIO_NUMBER']
##api_host = ENV['TWILIO_HOST']
# Render home page
def index
render 'index'
end
def voice
response = Twilio::TwiML::Response.new do |r|
r.Say "Yay! You're on Rails!", voice: "alice"
r.Sms "Well done building your first Twilio on Rails 5 app!"
end
render :xml => response.to_xml
end
# Handle a POST from our web form and connect a call via REST API
def call
contact = Contact.new
contact.user_phone = params[:userPhone]
contact.sales_phone = params[:salesPhone]
# Validate contact
if contact.valid?
#client = Twilio::REST::Client.new ##twilio_sid, ##twilio_token
# Connect an outbound call to the number submitted
#call = #client.calls.create(
:from => ##twilio_number,
:to => contact.user_phone,
:url => "#{##api_host}/connect/#{contact.encoded_sales_phone}" # Fetch instructions from this URL when the call connects
)
# Let's respond to the ajax call with some positive reinforcement
#msg = { :message => 'Phone call incoming!', :status => 'ok' }
else
# Oops there was an error, lets return the validation errors
#msg = { :message => contact.errors.full_messages, :status => 'ok' }
end
respond_to do |format|
format.json { render :json => #msg }
end
end
# This URL contains instructions for the call that is connected with a lead
# that is using the web form.
def connect
# Our response to this request will be an XML document in the "TwiML"
# format. Our Ruby library provides a helper for generating one
# of these documents
response = Twilio::TwiML::Response.new do |r|
r.Say 'FUCK.', :voice => 'alice'
# r.Dial params[:sales_number]
end
render text: response.text
end
# Authenticate that all requests to our public-facing TwiML pages are
# coming from Twilio. Adapted from the example at
# http://twilio-ruby.readthedocs.org/en/latest/usage/validation.html
# Read more on Twilio Security at https://www.twilio.com/docs/security
private
def authenticate_twilio_request
twilio_signature = request.headers['HTTP_X_TWILIO_SIGNATURE']
# Helper from twilio-ruby to validate requests.
#validator = Twilio::Util::RequestValidator.new(##twilio_token)
# the POST variables attached to the request (eg "From", "To")
# Twilio requests only accept lowercase letters. So scrub here:
post_vars = params.reject {|k, v| k.downcase == k}
is_twilio_req = #validator.validate(request.url, post_vars, twilio_signature)
unless is_twilio_req
render :xml => (Twilio::TwiML::Response.new {|r| r.Hangup}).text, :status => :unauthorized
false
end
end
end
Error image:
I am using ruby 2.4.1p111 (2017-03-22 revision 58053) [x86_64-darwin15] and Rails 5.1.0.
Your code is most likely failing at is_twilio_req = #validator.validate(request.url, post_vars, twilio_signature) because upon inspection of the gem's code, it is failing at sort below
data = url + params.sort.join
This is because in Rails 5.1, ActionController::Parameters no longer inherits from Hash, so Hash methods like sort (see Hash docs) will no longer work.
You will need to convert params into hash explicitly:
def authenticate_twilio_request
twilio_signature = request.headers['HTTP_X_TWILIO_SIGNATURE']
#validator = Twilio::Util::RequestValidator.new(##twilio_token)
# convert `params` which is an `ActionController::Parameters` object into `Hash`
# you will need `permit!` to strong-params-permit EVERYTHING so that they will be included in the converted `Hash` (you don't need to specifically whitelist specific parameters for now as the params are used by the Twilio gem)
params_hash = params.permit!.to_hash
post_vars = params_hash.reject {|k, v| k.downcase == k}
is_twilio_req = #validator.validate(request.url, post_vars, twilio_signature)
unless is_twilio_req
render :xml => (Twilio::TwiML::Response.new {|r| r.Hangup}).text, :status => :unauthorized
false
end
end
I am trying to learn and write an update API and to start small I am passing a single params in the API and and try to get the response.
the controller :
module Api
module V1
class OrderApiController < ApiController
def order_update
response = Hash.new
result = Hash.new
#order = Order.find(params[:id])
if #order.update_attributes(order_params)
result['order_id'] = order.id
response['result'] = result
response.merge! ApiStatusList::OK
else
response.merge! ApiStatusList::INVALID_REQUEST
end
render :json => response
end
private
def order_params
params.require(:order).permit( :id)
end
end
end
end
the api route in routes.rb is:
match 'mobile/order_update' =>'order_api#order_update'
The url link what I give is
http://localhost:3000/api/v1/mobile/order_update?key=docket&id=1
However this throws the following error
ActionController::ParameterMissing at /api/v1/mobile/order_update
param is missing or the value is empty: order
I dont know what am I doing wrong. I am new to Rails as well as API generation. Please help
This is caused by the order_params method, in which you're requiring order(expecting order to be a nested hash), whereas, you're not nesting it.
An approach you could take is to visit:
http://localhost:3000/api/v1/mobile/order_update?key=docket&order[id]=1
Also, I see you're setting #order instance variable, but in your control block(if #order.update_attributes), you're using a local variable which would give you another error.
I'd recommend you go through the Hartl Tutorial as there are a lot of things you'd be able to learn from there
UPDATE
Based on the new error mentioned in the comment, I think you should rather be visiting:
http://localhost:3000/api/v1/mobile/order_update?order[key]=docket&id=1
This is assuming your orders table has a column key based on the params being set
Also, change your order_params to:
private
def order_params
params.require(:order).permit( :key) #since you cannot update a primary key, but I guess you want to update the key column
end
The solution I used is as follows
In my order_api_controller.rb , I have Changed
def order_update
response = Hash.new
result = Hash.new
#order = Order.find(params[:id])
if #order.update_attributes(order_params)
result['order_id'] = order.id
response['result'] = result
response.merge! ApiStatusList::OK
else
response.merge! ApiStatusList::INVALID_REQUEST
end
render :json => response
end
and edited it to this
def order_update
response = Hash.new
result = Hash.new
debugger
#order = Order.find(params[:order][:id]) # passed the order symbol into params
if #order.update_attributes(order_params)
result['order_id'] = #order.id # Modified local variable to instance variable as per oreoluwa's suggestion
response['result'] = result
response.merge! ApiStatusList::OK
else
response.merge! ApiStatusList::INVALID_REQUEST
end
render :json => response
end
And used the url as Follows
http://localhost:3000/api/v1/mobile/order_update?key=docket&order[id]=1
This seems to do the trick
I want to send a request via Viralheat's API in my controller's update method so that when a user hits the submit button, an action is completed and the API call is made. I want to post to http://www.viralheat.com/api/sentiment/review.json?text=i&do¬&like&this&api_key=[* your api key *]
This will return some JSON in the format:
{"mood":"negative","prob":0.773171679917001,"text":"i do not like this"}
Is it possible to make that API call simultaneously while executing the controller method and how would I handle the JSON response? Which controller method would I put it in?
Ultimately I'd like to save the response mood to my sentiment column in a BrandUsers table. Submit is in main.html.erb which then uses the update method.
Controller
def update
#brand = Brand.find(params[:id])
current_user.tag(#brand, :with => params[:brand][:tag_list], :on => :tags)
if #brand.update_attributes(params[:brand])
redirect_to :root, :notice => "Brand tagged."
else
render :action => 'edit'
end
end
def main
#brands = Brand.all
if current_user
#brand = current_user.brands.not_tagged_by_user(current_user).order("RANDOM()").first
end
With the wrest gem installed, you could do something like
params[:api_key] = "your key"
url = "http://www.viralheat.com/api/sentiment/review.json"
response = url.to_uri.get(params).deserialize
response would contain the json already turned into a hash. So you can access the mood with
response[:mood]