简体   繁体   中英

Combination of all records with distinct column values in Rails

I'm relatively new to Ruby on Rails. I am using Rails 4.0.4. I have a table "Schedule" with a column titled ":course_id". I would like to find all combinations of distinct courses into a new table called "Itineraries".

So, if there were a schedule table with 3 sections made up by 2 different courses, each combination would be a unique combination of the 2 different courses.

For example: Schedule 1 has : { section_id: 4, course_id: 1 }, { section_id: 5, course_id: 1 }, { section_id: 6, course_id: 2 }

This would return 2 itineraries: Itinerary 1: { section_id: 4, course_id: 1 }, { section_id: 6, course_id: 2 }
Itinerary 2: { section_id: 5, course_id: 1 }, { section_id: 6, course_id: 2 }

Below is a list of my models and their connections.

Schedule:

class Schedule < ActiveRecord::Base
    has_many :sections
    has_many :courses, through: :sections
    has_many :subjects, through: :courses
end

Section:

class Section < ActiveRecord::Base
    belongs_to :courses
    belongs_to :schedule
end

Course:

class Course < ActiveRecord::Base
    belongs_to :subject
    belongs_to :schedule
    has_many :sections
end

In my schedules_controller, I have a method which accesses the schedules built from all the different sections available, and this is where I'm struggling to find a good method or way. I could loop through all sections of each distinct course and manually make those combinations, but it seems like there should be some more direct way to do such a thing.

def get_itineraries
    schedules = Schedule.all
end

Well, it seems that you need the cartesian product of n arrays (6, isn't it?)

In order to not having to reprogram it, you can use an existing gem:

gem 'cartesian'

You need to require this, in your application.rb

require 'cartesian'

If I got this right, you have a finite number of course_ids, 6, isn't it?

So, do the following:

itineraries=Array.new
(1..6).each do |i|
    itineraries[i]=Schedule.select(:section_id).where("course_id=?",i).uniq.map(&:section_id).sort
end

And there you have 6 arrays with sections per course.

After that, you can use the cartesian product as follows:

all_itineraries=itineraries[1].x(itineraries[2]).x(itineraries[3]).x(itineraries[4]).x(itineraries[5]).x(itineraries[6])

Each row of this array will contain 6 section_ids , the first for course_id=1 , the second for course_id=2 etc.

This is strictly a mathematical approach, in case you can't find a more "railsie" one...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM