0

I have 4 models. Departments, Courses, Sections, and Teacher All of them are heirachically connected with the proper belongs_to and has_many relations. A section belongs to a course which belongs to a department. A teacher has many sections, however, a course has many (is taught by many different) teachers.

I would like to construct the site in such a way that the URL /view/department_name/course_name/section_name/ shows the section with the name section_name, which belongs to the course named couse_name, which belongs to the department department_name.

However, I also want to /view/teacher_name/course_name/section_name to work the same way, where it shows all the sections associated with that teacher.

How can I do this?

FYI: the different models are connected by their IDs in the database. Section has a course_id integer associated with it, and course has a department_id integer. Section also has a department_id, which is redundant, but that's how I have it set up.

my routes.rb

Test2::Application.routes.draw do
  resources :courses
  resources :departments
  resources :teachers
  resources :sections
  resources :courses
3
  • you should post your routes.rb file to describe better the problem Commented Jul 26, 2012 at 4:03
  • Okay, I updated the OP with it. Commented Jul 26, 2012 at 4:19
  • 1
    railscasts.com/episodes/139-nested-resources watch this, maybe it will help Commented Jul 26, 2012 at 4:22

1 Answer 1

1

You mentioned things like section_name in your routes. You should make sure the names are all URL-safe.

Another point you have to consider is the two paths you want is in fact quite similar and thus you may need to handle both in the same controller action.

/view/department_name/course_name/section_name
/view/teacher_name/course_name/section_name

The only different part is the department_name vs teacher_name. Hopefully there is no any teacher have the same name with your department XD"

You may define the path as:

get '/view/:department_or_teacher_name/:course_name/:section_name' => 'some_controller#some_action'

Then in your action, you need something like this:

def some_action
  department_or_teacher = Department.find_by_name(params[:department_or_teacher_name]) || Teacher.find_by_name(params[:department_or_teacher_name])
  course = Course.find_by_name(params[:course_name])

  q = Section.where(name: params[:section_name]).where(course_id: course.id)
  if department_or_teacher.class.name == "Department"
    q = q.where(department_id: q.id)
  elsif department_or_teacher.class.name == "Teacher"
    q = q.where(teacher_id: q.id)
  end

  @section = q.first # I assume there should be only 1 section with a given name, under a specific course, and (under a specific department or a specific teacher)
end

The above generates 3 queries, which might not be very good. You may consider using joins:

def some_action
  department_or_teacher = Department.find_by_name(params[:department_or_teacher_name]) || Teacher.find_by_name(params[:department_or_teacher_name])

  q = Section.where(name: params[:section_name]).joins(:course).where("courses.name = ?", params[:course_name])

  if department_or_teacher.class.name == "Department"
    q = q.where(department_id: q.id)
  elsif department_or_teacher.class.name == "Teacher"
    q = q.where(teacher_id: q.id)
  end

  @section = q.first
end

There is still a difficulty in guessing the department or teacher. So if you redefine the path to something like this, the above could be cleaner:

get '/view/department/:department_name/:course_name/:section_name' => 'some_controller#some_action_for_department'
get '/view/teacher/:teacher_name/:course_name/:section_name' => 'some_controller#some_action_for_teacher'

def some_action_for_department
  @section = Section.where(name: params[:section_name])
                    .joins(:course).where("courses.name = ?", params[:course_name])
                    .joins(:department).where("departments.name = ?", params[:department_name]) # you mentioned there is a department_id in sections, thus you could actually setup a belongs_to :department in section
                    .first
end

def some_action_for_teacher
  @section = Section.where(name: params[:section_name])
                    .joins(:course).where("courses.name = ?", params[:course_name])
                    .joins(:teacher).where("teachers.name = ?", params[:teacher_name])
                    .first
end

This is the idea. I did not test it and just by guess. So please tell me if you encountered any problems.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.