In a Rails ( 4.1.5 / ruby 2.0.0p481 / win64 ) application I have a many-to-many relationship between Student and Course and a join model StudentCourse
Use JBuilder, it comes by default with Rails. Ignore the lines starting with '#':
Jbuilder.new do |j|
# courses: [{
j.courses <student.courses - replace this with whatever variable> do |course|
# id: <course.id>
j.id course.id
# name: <course.name>
j.name course.name
# students: [{
j.students <course.students - replace with whatever variable> do |student|
# name: <student.name>
j.name student.name
end
# }]
end
# }]
end
Not a lot of code. Removing the comments and simplifying some features, it will look like:
student_courses = <...blah...>
json = Jbuilder.new do |j|
j.courses student_courses do |course|
j.(course, :id, :name)
j.students <course.students - whatever method here>, :name
end
end.target!
Check out their guide, its pretty awesome to generate JSON in plain Ruby DSL. So go ahead and use whatever ruby code you want to fetch students/courses/studentcourses.
Use scope
to your advantage:
class Course < ActiveRecord::Base
# ...
scope :not_started, -> { joins(:student_courses) \
.where(student_courses: {started: false}) }
scope :with_classmates, -> { includes(:students) } # use eager loading
end
Then call:
@student.courses.not_started.with_classmates \
.to_json(include: {students: {only: :name}})
Output:
[
{
"id": 1,
"name": "english",
"description": null,
"students": [
{"name": "Aiden"},
{"name": "Alison"}]},
{
"id": 2,
"name": "music",
"description": null,
"students": [
{"name": "Aiden"},
{"name": "Alison"}]},
{
"id": 3,
"name": "dance",
"description": null,
"students": [
{"name": "Aiden"}]}]