Check whether a table column has any value - ruby-on-rails

I have model named shirt which has a field named fabric,
In the controller I have;
#fabrics = Shirt.uniq.pluck(:fabric)
On the view I would like to display a <div>...</div> but only if the fabric column of the shirts table contains at least one value. I have tried:
<% if #fabrics != nil %>
<div>
...
</div>
<% end %>
But even when the whole column has no value, the <div> is still visible. I have also tried with
<%if #fabrics != blank %> with no success.
How can I check whether the column is not empty before rendering the div?

Try
<% unless #fabrics.blank? %>

Shirt.uniq.pluck(:fabric) returns a Relation. Therefore it will never be nil.
This Relation defines parts of a sql query. This says: Give me (all|one of the) unique values of fabric in the database. To actually run that query, you need to call a method on that relation that triggers the database call: all, first, each, any?, blank? ...
Through the lack of context, I do not know how you use your Shirt model. But I guess the query will never give you the expected answer. Because Shirt.uniq.pluck(:fabric) will always return something as long there is at least one row in that table. Imagine there is only one row in the table and it's fabric is nil, than Shirt.uniq.pluck(:fabric).blank? would determine Shirt.uniq.pluck(:fabric) to [nil]. And [nil].blank? == false
If you work on one specific shirt, use #shirt.fabric.present? If you want to know if there is at least one shirt in the db without a fabric Shirt.where(fabric: nil).any?
I recommend to read:
http://guides.rubyonrails.org/active_record_querying.html
http://api.rubyonrails.org/classes/ActiveRecord/Relation.html

Try this in controller
#fabrics = Shirt.uniq.pluck(:fabric).reject { |f| f.nil? || f.empty? }

Related

Adding map and/or reject to a reduce in rails view

I am calculating an ROI value that averages over a category.
<% #categories.each do |category| %>
<h3><strong><%= category.name %><strong></h3>
<% #category_products = category.products_by_warehouse_id(params[:id]) %>
<!-- add map/reject below -->
<%#ROI = (#category_products.reduce(0.0) {|acc, item| acc + (item.heritable_sale_price.to_f * item.product_selections.length) / item.purchase_price.to_f }) %>
<p> Category ROI: <%= number_with_precision((#ROI / #category_products.length.to_f), precision:2) %></p>
.....(close tags)......
The value throws NaN when financial data is missing. For individual values, this is fine; however, it does the same for averages with missing data as well.
How can I add map/reject into my call to throw out nil values, and get the average of what's available?
#category_products.length.to_f would also have to skip over empty elements in the array if I go this route as well, to keep the sum and length consistent. Something like .where(purchase_price: [!nil, ""]).size may work.
So, in order to make sure, that none of the methods being accessed within the reduce block, to the item object are going to return nil, which hence, would throw a NoMethodError, you could firstly check them at the moment of creating your query. A where.not would do that. But keeping in mind that it'll leave aside each record in the database which doesn't satisfy the query criteria.
For that, then:
where.not(
heritable_sale_price: nil,
product_selections: nil,
purchase_price: nil
)
For that, you can analyze the option on setting a default value for each of those columns, so this helps you avoiding the previous query, and having to rescue on each case where there's no value for them. You can see the Rails Migration docs.

Ruby Find last record value in has many

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.

Ruby on Rails: Display Number of Search Results Found

I would like to display whatever number of items has been found and returned to the user. In my database, there are 4 items. The search feature works fine. What I now want to display is whatever number of records has been found. If user searches "aI", 2 items gets returned and I want to display the text that 2 items has been found. I tried to do that in view --> layout --> application.html.erb.
You have to count the actual results. Product (with a capital p) will always return all objects of that class in the database. Hence 26. Save the result in an ivar (#products) and call count on that in your view instead.
In Controller
#products = Product.fuzzy_search2(params[:search_string])
In View
<% if #products %>
<span> <%= #products.count %> Books Found</span>
<% end %>
I'm assuming that you are storing the search results in an ivar. You need to call .count on that ivar or .size / .length if it's stored in an array. The issue is that when you are calling Product.count you are getting the count of all products in your database always, because that's exactly what you are telling it to do.

Rails shows rows from model, which aren't created

I have this part of code:
<% current_user.meta_accounts.each do |meta_account| %>
<%= content_tag(:li, link_to(meta_account.name, 'javascript:void(0)')) %>
<% end %>
So, I want Rails to show all my MetaAccounts in list, but I get this:
<li>Wallet</li>
<li>Credit card</li>
<li>Debit card</li>
<li>Debts</li>
<li>javascript:void(0)</li> #This is the problem
So, it also shows me MetaAccount, which isn't created yet.
In my MetaAccounts table I have this. I'm using Postgres.
So, it also shows me the last row, where row_number is *. I don't know why, and how to avoid this.
Thanks for any help!
Try:
<% current_user.meta_accounts.select(&:persisted?).each do |meta_account| %>
<%= content_tag(:li, link_to(meta_account.name, 'javascript:void(0)')) %>
<% end %>
The * row you see in PostgreSQL is not an actual record, it's just a quick way to create new records. If you want to be sure, run the following query:
SELECT COUNT(*) FROM MetaAccounts WHERE user_id=1
It will return 4.
I think the problem comes from an unsaved MetaAccount object in current_user.meta_accounts. This could be the case for instance in a form, where you build an empty object bound to the form. Make sure you don't have a call to current_user.meta_accounts.build(...).
If so, you can simply skip in your each loop all MetaAccount objects with a blank name.

View array or one record in rails view

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.

Resources