Last active
April 28, 2020 18:28
-
-
Save pmn4/eb58b036cc78fb41a36c56bcd6189d68 to your computer and use it in GitHub Desktop.
ActiveRecord: Max By with Group
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module MostRecentBy | |
def self.included(klass) | |
klass.scope :most_recent_by, ->(group_by_col, max_by_col) { | |
from( | |
<<~SQL | |
( | |
SELECT #{table_name}.* | |
FROM #{table_name} JOIN ( | |
SELECT #{group_by_col}, MAX(#{max_by_col}) AS #{max_by_col} | |
FROM #{table_name} | |
GROUP BY #{group_by_col} | |
) latest | |
ON #{table_name}.date = latest.#{max_by_col} | |
AND #{table_name}.#{group_by_col} = latest.#{group_by_col} | |
) #{table_name} | |
SQL | |
) | |
} | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Price < ActiveRecord::Base | |
include MostRecentBy | |
belongs_to :security | |
scope :most_recent_by_security, -> { most_recent_by(:security_id, :date) } | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Security < ActiveRecord::Base | |
has_many :prices | |
has_one :latest_price, | |
-> { Price.most_recent_by_security }, | |
class_name: 'Price' | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Security.all.includes(:latest_price).to_json(include: :latest_price) | |
# or | |
Security.where(selection: :criteria).includes(:latest_price) | |
.to_json(include: :latest_price) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The goal is to eagerly load the price with the most recent date for each security in a set with as few queries as possible (two, ideally).
Price.most_recent_by
does the work of composing a query to accomplish that.The result: