For some reason, I keep getting an "undefined method 'each'" error every time I try to do the .each do when I have one result in the below.
If I use .inspect, I can see that there's a match. Does .each work if there's not more than 1 result? If not, what should I use instead?
<% friends = graph.get_object("/me/friends").map{ |hash| hash["id"] } %>
<% User.select([:id]).where(fbookid: friends).each do |common| %>
<% end %>
If I just run .inspect on the User.select line (no each), then I get
[#<User id: 1>]
Any help would be appreciated!
Thank you!
UPDATE
Adding additional parameters seemed to allow me to use each...I have no clue why. It's the same exact result (only 1).
User.select([:id, :email, :first_name]).where(fbookid: friends).each do |friend|
You get simple object not array so that it's not working. .each method working when if you get array you get simple object so that you can use direct means that
for example
# if name attributes
User.select([:id]).where(fbookid: friends).name
You can use each on User.select([:id]).where(fbookid: friends), even if there is only 1 element. It will not raise an exception even if there are no elements.
The error is happening somewhere else. Perhaps you are getting an error on something inside the each loop.
Can you post more code?
Related
I'm trying to find the last Econ_Result that belongs to a Econ_Report. I want to display the last record of the Econ_Result (ordered by "release_date") for each Econ_Report on the index view. In the controller I tried to take the list of all reports and find the last result using the following:
#econ_reports = EconReport.all
if #econ_reports.econ_results.size >= 1
#last_result = #econ_report.econ_results.last.release_date
end
econ_report.econ_results.size works on the index view when I place it in for each loop. When I try to call the value of the last record I run into issues with the fact that some reports don't yet have results (a temporary issue) so I threw in the if then check in the controller which is currently failing.
Thanks in advance for the rookie help.
Since #econ_reports is a collection of EconReport objects, you can't call an instance method like .econ_results on it. Instead, you can only call it on instances within the collection:
#econ_reports.each do |econ_report|
if econ_report.econ_results.any?
last_result = econ_report.econ_results.last
end
end
However, this can be terribly inefficient for a large collection of #econ_reports: both lines with econ_report.econ_results will query the database separately, meaning that you'll query the database independently for each econ_report in the collection. This is known as the N+1 query problem.
Luckily for you, as discussed in the link, Rails has a built-in solution to optimize this code so you'll only query the database once:
<% #econ_reports.includes(:econ_results).each do |econ_report| %>
<% if econ_report.econ_results.any? %>
<% last_result = econ_report.econ_results.last %>
# do something to display last_result
<% end %>
<% end %>
If you just want the release date you might try:
#last_result = #econ_report.econ_results.order('release_date DESC').limit(1).pluck(:release_date).first
It's worth noting that a Ruby if statement generally looks like:
if condition
end
The then is almost always omitted even though it is allowed.
Can someone explain the logic behind this code?(This is the correct code btw)
<% if #request.query['first_name'] && !#request.query['first_name'].empty? %>
Welcome! <%= #request.query['first_name'] %>
<% else %>
Hi! What is your name?
<% end %>
My intuition is to write the following instead:
<% if #request.query.inspect['first_name'].empty? %>
Hi! What is your name?
<% else %>
Welcome! <%= #request.query.inspect['first_name'] %>
<% end %>
I am trying to have a user form where people can input their names, when there is no input yet the text above the form says "Hi! What is your name?" when there is an input it has a message saying "Welcome! *User_name*"
The first block of code is not intuitive to me, the second one would make more sense.. ANy advice on how to understand the code?
Your intuition is correct, though you need an alternative to empty?. Rails adds a few different methods you can use:
blank? returns true if the receiver is nil, an empty array, string, or hash, or a string with only whitespace.
present? returns true if blank? is false. So your condition could be:
<% if #request.query['first_name'].present? %>
Welcome...
(I find it's always more intuitive to start with the positive condition - it would work just as well to check blank?).
Edit: It's pretty likely you can skip the query method entirely if all you expect there is either a string or nil. Just use:
<% if #request.query['first_name'] %>
You need to check if it's nil before you can check if its empty, because you are checking a Hash#empty?
irb(main):001:0> nil.empty?
NoMethodError: undefined method `empty?' for nil:NilClass
from (irb):1
irb(main):002:0> {}.empty?
=> true
The code checks for hash key existence, then check if the value of the hash is present. This action can be done in one check using:
#request.query.try(:[], 'first_name').empty?
You can avoid the first condition inside the if statement by transforimng nil into an empty string. I don't know if that is what you meant to do but you almost had.
First, you shouldn't call inspect in the hash because it will transform the entire thing into a 'complex' string. What you want to do turn only the value inside the first_name option, because in that case if the name exists it will still be the same, and if it doesn't, it will be turned into "nil".
Secondly, the method inspect isn't the best choice here, because the returned string will never be empty, given that nil.inspect => "nil". What you should use is the method to_s, wich will behave like this when applied to nil: nil.to_s => "".
Finally, you could update your code to:
<% if #request.query['first_name'].to_s.empty? %>
Hi! What is your name?
<% else %>
Welcome! <%= #request.query['first_name'] %>
<% end %>
I'm trying to understand how I'm getting two different outputs from rails
If I have this:
<%= if value.user.present?
link_to value.user.email, value.user
end %>
I gives me what I wanted. It out puts the email of the user with its link associated with it.
But when I take the if statement out,
<%= link_to value.user.email, value.user %>
I get this error.
undefined method `email' for nil:NilClass
I don't get it? Aren't I just doing the same thing with the first statement? It outputs the link_to.
Why am I get two different outputs with what I thought was the same statement?
That's happening because you called a method on nil (value.user is nil)
An easy way to shorten it up...
<%= link_to(value.user.email, value.user) if value.user %>
A note, if value.user could be nil (not false), but is still considered 'falsey' in ruby.
in your if condition it checks whether your user is present and if present it will give the proper output... but somehow if your user is not present it will check like for nil and generates that error, to avoid that you have to write the condition or rescue nil on that line...
This error would pop up if any of your value.user items do not have an email associated.
I've encountered this when migrating and not all rows have the item assigned.
In my method via some calculations a get data, then i need to view it in view, but if write
#ar.each do |a|
when i have only one record i get error, also when i have one error each is bad idea. So how to do this this?
So i have such code in method:
non_original = []
#articles.each do |a|
non_original << get_non_tecdoc("LA44", 1, "KNECHT")
end
#non_original = non_original
get_non_tecdoc returns object, or nothing...
So in view i have:
-#non_original.each do |no|
=no.brand
=no.description
=no.price
=no.quantity
But what to do if #non_original has one record, then #non_original.each gives error. So how to do check in view? If #non_original has one record, than simple #non_original.brand etc, but if more than one, than use each loop?
This will work with #ar as a single value as well as an array:
Array(#ar).each do |a|
p a
end
This Array is a method on Kernel.
<%= debug #ar %>
This will give you a nice YAML format to look at in your view (assuming ERB).
EDIT: I believe this is what you want, since you're not interested in debugging.
In your controller, use the splat operator to convert a singleton element to an array (it doesn't modify arrays):
#ar = *#ar
Then #ar.each will work as expected in your view.
Alternatively, you could check in your view:
<% if #ar.is_a?(Array) %>
<% #ar.each ... %>
<% else %>
<%= #ar %>
<% end%>
Why don't you try using #ar.inspect and output it to the console to see the instance variables contents.
As long as #ar is an array you should not get a error. If you are returning one record change it to an array with one record.
If you are using active record query interface like the "where" clause; it will return an array with 0 or more active_record objects. If you use find it will return one instance of an active_record object.
So if your method that queries is using the active record where clause #ar should always return an array.
Please try this:
Tablename.find_by_table_id
Example:
if account_id is 10 then, take following example,
#getResults = Account.find_by_account_id(10)
It will gives single record.
we can get values using #getResults.id,#getResults.name ....like wise.
Is there a way to write a clean if nil then in a view. Assuming my lack of ruby is biting me here. Example,
If object nil, then return, nothing found
have
<%= #objects.count if #objects %>
want something like this
<%= #objects.count if #objects then "nothing found" %>
There are many ways to write something like this.
Something simple would be:
<% if #objects %>
<%= #objects.count %>
<% else %>
nothing found
<% end %>
If you get into a slightly more complex conditional I would suggest moving the logic into a helper and call it from the view. ex:
<%= count_for(#object) %>
Here's a good solution for you:
<%= "nothing found" unless #objects.try(:length).to_i > 0 %>
One of the issues is that you can't run count on a nil object. Therefore you need to use Rails' super handy .try() method to return nil when #objects = nil, rather than NoMethodError.
Next issue: You can't make a comparison between nil and a number using > so you need to convert the results of #objects.length to an integer which will return 0 for nil.
Lastly, try calling length rather than count. This will avoid running any extra queries when #objects is defined.
Avoids: SELECT COUNT(*) FROM 'objects'
Also if you want to display the count using this one-liner technique you can simply write up a shorthand if/else statement as follows:
<%= #objects.try(:length).to_i > 0 ? #objects.length : "nothing found" %>
One last option:
Use the pluralize method, which can handle a nil count:
Showing <%= pluralize( #objects.try(:length), 'object' ) %>
Sorry, I know this is pretty late, but hopefully helpful for someone else!