How can I use activerecord's query interface and scopes to identify the favorite in a race

I have two models Starter and Race.

Starter    belongs_to :race
Race       has_many :starters

The attributes for Starter and race follow:

Starter attributes:  id, race_id, finish_position, odds
Race: id, race_date, race_number, field_size

I’m trying to accomplish two things:

  1. Select the favorite in each race. #for a particular race the Starter with the lowest odds*
  2. Select any beaten favorites *#a favorite that has a finish_position > 1*

The logic for determining favorites and beaten favorites is pretty straight forward (see above), but I’m having a hard time translating the logic into activerecord also is this an example were activerecord scopes could be utilized.

Here’s my attempt at favorite:

Starter.joins(:race).where(:finish_position => minimum(finish_position))

This isn’t working, but I still working at it.

I guess the ideal would be to have a favorite scope and a beaten scope.

  • Getting frequent Gem RemoteFetcher::FetchError. Any workarounds?
  • How to check the field 'Content-Length ' of an HTTP request using Ruby on Rails 3?
  • How can I use content_for to put something in :yield
  • Rails3 not reloading code in lib while in development mode
  • Rails 3 gem for capturing referrer info?
  • How to generate scaffold for data type with “extra description” in Rails 3?
  • Login with Facebook via Rails
  • Rails date i18n with custom formats not translating
  • 2 Solutions collect form web for “How can I use activerecord's query interface and scopes to identify the favorite in a race”

    For favorites, you can use this

    favorites = Starter.group(:race_id).having('min(odds)')
    

    For beaten favorites

    beaten_favorites = favorites.where(['finish_position > ?', 1])
    

    Some principles at first:

    1. The “favorite” and “bean_favorites” only make sense when a race exists. So they are better to be instance methods instead of class methods.

    2. Your race should know no more than one level of Starter’s methods, according Single Responsibility Principle

    Now comes the code

    class Race < ActiveRecord::Base
      def favorite
        starters.lowest_odds
      end
    
      def beaten_favorite
        starters.finished_lowest_odds
      end
    end
    
    class Starter < ActiveRecords::Base
      scope :by_odds, order('odds DESC')
      scope :finished, where('finished_position > 1')
    
      def lowest_odds
        by_odds.last
      end
    
      def finished_lowest_odds
        finished.lowest_odds
      end
    end
    

    Now to solve the question

    @race.favorite
    @race.beaten_favorite
    
    Ruby is the best programming language in the world - Ruby on Rails.