diff --git a/app/controllers/concerns/commentable_actions.rb b/app/controllers/concerns/commentable_actions.rb index e46ba7da4..286d2a297 100644 --- a/app/controllers/concerns/commentable_actions.rb +++ b/app/controllers/concerns/commentable_actions.rb @@ -73,7 +73,7 @@ module CommentableActions end def tag_cloud - resource_model.last_week.tag_counts.order("#{resource_name.pluralize}_count": :desc, name: :asc).limit(5) + TagCloud.new(resource_model, params[:search]) end def load_geozones diff --git a/app/helpers/tags_helper.rb b/app/helpers/tags_helper.rb index 59bc56bce..da7824622 100644 --- a/app/helpers/tags_helper.rb +++ b/app/helpers/tags_helper.rb @@ -3,26 +3,12 @@ module TagsHelper def taggable_path(taggable_type, tag_name) case taggable_type when 'debate' - debates_path(tag: tag_name) + debates_path(search: tag_name) when 'proposal' - proposals_path(tag: tag_name) + proposals_path(search: tag_name) else '#' end end - def taggable_counter_field(taggable_type) - "#{taggable_type.underscore.pluralize}_count" - end - - def tag_cloud(tags, classes, counter_field = :taggings_count) - return [] if tags.empty? - - max_count = tags.sort_by(&counter_field).last.send(counter_field).to_f - - tags.each do |tag| - index = ((tag.send(counter_field) / max_count) * (classes.size - 1)) - yield tag, classes[index.nan? ? 0 : index.round] - end - end end diff --git a/app/models/tag_cloud.rb b/app/models/tag_cloud.rb new file mode 100644 index 000000000..086d88c48 --- /dev/null +++ b/app/models/tag_cloud.rb @@ -0,0 +1,38 @@ +class TagCloud + + attr_accessor :resource_model, :scope + + def initialize(resource_model, scope=nil) + @resource_model = resource_model + @scope = scope + end + + def tags + resource_model_scoped. + last_week.tag_counts. + where("lower(name) NOT IN (?)", category_names + geozone_names + default_blacklist). + order("#{table_name}_count": :desc, name: :asc). + limit(10) + end + + def category_names + ActsAsTaggableOn::Tag.where("kind = 'category'").map {|tag| tag.name.downcase } + end + + def geozone_names + Geozone.all.map {|geozone| geozone.name.downcase } + end + + def resource_model_scoped + scope && resource_model == Proposal ? resource_model.search(scope) : resource_model + end + + def default_blacklist + [''] + end + + def table_name + resource_model.to_s.downcase.pluralize + end + +end \ No newline at end of file diff --git a/app/views/shared/_tag_cloud.html.erb b/app/views/shared/_tag_cloud.html.erb index 06bf85c2b..6b27de955 100644 --- a/app/views/shared/_tag_cloud.html.erb +++ b/app/views/shared/_tag_cloud.html.erb @@ -3,10 +3,9 @@
- <% tag_cloud @tag_cloud, %w[s m l] do |tag, css_class| %> - <%= link_to taggable_path(taggable, tag.name), class: css_class do %> - <%= tag.name %> - (<%= tag.send(taggable_counter_field(taggable)) %>) + <% @tag_cloud.tags.each do |tag| %> + <%= link_to taggable_path(taggable, tag.name) do %> + <%= tag.name %> <% end %> <% end %> diff --git a/spec/features/tags_spec.rb b/spec/features/tags_spec.rb index 3f57c6b91..0b95e1de4 100644 --- a/spec/features/tags_spec.rb +++ b/spec/features/tags_spec.rb @@ -54,22 +54,6 @@ feature 'Tags' do expect(page).to have_content "Hacienda" end - scenario 'Tag Cloud' do - 1.times { create(:debate, tag_list: 'Medio Ambiente') } - 5.times { create(:debate, tag_list: 'Corrupción') } - 5.times { create(:debate, tag_list: 'Educación') } - 10.times { create(:debate, tag_list: 'Economía') } - - visit debates_path - - within(:css, "#tag-cloud") do - expect(page.find("a:eq(1)")).to have_content("Economía (10)") - expect(page.find("a:eq(2)")).to have_content("Corrupción (5)") - expect(page.find("a:eq(3)")).to have_content("Educación (5)") - expect(page.find("a:eq(4)")).to have_content("Medio Ambiente (1)") - end - end - scenario 'Create' do user = create(:user) login_as(user) @@ -141,4 +125,81 @@ feature 'Tags' do expect(page).to_not have_content 'Economía' end + context 'Tag cloud' do + + scenario 'Proposals' do + earth = create(:proposal, tag_list: 'Medio Ambiente') + money = create(:proposal, tag_list: 'Economía') + + visit proposals_path + + within "#tag-cloud" do + expect(page).to have_content "Medio Ambiente" + expect(page).to have_content "Economía" + end + end + + scenario 'Debates' do + earth = create(:debate, tag_list: 'Medio Ambiente') + money = create(:debate, tag_list: 'Economía') + + visit debates_path + + within "#tag-cloud" do + expect(page).to have_content "Medio Ambiente" + expect(page).to have_content "Economía" + end + end + + scenario "scoped by category" do + create(:tag, kind: 'category', name: 'Medio Ambiente') + create(:tag, kind: 'category', name: 'Economía') + + earth = create(:proposal, tag_list: 'Medio Ambiente, Agua') + money = create(:proposal, tag_list: 'Economía, Corrupción') + + visit proposals_path(search: 'Economía') + + within "#tag-cloud" do + expect(page).to have_css(".tag", count: 1) + expect(page).to have_content "Corrupción" + expect(page).to_not have_content "Economía" + end + end + + scenario "scoped by district" do + create(:geozone, name: 'Madrid') + create(:geozone, name: 'Barcelona') + + earth = create(:proposal, tag_list: 'Madrid, Agua') + money = create(:proposal, tag_list: 'Barcelona, Playa') + + visit proposals_path(search: 'Barcelona') + + within "#tag-cloud" do + expect(page).to have_css(".tag", count: 1) + expect(page).to have_content "Playa" + expect(page).to_not have_content "Agua" + end + end + + scenario "tag links" do + proposal1 = create(:proposal, tag_list: 'Medio Ambiente') + proposal2 = create(:proposal, tag_list: 'Medio Ambiente') + proposal3 = create(:proposal, tag_list: 'Economía') + + visit proposals_path + + within "#tag-cloud" do + click_link "Medio Ambiente" + end + + expect(page).to have_css ".proposal", count: 2 + expect(page).to have_content proposal1.title + expect(page).to have_content proposal2.title + expect(page).to_not have_content proposal3.title + end + + end + end diff --git a/spec/models/tag_cloud_spec.rb b/spec/models/tag_cloud_spec.rb new file mode 100644 index 000000000..d040c0527 --- /dev/null +++ b/spec/models/tag_cloud_spec.rb @@ -0,0 +1,116 @@ +require 'rails_helper' + +describe TagCloud do + + describe "#tags" do + + it "returns proposal tags" do + create(:proposal, tag_list: 'participation') + create(:debate, tag_list: 'world hunger') + + tag_cloud = TagCloud.new(Proposal) + + expect(tag_names(tag_cloud)).to contain_exactly('participation') + end + + it "returns debate tags" do + create(:proposal, tag_list: 'participation') + create(:debate, tag_list: 'world hunger') + + tag_cloud = TagCloud.new(Debate) + + expect(tag_names(tag_cloud)).to contain_exactly('world hunger') + end + + it "returns tags from last week" do + create(:proposal, tag_list: 'participation', created_at: 1.day.ago) + create(:proposal, tag_list: 'corruption', created_at: 2.weeks.ago) + + tag_cloud = TagCloud.new(Proposal) + + expect(tag_names(tag_cloud)).to contain_exactly('participation') + end + + it "does not return category tags" do + create(:tag, kind: 'category', name: 'Education') + create(:tag, kind: 'category', name: 'Participation') + + create(:proposal, tag_list: 'education, parks') + create(:proposal, tag_list: 'participation, water') + + tag_cloud = TagCloud.new(Proposal) + + expect(tag_names(tag_cloud)).to contain_exactly('parks', 'water') + end + + it "does not return geozone names" do + create(:geozone, name: 'California') + create(:geozone, name: 'New York') + + create(:proposal, tag_list: 'parks, California') + create(:proposal, tag_list: 'water, New York') + + tag_cloud = TagCloud.new(Proposal) + + expect(tag_names(tag_cloud)).to contain_exactly('parks', 'water') + end + + it "returns tags scoped by category" do + create(:tag, kind: 'category', name: 'Education') + create(:tag, kind: 'category', name: 'Participation') + + create(:proposal, tag_list: 'education, parks') + create(:proposal, tag_list: 'participation, water') + + tag_cloud = TagCloud.new(Proposal, 'Education') + + expect(tag_names(tag_cloud)).to contain_exactly('parks') + end + + it "returns tags scoped by geozone" do + create(:geozone, name: 'California') + create(:geozone, name: 'New York') + + create(:proposal, tag_list: 'parks, California') + create(:proposal, tag_list: 'water, New York') + + tag_cloud = TagCloud.new(Proposal, 'California') + + expect(tag_names(tag_cloud)).to contain_exactly('parks') + end + + xit "returns tags scoped by category for debates" + xit "returns tags scoped by geozone for debates" + + it "orders tags by count" do + 3.times { create(:proposal, tag_list: 'participation') } + create(:proposal, tag_list: 'corruption') + + tag_cloud = TagCloud.new(Proposal) + + expect(tag_names(tag_cloud).first).to eq 'participation' + expect(tag_names(tag_cloud).second).to eq 'corruption' + end + + it "orders tags by count and then by name" do + 3.times { create(:proposal, tag_list: 'participation') } + 3.times { create(:proposal, tag_list: 'health') } + create(:proposal, tag_list: 'corruption') + + tag_cloud = TagCloud.new(Proposal) + + expect(tag_names(tag_cloud).first).to eq 'health' + expect(tag_names(tag_cloud).second).to eq 'participation' + expect(tag_names(tag_cloud).third).to eq 'corruption' + end + + it "returns a maximum of 10 tags" do + 12.times { |i| create(:proposal, tag_list: "Tag #{i}") } + + tag_cloud = TagCloud.new(Proposal) + + expect(tag_names(tag_cloud).count).to eq(10) + end + end + +end \ No newline at end of file diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb index 437a3c7ca..f9331d328 100644 --- a/spec/support/common_actions.rb +++ b/spec/support/common_actions.rb @@ -175,4 +175,8 @@ module CommonActions create(:debate, :with_confidence_score, cached_votes_up: 80)] end + def tag_names(tag_cloud) + tag_cloud.tags.map(&:name) + end + end