Skip to content

Instantly share code, notes, and snippets.

@fidelisrafael
Last active September 2, 2015 12:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fidelisrafael/4a286fe35fcb9b1b0abb to your computer and use it in GitHub Desktop.
Save fidelisrafael/4a286fe35fcb9b1b0abb to your computer and use it in GitHub Desktop.
Course x Discipline
# course.rb
# rails g model course title:string
class Course < ActiveRecord::Base
has_and_belongs_to_many :disciplines
scope :programming, -> {
where("title LIKE ?", '%Programming%')
}
end
# discipline.rb
# rails g model discipline title:string
class Discipline < ActiveRecord::Base
has_and_belongs_to_many :courses
end
# join table
# rails g migration create_courses_disciplines:index course_id:integer discipline_id:integer:index
class CreateCoursesDisciplines < ActiveRecord::Migration
def change
create_table :courses_disciplines, id: false do |t|
t.integer :course_id, index: true
t.integer :discipline_id, index: true
end
end
end
['Arte', 'Musica', 'Literatura'].each {|d| Discipline.find_or_create_by(title: d) }
10.times do |i|
c = Course.find_or_create_by(title: "Course #{i.next}")
c.disciplines = Discipline.all
end
c = Course.first
c.disciplines.count # 3
# can't do this
# c.active_disciplines.count # 0
d = Discipline.first
d.courses.count # 10
d.courses.programming.count # 0
Course.create(title: 'Programming in Ruby', disciplines: [d])
d.courses.count # 11
d.courses.programming.count # 1
# course.rb
# rails g model course title:string
class Course < ActiveRecord::Base
has_many :course_disciplines
has_many :disciplines, through: :course_disciplines
has_many :active_disciplines, -> {
where("course_disciplines.active = ? ", true)
}, through: :course_disciplines, source: :discipline
end
# discipline.rb
# rails g model discipline title:string
class Discipline < ActiveRecord::Base
has_many :course_disciplines
has_many :courses, through: :course_disciplines
has_many :programming_courses, -> {
where("courses.title LIKE ?", '%Programming%')
}, through: :course_disciplines, source: :course
end
# course_discipline.rb
# rails g model CourseDiscipline course:references discipline:references active:boolean
class CourseDiscipline < ActiveRecord::Base
belongs_to :course
belongs_to :discipline
end
['Arte', 'Musica', 'Literatura'].each {|d| Discipline.find_or_create_by(title: d) }
10.times do |i|
c = Course.find_or_create_by(title: "Course #{i.next}")
c.disciplines = Discipline.all
end
c = Course.first
c.disciplines.count # 3
c.active_disciplines.count # 0
d = Discipline.first
d.courses.count # 10
d.programming_courses.count # 0
Course.create(title: 'Programming in Ruby', disciplines: [d])
d.courses.count # 11
d.programming_courses.count # 1
@fidelisrafael
Copy link
Author

Unique Constraints

# rails g migration add_indices_to_courses_disciplines
class AddIndicesToCoursesDisciplines < ActiveRecord::Migration
  def change
    # using has_and_belongs_to_many
    table_name =  :courses_disciplines
    # using has_many :through
    table_name =  :course_disciplines
    add_index table_name, [:course_id, :discipline_id], unique: true
  end
end
Course.first.disciplines = []
Course.first.disciplines << Discipline.last
Course.first.disciplines << Discipline.last 
# ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_courses_disciplines_on_course_id_and_discipline_id"
Discipline.last.courses = []
Discipline.last.courses << Course.last
Discipline.last.courses << Course.last
# ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_course_disciplines_on_course_id_and_discipline_id"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment