Rockster160
Rockster160

Reputation: 1648

Filter by most recent association for all objects ActiveRecord

Say I've got an object Assignment that has_many :exercises

What is the best way to scope assignments based on ONLY the most recent exercise for each object? Or, how can I select only the Exercise that is the most recent for each assignment?

Something like this is what I'm imagining for the latter:

Exercise.distinct(:assignment_id)

But that doesn't work. (Returns all Exercises) I've also tried

Exercise.group(:assignment_id)

But that complains that the exercises.id column must also appear in the group clause. However, adding that groups by both assignment_id and id (obviously), which, again, returns all Exercises.

My other option, which I'd also like to know how to do (Never seems to work out as well as I want) is to be able to filter assignments based on the most recent exercise.

Assignment.where("most_recent_exercise.created_at <= ?", DateTime.current.beginning_of_day)

Any help is greatly appreciated!

As an example, given the below objects (Assume created in the order the ids are given)

Assignment 1
  Exercise 1
  Exercise 2
  Exercise 3

Assignment 2
  Exercise 4

Assignment 3
  Exercise 5
  Exercise 6

I want to be able to call

Exercise.most_recent and get exercises 3, 4, 6 since they are the most recently created Exercise for their respective Assignments.

Upvotes: 0

Views: 147

Answers (1)

jvillian
jvillian

Reputation: 20263

how can I select only the Exercise that is the most recent for each assignment?

@assignment.exercises.order(:created_at).last

This is not pretty, but may work:

Exercise.where(
  id: Exercise.all.order(:assignment_id, :created_at).
      map{|e| e.attributes.with_indifferent_access}.
      group_by{|e| e[:assignment_id]}.
      map{|k,v| v.first}.
      map{|e| e[:id]}
)

Upvotes: 1

Related Questions