Skip to content

Commit

Permalink
Allow sections to be unique within lessons only
Browse files Browse the repository at this point in the history
- Add migration to fix the unique index
- Add scope to the uniqueness validation
- Add user factory
- Add user association to lesson factory
- Lesson factory corrections
- Add section factory
- Add section model spec

NOTE: We modify the start_time and end_time validations to provide a
default value for lesson.duration_in_seconds because there's an issue
with shoulda matchers and validations that refer to associated models
according to this issue thoughtbot/shoulda-matchers#1435
  • Loading branch information
mauriciofierrom committed Jul 23, 2024
1 parent 252ea32 commit fb0267d
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 9 deletions.
16 changes: 11 additions & 5 deletions app/models/section.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ class Section < ApplicationRecord
class_name: "VideoPoint",
mapping: [ %w(end_time_hour hour), %w(end_time_minute minute), %w(end_time_second second) ]

validates :name, presence: true
validates :name, presence: true, uniqueness: { scope: :lesson_id }

validates :start_time_hour, :start_time_minute, :start_time_second,
presence: true,
numericality: {
Expand All @@ -29,16 +30,21 @@ class Section < ApplicationRecord
less_than_or_equal_to: 59
}

# Due to this issue in shoulda matchers library we'll have to add a default max value
# https://github.com/thoughtbot/shoulda-matchers/issues/1435
validates :start_time,
numericality: {
less_than: -> (section) { section.lesson.duration_in_seconds },
message: -> (object, data) { "must be less than #{object.lesson.duration_in_seconds}" }
less_than: -> (section) { section.lesson&.duration_in_seconds || 9999.0 },
message: -> (object, data) { "must be less than #{object.lesson.duration_in_seconds}" },
allow_nil: true
}

# Due to this issue in shoulda matchers library we'll have to add a default max value
# https://github.com/thoughtbot/shoulda-matchers/issues/1435
validates :end_time,
numericality: {
less_than_or_equal_to: -> (section) { section.lesson.duration_in_seconds },
message: -> (object, data) { "must be less than #{object.lesson.duration_in_seconds}" }
less_than_or_equal_to: -> (section) { section.lesson&.duration_in_seconds || 9999.0 },
message: -> (object, data) { "must be less than #{object.lesson.duration_in_seconds}" },
}

validates :end_time,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class FixSectionNameUniquenessIndex < ActiveRecord::Migration[7.0]
def change
remove_index :sections, :name
add_index :sections, [:name, :lesson_id], unique: true
end
end
4 changes: 2 additions & 2 deletions db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions spec/factories/lesson.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
name do
"#{Faker::Music::RockBand.song} - #{Faker::Music::RockBand.name}"
end
video_url { Faker::Internel.url(host: 'youtu.be') }
video_url { Faker::Internet.url(host: "youtu.be", scheme: "https") }
duration_in_seconds do
Faker::Number.between(from: 0.0, to: 5.minutes.seconds.to_f)
Faker::Number.between(from: 0, to: 5.minutes.seconds)
end
instrument
user
end
end
16 changes: 16 additions & 0 deletions spec/factories/section.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
FactoryBot.define do
factory :section do
lesson
sequence(:name) { |n| "Section #{n}" }

start_time_hour { 0 }
start_time_minute { 0 }
start_time_second { 1 }

end_time_hour { 0 }
end_time_minute { 0 }
end_time_second { Faker::Number.between(from: 1, to: 59 ) }

playback_speed { 0.5.step(by: 0.5, to: 2.0).to_a.sample }
end
end
7 changes: 7 additions & 0 deletions spec/factories/user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
FactoryBot.define do
factory :user do
sequence(:email) { |n| "user#{n}@example.com" }
password { "password123" }
confirmed_at { Date.yesterday }
end
end
13 changes: 13 additions & 0 deletions spec/models/section_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
require 'rails_helper'

describe Section, type: :model do
subject { create(:section) }

describe 'associations' do
it { should belong_to(:lesson) }
end

describe 'validations' do
it { should validate_uniqueness_of(:name).scoped_to(:lesson_id) }
end
end

0 comments on commit fb0267d

Please sign in to comment.