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
Related
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%>
I have 1 column called 'message_notification' inside table 'configuration'. I want to produce save result as JSON object in this column:
message_notification: [
{
"alert" : "how are you doing today?"
},
{
"alert" : "where have you been today?"
}
]
for the form, i use
<%= simple_form_for(#configuration) do |f| %>
Alert 1: <%= check_box_tag "configuration[message_notification][][alert]", 'how are you doing today?' %><label>Alert 1</label><br/>
Alert 2: <%= check_box_tag "configuration[message_notification][][alert]", 'where have you been today?' %><label>Alert 2</label><br/>
<%= f.submit %>
<% end %>
How to achieve this?
[UPDATED]
above code will resolve as a ruby hash (not as JSON)
my controller
#configuration.message_notification = {
alert: params[:message][:alert]
}.to_json
result:
message_notification: [
{
"alert" => "how are you doing today?"
},
{
"alert" => "where have you been today?"
}
]
[UPDATED 2]
In console:
=> a = value.message_notification
=> "[{\"alert\"=>\"alert1\"}, {\"alert\"=>\"alert2\"}]"
=> puts a
=> [{"alert"=>"alert1"}, {"alert"=>"alert2"}]
=> nil
You can use, to_json to convert the ruby hash to JSON object
just require 'json' in your controller.
params = {"utf8"=>"✓", "_method"=>"new", "authenticity_token"=>"txroAHF2+YZOrm48DtBZdVqKzxLYyHFq4+GWQFnM6kNldXgRZJMPv0yfj0/tfZVpuVvh39UVX4Fb66FNkkCZqA==", "message"=>{"name"=>"Dan Murphy Roundabout Test", "company"=>"transtech", "location_id"=>"", "message_notification"=>[{"alert"=>"alert1"}, {"alert"=>"alert2"}], "commit"=>"save", "controller"=>"message", "action"=>"create", "id"=>"1717"}}
Since your params object is above, according to your requirement you can use,
params['message']['message_notification'] = (params['message']['message_notification'].to_json)
this converts the message_notification in the params to a json object, and stores in the DB.
Here's what I did.
def resource_params
params.require(:appointment_modules_dataset_intake).permit(
:appointment_id,
:main_issue,
:cvf
).tap do |p|
p[:cvf] = JSON.parse(p[:cvf]) # This is the significant line
end
end
I have a table called "Weights" that holds a user's weight for a specific day. I can retrieve all relevant data as JSON with the following line of code in my controller's index action:
#weights = Weight.where(:user_id => current_user.id).to_json
The output then looks like:
[{"id":72,"user_id":71,"kilograms":94.0,"day":"2016-06-03","created_at":"2016-06-03T06:58:35.139Z","updated_at":"2016-06-03T06:58:35.139Z"},{"id":75,"user_id":71,"kilograms":34.0,"day":"2016-06-02","created_at":"2016-06-03T13:05:49.862Z","updated_at":"2016-06-03T13:05:49.862Z"},{"id":76,"user_id":71,"kilograms":56.0,"day":"2016-05-29","created_at":"2016-06-03T13:06:01.747Z","updated_at":"2016-06-03T13:06:01.747Z"}]
However, what I would need is an output that looks like:
{2016-06-03 => 94.0, 2016-06-02 => 34.0, 2016-05-29 => 56.0}
How can I achieve this? (I just started coding so I'm sorry if this is a really noob question)
Many thanks.
UPDATE My request refers to a chart I want to display using Chartkick. The documentation says:
Times can be a time, a timestamp, or a string (strings are parsed)
<%= line_chart({20.day.ago => 5, 1368174456 => 4, "2013-05-07 00:00:00 UTC" => 7}) %>
My weights_controller.rb index action now
def index
result = {}
Weight.where(:user_id => current_user.id).each do |weight|
result[weight.day] = weight.kilograms
end
end
Thus I need my data in format described above.
Let try this:
#result = {}
Weight.where(:user_id => current_user.id).each do |weight|
result[weight.day] = weight.kilograms
end
Now the result will be a hash:
{'2016-06-03' => 94.0, '2016-06-02' => 34.0, '2016-05-29' => 56.0}
If you want result to be json:
#result.to_json
Update Simply use it in the view for example:
<% #result.each do |day, kg| %>
<p>Day: <%= day %>, Kg: <%= kg %><p>
<% end %>
I have STI models like this : Photo < Medium and Video < Medium.
Somewhere in a view, i would like to show them like that :
# app/views/albums/show.html.slim
ul
li= render #album.media
The render search for a albums/_photo or albums/_video partial :
# app/views/albums/_photo.html.slim
h3= photo.title
= image_tag photo.file.url
p= photo.description
# app/views/albums/_video.html.slim
h3= video.title
= video_tag video.file.url
p= video.description
Now, i would like to make a template to use in app/views/albums/show.html.slim for not repeat commons fields between media. Something like that :
# app/views/albums/_medium.html.slim
h3= medium.title
= yield(:medium_tag)
p= medium.description
= yield(:medium_additionnals)
# app/views/albums/_photo.html.slim
- content_for(:medium_tag) do
= image_tag photo.file.url
- content_for(:medium_additionnals) do
# any additionnals fields
# app/views/albums/_video.html.slim
- content_for(:medium_tag) do
= video_tag video.file.url
- content_for(:medium_additionnals) do
# any additionnals fields
But this give me in yields concatenate contents...
Someone has a solution / alternative to do this ?
[EDIT]
With this templates :
# app/views/albums/show.html.slim
= render #album.media
# app/views/albums/_medium.html.slim
div
h3= medium.title
= yield(:medium_tag)
# app/views/albums/_photo.html.slim
- content_for(:medium_tag) do
| TEST
The resulting HTML :
<div>
<h3>Photo1</h3>
TEST
</div>
<div>
<h3>Photo2</h3>
TESTTEST
</div>
<div>
<h3>Photo3</h3>
TESTTESTTEST
</div>
<div>
<h3>Photo4</h3>
TESTTESTTESTTEST
</div>
...
The yield result is concatened as many time as media count.
Your code seems really good, although I don't get how your render call is cycling through each medium item
You could use a helper to return the relevant data, although that wouldn't be the most efficient:
#app/helpers/application_helper.rb
module ApplicationHelper
output = Slim::Engine.new "h3={item.title}"
output += Slim::Engine.new "- eval(#{item.model_name.human}_tag) item.file.url"
output += Slim::Engline.new "p=item.description"
end
end
This would allow you to run:
#app/views/albums/_photo.html.slim
= media photo
#app/views/albums/_video.html.slim
= media video
-
Alternatively, you could just put it into a _medium partial:
#app/views/albums/_photo.html.slim
= render partial: "medium", locals: { item: photo }
#app/views/albums/_video.html.slim
= render partial: "medium", locals: { item: video }
_medium would then have the following:
#app/views/albums/_medium.html.slim
h3=item.title
- eval("#{item.model_name.human}_tag") item.file.url
p=item.description
So, I just discovered select2. Awesome. Now I'm trying to figure out how to use it, server side with ajax / json. All of the examples I see, everywhere, show using select2 with JSONP to retrieve data from an external source. I feel like this should be even easier if calling from a local model, no? I'll get right to the nitty gritty. json returns a value, but the searchbox doesn't autocomplete, it stays blank.
view html:
<%= form_tag request_pal_path, remote: true do %>
<%= hidden_field_tag :email, nil, class: 'ui-corner-all' %>
<%= submit_tag "Send request", class: 'button' %>
<% end %>
and calling some js on it:
$(document).ready(function() {
$("#find_user #email").select2({
width: '400px',
placeholder: "Find user...",
minimumInputLength: 1,
multiple: false,
id: function(obj) {
return obj.id; // use slug field for id
},
ajax: { // instead of writing the function to execute the request we use Select2's convenient helper
url: "/users",
dataType: 'json',
data: function (term, page) {
return {
q: term, // search term
page_limit: 10
};
},
results: function (data, page) { // parse the results into the format expected by Select2.
// since we are using custom formatting functions we do not need to alter remote JSON data
return {results: data};
}
},
formatResult: FormatResult,
formatSelection: FormatSelection,
escapeMarkup: function (m) { return m; }
});
})
function FormatResult(user) {
return '<div>' + user.name + '</div>';
}
function FormatSelection(user) {
return user.name;
}
which goes to the controller, user index action:
def index
#find = User.where('name LIKE ?', "%#{params[:q]}%")
#users = #find.where('id NOT IN (?)', current_user.id).order('random()').page(params[:page]).per(100)
#title = "Potential pals"
respond_to do |format|
format.html
format.js {
#find = #find
#users = #users
}
format.json { #find }
end
end
and I made a .json file for it to respond to (not sure if this is even necessary):
<% #find.each do |user| %>
<%= user.name %>
<% end %>
So, the json is working, to an extent. If I look in the developer console, it shows a response coming from http://localhost:3000/users.json?q=tay, or whereever, and it returns a single value, for Taylor (in that instance). But when I search inside of the select2 search box, it just spins and spins, with no results. No console errors, so that's nice, ha. Thoughts? Thanks!
The select2 plugin expects JSON data in the following format:
[ { "text": "Taylor", "id": 1 }, { "text" : "Tailor", "id": 2 }, ...]
So you need to replace name with text in your user model when converting to JSON:
def as_json(*args)
super.tap { |hash| hash["text"] = hash.delete "name" }
end
and then in the index method:
def index
#find = User.where('name LIKE ?', "%#{params[:q]}%")
#users = #find.where('id NOT IN (?)', current_user.id).order('random()').page(params[:page]).per(100)
#title = "Potential pals"
respond_to do |format|
format.html
format.js {
#find = #find
#users = #users
}
format.json { render json: #find, :only => [:text, :id] } # might be :name here ?
end
end
and you don't need the view for JSON.
I guess the problem is in your .json file, since select2 needs json array or json object. Try to remove it and respond with format.json { render json: #find.to_json }. Other code seems ok to me.