4

I have a Commodity(name:string) model and a Price(amount:float) model such that:

class Commodity < ApplicationRecord
  has_many :prices
end

And

class Price < ApplicationRecord
  belongs_to :commodity
end

Thus, one commodity can have many prices.

I have a Ransack search form for Commodity, which obviously enables a user to search for commodities. I wish to include a sort_link(@q, :prices_amount) sorting filter. Clicking this link should display all the commodities sorted according to their prices (if one commodity has multiple prices, that commodity will show multiple times, with each repeated commodity's price shown accordingly). Currently, Ransack does indeed show a commodity multiple times, (as many as the number of prices each commodity has) but I do not know a way to display that price for each repeated commodity.

I wish to know how should I display that price in my frontend. I display the query results via:

<%[email protected] do |commodity|%>
  <%=commodity.name%>    
  <%=commodity.prices.first.amount%> <!-- In place of prices.first, I was to display the amount that Ransack found -->
<%end%>

I'm using prices.first.amount right now as a placeholder. How do I replace this by the amount that Ransack found while sorting?

4
  • can you give more information? you have a commodity table that shows all the commodities, right? but you want to sort by prices, but if it has many prices, how do you want to do it? the sort link with use the lower price that the commodity has, or the bigger? give more details please
    – xploshioOn
    Commented Jun 7, 2018 at 16:37
  • Hi @xploshioOn, I have edited my question. If it's still not clear as to what I want, I'll edit it again.
    – a3y3
    Commented Jun 8, 2018 at 8:07
  • Ok it gives more details, can you add too the code that you have at the moment to show all the commodities?
    – xploshioOn
    Commented Jun 8, 2018 at 19:07
  • @xploshioOn, I've added code to display commodities.
    – a3y3
    Commented Jun 12, 2018 at 10:24

2 Answers 2

3
+50

I would recommend creating a scope to include the price with the Commodity instance. e.g.

class Commodity < ApplicationRecord
  scope :with_price, -> {joins(:prices).select("commodities.*, prices.amount as price_amount")}
end

This will create a virtual attribute price_amount on your instances of Commodity

In the controller it would be something like

@q = Commodity.ransack(params[:q])
@commodities = @q.result.with_price

Assuming that you're "Displaying" these as a table you can display the results as requested using the following

<table>
  <thead>
    <tr>
      <th><%= sort_link(@q, :name, 'Commodity' %></th>
      <th><%= sort_link(@q, :prices_amount, 'Price') %></th>
    </tr> 
  </thead>
  <tbody>
    <% @commodities.each do |commodity| %>
      <tr> 
        <td><%= commodity.name %></td>
        <td><%= number_to_currency(commodity.price_amount) %></td>
      </tr>
    <% end %>
  </tbody>
</table>
2
  • Perfect! This is brilliant, simple, and exactly what I was looking for. This should probably be explained on the Ransack documentation too.
    – a3y3
    Commented Jun 13, 2018 at 8:35
  • 1
    @a3y3 this actually has nothing to do with ransack as you mentioned your sorting was working correctly the issue was you were not sure which price was causing the position. When you run a select query in ActiveRecord it will map all the columns into attributes for your active record instance so we just added prices.amount to those attributes under the alias price_amount so that you knew which price caused the position in the sort. Glad it worked out for you. Commented Jun 13, 2018 at 12:53
0

There is some missing information to this to be clear, but yes, it's simple. and you even have the answer, if you have the association like in the example you posted, then it have to work with the code you sent

sort_link(@q, :prices_amount)

where "prices" is the name of the association and "amount" is your attribute.

Not the answer you're looking for? Browse other questions tagged or ask your own question.