diff --git a/db/migrate/20150825160320_create_ranking_item_table.rb b/db/migrate/20150825160320_create_ranking_item_table.rb new file mode 100644 index 0000000..62ee3e8 --- /dev/null +++ b/db/migrate/20150825160320_create_ranking_item_table.rb @@ -0,0 +1,25 @@ +class CreateRankingItemTable < ActiveRecord::Migration + + def self.up + create_table :proposals_discussion_plugin_ranking_items do |t| + t.integer :position + t.string :abstract + t.integer :votes_for + t.integer :votes_against + t.integer :hits + t.decimal :effective_support + t.integer :proposal_id + t.timestamps + end + add_index( + :proposals_discussion_plugin_ranking_items, + [:proposal_id], + name: 'index_proposals_discussion_plugin_ranking_proposal_id' + ) + end + + def self.down + drop_table :proposals_discussion_plugin_ranking_items + end + +end diff --git a/lib/proposals_discussion_plugin/api.rb b/lib/proposals_discussion_plugin/api.rb index 9c0cbc5..ec4b0e4 100644 --- a/lib/proposals_discussion_plugin/api.rb +++ b/lib/proposals_discussion_plugin/api.rb @@ -6,6 +6,8 @@ class ProposalsDiscussionPlugin::API < Grape::API get ':id/ranking' do article = find_article(environment.articles, params[:id]) ranking = Rails.cache.fetch("#{article.cache_key}/proposals_ranking", expires_in: 30.minutes) do + #FIXME call update_ranking in an async job + article.update_ranking {:proposals => article.ranking, :updated_at => DateTime.now} end ranking[:proposals] = paginate ranking[:proposals] diff --git a/lib/proposals_discussion_plugin/proposal.rb b/lib/proposals_discussion_plugin/proposal.rb index f8b5b40..0173ef7 100644 --- a/lib/proposals_discussion_plugin/proposal.rb +++ b/lib/proposals_discussion_plugin/proposal.rb @@ -7,6 +7,8 @@ class ProposalsDiscussionPlugin::Proposal < TinyMceArticle has_many :locations, :class_name => 'Region', :through => :article_categorizations, :source => :category + has_one :ranking_item + def self.short_description _("Proposal") end diff --git a/lib/proposals_discussion_plugin/proposals_holder.rb b/lib/proposals_discussion_plugin/proposals_holder.rb index b26f0d0..c23b731 100644 --- a/lib/proposals_discussion_plugin/proposals_holder.rb +++ b/lib/proposals_discussion_plugin/proposals_holder.rb @@ -41,6 +41,10 @@ class ProposalsDiscussionPlugin::ProposalsHolder < Folder end def ranking + ProposalsDiscussionPlugin::RankingItem.joins(:proposal => :parent).where('parents_articles.id' => self.id) + end + + def compute_ranking max_hits = proposals.maximum(:hits) min_hits = proposals.minimum(:hits) @@ -48,9 +52,17 @@ class ProposalsDiscussionPlugin::ProposalsHolder < Folder w = [(proposal.hits - max_hits).abs, (proposal.hits - min_hits).abs, 1].max.to_f effective_support = (proposal.votes_for - proposal.votes_against)/w - {:id => proposal.id, :abstract => proposal.abstract, :votes_for => proposal.votes_for, :votes_against => proposal.votes_against, :hits => proposal.hits, :effective_support => effective_support} + ProposalsDiscussionPlugin::RankingItem.new(:proposal => proposal, :abstract => proposal.abstract, :votes_for => proposal.votes_for, :votes_against => proposal.votes_against, :hits => proposal.hits, :effective_support => effective_support) + end + ranking.sort_by { |p| p.effective_support }.reverse + end + + def update_ranking + new_ranking = compute_ranking + transaction do + self.ranking.destroy_all + new_ranking.each {|item| item.save!} end - ranking.sort_by { |p| p[:effective_support] }.reverse end def cache_key_with_person(params = {}, user = nil, language = 'en') diff --git a/lib/proposals_discussion_plugin/ranking_item.rb b/lib/proposals_discussion_plugin/ranking_item.rb new file mode 100644 index 0000000..2aa0a7c --- /dev/null +++ b/lib/proposals_discussion_plugin/ranking_item.rb @@ -0,0 +1,7 @@ +class ProposalsDiscussionPlugin::RankingItem < Noosfero::Plugin::ActiveRecord + + belongs_to :proposal + + attr_accessible :proposal, :abstract, :votes_for, :votes_against, :hits, :effective_support + +end diff --git a/test/unit/api_test.rb b/test/unit/api_test.rb index 59f9996..abc2e35 100644 --- a/test/unit/api_test.rb +++ b/test/unit/api_test.rb @@ -33,7 +33,7 @@ class APITest < ActiveSupport::TestCase get "/api/v1/proposals_discussion_plugin/#{topic.id}/ranking?#{params.to_query}" json = JSON.parse(last_response.body) - assert_equal [proposal2.id, proposal3.id, proposal1.id], json['proposals'].map {|p| p['id']} + assert_equal [proposal2.abstract, proposal3.abstract, proposal1.abstract], json['proposals'].map {|p| p['abstract']} end should 'suggest article children' do diff --git a/test/unit/ranking_item_test.rb b/test/unit/ranking_item_test.rb new file mode 100644 index 0000000..6ea597e --- /dev/null +++ b/test/unit/ranking_item_test.rb @@ -0,0 +1,19 @@ +require_relative '../test_helper' + +class RankingItemTest < ActiveSupport::TestCase + + def setup + @profile = fast_create(Community) + @person = fast_create(Person) + @discussion = ProposalsDiscussionPlugin::Discussion.create!(:name => 'discussion', :profile => person, :allow_topics => false) + end + + attr_reader :profile, :person, :discussion + + should 'return associated ranking item in proposal' do + proposal = ProposalsDiscussionPlugin::Proposal.create!(:name => 'test', :abstract => 'abstract', :profile => profile, :parent => discussion) + discussion.update_ranking + assert proposal.ranking_item + end + +end diff --git a/test/unit/topic_test.rb b/test/unit/topic_test.rb index 7e1b432..d232985 100644 --- a/test/unit/topic_test.rb +++ b/test/unit/topic_test.rb @@ -62,4 +62,24 @@ class TopicTest < ActiveSupport::TestCase assert_equal 10, topic.max_score end + should 'generate ranking for topics' do + topic2 = ProposalsDiscussionPlugin::Topic.new(:name => 'test2', :profile => @profile, :parent => @discussion) + proposal1 = ProposalsDiscussionPlugin::Proposal.create!(:parent => topic, :profile => profile, :name => "proposal1", :abstract => 'abstract') + proposal2 = ProposalsDiscussionPlugin::Proposal.create!(:parent => topic, :profile => profile, :name => "proposal2", :abstract => 'abstract') + proposal3 = ProposalsDiscussionPlugin::Proposal.create!(:parent => topic2, :profile => profile, :name => "proposal3", :abstract => 'abstract') + + topic.update_ranking + topic2.update_ranking + assert_equal [proposal1.abstract, proposal2.abstract], topic.ranking.map(&:abstract) + assert_equal [proposal3.abstract], topic2.ranking.map(&:abstract) + end + + should 'update ranking for a topic' do + proposal1 = ProposalsDiscussionPlugin::Proposal.create!(:parent => topic, :profile => profile, :name => "proposal1", :abstract => 'abstract') + proposal2 = ProposalsDiscussionPlugin::Proposal.create!(:parent => topic, :profile => profile, :name => "proposal2", :abstract => 'abstract') + topic.update_ranking + topic.update_ranking + assert_equal [proposal1.abstract, proposal2.abstract], topic.ranking.map(&:abstract) + end + end -- libgit2 0.21.2