Skip to content

Commit

Permalink
add broadcast_id to tracks
Browse files Browse the repository at this point in the history
  • Loading branch information
codez committed Jan 29, 2019
1 parent 5fdc990 commit 4eed31c
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 42 deletions.
9 changes: 1 addition & 8 deletions app/controllers/tracks_controller.rb
Expand Up @@ -106,17 +106,10 @@ def fetch_entries
scope = super
scope = scope.within(*start_finish) if params[:year]
scope = scope.for_show(params[:show_id]) if params[:show_id]
scope = scope.where(broadcast_id: params[:broadcast_id]) if params[:broadcast_id]
scope
end

def model_scope
if params[:broadcast_id]
Broadcast.find(params[:broadcast_id]).tracks
else
super
end
end

def index_params?
super || params[:broadcast_id].present?
end
Expand Down
12 changes: 8 additions & 4 deletions app/models/broadcast.rb
Expand Up @@ -17,14 +17,18 @@
class Broadcast < ApplicationRecord

include UserStampable
include NonOverlappable

belongs_to :show

has_many :audio_files, dependent: :restrict_with_error
has_many :tracks, dependent: :nullify

validates :label, :started_at, :finished_at, presence: true
validates :started_at, :finished_at, uniqueness: true

after_create :assign_tracks

before_validation :set_show_label_if_empty

scope :list, -> { order('broadcasts.started_at') }
Expand All @@ -48,14 +52,14 @@ def duration
finished_at - started_at
end

def tracks
Track.within(started_at, finished_at)
end

private

def set_show_label_if_empty
self.label ||= show.name if show
end

def assign_tracks
Track.within(started_at, finished_at).update_all(broadcast_id: id)
end

end
24 changes: 24 additions & 0 deletions app/models/concerns/non_overlappable.rb
@@ -0,0 +1,24 @@
module NonOverlappable

extend ActiveSupport::Concern

included do
validate :assert_not_overlapping
end

private

def assert_not_overlapping
scope = overlapping_scope
scope = scope.where.not(id: id) if persisted?
if scope.exists?
errors.add(:started_at, :must_not_overlap)
throw :abort
end
end

def overlapping_scope
self.class.where('started_at < ? AND finished_at > ?', finished_at, started_at)
end

end
28 changes: 19 additions & 9 deletions app/models/track.rb
Expand Up @@ -2,15 +2,22 @@
#
# Table name: tracks
#
# id :integer not null, primary key
# title :string not null
# artist :string
# started_at :datetime not null
# finished_at :datetime not null
# id :integer not null, primary key
# title :string not null
# artist :string
# started_at :datetime not null
# finished_at :datetime not null
# broadcast_id :integer
#

class Track < ApplicationRecord

include NonOverlappable

belongs_to :broadcast, optional: true

before_save :assign_broadcast, if: :started_at_changed?

validates :title, :started_at, :finished_at, presence: true
validates :started_at, :finished_at, uniqueness: true

Expand All @@ -22,10 +29,7 @@ def within(start, finish)
end

def for_show(show_id)
joins('INNER JOIN broadcasts ' \
'ON tracks.started_at >= broadcasts.started_at ' \
'AND tracks.started_at < broadcasts.finished_at')
.where(broadcasts: { show_id: show_id })
joins(:broadcast).where(broadcasts: { show_id: show_id })
end
end

Expand All @@ -38,4 +42,10 @@ def duration
finished_at - started_at
end

private

def assign_broadcast
self.broadcast = Broadcast.at(started_at).first
end

end
11 changes: 6 additions & 5 deletions app/serializers/track_serializer.rb
Expand Up @@ -2,11 +2,12 @@
#
# Table name: tracks
#
# id :integer not null, primary key
# title :string not null
# artist :string
# started_at :datetime not null
# finished_at :datetime not null
# id :integer not null, primary key
# title :string not null
# artist :string
# started_at :datetime not null
# finished_at :datetime not null
# broadcast_id :integer
#

class TrackSerializer < ApplicationSerializer
Expand Down
11 changes: 6 additions & 5 deletions config/locales/de.yml
Expand Up @@ -95,16 +95,17 @@ de:

errors:
messages:
identifier_format: darf nur die Zeichen a-z, 0-9 und '_' enthalten.
must_decrease: muss mit der Zeit kleiner werden.
must_not_change: darf nicht verändert werden.
identifier_format: darf nur die Zeichen a-z, 0-9 und '_' enthalten
must_decrease: muss mit der Zeit kleiner werden
must_not_change: darf nicht verändert werden
must_not_overlap: darf sich nicht mit anderen Einträgen überschneiden
models:
profile:
attributes:
default:
must_exist: muss definiert sein.
must_exist: muss definiert sein
downgrade_action:
delete_must_be_last: Löschen darf erst am Ende aller Aktionen geschehen.
delete_must_be_last: Löschen darf erst am Ende aller Aktionen geschehen

time:
formats:
Expand Down
1 change: 1 addition & 0 deletions config/locales/en.yml
Expand Up @@ -26,6 +26,7 @@ en:
identifier_format: may only contain a-z, 0-9 and '_'
must_decrease: must decrease over time
must_not_change: must not be changed
must_not_overlap: must not overlap with other entries
models:
profile:
attributes:
Expand Down
1 change: 1 addition & 0 deletions db/migrate/20190127185449_create_tracks.rb
Expand Up @@ -5,6 +5,7 @@ def change
t.string :artist
t.datetime :started_at, null: false, index: { unique: true }
t.datetime :finished_at, null: false, index: { unique: true }
t.integer :broadcast_id, index: true
end
end
end
2 changes: 2 additions & 0 deletions db/schema.rb
Expand Up @@ -117,6 +117,8 @@
t.string "artist"
t.datetime "started_at", null: false
t.datetime "finished_at", null: false
t.integer "broadcast_id"
t.index ["broadcast_id"], name: "index_tracks_on_broadcast_id"
t.index ["finished_at"], name: "index_tracks_on_finished_at", unique: true
t.index ["started_at"], name: "index_tracks_on_started_at", unique: true
end
Expand Down
Binary file modified doc/models.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 10 additions & 5 deletions test/fixtures/tracks.yml
Expand Up @@ -2,33 +2,38 @@
#
# Table name: tracks
#
# id :integer not null, primary key
# title :string not null
# artist :string
# started_at :datetime not null
# finished_at :datetime not null
# id :integer not null, primary key
# title :string not null
# artist :string
# started_at :datetime not null
# finished_at :datetime not null
# broadcast_id :integer
#

jayz:
title: "99 problems"
artist: "Jay-Z"
started_at: <%= Time.zone.local(2013, 5, 20, 20, 01, 13).to_s(:db) %>
finished_at: <%= Time.zone.local(2013, 5, 20, 20, 04, 51).to_s(:db) %>
broadcast: g9s_mai

choco:
title: Schwenger
artist: Chocolococolo
started_at: <%= Time.zone.local(2013, 5, 20, 20, 10, 44).to_s(:db) %>
finished_at: <%= Time.zone.local(2013, 5, 20, 20, 13, 5).to_s(:db) %>
broadcast: g9s_mai

goeldin:
title: Liebi i Zyte vom kommende Ufstand
artist: "Göldin & Bit-Tuner"
started_at: <%= Time.zone.local(2013, 6, 12, 20, 36, 21).to_s(:db) %>
finished_at: <%= Time.zone.local(2013, 6, 12, 20, 39, 9).to_s(:db) %>
broadcast: g9s_juni

shakira:
title: Loco
artist: Shakira
started_at: <%= Time.zone.local(2013, 5, 20, 11, 45, 13).to_s(:db) %>
finished_at: <%= Time.zone.local(2013, 5, 20, 11, 48).to_s(:db) %>
broadcast: klangbecken_mai1
59 changes: 59 additions & 0 deletions test/models/broadcast_test.rb
Expand Up @@ -63,4 +63,63 @@ class BroadcastTest < ActiveSupport::TestCase
assert_equal broadcasts(:klangbecken_mai1, :g9s_mai, :klangbecken_mai2),
Broadcast.within(bc.started_at - 1.minute, bc.finished_at + 1.minute).list
end

test 'creating broadcasts sets relation in tracks' do
t1 = Track.create!(
title: 'foo',
started_at: Time.zone.local(2016, 8, 20, 9, 18, 13),
finished_at: Time.zone.local(2016, 8, 20, 9, 22, 17)
)
t2 = Track.create!(
title: 'foo',
started_at: Time.zone.local(2016, 8, 20, 9, 27, 1),
finished_at: Time.zone.local(2016, 8, 20, 9, 29, 59)
)
t3 = Track.create!(
title: 'foo',
started_at: Time.zone.local(2016, 8, 20, 10, 4, 13),
finished_at: Time.zone.local(2016, 8, 20, 10, 9, 33)
)

b = Broadcast.create!(
show: shows(:klangbecken),
started_at: Time.zone.local(2016, 8, 20, 8),
finished_at: Time.zone.local(2016, 8, 20, 10)
)

assert_equal b, t1.reload.broadcast
assert_equal b, t2.reload.broadcast
assert_nil t3.reload.broadcast
end

test 'broadcasts lapping to next is invalid' do
broadcast = broadcasts(:klangbecken_mai1)
broadcast.finished_at += 1.minute
assert !broadcast.valid?
assert_equal ['must not overlap with other entries'], broadcast.errors['started_at']
end

test 'broadcasts lapping to previous is invalid' do
broadcast = broadcasts(:klangbecken_mai1)
broadcast.started_at -= 1.minute
assert !broadcast.valid?
assert_equal ['must not overlap with other entries'], broadcast.errors['started_at']
end

test 'broadcasts during other is invalid' do
broadcast = broadcasts(:klangbecken_mai1)
broadcast.started_at = broadcasts(:g9s_mai).started_at + 5.minutes
broadcast.finished_at = broadcasts(:g9s_mai).finished_at - 5.minutes
assert !broadcast.valid?
assert_equal ['must not overlap with other entries'], broadcast.errors['started_at']
end

test 'broadcasts at same time as other is invalid' do
broadcast = broadcasts(:klangbecken_mai1)
broadcast.started_at = broadcasts(:g9s_mai).started_at
broadcast.finished_at = broadcasts(:g9s_mai).finished_at
assert !broadcast.valid?
assert_equal ['must not overlap with other entries'], broadcast.errors['started_at']
end

end
17 changes: 11 additions & 6 deletions test/models/track_test.rb
Expand Up @@ -2,14 +2,14 @@
#
# Table name: tracks
#
# id :integer not null, primary key
# title :string not null
# artist :string
# started_at :datetime not null
# finished_at :datetime not null
# id :integer not null, primary key
# title :string not null
# artist :string
# started_at :datetime not null
# finished_at :datetime not null
# broadcast_id :integer
#


require 'test_helper'

class TrackTest < ActiveSupport::TestCase
Expand Down Expand Up @@ -50,4 +50,9 @@ class TrackTest < ActiveSupport::TestCase
Track.for_show(shows(:info).id).list
end

test 'changing started_at updates broadcast' do
tracks(:jayz).update!(started_at: Time.zone.local(2013, 5, 20, 19, 58, 13))
assert_equal broadcasts(:klangbecken_mai1), tracks(:jayz).broadcast
end

end

0 comments on commit 4eed31c

Please sign in to comment.