Rails each skipping if nil value - ruby-on-rails

I'm currently iterating through a list of arrays, referencing data from a joined record (Students):
index.html.erb
<% #activities.compact.each do |activity| %>
<div class="img" style="background-image: url(<%= activity.student.image.url(:thumb) %>)">
<% end %>
If for some reason a user deletes the joined record (Student), Rails throws this error:
NoMethodError in Activities#index
undefined method `image' for nil:NilClass
Is there a way to tell Rails to still render the page but sub in a default value to that record if none exists?

Sure! For example,
activity.student.try{|s| s.image.url(:thumb)} || image_path("default.png")
You might want to put that into a helper though, since it seems like it's starting to get complicated.
Also, I would be wary of XSS problems here if users control any part of the attachment URL (e.g. if you are using the filename of their uploaded file). I'm not sure whether erb does the right thing when outputting to an attribute. Maybe it does---I'm just not sure.

If you use carrierwave gem for uploads, there'a built-in solution for default images https://github.com/carrierwaveuploader/carrierwave#providing-a-default-url

Try
<% #activities.compact.each do |activity| %>
<% if activity.student.present? %>
<div class="img" style="background-image: url(<%= activity.student.image.url(:thumb) %>)">
<% end %>
<% end %>

Related

Rails: Using debugger to change execution path of Rails application

I'm running Rails v4.x and Ruby v2.3. I'd like to use a debugging tool (e.g., debugger) to dynamically test different execution paths in a Rails view. Specifically I'm trying to test the two paths of an if statement (ie., "if" block and "else" block) within a Rails view. Here is the code withing the View I'd like to test:
<% if #categories.any? %>
<% #categories.each do |category| %>
<ul class="listing">
<div class="row">
<div class="well col-md-4 col-md-offset-4">
<li class="article-title">
<%= link_to "#{category.name}", category_path(category) %>
<li><small><%= pluralize(category.articles.count, "article") %></small></li>
</li>
</div>
</div>
</ul>
<% end %>
<% else %>
<div class="center">
<p>There are no categories currently defined at this time</p>
</div>
<% end %>
To do this I'd like to be able to dynamically change the return value of the #categories.any? method so as to force the desired execution path. Is there a tool that I could use to do this? Can I do with "debugger"? Pry?. If so could you provide some simple instructions of how it could be done?
NOTE: #categories is an instant variable containing values from a data model (Category). I'd prefer not delete the contents of the Category table just to test the else part of the aforementioned code.
Regards,
Jet
Well, as you will have to edit the file anyway, to add a debugger line, you can just as well add another variable, can't you?
<% if (#categories.any? && !#never_run) || #always_run %>

How to check if an array index exists using Ruby and/or Rails

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

passing a hash to a route in rails

In the preview action in my controller, I have
#models = Model.all
In the view, Im trying to loop through all the models, draw out their associated images, and use those to link_to their own profiles.
<% #models.each do |m| %>
<div> <%= link_to(image_tag (m.avatar.url(:thumb)), model_path())%> </div>
<% end %>
I need to pass in the id of each model to the route. Using m.id doesn't work because the route is expecting a hash.
Not entirely sure how to do this. Other posts on SO refer to unsaved instances and such, which aren't really relevant to this.
Try changing your view code from this:
<% #models.each do |m| %>
<div> <%= link_to(image_tag (m.avatar.url(:thumb)), model_path())%> </div>
<% end %>
To:
<% #models.each do |m| %>
<div> <%= link_to(image_tag(m.avatar.url(:thumb)), model_path(m))%> </div>
<% end %>
As usual the error might be in a completely different place - your brackets.
model_path can accept both list of attributes and a hash. Most likely you think it is expecting a hash due to the error message (which you should include in the question). In fact however, you are passing the path to the image_tag, not to the link_to:
link_to(image_tag (m.avatar.url(:thumb)), model_path())
is parsed as
link_to( image_tag(m.avatar.url(:thumb), model_path()) )
While:
link_to(image_tag (m.avatar.url(:thumb)), model_path())
is parsed as
link_to( image_tag(m.avatar.url(:thumb)), model_path() )
This space between a method name and a bracket is a silent killer. It is a image_tag which is expecting a hash in a second argument. :)
That being said - it will still not work, but you should get a different problem now.

Rails Carrierwave url is nil unless queried again

I am having an issue with carrierwave/active-record in my rails application. My problem is that the following code resolves all of the images to null
<% Ad.all.limit(30).each do |ad| %>
<img src="<%= ad.carrier_image.url %>" >
<% end %>
Where as the following renders all the images just fine
<% Ad.all.limit(30).each do |ad| %>
<img src="<%= Ad.find(ad.id).carrier_image.url %>" >
<% end %>
The urls are there, just on the initial loop the carrier_image does not seem to be preloaded into the active record objects I think this is an issue with my understanding of rails eager loading, but I am having trouble figuring out how one would avoid this issue
What happens when you use the rails image_tag helper? You're also missing the brackets off the url call as per the carrierwave documentation, but I don't think that's what's causing you drama.
<%= image_tag ad.carrier_image_url() %>
As a side note, you should really move the "Ad.all.limit(30)" out of your view if you wish to keep it all "railsy".

how to use database field as attribute value in rails template

I basically want to do this:
<% #videos.each do |vid| %>
<div id=vid.location>
...
<% end %>
how do I evaluate vid.locaion and use it as the id attribute?
i've tried the above, id="#{vid.location}" and id="<% vid.location %>" (the last one with and without quotes.
any help appreciated
Easy,
<div id="<%= vid.location %>">
Your first attempt was wrong as you're still in markup - not ruby. In the last one you used <% rather than <%=, so while it was evaluating the getter, it just didn't present it to your view.

Resources