diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index a5aaf5c01..6e5b1df3d 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -32,6 +32,7 @@ var initialize_modules = function() {
App.Tags.initialize();
App.Stats.initialize();
App.LocaleSwitcher.initialize();
+ App.DebatesOrderSelector.initialize();
};
$(function(){
diff --git a/app/assets/javascripts/debates_order_selector.js.coffee b/app/assets/javascripts/debates_order_selector.js.coffee
new file mode 100644
index 000000000..94002f5ac
--- /dev/null
+++ b/app/assets/javascripts/debates_order_selector.js.coffee
@@ -0,0 +1,17 @@
+App.DebatesOrderSelector =
+
+ href_with_params: (query_params) ->
+ loc = window.location
+
+ loc.protocol + "//" + loc.hostname +
+ (if loc.port then ':' + loc.port else '') +
+ loc.pathname +
+ loc.hash +
+ '?' + $.param(query_params)
+
+ initialize: ->
+ $('.js-order-selector').on 'change', ->
+ query_params = window.getQueryParameters()
+ query_params['order'] = $(this).val()
+ window.location.assign(App.DebatesOrderSelector.href_with_params(query_params))
+
diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb
index cf6d14f65..efa441d81 100644
--- a/app/controllers/debates_controller.rb
+++ b/app/controllers/debates_controller.rb
@@ -1,11 +1,12 @@
class DebatesController < ApplicationController
+ before_action :parse_order, only: :index
before_action :authenticate_user!, except: [:index, :show]
load_and_authorize_resource
respond_to :html, :js
def index
- @debates = Debate.search(params).page(params[:page]).for_render
+ @debates = Debate.search(params).page(params[:page]).for_render.send("sort_by_#{@order}")
set_debate_votes(@debates)
end
@@ -71,4 +72,9 @@ class DebatesController < ApplicationController
@featured_tags = ActsAsTaggableOn::Tag.where(featured: true)
end
+ def parse_order
+ @valid_orders = ['total_votes', 'created_at', 'likes']
+ @order = @valid_orders.include?(params[:order]) ? params[:order] : 'created_at'
+ end
+
end
diff --git a/app/helpers/debates_helper.rb b/app/helpers/debates_helper.rb
new file mode 100644
index 000000000..52bb9c17c
--- /dev/null
+++ b/app/helpers/debates_helper.rb
@@ -0,0 +1,12 @@
+module DebatesHelper
+ def available_options_for_order_selector(valid_orders, current_order)
+ options_for_select(available_order_filters_array(valid_orders), current_order)
+ end
+
+ private
+
+ def available_order_filters_array(orders)
+ orders.map { |f| [t("debates.index.order_#{f}"), f] }
+ end
+
+end
diff --git a/app/models/debate.rb b/app/models/debate.rb
index 15590fc60..779cca33a 100644
--- a/app/models/debate.rb
+++ b/app/models/debate.rb
@@ -28,6 +28,10 @@ class Debate < ActiveRecord::Base
scope :archived, -> { where("archived_at IS NOT NULL AND hidden_at IS NULL") }
scope :flagged_as_inappropiate, -> { where("inappropiate_flags_count > 0") }
scope :for_render, -> { includes(:tags) }
+ scope :sort_by_total_votes, -> { reorder(cached_votes_total: :desc) }
+ scope :sort_by_likes , -> { reorder(cached_votes_up: :desc) }
+ scope :sort_by_created_at, -> { reorder(created_at: :desc) }
+
# Ahoy setup
visitable # Ahoy will automatically assign visit_id on create
diff --git a/app/views/debates/_order_selector.erb b/app/views/debates/_order_selector.erb
new file mode 100644
index 000000000..de18cfc45
--- /dev/null
+++ b/app/views/debates/_order_selector.erb
@@ -0,0 +1,5 @@
+
diff --git a/app/views/debates/index.html.erb b/app/views/debates/index.html.erb
index 59d11f37c..13600160c 100644
--- a/app/views/debates/index.html.erb
+++ b/app/views/debates/index.html.erb
@@ -4,18 +4,7 @@
<%= t("debates.index.showing") %>
-
-
+ <%= render 'order_selector' %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 049f15435..c1d872ea1 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -33,9 +33,9 @@ en:
index:
create_debate: Create a debate
showing: You are seeing debates
- filter_news: the newest
- filter_votes: the most voted
- filter_rated: the best rated
+ order_created_at: the newest
+ order_total_votes: the most voted
+ order_likes: the best rated
filter_topic: "You are seeing %{number} debates with the topic '%{topic}'"
debate:
debate: Debate
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 58ae07441..c116b7899 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -33,9 +33,9 @@ es:
index:
create_debate: Crea un debate
showing: "Estás viendo los debates"
- filter_news: "más nuevos"
- filter_votes: "más votados"
- filter_rated: mejor valorados
+ order_created_at: "más nuevos"
+ order_total_votes: "más votados"
+ order_likes: mejor valorados
filter_topic: "Estás viendo %{number} debates con el tema '%{topic}'"
debate:
debate: Debate
diff --git a/spec/features/debates_spec.rb b/spec/features/debates_spec.rb
index 22b689308..82669770d 100644
--- a/spec/features/debates_spec.rb
+++ b/spec/features/debates_spec.rb
@@ -350,4 +350,60 @@ feature 'Debates' do
expect(InappropiateFlag.flagged?(user, debate)).to_not be
end
+ feature 'Debate index order filters', :js do
+
+ before do
+ # TODO consider using debate title literally
+ @most_voted_debate = create(:debate)
+ @most_liked_debate = create(:debate)
+ @most_recent_debate = create(:debate)
+ create_list(:vote, 2, votable: @most_liked_debate)
+ create_list(:vote, 2, votable: @most_voted_debate, vote_flag: false)
+ create(:vote, votable: @most_voted_debate)
+ end
+
+ scenario 'Default order is created_at' do
+ visit debates_path
+
+ expect(page).to have_select('order-selector', selected: 'the newest')
+ expect(@most_recent_debate.title).to appear_before(@most_liked_debate.title)
+ end
+
+ scenario 'Debates are ordered by most voted' do
+ visit debates_path
+
+ select 'the most voted', from: 'order-selector'
+ expect(page).to have_select('order-selector', selected: 'the most voted')
+
+ expect(find("#debates .debate", match: :first)).to have_content(@most_voted_debate.title) # Necessary to force capybara to wait for redirect
+ expect(current_url).to include('order=total_votes')
+ expect(@most_voted_debate.title).to appear_before(@most_liked_debate.title)
+ expect(@most_liked_debate.title).to appear_before(@most_recent_debate.title)
+ end
+
+ scenario 'Debates are ordered by best rated' do
+ visit debates_path
+
+ select 'the best rated', from: 'order-selector'
+ expect(find("#debates .debate", match: :first)).to have_content(@most_liked_debate.title)
+
+ expect(current_url).to include('order=likes')
+ expect(@most_liked_debate.title).to appear_before(@most_voted_debate.title)
+ expect(@most_voted_debate.title).to appear_before(@most_recent_debate.title)
+ end
+
+ scenario 'Debates are ordered by newest' do
+ visit debates_path
+
+ select 'the most voted', from: 'order-selector'
+ expect(find("#debates .debate", match: :first)).to have_content(@most_voted_debate.title)
+
+ select 'the newest', from: 'order-selector'
+ expect(find("#debates .debate", match: :first)).to have_content(@most_recent_debate.title)
+
+ expect(current_url).to include('order=created_at')
+ expect(@most_recent_debate.title).to appear_before(@most_liked_debate.title)
+ expect(@most_liked_debate.title).to appear_before(@most_voted_debate.title)
+ end
+ end
end
diff --git a/spec/support/matchers/appear_before.rb b/spec/support/matchers/appear_before.rb
new file mode 100644
index 000000000..bb1d65072
--- /dev/null
+++ b/spec/support/matchers/appear_before.rb
@@ -0,0 +1,6 @@
+RSpec::Matchers.define :appear_before do |later_content|
+ match do |earlier_content|
+ page.body.index(earlier_content) < page.body.index(later_content)
+ end
+end
+