Rails 3 complicated sorting -


i need sort league table in rails 3, have leaguetable model, team model , match model.
basic sorting done points summary, easy part. when 2 teams got same points number, want sort them points won in matches between 2 teams.
got no idea how this.

edit:

# league_table.rb model class leaguetable < activerecord::base     belongs_to :team end   # match.rb model class match < activerecord::base     belongs_to :team_home, :class_name => "team"     belongs_to :team_away, :class_name => "team" end   # team.rb model class team < activerecord::base     has_many :matches end   # schema.rb create_table "league_tables", :force => true |t|     t.integer  "team_id"     t.integer  "points"     t.integer  "wins"     t.integer  "draws"     t.integer  "looses"     t.integer  "goals_won"     t.integer  "goals_lost"     t.datetime "created_at"     t.datetime "updated_at"     t.integer  "matches"     t.integer  "priority"   end    create_table "matches", :force => true |t|     t.integer  "team_home_id"     t.integer  "team_away_id"     t.integer  "score_home"     t.integer  "score_away"     t.datetime "created_at"     t.datetime "updated_at"   end    create_table "teams", :force => true |t|     t.string   "name"     t.datetime "created_at"     t.datetime "updated_at"   end 

very interesting question. here (more less) how handle it, using recursion , magic of group_by.

  1. you need class method that, given array of teams, calculates number of points (goals for, goals against...) each team has got in matches between teams only. assume return hash of hashes: {team_foo => {:points => 10, :goals_for => 33, :goals_against => 6}, team_bar => {:points => 18, :goals_for => 50, :goals_against => 11}...}.
  2. the final order of teams put array final_order, empty now.
  3. take teams array , apply method mentioned above. should have teams , number of points (goals for, goals against...) teams have gained in games played. store somewhere, under name all_teams_scores.
  4. take teams , group them using group_by: teams.group_by {|t| all_teams_scores[t][:points]}. orderedhash, looking like: {10 => [team_foo], 18 => [team_bar, team_xyz]}. key group by, value array. store hash, e.g. league_table.
  5. sort keys of league_table (remember reverse when needed) , check values of league_table according them. if array has 2 or more elements, apply points 3.-5. teams in array. if array has 1 element, append element final_order.
  6. done.

some remarks:

  • remember in worst case left 2 or more teams have gained same number of points (goals...) in direct games. need handle that, or sort random.
  • the above steps group points only. if need first sort points in games, points in direct games, work. if want sort points in games, points in direct games, goals in games - need refine above algorithm. should not hard, though ;)
  • you can group_by array (which helps when want sort on number of things before or after sort direct games).
  • unless site going heavily used, generate table whenever requested. no need store in dabase - unless season on , no changes game results made.
  • if decide store table in database, ensure fields related position of team in table not editable user. best way implement above algorithm stored procedure (postgresql supports pl/ruby, although never used it), create view based on , access league table rails through (views are, generally, read only). of course, removing access these fields administrative interface ok, 99.99% situations ;)
  • this may not (and not) optimal solution in terms of speed or memory efficiency (although have not checked it), suppose code produced according method should easy read, understand , maintain later on.

hope helps.


Comments