Geojson data format output properly in a rails app - ruby-on-rails

i m trying to implement a service that displays data in geojson format.
I hit my database with this :
sql =
"select ST_AsGeoJSON(boundaries)
from cluster_shapes
where category = '#{params[:category]}'
and area_id =
(select id
from areas
where name = '#{params[:city]}' )"
connection = ActiveRecord::Base.connection
#clusters = ActiveRecord::Base.connection.execute(sql)
respond_to do |format|
format.json { render json: #clusters }
end
And I get ugly results that is not valid geojson
[
{
st_asgeojson: "{"type":"Polygon","coordinates":[[[23.819537,38.039409],[23.81892,38.04068],...}"
,
st_asgeojson: "{"type":"Polygon","coordinates":[[[23.919537,38.039409],[22.81892,38.04068],...}"
,
...
If I remove the ugly part st_asgeojson and make it look like this , it is valid geojson.
{"type":"Polygon","coordinates":[[[23.819537,38.039409],[23.81892,38.04068],[23.820912,38.040237],[23.8209752169298,38.0400047630785],[23.8209519774174,38.0399755885062],[23.8205266,38.0394558],[23.819537,38.039409]]]}
So the question is how do i get rid of "st_asgeojson" ,or am i doing it wrong ?
PS:A model exist, if query is modified the result is pretty the same.

It seems like what you want is simply nested inside your #clusters json, so you can simply parse it out...
instead of:
format.json { render json: #clusters }
you should change it to
format.json { render json: #clusters[0].st_asgeojson }
Or if you are expecting more than one result to be returned from you sql query, try
format.json { render json: #clusters.map {|x| x.st_asgeojson }}

Related

Parse Json Request from CURL in Rails

I need to parse Json data from curl request.Need to split Mac,Parameter,datatype,value from below curl request and pass those data's as input for set method(For each Mac separately).Can anyone please guide how to split?
curl -k -s -H "Content-Type: application/json" -d '{"Data": {"Mac":"10.43.33.34","Parameter":"Device.wifi","datatype":"string","value":"5Ghz"},{"Mac":"15.23.43.48","Parameter":"Device.wifi","datatype":"string","value":"2.4GHZ"}}' http://test:3000/api/executions_api_set/
Set API
def show
client = SetClient.new
versionResponse = client.set_req(mac,parameter,datatype,value)
if versionResponse.code == "200"
value = JSON.parse(versionResponse.body)
render json: {Mac: mac,Response:value}, status: :ok
else
render json: {Mac: mac,Parameter: parameter,status: 'Failed',responsecode:versionResponse.code}, status: :ok
end
end
end
end
end
Updated Code
def create
value = ''
client = SetClient.new
params["Data"].each do |mac_attributes|
#mac_address, #Parameter, #dataType, #value = mac_attributes.values_at("Mac", "Parameter", "datatype", "value")
#versionResponse = client.set_req_api(#mac_address,#Parameter,#dataType,#value)
puts "versionResponse.status_code #{#versionResponse.code}"
end
if #versionResponse.code == "200"
value = JSON.parse(#versionResponse.body)
render json: {Mac_address: #mac_address,Response:value}, status: :ok
else
render json: {Mac_address: #mac_address,Parameter:#Parameter,status: 'Failed',responsecode:#versionResponse.code}, status: :ok
end
end
end
end
I'm not entirely sure what you're trying to do, but if you want the controller to call a method for each JSON object in the array, it would look something like:
def show
params["Data"].each do |hash_of_mac_attributes|
mac, parameter, datatype, value = hash_of_mac_attributes.values_at("Mac", "Parameter", "datatype", "value")
method_you_want_to_call(mac, parameter, datatype, value)
end
This is assuming that rails is correctly detecting and parsing the JSON body into the params hash for you. If it's not, that's a separate issue that can be addressed.
UPDATE
In order to return the result from each call to the external service we need to store each call in an array and render the array in the response. Something like the following:
def show
json_array = params["Data"].map do |hash_of_mac_attributes|
mac, parameter, datatype, value = hash_of_mac_attributes.values_at("Mac", "Parameter", "datatype", "value")
response = client.set_req_api(mac, parameter, datatype, value)
build_json_for_mac_lookup(response: response, mac: mac, parameter: parameter)
end
render json: json_array
end
def build_json_for_mac_lookup(arguments:, mac:, parameter:)
json_body = {Mac_address: mac}
if response.code == "200"
json_body.merge(Response: JSON.parse(response.body))
else
json_body.merge(Parameter: parameter, status: 'Failed', responsecode: response.code)
end
end

Rails how to return single JSON object instead of array of JSON objects?

I am limiting to 1, so I thought it would simple return an object in this case the same as .find_by_email
Code:
# GET /users/:identified/type/:social_type
# Returns a single record - so limit 1
def find
#user = User.where("identified = ? AND social_type = ?", params[:identified], params[:social_type]).limit(1)
if not #user.empty?
render json: #user.as_json, status: :created
else
render json: #user, status: :not_found
end
end
Current Response:
[{"id":7,"voy_num":null,"voy_pin":null}]
How can ensure I return a single JSON object?
To get the single object, use first with where like this:
#user = User.where("identified = ? AND social_type = ?", params[:identified], params[:social_type]).first

Rails Render JSON Object instead of entire array

In my controller I have the present code that results in a JSON array, even though there is only one result:
def getSharedSpecial
#result = Campaign.find_by_sql("SELECT
id
,name
,image
,ad_caption
,ad_details
FROM campaigns
WHERE id = " + params[:shared_campagin_id].to_s + "
LIMIT 1;")
respond_to do |format|
format.html
format.json { render json: { special_shared: #result }}
end
end
returns:
"special_shared":[
{
"id":41,
"name":"tester the way",
"image":{
"url":"/uploads/campaign/image/41/Gilded_pic.jpg"
},
"ad_caption":"yfftitu6",
"ad_details":"jku"
}
]
}
As can be seen given the [], this is a JSON array.
How can I create just an object and not an entire array?
The problem is that find_by_sql always returns an array even though you are only looking for a single record. There is no need to use find_by_sql and you've opened yourself to SQL injection attacks by doing so, so just write the finder the traditional way:
#result = Campaign.select(:id, :name, :image, :ad_caption, :ad_details).find(params[:shared_campagin_id])

looping from database and no implicit conversion of Symbol into Integer

I encounter a strange problem when trying to alter values from a Hash. I have the following setup:
def index
data, total = Role.with_filtering(params, current_holding_company)
data.each do |total_user|
total_user = { total_user: RoleUser.where(role_id: data[:id]).group(:user_id).count.to_s }
data[:total_user] = total_user
end
respond_to do |format|
format.json { render json: { data: data, total_count: total }.to_json, status: 200 }
end
end
When I execute this code I get: "TypeError: no implicit conversion of Symbol into Integer" . What am I doing wrong?
data is output from database, so my goal is i want to add total_user in every record with add new key and value into data
This might not completely solves your issue but hopefully will guide you to the correct path.
In ruby the error TypeError: no implicit conversion of Symbol into Integer usually happens when you miss treat an array!
lets suppose you have
numbers = [1,2,3]
#now
numbers[0]
# > 1
numbers[2]
# > 3
#But
numbers[:1]
# throws TypeError: no implicit conversion of Symbol into Integer
So, you must be passing a symbol on an array [] operator by mistake
One way to debug this kind of issues is by checking class type of your objects, something like this in the consol
data.class
# > Array (for example)
try this....
def index
data, total = Role.with_filtering(params, current_holding_company)
data.each do |total_user|
total_user = { "total_user" => RoleUser.where(role_id: data[:id]).group(:user_id).count.to_s }
data[:total_user] = total_user
end
respond_to do |format|
format.json { render json: { data: data, total_count: total }.to_json, status: 200 }
end
end

Rails rest put HTTP/1.0 501 Not Implemented

I need to use RESTful input to my Rails app. First I'm trying to just understand REST and I'm using WizTools RestClient on my MAC for testing.
I have a table called priorities and I'm trying to update a field called prioritydesc.
This is the info I'm using
METHOD = PUT
URL = http://mywebsite/priorities/4
HEADER = prioritydesc
VALUE = "TEST"
The results I'm getting is:
HTTP/1.0 501 Not Implemented
If I use the resttesttest.com site, I get:
Origin http://resttesttest.com is not allowed by Access-Control-Allow-Origin.
Thanks for the help!
UPDATE1:
Do I need gem "oauth-plugin"?
UDPATE2:
This is my priorities_controller PUT:
# PUT /priorities/1
# PUT /priorities/1.json
def update
#priority = Priority.find(params[:id])
respond_to do |format|
if #priority.update_attributes(params[:priority])
format.html { redirect_to #priority, notice: 'Priority was successfully updated.' }
format.json { head :ok }
else
format.html { render action: "edit" }
format.json { render json: #priority.errors, status: :unprocessable_entity }
end
end
end
UPDATE3
I tried on localhost using:
METHOD = PUT
URL = http://localhost/priorities/1
HEADER = prioritynum
VALUE = 5
And got
"<html><body>You are being redirected.</body></html>"
That seems OK to me.
But, the value didn't update.
UPDATE4
I used this:
METHOD = POST
URL = http://localhost/priorities
HEADER = prioritynum
VALUE = 5
And it added a new record! But, the prioritynum was blank
I also tried using
http://localhost:5000/priorities?prioritynum=5
Should the data field(s) like (prioritynum=5) be in the header or the body?
I put this in the body and it didn't work:
typecode="test"
UPDATE5
OK this worked !!
METHOD = PUT
URL = http://mywebsite/priorities?priority[prioritynum]=5
I got it working for the types controller - I used this:
Method = POST
URL = http://mywesite/types?type[typecode]=test&type[typedesc]=test%20description

Resources