Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Week 3 part 1 #5

Merged
merged 2 commits into from
Jul 9, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions app/controllers/queue_items_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,20 @@ def create
def destroy
queue_item = QueueItem.find(params[:id])
queue_item.destroy if current_user.queue_items.include?(queue_item)
current_user.normalize_queue_item_positions
redirect_to my_queue_path
end

def update_queue
begin
update_queue_items
current_user.normalize_queue_item_positions
rescue ActiveRecord::RecordInvalid
flash[:error] = "Invalid position numbers"
end
redirect_to my_queue_path
end

private

def queue_video(video)
Expand All @@ -30,4 +41,12 @@ def current_user_queued_video?(video)
current_user.queue_items.map(&:video).include?(video)
end

def update_queue_items
ActiveRecord::Base.transaction do
params[:queue_items].each do |queue_item_data|
queue_item = QueueItem.find(queue_item_data["id"])
queue_item.update_attributes!(position: queue_item_data["position"], rating: queue_item_data["rating"]) if queue_item.user == current_user
end
end
end
end
3 changes: 3 additions & 0 deletions app/helpers/application_helper.rb
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
module ApplicationHelper
def options_for_video_reviews(selected=nil)
options_for_select((1..5).map {|num| [pluralize(num, "Star"), num]}, selected)
end
end
18 changes: 17 additions & 1 deletion app/models/queue_item.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,29 @@ class QueueItem < ActiveRecord::Base
delegate :category, to: :video
delegate :title, to: :video, prefix: :video

validates_numericality_of :position, {only_integer: true}

def rating
review = Review.where(user_id: user.id, video_id: video.id).first
review.rating if review
end

def rating=(new_rating)
if review
review.update_column(:rating, new_rating)
else
review = Review.create(user: user, video: video, rating: new_rating)
review.save(validate: false)
end
end

def category_name
category.name
end

private

def review
@review ||= Review.where(user_id: user.id, video_id: video.id).first
end

end
9 changes: 8 additions & 1 deletion app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,12 @@ class User < ActiveRecord::Base

has_secure_password validations: false

has_many :queue_items
has_many :queue_items, -> { order(:position) }

def normalize_queue_item_positions
queue_items.each_with_index do |queue_item, index|
queue_item.update_attributes(position: index+1)
end
end

end
48 changes: 25 additions & 23 deletions app/views/queue_items/index.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,29 @@
%article
%header
%h2 My Queue
%table.table
%thead
%tr
%th(width="10%") List Order
%th(width="30%") Video Title
%th(width="10%") Play
%th(width="20%") Rating
%th(width="15%") Genre
%th(width="15%") Remove
%tbody
- @queue_items.each do |queue_item|
= form_tag update_queue_path do
%table.table
%thead
%tr
%td= queue_item.position
%td
= link_to queue_item.video_title, queue_item.video
%td
= button_to "Play", nil, class: "btn btn-default"
%td= queue_item.rating
%td
= link_to queue_item.category_name, queue_item.category
%td
= link_to queue_item, method: :delete do
%i.glyphicon.glyphicon-remove
= button_to "Update Instant Queue", nil, class: "btn btn-default"
%th(width="10%") List Order
%th(width="30%") Video Title
%th(width="10%") Play
%th(width="20%") Rating
%th(width="15%") Genre
%th(width="15%") Remove
%tbody
- @queue_items.each do |queue_item|
%tr
= hidden_field_tag("queue_items[][id]", queue_item.id)
%td= text_field_tag("queue_items[][position]", queue_item.position)
%td
= link_to queue_item.video_title, queue_item.video
%td
= button_to "Play", nil, class: "btn btn-default"
%td= select_tag "queue_items[][rating]", options_for_video_reviews(queue_item.rating), include_blank: true
%td
= link_to queue_item.category_name, queue_item.category
%td
= link_to queue_item, method: :delete do
%i.glyphicon.glyphicon-remove
= submit_tag "Update Instant Queue", class: 'btn'
2 changes: 1 addition & 1 deletion app/views/videos/show.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
%fieldset
.form-group
%label Rate this video
= f.select :rating, options_for_select([5,4,3,2,1].map {|number| [pluralize(number, "Star")]})
= f.select :rating, options_for_video_reviews
.form-group
%label Write Review
= f.text_area :content, rows: 6, class: "span6"
Expand Down
1 change: 1 addition & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
end
resources :categories
resources :queue_items, only: [:create, :destroy]
post 'update_queue', to: 'queue_items#update_queue'

get 'my_queue', to: 'queue_items#index'

Expand Down
76 changes: 76 additions & 0 deletions spec/controllers/queue_items_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@
delete :destroy, id: queue_item.id
expect(QueueItem.count).to eq(0)
end

it "normalizes the remaining queue_items" do
alice = Fabricate(:user)
session[:user_id] = alice.id
queue_item1 = Fabricate(:queue_item, user: alice, position: 1)
queue_item2 = Fabricate(:queue_item, user: alice, position: 2)
delete :destroy, id: queue_item1.id
expect(QueueItem.first.position).to eq(1)
end

it "does not delete the queue item if the queue item is not in the current user's queue" do
alice = Fabricate(:user)
bob = Fabricate(:user)
Expand All @@ -94,4 +104,70 @@
expect(response).to redirect_to sign_in_path
end
end

describe "POST update_queue" do
context "with valid inputs" do
let(:alice) { Fabricate(:user) }
let(:video) { Fabricate(:video) }
let(:queue_item1) { Fabricate(:queue_item, user: alice, position: 1, video: video) }
let(:queue_item2) { Fabricate(:queue_item, user: alice, position: 2, video: video) }
before do
session[:user_id] = alice.id
end
it "redirects to the my queue page" do
post :update_queue, queue_items: [{id: queue_item1.id, position: 2}, {id: queue_item2.id, position: 1}]
expect(response).to redirect_to my_queue_path
end

it "reorders the queue items" do
post :update_queue, queue_items: [{id: queue_item1.id, position: 2}, {id: queue_item2.id, position: 1}]
expect(alice.queue_items).to eq([queue_item2, queue_item1])
end
it "normalizes the position numbers" do
post :update_queue, queue_items: [{id: queue_item1.id, position: 3}, {id: queue_item2.id, position: 2}]
expect(alice.queue_items.map(&:position)).to eq([1, 2])
end
end

context "with invalid inputs" do
let(:alice) { Fabricate(:user) }
let(:video) { Fabricate(:video) }
let(:queue_item1) { Fabricate(:queue_item, user: alice, position: 1, video: video) }
let(:queue_item2) { Fabricate(:queue_item, user: alice, position: 2, video: video) }
before do
session[:user_id] = alice.id
end

it "redirects to the my queue page" do
post :update_queue, queue_items: [{id: queue_item1.id, position: 3.4}, {id: queue_item2.id, position: 2}]
expect(response).to redirect_to my_queue_path
end
it "sets the flash error message" do
post :update_queue, queue_items: [{id: queue_item1.id, position: 3.4}, {id: queue_item2.id, position: 2}]
expect(flash[:error]).to be_present
end
it "does not change the queue items" do
post :update_queue, queue_items: [{id: queue_item1.id, position: 3}, {id: queue_item2.id, position: 2.1}]
expect(queue_item1.reload.position).to eq(1)
end
end
context "with unauthenticated users" do
it "redirects to the sign in path" do
post :update_queue, queue_items: [{id: 2, position: 3}, {id: 5, position: 2}]
expect(response).to redirect_to sign_in_path
end
end
context "with queue items that do not belong to the current user" do
it "does not change the queue items" do
alice = Fabricate(:user)
session[:user_id] = alice.id
bob = Fabricate(:user)
video = Fabricate(:video)
queue_item1 = Fabricate(:queue_item, user: bob, position: 1, video: video)
queue_item2 = Fabricate(:queue_item, user: alice, position: 2, video: video)
post :update_queue, queue_items: [{id: queue_item1.id, position: 3}, {id: queue_item2.id, position: 2}]
expect(queue_item1.reload.position).to eq(1)
end
end
end
end
2 changes: 1 addition & 1 deletion spec/fabricators/queue_item_fabricator.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Fabricator(:queue_item) do

position {[1,2,3].sample }
end
28 changes: 28 additions & 0 deletions spec/models/queue_item_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
describe QueueItem do
it { should belong_to(:user) }
it { should belong_to(:video) }
it { should validate_numericality_of(:position).only_integer}

describe "#video_title" do
it "returns the title of the associated video" do
Expand All @@ -27,6 +28,33 @@
end
end

describe "#rating=" do
it "changes the rating of the review if the review is present" do
video = Fabricate(:video)
user = Fabricate(:user)
review = Fabricate(:review, user: user, video: video, rating: 2)
queue_item = Fabricate(:queue_item, user: user, video: video)
queue_item.rating = 4
expect(Review.first.rating).to eq(4)
end

it "clears the rating of the review if the review is present." do
video = Fabricate(:video)
user = Fabricate(:user)
review = Fabricate(:review, user: user, video: video, rating: 2)
queue_item = Fabricate(:queue_item, user: user, video: video)
queue_item.rating = nil
expect(Review.first.rating).to be_nil
end
it "creates a review with the rating if the review is not present" do
video = Fabricate(:video)
user = Fabricate(:user)
queue_item = Fabricate(:queue_item, user: user, video: video)
queue_item.rating = 3
expect(Review.first.rating).to eq(3)
end
end

describe "#category_name" do
it "returns the category name of the video" do
category = Fabricate(:category, name: "comedies")
Expand Down
9 changes: 9 additions & 0 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
require 'spec_helper'

describe User do
it { should validate_presence_of(:email) }
it { should validate_presence_of(:password) }
it { should validate_presence_of(:full_name) }
it { should validate_uniqueness_of(:email) }
it { should have_many(:queue_items).order(:position)}
end