I am trying to output just the date on the generated line, but when I execute this code, which I am sure is not elegant at all, it gives me undefined method 'strftime' for nil:NilClass
<% #person.subordinates.each do |sub| %>
<tr>
<td>
<% if sub.position == 'alumni' %>
<p>
<%= link_to(sekret_person_path(sub.position, sub.user_name)) do %>
<strong><%= sub.fname %> <%= sub.lname %>,</strong>
<% end %> <%= sub.startdate.strftime("%Y") %> - <%= sub.graddate.strftime("%Y") %>
</p>
<% end %>
</td>
</tr>
<% end %>
Further up in my code, I am using #person.startdate.strftime("%m/%d/%Y") without any issue, but I think my issue is that I am using the sub call, which is grabbing any people that are flagged as sub to this person.
Your error says that one of your attributes is nil. The sytax is correct. Try debugging with:
#person.subordinates.select { |sub| sub.startdate.nil? || sub.graddate.nil? }
The elements that are retrieved on this line will be the ones that are giving you errors, because you are trying to run nil.strftime('%Y'), which makes sense.
You should use a condition on your .erb to stop it, like:
<%= sub.startdate && sub.startdate.strftime("%Y") %> - <%= sub.graddate && sub.graddate.strftime("%Y") %>
It is not an error with Rails.
strftime is being called on nil object. Make sure you are calling strftime on a date, time, or datetime object.
Refer to strftime on rails apidock - https://apidock.com/ruby/DateTime/strftime
Another way to solve this that will guard against nils would be:
<%= sub.startdate&.strftime("%Y") %> - <%= sub.graddate&.strftime("%Y") %>
That way you don't have to add a conditional to make sure that any method/attribute in the chain exists prior to calling them. This works because of the safe navigation operator, which is explained in depth here: https://rubyinrails.com/2017/11/17/safe-navigation-operator-ampersand-dot-in-ruby/
Related
Is there a Ruby (preferably) or Rails way to check if the second index of an array exists?
In my Rails (4.2.6) app I have the following code in my view that shows the first two thumbnails for an array of photos:
<% if array.photos.any? %>
<%= image_tag array.photos.first.image.url(:thumb) %>
<%= image_tag array.photos[1].image.url(:thumb) %>
<% end %>
However if there is no second item in the array, then there is an error
I've tried the following if statements to make the rendering of the second thumbnail conditional, but they don't work:
<% if array.photos.include?(1) %>
<% if array.photos.second? %>
<% if array.photos[1]? %>
<% if array.photos[1].any? %>
I figured that another way to get what I want would be to simply check the length of the array
Still I was wondering if Ruby (or Rails) had a method or way to check if a specific index in an array exists or not. Thanks in advance
EDIT: To clarify I just want to show the first two thumbnails in the array, if any
You can use an .each, but if you want to follow this approach.
Instead of this:
<%= image_tag array.photos[1].image.url(:thumb) %>
Maybe you can use this:
<%= if(!array.photos[1].nil?) image_tag array.photos[1].image.url(:thumb) %>
Or:
<%= image_tag array.photos[1].image.url(:thumb) unless array.photos[1].nil? %>
Here, why not
(0...array.photos.size).each do |photo|
......
end
array.photos.each do |photo|
......
end
Say I have an instance variable #n, and I'm calling <%= #n.title %> in my view.
If #n equals a valid record, then this will print normally. But if #n is blank or invalid, then the entire page will show an error message, because of this one little line.
Is there a way to get #n.title to just print nil if #n is nil or invalid?
I'm looking for a way to do this without conditional statements. For example, if I wanted to print
<%= #v1.title %>,<%= #v2.title %>,<%= #v3.title %>,<%= #v4.title %>,
if I wanted to use conditionals to print without errors, it would require 12 lines of code:
<% if #v1 %>
<%= #v1.title %>,
<% end %>
<% if #v2 %>
<%= #v2.title %>,
<% end %>
<% elsif #v3 %>
<%= #v3.title %>,
<% end %>
<% elsif #v4 %>
<%= #v4.title %>,
<% end %>
It seems a shame to use 12 lines on this. It would be nice to be able to accomplish the error-handling right when printing.
You can totally do this easily with the try() method. I use it all the time.
<%= #n.try( :title ) %>
That will return nil if #n is nil or if the title method doesn't exist on #n.
You can also chain them together like this:
#n.try( :title ).try( :to_s )
Or even use it on a hash:
#n.try( :[], 'name' ) # Which is the same as #n['name']
See http://api.rubyonrails.org/classes/Object.html#method-i-try
EDIT (Jan 11, 2016)
You can now use the "safe navigation operator" as of Ruby 2.3.0.
#n&.title&.to_s
As well as the Array#dig and Hash#dig methods introduced in Ruby 2.3.0.
hash = { 'name' => 'bob' }
hash.dig( 'name' ) # Which is the safe way to do hash['name']
You can add some logic to your view that differentiates between development (where some errors can be ignored) and production environments (where errors should cause your app to fail in an obvious and ugly manner). Ruby's nil has a "falsey" nature, so you can use that concept to your benefit as well.
<% if Rails.env.development? %>
<% if #n %>
<%= #n.title %>
<% else %>
<%= nil %>
<% end %>
<% else %>
<%= #n.title %>
<% end %>
I'm building a simple app for displaying movies using themoviedb gem. However, when I try to do a search query, it displays the error I mentioned. Now, that doesn't happen every time - only in certain cases (e.g. Matrix works fine, but Fight Club shows the error)
Here's my code:
<% #movie.each do |movie| %>
<%= link_to movie_path(movie.id) do %>
<%= image_tag("#{#configuration.base_url}w154#{movie.poster_path}") if movie.poster_path %>
<% end %>
<div class="moviesindex">
<%= link_to movie.title, movie_path(movie.id) %>
(<%= movie.release_date.to_date.strftime("%Y") %>) <br />
</div>
<% end %>
Be forgiving for realease_date if movie.release_date can be nil at times using try:
<%= movie.release_date.try(:year) %>
This will give you release year if release_date is valid and gives you nil if release_date is nil.
Since release_date, I assume is already either a Date or DateTime or ActiveSupport::TimeWithZone, the to_date is not necessary. Also I think date.year is more cleaner than date.strftime("%Y").
In the Rails views, I regularly find lines like:
<%= my_var %>
What if I had a slightly more complex situation and I needed to trigger the printing with plain code instead of <%= %>?
Example:
<% .....
puts my_var
%>
I guess is a silly question but bear with me, I'm a ruby beginner.
Look at documentation of ERB
In <% %> you put expressions that are not for printing out.
In <%= %> you put code for printing out.
Example:
<% if #cost < 10 %>
<b>Only <%= #cost %>!!!</b>
<% else %>
Call for a price, today!
<% end %>
You can use helper method which is much more cleaner.
I'm fairly new to rails (only about a month's experience), so this may be trivial. In my app, if I call
<%= Group.find(:all).each do |g| %>
<p><%= g.name %></p>
<%= end %>
it prints out all of the groups' names correctly. However, afterwards, it returns all of them (with the hexcodes, and stuff). I figure that's because .find returns everything you have it iterate over. Anyways - on to my question: Is .find the wrong method, or how do I go about iterating over every Group, without returning them afterwards?
I would appreciate any help or insight you all have.
Thanks!
I'm guessing you're doing something like
<%= Group.find(:all).each do |g| %>
<p><%= g.name %></p>
<%= end %>
That would print the return value of the whole statement. Instead, do this
<% Group.find(:all).each do |g| %>
<p><%= g.name %></p>
<% end %>
That wouldn't print the returned value.
Sidenote: Group.find(:all) is the same as Group.all