I have a rails table called Movies. Movies are being collected and saved from an API which means that some movies may have a release_date and some may not.
All Movies are being displayed on the home page and they are sorted by {|t| - t.release_date.strftime("%Y%m%d").to_i}
<% #movies.sort_by{|t| - t.release_date.strftime("%Y%m%d").to_i}.each do |movie| %>
<% movie.title %>
<% movie.release_date.strftime("%Y") %>
<% end %>
So this code works fine but only as long as the returned movies have a release date. If they don't have a release date assigned, it gives me the following error.
ActionView::Template::Error (undefined method `strftime' for nil:NilClass):
But im only getting this error if the movie has no release_date.
So how can i add an exception to only display films WITH a release_date, where using strftime would no longer be a problem.
I've tried
<% unless movie.release_date.blank? %>
<% #movies.sort_by{|t| - t.release_date.strftime("%Y%m%d").to_i}.each do |movie| %>
<% #movie.title %>
<% #movie.release_date.strftime("%Y") %>
<% end %>
<% end %>
But that doesn't work as it gives an undefined method for 'movie'
You should be able to use reject to reject nil release_date like follows:
<% #movies.reject{ |m| m.release_date.nil? } %>
Another problem is you are using the variable movie as instance variable #movie within your each block.
Try:
<% #movies.reject{ |m| m.release_date.nil? }.sort_by{|t| - t.release_date.strftime("%Y%m%d").to_i}.each do |movie| %>
<% movie.title %>
<% movie.release_date.strftime("%Y") %>
<% end %>
Update:
And yes, as pointed by #NicolasGarnil in his answer, it's better to do these in SQL side than in ruby side. Select only the required records and let database do the sorting. So you could update your code to be something like:
In controller:
#movies = Movie.where('release_date is not null').order('release_date desc');
Then in your view:
<% #movies.each do |movie| %>
<% movie.title %>
<% movie.release_date.strftime("%Y") %>
<% end %>
For performance reasons you should not be using ruby to sort your records. This should be done at a database level.
You should first ensure that the release_date values are persisted in an appropriate format and then just use Movie.order("release_date desc"). Records with null values will be placed at the end of the results.
Related
This is so simple but isnt working. What am I missing?
controlelr
#guide = Guide.friendly.find(params[:guide_id])
#category = #guide.categories.friendly.find params[:id]
#items = #category.category_items
view
<% #items.each do |item| %>
<%= item.category_item_values.value %>
<% end %>
gives the no method error of
undefined method 'value' for #<CategoryItemValue::ActiveRecord_Associations_CollectionProxy:0x007ff9706d24c0>
There is a values column in the category_item_values table so I'm not sure what the problem is.
item.category_item_values is the CollectionProxy instance (one might think of it as of an kinda array.)
Each category_item has [likely, you did not provide sufficiently enough info to guess more precisely] many values. If the assumption above is correct, here you go:
<% #items.each do |item| %>
<% item.category_item_values.each do |value| %>
<%= value %> # or maybe (depending on your model) <%= value.value %>
<% end %>
<% end %>
You will have to loop over each of the category_item_values to get the result as this suggests <CategoryItemValue::ActiveRecord_Associations_CollectionProxy:0x007ff9706d24c0> that your category_item_value is a association.
So you could do something like
<% item.category_item_values.each do |category_item_value| %>
<%= category_item_value.value %>
<% end %>
I'm new to rails and I'm trying to build a view that will list the parents and related children
Ex:
Passport has many Visas
I want to list information about the passport and the visas that the passport has.
So I have
<% #passport_list.each do |passport| %>
# passportFields
<% passport.visas.each do |visa| %>
<%= t.text_field :visa_type %>
<% end %>
<% end %>
I'm getting the error
undefined method `visa_type' for #Passport:0x000000091b8b28
It looks like rails is trying to find the property visa_type for passport, instead of in visa. How does the scope work within each? Can I force it to access visa_type from visa?
I think you're looking for the fields_for form helper. This will allow you to create fields for the relevant visa attributes. Replace your code sample with the following, and you should be all set.
<% #passport_list.each do |passport| %>
# passportFields
<% t.fields_for :visas do |visa_fields| %>
<%= visa_fields.text_field :visa_type %>
<% end %>
<% end %>
You can also iterate over the list as follows:
<% #passport_list.each do |passport| %>
# passportFields
<% passport.visas.each do |visa| %>
<% t.fields_for :visas do |visa_fields| %>
<%= visa_fields.text_field :visa_type %>
<% end %>
<% end %>
<% end %>
For more information on fields_for, check out the link I added above, and to customize further for your use case, check out the "One-to-many" section.
IMO you should always handle the null case of an object.
Something like this if you use rails (present? is a Rails function)...
<% if #passport_list.present? %>
<% #passport_list.each do |passport| %>
passportFields
<% passport.visas.each do |visa| %>
<%= t.text_field :visa_type %>
<%end%>
<%end%>
<% else %>
<p>Nothing to see here</p>
<% end %>
However if your #passport_list is backed by an ActiveRecord Query, you can handle this in the model/helper/controller by returning the .none query on the model. Note that this differs from an empty array because it is an ActiveRecord Scope, so you can chain AR queries onto it
# scope on AR model
def self.awesomeville
where(country_of_origin: "awesomeville")
end
# method queried in controller
#passport_list = Passport.all
if #passport_list.present?
#passport_list
else
Passport.none
end
# additional filtering in view is now possible without fear of NoMethodError
#passport_list.awesomeville
Whereas a ruby Array would raise an error as it would respond to the Array methods.
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").
im having an issue displaying the name per category with the following code,
Can anyone advise please?
<% if #products.category.name == "categoryname" %>
<% #products.each do | product | %>
<%= product.name %>
<% end %>
<% end %>
I get the following error:
undefined method `category' for #
It appears you're calling the if statement on the #products.all
#products doesn't have a .category I'd assume judging by your error.
You'll need to change the code to this for it to work...
<% #products.each do | product | %>
<% if #products.category.name == "Name Here" %>
<%= product.name %>
<% end %>
<% end %>
I am assuming that #products is an array or AR::Relationship. You probably want/need to loop through that variable. Looks like you are trying to access a specific instance instead of the whole array.
maybe, #products.first.category.name or something like that
I have a collection of invoices. One of the attributes is exchange_rate (is used to calculate the currency from US dollars for Mexican pesos). I need to create a warning if even ONE of the records doesn't have an exchange_rate set.
I could check if the exchange_rate of a record in a collection is blank like this...
<% is_blank = false %>
<% #invoices.each do |invoice| %>
<% if invoice.exchange_rate.blank? %>
<% is_blank = true %>
<% end %>
<% end %>
<% if is_blank %>
shoot warning: all of the invoices must have an exchange rate in order
to calculate pesos total
<% end %>
What is a more Railsy way of writing the above?
Simply like this, using the Enumerable#any? method:
<% if #invoices.any? { |i| i.exchange_rate.blank? } %>
shoot warning: all of the invoices must have an exchange rate in order
to calculate pesos total
<% end %>