The following loop goes through the sales column and lists all 4 existing product values, like 19.99 19.99 3.99 3.99 to the corresponding user id.
<% #sales.each_with_index do |sale, index| %>
<% if current_user.id == sale.user_id %>
<% price = Warehouse.where(:product => sale.product).pluck(:mrr) %>
<%= value = price.split(',').join('.').to_f %>
<% else %>
<% end %>
Now I want to save the results/values into a new global variable and add up each out of "value". So the result of 19.99 19.99 3.99 3.99 should be 47.96.
I'm completely lost. Any Ideas?
You could do something like this:
<% total = 0 %>
<% #sales.each_with_index do |sale, index| %>
<% if current_user.id == sale.user_id %>
<% price = Warehouse.where(:product => sale.product).pluck(:mrr) %>
<%= value = price.split(',').join('.').to_f %>
<% total += value %>
<% end %>
<% end %>
<%= "Total is #{total}" %>
It is highly questionable to have code like this in the view though. You could get prices and calculate totals in your controller instead.
Also note that you are missing an end. I changed the unneeded else to an end.
In your controller you can create a instant variable prefixed by # so it can be used throughout your view
For example in your controller
#total_value = 0
And in your view
<%#sales.each_with_index do |sale, index| %>
<% if current_user.id == sale.user_id %>
<% price = Warehouse.where(:product => sale.product).pluck(:mrr) %>
<%= value = price.split(',').join('.').to_f %>
<% #total_value += value %>
<% else %>
<% end %>
You shouldn't add that kind of logic in your view. Create a view object class (that the controller instantiates) too handle all of this. You also probably can do something like:
user.sales.each do |sale|
total += find_price(sale)
# do more stuff
end
If you are asking 'if current_user.id == sale.user_id' then you most likely doing it wrong.
In that view object you could have a hash that has all the prices you want to show and iterate over that in your view.
Related
In my rails app I have below code to print some data from database.
<% #di.each do |d| %>
<% if d["visibility_team"] == 'for_all' %>
//my code goes here
<% end %>
<% end %>
I just want to print first 3 occurrence which fulfill the d["visibility_team"] == 'for_all' condition.
How can I do this?
If you can't get #di as 3 records from DB, how about keeping counter how many ds were printed?
Something like this (feel free to style it the way you want)
<% counter = 0 %>
<% #di.each do |d| %>
<% if d["visibility_team"] == 'for_all' %>
<% counter += 1 %>
<% break if counter == 3 %>
//your code goes here
<% end %>
<% end %>
However it's usually a bad taste to have so much logic in views.
Let say I have a controller Transactions:
#transactions = Transaction.all.group(:type)
#transaction_date_asc = Transaction.all.order(:DATE => :desc).group(:type)
#transaction_date_desc = Transaction.all.order(:DATE => :asc).group(:type)
In my view I need to loop all 3 instances.
Something like this where I want to show newest and oldest amount or discount for each transaction type.
<% #transactions do |transaction|%>
transaction.type.name
<%end%>
<% #transaction_date_asc do |transaction_asc|%>
transaction_asc.amount
<%end%>
<% #transaction_date_desc do |transaction_desc|%>
transaction_desc.amount
<%end%>
<% #transaction_date_asc do |transaction_asc|%>
transaction_asc.discount
<%end%>
<% #transaction_date_desc do |transaction_desc|%>
transaction_desc.discount
<%end%>
How am I supposed to place loops, columns and <%end> in my view?
Someone may come up with a better solution, but from my seat it looks like you need to do a query for each group in your view to get the first date transaction, but on the plus side, you only need one query in the controller for the transactions with the last date.
#transactions = Transaction.group(:type).having('DATE = MAX(DATE)')
In the view...
<% #transactions do |transaction| %>
<% first_transaction = Transaction.where(type: transaction.type).order('transaction_date').first %>
<%= transaction.type.name %>
<%= first_transaction.amount %>
<%= transaction.amount %>
<%= first.transaction.discount %>
<%= transaction.discount %>
<% end %>
However... to keep the logic in the view cleaner you could have an instance method for transaction types that will return the first and last transaction.
class Type << ActiveRecord::Base
def first_transaction
Transaction.where(type: self).order('transaction_date ASC').first
end
def last_transaction
Transaction.where(type: self).order('transaction_date DESC').first
end
end
Then in the controller...
#types = Type.all
then in the view...
<% #types.each do |type| %>
<%= type.name %>
<%= type.first_transaction.try(:amount) %>
<%= type.last_transaction.try(:amount) %>
<%= type.first_transaction.try(:discount) %>
<%= type.last_transaction.try(:discount) %>
<% end %>
The reason I'm suggesting #try is to handle the case of no transactions being present for a specific type.
I have created a simple appointment system, and I now need to display something inside a loop if there's two or more appointments with the same date and time. The appointments are displayed in order of time, so they're just appearing one after the other.
Controller
def index
#todays_apps = current_user.appointments.order(time ASC)
end
View
<% #todays_apps.each do |app| %>
<%= app.business_name %>
<%= app.business_address %>
<%= app.time %>
<% end %>
I'm looking to display a message or icon the appointment shares a date and time with another appointment. Tried a collection of things with no luck.
You can group your collection by time and modify your iteration accordingly. You can group it like
#todays_apps.group_by(&:time)
The outcome will be something like
=> { timestamp1 => [app1,app2], timestamp2 => [app3], timestamp3 => [app4]}
Or you can try a quick hacky way like:
<% previous_time = nil %>
<% #todays_apps.each do |app| %>
<%= app.business_name %>
<%= app.business_address %>
<%= 'Your message or class or anything' if previous_time == app.time %>
<%= previous_time = app.time %>
<% end %>
Try Like this:
controller:
def index
#appointments = current_user.appointments.order("time ASC")
#todays_apps = #appointments.group_by(&:time)
end
View:
<% #todays_apps.each do |time, appointments| %>
<%= time %>
<% appointments.each do |appointment| %>
<%= appointment.business_name %>
<%= appointment.business_address %>
<% end %>
<% end %>
It will list all the appointments for particular time.
Thanks
New to Rails! I have products which are associated to a campaign. Each #product has a .price and .orders_count associated to it.
What I wanted to do is multiply the .price with .orders_count for each #product, and add them all up to get a total cost for the #campaign.
Being new to Rails, wasn't sure how to do the write syntax and had the following in the view. This does the first piece, but does not add them all up at the end. Thanks for the help!
<% #products.each do |p| %>
<% if p.orders_count? %>
<%= (number_to_currency((p.price) * p.orders_count)) %>
<% end %>
<% end %>
Try setting a variable to keep track of the sum of all products, and add the product to it each time through the loop. Try this:
<% sum = 0 %>
<% #products.each do |p| %>
<% if p.orders_count? %>
<% product = (number_to_currency((p.price) * p.orders_count)) %>
<% sum += product %>
<%= product %>
<% end %>
<% end %>
The sum is: <%= sum %>
I'm looking for a function we can use in a loop to do this:
<% for rink in #rinks_in_region %>
<%= rink.city #Show Only if city (n-1) != n %>
<%= link_to_rink(rink.name+" Ice Rink",rink) %>
<br>
<% end -%>
Basically just show the city only if it's different than the previous one.
Make sense? Thanks for your help!
Alextoul
You could use the group_by method on #rinks_in_region to group rinks by city and then use those groupings to display cities and rinks. It returns a hash mapping the thing you are grouping by, city in this case, to the values in the original collection that are in that group. So:
<% #rinks_in_region.group_by(&:city).each_pair do |city, rinks| %>
<%= city %>
<% rinks.each do |rink| %>
<%= link_to_rink(rink.name+" Ice Rink",rink) %>
<br/>
<% end -%>
<% end -%>
<% prev_city = nil -%>
<% for rink in #rinks_in_region %>
<%= rink.city if rink.city != prev_city %>
<% prev_city = rink.city -%>
<%= link_to_rink(rink.name+" Ice Rink",rink) %>
<br>
<% end -%>
Not a ruby answer, but introduce a new variable, call it 'temp' or something and set that to the current element in your foreach. That way at the beginning of your loop you have access to last loops element.
temp = ''
<% for rink in #rinks_in_region %>
<%= rink.city #Show Only if city != temp %>
<%= link_to_rink(rink.name+" Ice Rink",rink) %>
<br>
temp = city
<% end -%>
temp = ''