Rails JSON API: Updating picture in view doesn't show - ruby-on-rails

New to Rails API's. I want to have an updating picture displayed in my views. The JSON data I'm pulling from can be found here
My Model
def self.get_api_info
helio_api = "http://www.lmsal.com/hek/her?cosec=2&cmd=search&type=column&event_type=fl,bu&event_starttime=2017-03-01T00:00:00&event_endtime=2017-03-08T00:00:00&event_coordsys=helioprojective&x1=-1200&x2=1200&y1=-1200&y2=1200"
request_to_helio_api = Net::HTTP.get(URI(helio_api))
JSON.parse request_to_helio_api
end
My Controller
def index
#helio_info = HelioApi.get_api_info
end
And my View
<img src="<%= #helio_info["gs_thumburl"] %>" />

The structure of the API you're accessing is
{
"result": [
{ "gs_thumburl": "some_string", ... },
{ "gs_thumburl": "some_string", ... },
{ "gs_thumburl": "some_string", ... }
]
}
So to go from #helio_info to some_string you need to grab the result array #helio_info["result"] and then an element in that array #helio_info["result"][0], and finally grab the url #helio_info["result"][0]["gs_thumburl"]. Ruby said no implicit conversion of String into Integer because you tried to access an array using a string key, and it expects integer keys.

Thanks for the insight Pavan. Here's what I ended up doing:
Model kept the same
Controller
def index
#helio_info = HelioApi.get_api_info['result']
puts "!!!!!!!!!!!!!!*********!!!!!!!!!********!!!!!"
puts #helio_info
end
View
<% #helio_info.each do |info| %>
<% if info['gs_thumburl'] != "" %>
<img src="<%= info['gs_thumburl']%>"/>
<%end%>

Related

How to pass the search parameters in the link to print

How to pass the search parameters in the link to print.
I have a method #index controller #TicketsController
def index
#search = current_account.searches.find_by(id: params[:search_id])
#q = policy_scope(Ticket).ransack(params[:q])
if params[:q].blank? && params[:advanced_search].blank? || params[:q]&.to_unsafe_h&.length == 1 && params[:q][:s].present?
#q.add_default_condition('status', 'in', 'open')
session[:last_ticket_search] = nil
else
session[:last_ticket_search] = {q: params[:q]}
if params[:advanced_search].present?
session[:last_ticket_search].merge!(advanced_search: 't', selected_columns: params[:selected_columns])
session[:last_ticket_search].merge!(params[:search_id].present? ? {search_id: params[:search_id]} : {commit: 'Apply'})
end
end
#selected_columns = selected_columns
#tickets = #q.result.select('tickets.*')
.includes(:account, :ticket_responses, :assignee, :tags)
.order('tickets.created_at DESC')
.paginate(page: params[:page], per_page: per_page('tickets'))
end
I need to make a page for printing all objects.
For this I made the link Print in `tickets/index.html.erb
<a class="btn btn-primary print-button" href="<%= tickets_path(variant: :print) %>" target="_blank" title="Print ticket" data-tooltip data-placement="bottom">
<i class="fa fa-print"></i>
</a>
The point is that if you click on it will open the whole list of objects here, all is well. But if I use search, I will generate the list of all objects. I need a list of objects I defined in the search. So how do I pass a search parameter in the controller to generate the print page?
I tried that.
<%= tickets_path(q: params[:q], advanced_search: params[:advanced_search], variant: :print) %>
But the controller does not share parameters and accepts a string.
need: "utf8"=>"✓", "q"=><ActionController::Parameters {"assignee_id_eq"=>"", "status_in"=>"closed", "ticket_type_eq"=>"", "simple_search"=>""}
I get: {"q"=>"assignee_id_eq=&simple_search=&status_in=closed&ticket_type_eq=", "variant"=>"print", "controller"=>"tickets", "action"=>"index"}
Just create an instance variable with your required parameters parsed into a hash which will be available in the view:
def new
#search_params = Rack::Utils.parse_nested_query params[:q]
...
end
and in the view:
<%= tickets_path(q: #search_params[:q], advanced_search: params[:advanced_search], variant: :print) %>

how to create a array of hashes in Rails 4?

I am trying to make this behavior with my custom toastr notification
this is what i have
def toast(type, text)
flash[:toastr] = { type => text }
end
I call this in my controller like this
toast('success',"this is a message")
and it would output to my template like so
<% flash[:toastr].each do |type, message| %>
toastr.<%= type %>('<%= message %>')
<% end %>
however it only outputs 1 message
now here is the functionality I am trying to make, which is display multiple flash messages
http://tomdallimore.com/blog/extending-flash-message-functionality-in-rails/
it works because of the following method
def flash_message type, text
flash[type] ||= []
flash[type] << text
end
everytime you call #flash_message, it would save the flash message in an array, and I can use for each on the array to display it.
I am having trouble converting my #toast into that, #toast CURRENTLY does this
flash[:toastr] = {'success' => "this is a message"}
I would like to do this
flash[:toastr] = [{'success' => "this is a message'},{'error' => "problem!"}]
Can someone help me modify toast method to accept an array of hashes, and inserts a new hash everytime its called?
def toast(type, text)
flash[:toastr] ||= []
flash[:toastr] << { type => text }
end
Using Array#push:
def toast type, text
flash[:toastr] ||= []
flash[:toastr].push({ type => text })
end
Using append (<<):
def toast type, text
flash[:toastr] ||= []
flash[:toastr] << { type => text }
end

AJAX Response Rails 4 Does Not Return In Text Field

I've just started coding in Rails 4, so I may need very specific instruction. I'm using AJAX to take user input from a text field, modify it (for simplicity's sake I'm just adding " yay!" on the end of it), and return the response as a string to the text field.
I believe I am sending my AJAX request correctly, but something in my controller or view isn't modifying or displaying the result.
Here is my code:
View (solve.html.erb):
<head>
<script>
function myFunction() {
var xmlhttp = new XMLHttpRequest();
var url = "solve";
var params = "field1=" + document.getElementById("field1").value;
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("field1").innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open("GET", url + "?" + params, true);
xmlhttp.send();
}
</script>
</head>
<h1>Solve!</h1>
<p>Type it in, type it in.</p>
<div class="col-lg-6">
<div class="input-group">
<input id="field1" type="text" class="form-control" placeholder="1+1">
<span class="input-group-btn">
<button class="btn btn-default" type="button" onclick="myFunction()">Solve</button>
</span>
</div>
</div>
Routes (routes.rb):
resources :equations
#rest of my routes code
get 'solve' => 'equations#solve'
Controller (equations_controller.rb):
class EquationsController < ApplicationController
def solve
if request.post?
new_var = params[:field1]
other_var = "#{new_var} yay!"
return other_var
end
end
end
If you have any questions, I'll get right back to you. Thank you so much for your help! Anything is greatly appreciated.
You're making a GET request but checking if the request is POST in your EquationsController#solve method. Update controller code as follows:
class EquationsController < ApplicationController
def solve
if request.get? # Change to `request.get?`
new_var = params[:field1]
other_var = "#{new_var} yay!"
return other_var
end
end
end
Then the second problem is, you should be writing the output instead of returning it from the controller. As you are expecting text/plain mime type, you should render text instead:
class EquationsController < ApplicationController
def solve
if request.get?
new_var = params[:field1]
other_var = "#{new_var} yay!"
render plain: other_var # Change to `render plain: other_var`
end
end
end
This however, is not the recommended way to handle AJAX requests/responses in Rails. Please refer to: Working with JavaScript in Rails. Also, please see The response object for details on the same.
Try this in myFunction()
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("field1").value = xmlhttp.responseText;
}
I think this works
ok, I think the controller's action is rendering the default 'solve.html.erb' view. so you should return just the value you wish like
class EquationsController < ApplicationController
def solve
if request.post?
new_var = params[:field1]
other_var = "#{new_var} yay!"
render html: other_var
end
end
end
and in js
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById("field1").value = xmlhttp.responseText;
}

Looping through Hash(Array)

I have this problem, where I keep on getting
TypeError: can't convert String into Integer
This is where I'm going through this #data object.
here is the #data object
#data = HTTParty.get("")
{
"body"=>{
"predictions"=>{
"direction"=>{
"prediction"=>[
{
"epochTime"=>"1362931090892",
},
{
"epochTime"=>"1362931747892",
},
{
"epochTime"=>"1362932467892",
},
{
"epochTime"=>"1362933187892",
},
{
"epochTime"=>"1362933847892",
}
],
"title"=>"xxxx"
},
"a"=>"xx",
"b"=>"x"
},
"name"=>"some"
}
}
and my code to go through above has been
<% if #data["body"]["predictions"].present? %>
<% #data["body"]["predictions"].each do |p| %>
<%p["direction"].each do |d|%>
<% d["prediction"].each do |k|%>
<h4><%= k["epchoTime.."] %> </h4>
<%end%>
<%end%>
<%end%>
<%end%>
I have no idea how to go through this, I assume this is due to the fact I should access stuff like I do in C++ with name[integer] value, but I would like to use ["name"]. How can I make my code work ?
Thanks for your precious time and consideration.
Here's an example, using Nokogiri, of parsing the raw XML:
require 'nokogiri'
doc = Nokogiri::XML(<<EOT)
<body>
<predictions>
<direction>
<prediction>
<epochTime>1362931090892</epochTime>
<epochTime>1362931747892</epochTime>
<epochTime>1362932467892</epochTime>
<epochTime>1362933187892</epochTime>
<epochTime>1362933847892</epochTime>
</prediction>
<title">xxxx</title>
<a>"xx"</a>
<b>"x"</b>
<name>"some"</name>
</direction>
</predictions>
</body>
EOT
epoch_times = doc.search('epochTime').map(&:text)
Which returns an array of epochTime values:
[
[0] "1362931090892",
[1] "1362931747892",
[2] "1362932467892",
[3] "1362933187892",
[4] "1362933847892"
]
Sometimes we need to loop through all prediction blocks containing the epochTime blocks. This will do it:
epoch_times = doc.search('prediction').map{ |predict|
predict.search('epochTime').map(&:text)
}
[
[0] [
[0] "1362931090892",
[1] "1362931747892",
[2] "1362932467892",
[3] "1362933187892",
[4] "1362933847892"
]
]
Sometimes you need to find a particular node and grab all the elements of a certain type inside it:
doc = Nokogiri::XML(<<EOT)
<body>
<predictions>
<direction>
<prediction id="1">
<epochTime>1362931090892</epochTime>
<epochTime>1362931747892</epochTime>
<epochTime>1362932467892</epochTime>
<epochTime>1362933187892</epochTime>
<epochTime>1362933847892</epochTime>
</prediction>
<title">xxxx</title>
<a>"xx"</a>
<b>"x"</b>
<name>"some"</name>
</direction>
</predictions>
</body>
EOT
epoch_times = doc.search('prediction[id="1"]').map{ |predict| predict.search('epochTime').map(&:text) }
[
[0] [
[0] "1362931090892",
[1] "1362931747892",
[2] "1362932467892",
[3] "1362933187892",
[4] "1362933847892"
]
]
the Tin Man has a good point about keeping this logic outside the view, and should be a work of a model. Here is a cleaner view though.
<% #data['body']['predictions']['direction']['prediction'].each do |x| %>
<% x.each do |k, v| %>
<h4><%= v %></h4>
<% end %>
<% end %>
Looks like you are ignoring the keys which don't have nested values say title and a , b .
"title"=>"xxxx"
},
"a"=>"xx",
"b"=>"x"
},
Your final code should look like
if #data["body"]["predictions"].present?
#data["body"]["predictions"].each do |p|
p.each do |d|
if d.kind_of? Hash
d.each do |k|
if k.kind_of? Array
k.each do |x|
if x.kind_of? Array
x.each do |y|
if y.kind_of? Hash
puts y["epochTime"]
end
end
end
end
end
end
end
end
end
end
The above code is ugly but you are C++ programmmer , you might like it :P
The whole hash things was getting out of hand as I had constantly detect each one's present and loop through it, so As Tin man suggested, I used XML 'nokogiri' and then used .css method to detect if it existed and looped through it, since original response was in xml.
#doc.css('predictions').each do |predictions_node|
predictions_node.css('direction').each do |direction_node|
direction_node.css('prediction').each do |prediction|
// stuff here
Thanks for your time and consideration.

how to group a json from a sql result

I have a JSON that's returned from my rails API like this
[{"tipo":"1","dia":"02/10/2012","empresa_id":"17","horas":"0:15","tempo":"900"},
{"tipo":"2","dia":"02/10/2012","empresa_id":"17","horas":"0:12","tempo":"720"}]
but I need it to be something like this
`[empresa_id: 17, [{"tipo":"1","dia":"02/10/2012","horas":"0:15","tempo":"900"},
{"tipo":"2","dia":"02/10/2012","horas":"0:12","tempo":"720"}]]
I need to group the results within empresa_id...how do I do that?
In your model's view folder, create a file called modelname.json.erb. Here, you can use ruby code to edit how you want to format your json. Here's an untested code example of what it might look like:
[
<% i = 0
#modelname.each do |model| %>
{
"id": <%= model.id %>,
"name": "<%= model.name %>"
}<% if i != (#modelname.size - 1) %>,<% end %>
<% i += 1 %>
<% end %>
]
In your controller, by default you will have something like this for the output:
format.json { render json: #modelname }
Change it to this:
format.json
By doing this, it will look for the json view you just created!
Try this:
require 'json'
s = '[{"tipo":"1","dia":"02/10/2012","empresa_id":"17","horas":"0:15","tempo":"900"}, {"tipo":"2","dia":"02/10/2012","empresa_id":"17","horas":"0:12","tempo":"720"}]'
j = JSON.parse(s)
r = j.inject({}) do |f,c|
key = c.delete('empresa_id')
(f[key]||=[]) << c
f
end
p r
resulting in
{"17"=>[{"tipo"=>"1", "dia"=>"02/10/2012", "horas"=>"0:15", "tempo"=>"900"}, {"tipo"=>"2", "dia"=>"02/10/2012", "horas"=>"0:12", "tempo"=>"720"}]}
See live demo here

Resources