can't convert String into Integer from inside hash - ruby-on-rails

I am trying to display a given value from a block of search data per result in the listing. I am getting the error "can't convert String into Integer" How do I display the next level array inside my linked_agents?
My code for the particular column is such
<td>
<% if result['primary_type'] === "resource" or result['primary_type'] === "digital_object" or result['primary_type'] === "accession" %>
<%= display_agents(result) %>
<% end %>
</td>
and the code
def display_agents(hash, opts = {})
object = JSON.parse( hash["json"] )["linked_agents"]
object2 = object["_resolved"]
html = "<div class='audit-display-compact'><small>"
html << "<ul style='list-style-type:none'>"
html << "<li>#{object2}</li>"
html << "</ul>"
html << "</small></div><div class='clearfix'></div>"
html.html_safe
end
Here is what is inside linked_agents.
[{"_resolved"=>{"names"=>[{"sort_name"=>"John Smith"}]}}]
How can I get all the sort_name's to display the data? There could be more than one _resolved each containing a sort_name.
Thanks

More data would've been more helpful than less data, but essentially your problem is this: "json" contains a string. Nothing more. Not an object. Nothing you could reference with results[]. Assuming the JSON is all properly formatted, what you would need to do is something like this:
<%= JSON.parse( result["json"] )["linked_agents"]["_resolved"]["sort_name"] %>
Now, this is horribly sloppy, and not the way you're going to want to accomplish your goals (assuming this is even effective with your data set). In actuality, what you'll want to do is parse that JSON into a variable, and work through in hash form.
It is difficult to clearly keep the topics at work here because there isn't a clear question. I would encourage you to make sure you have a basic familiarity of ruby arrays, hashes, and nested structures consisting thereof. Additionally, take a look at how you're retrieving the data that goes into results["json"].
There are many ways to accomplish many things once your data is properly structured, but you need to have a clear understanding of these types of structure before you can work magic (and you need to possess a basic knowledge of what you aren't understanding before we can provide you with solutions).
I hope that is helpful. Feel free to discuss points of confusion in the comment, and I will update this answer as we approach a solution for your problem.

Related

What exactly is a template engine?

I have done some googling and I understand that the template engine of Ruby is erb but what does a template engine mean?
Template engine are nothing but presentation layer, that represent actual logic/variable of rails application in html format. So end user can get what they are looking for.
Consider if you have #users object and you want to loop through each record and represent name of each user detail on webpage. There is no way in simple html to do so. So erb and other template engines comes in picture.
These engines covert/evaluate values of variables, functions and user defined syntax to html format and represent to end user.
Hope this helps you.
Template is a pattern, mold, or the like, usually consisting of a thin plate of wood or metal, serving as a gauge or guide in mechanical work that determines or serves as a pattern; a model:
- Dictionary Definition
In our world of Programming, The template is a framework of any repetitive work sharing a common pattern. We extract out the common pattern as a template, now you can embed the changing/dynamic data and create your copy of the work.
Example: You notice forms you get in hospitals or Govt. offices where there are blank-fields for you to write your dynamic data. At last, you get your copy of the application. Don't you?
To facilitate this we have ERB as an engine in the standard library of Ruby.
Let's get our hand dirty; Try this and see results:
require 'erb'
your_template = <<-TEMP
This document is a template for <%= title %> <%= full_name %>.
Now we are going to have a line written <%= n %> times.
<% n.times do %>
This line must repeat <%= n %> times.
<% end %>
TEMP
title = 'Mr.'
full_name = 'Shiva Gaire'
n = 5
generated_doc = ERB.new(your_template).result
puts generated_doc
Output
This document is a template for Mr. Shiva Gaire.
Now we are going to have a line written 5 times.
This line must repeat 5 times.
This line must repeat 5 times.
This line must repeat 5 times.
This line must repeat 5 times.
This line must repeat 5 times.

How to properly parse JSON into usable output (Ruby on Rails)

I'm using an API that I call with something like this:
Controller:
#bounces = SendgridToolkit::Bounces.new(API_USERNAME, API_PASSWORD)
View:
And that returns data like this: (for JSON, though an XML call is also possible)
[{"status"=>"550", "created"=>2015-07-06 18:37:38 UTC, "reason"=>"550 Unrouteable address ", "email"=>"jake#fake.com"}]
It's useful to me, but unfortunately it's not the way I want to present it in my Rails application. What's the best way to transform this data, since I don't have access to the poorly formatted string itself, only the code that requests it from the application I'm interacting with?
I'm having some issues coming up with the right question to ask Google, and would appreciate any suggestions you have to offer from experience.
Thanks in advance for your help!
EDIT:
For example, this returns an error no matter where I put it (The view or the controller), saying that string is an undefined method:
string = '[{"status":"550","reason":"550 Unrouteable address ","email":"jake#fake.com"}]'
#showbounces = #bounces.retrieve.to_json JSON.parse(string)
#newsletters = Newsletter.all
returns:
no implicit conversion of Symbol into Integer:
#showbounces = #bounces.retrieve.to_json JSON.parse(string)
Ultimately I'd like to extract select information from the JSON/XML and use it for things like graphs in my view that I can format with CSS and HTML.
You don't need to parse the JSON output string from the web service. The SendgridToolkit gem takes care of that. It returns the data as Ruby objects (arrays and/or hashes), ready to be used in your code.
For example, in your controller:
def index
bounces = SendgridToolkit::Bounces.new(API_USERNAME, API_PASSWORD)
#all_bounces = bounces.retrieve
end
and then in your view:
<ul>
<% #all_bounces.each do |bounce| %>
<li>Bounced <%= bounce['email'] %> (<%= bounce['reason'] %>)</li>
<% end %>
</ul>

Better ways to return HTML from a method in rails?

this is my first post here so be nice ;-)
I am currently learning the ropes of RoR (and general programming concepts) and I'm not sure if how I am returning some data from a method is 'the right way' (or maybe the 'rails way') to do so.
I have a form that a user can enter a value into and my 'app' will poll the requested data from an external web service.
In my view, I have a table to contain said data and in one cell I've included a call to the following method:
extract of view:
<tr>
<td>Subscriber</td>
<%= is_subscribed?(#search_result.expiry) %>
</tr>
So, I'm calling this little is_subscribed? method (which I've stored in a helper) as per below:
def is_subscribed?(sub_date)
if sub_date >= Date.today
return '<td class="text-success">Yes</td>'.html_safe
else
return '<td class="bg-danger">No</td>'.html_safe
end
end
Depending on the result of the comparison, I return some HTML with one class and a value or some HTML with another class.
The above does work and the class is applied correctly in the resulting HTML. What I would like to know is whether there a simpler way to do this, is this way bad practise? I am also curious how would someone else handle this sort of task.
Thanks!
It's fine how you've done it. Here's a variant:
def subscribed_td(sub_date)
sub_date >= Date.today ?
content_tag(:td, 'Yes', class: 'text-success') :
content_tag(:td, 'No', class: 'bg-danger')
end
The main difference is simply the function name is more accurate imo, as I'd expect a function called is_subscribed? to return a boolean. It's also using content_tag to be a bit more concise, and a ternary instead of the if-then (which is not to everyone's taste). You could try to be fancy here with just a single content_tag expression and then use ternaries inside it to vary the arguments, but that's OTT DRY-ness imo.

Why do I get nil objects iterating an array in an ERB template?

I am new to Ruby and currently trying a few experiments.
I am confused about these scripts:
<%=#myworlds[2].topic%>
and
<% id = 1 %>
<%=#myworlds[id+1].topic%>
#mywodrld is an instance of a model and topic is the field. When executing the first one, the program runs correctly. When I run the second script, I get the following error:
You have a nil object when you didn't expect it!
The error occurred while evaluating nil.topic
What causes the nil object?
When I try your approach, I can't replicate your problem. It works fine for me. My guess is that you might use the variable id somewhere else also and that when you call #myworlds[id+1].topic id has some other value. But as I said, only a guess.
However, I recommend that you use another syntax when looping through collections of models in Ruby. Try something like this:
<% #myworlds.each do |myworld| %>
<h1><%= myworld.topic %></h1>
<% end %>
And if you really need the value of the iterator, you could always go with:
<% #myworlds.each_with_index do|myworld, i| %>
Where i keeps track of the current index in the array. Another good thing with this is that id no longer exists in memory after the block ended.
Are you sure that you have no other differences between these two code snippets?
In your comment you say that you have #myworlds[#id+1], in the original question you say #myworlds[id+1] (local variable versus instance variable). Can you show the exact code?
Both scripts are OK. You can create variables in one <% %> block, and you can use them in another one (if they are in the same .erb file, of course).
The error message says that your array has no element with index #id+1 or id+1. You have to debug the value of the expression used for the index. I guess that there is somewhere some small mistake, like a typo.
What is the output of your debug(#myworlds[#id+1]) statement when #myworlds[#id+1].topic raises the error?
Also try to debug the value of id:
<pre>The id = <%= debug(id) %> (<%= id.inspect %>)</pre>
(Depending on your version of Rails you may want to use h( id.inspect ))
I'm guessing but for some reason id+1 is probably not equal to 2.
To check the value of id+1 you can do that :
raise (id+1).inspect
Inspect is very useful is you want to see what is in an object :)
I think I know how to solve the problem is. You are trying to each an array data from a model, but u use the parameter [#id+1]. No matter the "id" is global or local variable, but the problem is in the end of array, there are no array with index "id+1". You should add another parameter to prevent the unrecognized parameter.
Try this
if((#myworlds.length-1) > #id)
#id = #id+1
end
:D
It looks like you're looping over an array, but possibly using a for or while loop to accomplish it, rather than use an [].each. Your sample code doesn't give us enough information to work from so we're shooting in the dark attempting to help you.
Manually creating your index then trying to walk the array tends to run into problems where you either miss the first or last item, or you go too far and get the error you are seeing. Because each returns only the items in the array it can't do that.
Something like this might work better:
<% #myworlds.each do |world| %>
...
<%= world.topic %>
<% end %>
I didn't see the answer #DanneManne gave before I wrote my response. I think he's got the right solution.

Rails: Flatten array in parameter

I'm trying to flatten an array for my form.
def update
#tour = Tour.find(params[:id])
params[:tour][:hotel_ids][0] = params[:tour][:hotel_ids][0].split(',')
...
This results in:
"hotel_ids"=>[["1","2"]]
Naturally I want it to be
"hotel_ids"=>["1","2"]
My Form:
<%= text_field_tag 'tour[hotel_ids][]', nil %>
Hope anyone can help with this.
EDIT
I've gotten it to work, somehow. This might be a bad way to do it though:
I changed the text_field that get's the array from jquery to:
<%= text_field_tag 'tour[h_ids][]', nil %>
then in my controller I did:
params[:tour][:hotel_ids] = params[:tour][:h_ids][0].split(',')
And this works, I had to add h_ids to attr_accessor though. And it will probably be a big WTF for anyone reading the coder later... but is this acceptable?
This is ruby!
params[:tour][:hotel_ids][0].flatten!
should do the trick!
ps: the '!' is important here, as it causes the 'flatten' to be saved to the calling object.
pps: for those ruby-related questions I strongly suggest experimenting with the irb or script/console. You can take your object and ask for
object.inspect
object.methods
object.class
This is really useful when debugging and discovering what ruby can do for you.
Simply use <%= text_field_tag 'tour[hotel_ids]', nil %> here, and then split like you do in example.
What really happens in your example is that Rails get param(-s) tour[hotel_ids][] in request and it thinks: "ok, so params[:tour][:hotel_ids] is an array, so I'll just push every value with this name as next values to this array", and you get exactly this behavior, you have one element in params[:tour][:hotel_ids] array, which is your value ("1,2"). If you don't need (or don't want) to assign multiple values to same param then don't create array (don't add [] at the end of the name)
Edit:
You can also go easy way (if you only want answer to posted question, not solution to problem why you have now what you expect) and just change your line in controller to:
params[:tour][:hotel_ids] = params[:tour][:hotel_ids][0].split(',')
#split returns array and in your example you assigned this new array to first position of another array. That's why you had array-in-array.

Resources