0

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?

5
  • How are these products related? Commented Nov 13, 2016 at 17:25
  • With products doesn't come to my mind any example which makes sense. I'll edit the question Commented Nov 13, 2016 at 17:34
  • I still can't see the connection between your records. In my point of view you loop through random sets of records and display it. What's the connection between all these records? Do they share the same type, id, or what? Commented Nov 13, 2016 at 18:08
  • in that example they share same type Commented Nov 13, 2016 at 18:19
  • but just to make sure, i'm not trying to nest loops. i just want call separate attributes from different instances Commented Nov 13, 2016 at 18:22

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

6 Comments

Hi thanks for your answer. The point of the question was understanding the usage of different loops in a view. So basically looping multiple instance variables is not something doable but instead, when I need to apply conditions that cannot exist together (such as order asc and desc) the proper way is to set a local variable or an instance method. Am I understanding it correctly?
Generally multiple instance variables should not be used, for any reason. See rule # 4 of Sandi Metz' rules for developers... robots.thoughtbot.com/sandi-metz-rules-for-developers
It's ok to loop through nested relationships, but generally two concurrent loops are challenging. What you can do in those cases is use #each_with_index on a primary "loop" and then use the index to access elements in other collections.
Ok this made clear what was confusing me and gave me better alternative approaches so I can accept this answer. Link too was interesting as I'm new to rails and at the moment I'm focusing on best practices to follow. Thanks a lot!
Sorry let say I have also a column customer_id. On the second solution how would I render it? type.transaction.customer.name? And also is it really necessary to have the instance method by type on the second solution? Couldn't it be by transaction as the first one? The first solution is very clear and easy but it puts too much logic on view. The second solution is better but more confusing. Looking at the first solution isn't it possible to define first_transaction on transactions model or controller instead of view? That would be perfect for clarity.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.