3

I have an app with two models, ClassSection and ClassDate (classes in these models refer to classes at a school).

Here are the models:

class ClassSection < ActiveRecord::Base
  default_scope { order('code ASC') }
  scope :published, -> { order('code ASC').order('id ASC').where(published: true) }

  has_many :class_dates, dependent: :destroy

  def begins
    if self.class_dates.count > 0
      self.class_dates.order('start_time ASC').first.start_time
    else
      nil
    end
  end

  def ends
    if self.class_dates.count > 0
      self.class_dates.order('start_time ASC').last.start_time
    else
      nil
    end
  end

  def date_range
    if self.begins != nil && self.ends != nil
      "#{self.begins.to_formatted_s(:class_date)} to #{self.ends.to_formatted_s(:class_date)}"
    else
      "No dates"
    end
  end
end

class ClassDate < ActiveRecord::Base
  scope :upcoming, -> { where("start_time >= ? ", Time.now.to_date).order('start_time ASC').limit(10) }
  default_scope { order('start_time ASC' ) }

  belongs_to :class_section
end

Notice in the scope for :published ClassSections that I'm first sorting based on the code for the class (like ENG 101) and then sorting by the id. I'd rather sort by the first ClassDate based on it's start_time (which is a datetime attribute of ClassDate). How can I write the scope to sort by earliest start_time?

For an answer to this, take a look at Sorting a hash using a method from the corresponding model

Community
  • 1
  • 1
Kevin K
  • 2,191
  • 2
  • 28
  • 41

1 Answers1

2

Do not use default_scope unless you really have to.


You have to include the relation to order on it's attribute(s):

scope :ordered, { includes(:class_dates).order('class_dates.start_time DESC, class_sections.codes ASC') }
Community
  • 1
  • 1
MrYoshiji
  • 54,334
  • 13
  • 124
  • 117
  • Based on your answer I'm using: scope :ordered, -> { includes(:class_dates).order('class_dates.start_time ASC, class_sections.code ASC') } which doesn't quite work like I'd hoped. I want the classes with the same code to be grouped together. I tried simply flipping it to this: scope :ordered, -> { includes(:class_dates).order('class_sections.code ASC, class_dates.start_time ASC') } and I got this error: SQLite3::SQLException: no such column: class_dates.start_time: SELECT "class_sections".* FROM "class_sections" ORDER BY class_sections.code ASC, class_dates.start_time ASC – Kevin K Sep 17 '14 at 18:59