diff --git a/Gemfile b/Gemfile index d393a76b3..bff809a9f 100644 --- a/Gemfile +++ b/Gemfile @@ -31,7 +31,7 @@ gem 'acts_as_commentable_with_threading' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development - +gem 'acts-as-taggable-on' gem "responders" gem 'foundation-rails' diff --git a/Gemfile.lock b/Gemfile.lock index f9cb656a5..470e5ccc8 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -36,6 +36,8 @@ GEM minitest (~> 5.1) thread_safe (~> 0.3, >= 0.3.4) tzinfo (~> 1.1) + acts-as-taggable-on (3.5.0) + activerecord (>= 3.2, < 5) acts_as_commentable_with_threading (2.0.0) activerecord (>= 4.0) activesupport (>= 4.0) @@ -194,6 +196,7 @@ PLATFORMS ruby DEPENDENCIES + acts-as-taggable-on acts_as_commentable_with_threading byebug capybara diff --git a/app/assets/stylesheets/debates.scss b/app/assets/stylesheets/debates.scss new file mode 100644 index 000000000..cb4df7794 --- /dev/null +++ b/app/assets/stylesheets/debates.scss @@ -0,0 +1,7 @@ +#tag_cloud { + width: 400px; + line-height: 1.6em; + .s { font-size: 0.8em; } + .m { font-size: 1.2em; } + .l { font-size: 1.8em; } +} \ No newline at end of file diff --git a/app/controllers/debates_controller.rb b/app/controllers/debates_controller.rb index 718772015..2bf5a0024 100644 --- a/app/controllers/debates_controller.rb +++ b/app/controllers/debates_controller.rb @@ -3,7 +3,11 @@ class DebatesController < ApplicationController before_action :authenticate_user!, only: [:new, :create] def index - @debates = Debate.all + if params[:tag] + @debates = Debate.tagged_with(params[:tag]) + else + @debates = Debate.all + end end def show @@ -35,7 +39,7 @@ class DebatesController < ApplicationController end def debate_params - params.require(:debate).permit(:title, :description, :external_link, :terms_of_service) + params.require(:debate).permit(:title, :description, :tag_list, :terms_of_service) end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index de6be7945..e3f79f023 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,2 +1,7 @@ module ApplicationHelper + + def tags(debate) + debate.tag_list.map { |tag| link_to sanitize(tag), debates_path(tag: tag) }.join(', ').html_safe + end + end diff --git a/app/models/debate.rb b/app/models/debate.rb index aee0618da..d924e494e 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -1,5 +1,6 @@ class Debate < ActiveRecord::Base acts_as_commentable + acts_as_taggable belongs_to :author, class_name: 'User', foreign_key: 'author_id' diff --git a/app/views/debates/_debate.html.erb b/app/views/debates/_debate.html.erb index 637c0086c..d6c899bbe 100644 --- a/app/views/debates/_debate.html.erb +++ b/app/views/debates/_debate.html.erb @@ -1,9 +1,12 @@ -
+

<%= link_to debate.title, debate %>

<%= debate.description %>

+

Creado el: <%= l debate.created_at.to_date %> por: <%= debate.author.name %>

+ +

<%= render 'shared/tags', debate: debate %>

-

\ No newline at end of file +



\ No newline at end of file diff --git a/app/views/debates/_form.html.erb b/app/views/debates/_form.html.erb index 4ece98d8f..9d0af3892 100644 --- a/app/views/debates/_form.html.erb +++ b/app/views/debates/_form.html.erb @@ -20,6 +20,11 @@

Explica con todo el detalle que puedas y de una manera sencilla la idea y que crees que conseguiríamos con ella

<%= f.text_area :description %> +
+ <%= f.label :tag_list, "Temas (separados por comas)" %>
+ <%= f.text_field :tag_list, value: @debate.tag_list.to_s %> +
+ <% if @debate.new_record? %> <%= f.check_box :terms_of_service %> Acepto la política de privacidad y el aviso legal diff --git a/app/views/debates/index.html.erb b/app/views/debates/index.html.erb index ffd5803ee..50ac86a50 100644 --- a/app/views/debates/index.html.erb +++ b/app/views/debates/index.html.erb @@ -4,5 +4,7 @@ <%= render @debates %>
-
+<%= render 'shared/tag_cloud' %> + +

<%= link_to 'New Debate', new_debate_path %> diff --git a/app/views/debates/show.html.erb b/app/views/debates/show.html.erb index 1d3a8ddac..ce1472104 100644 --- a/app/views/debates/show.html.erb +++ b/app/views/debates/show.html.erb @@ -7,6 +7,9 @@

+<%= render 'shared/tags', debate: @debate %> + +

Deja tu comentario <%= render 'comments/form', parent: @debate %> diff --git a/app/views/shared/_tag_cloud.html.erb b/app/views/shared/_tag_cloud.html.erb new file mode 100644 index 000000000..bb61c5a4d --- /dev/null +++ b/app/views/shared/_tag_cloud.html.erb @@ -0,0 +1,5 @@ +
+ <% tag_cloud Debate.tag_counts, %w[s m l] do |tag, css_class| %> + <%= link_to sanitize("#{tag.name}(#{tag.taggings_count})"), debates_path(tag: tag.name), class: css_class %> + <% end %> +
diff --git a/app/views/shared/_tags.html.erb b/app/views/shared/_tags.html.erb new file mode 100644 index 000000000..990c0d41f --- /dev/null +++ b/app/views/shared/_tags.html.erb @@ -0,0 +1,3 @@ +<% if debate.tags.any? %> + Temas: <%= tags(debate) %> +<% end %> \ No newline at end of file diff --git a/config/initializers/acts_as_taggable_on.rb b/config/initializers/acts_as_taggable_on.rb new file mode 100644 index 000000000..ead1691e4 --- /dev/null +++ b/config/initializers/acts_as_taggable_on.rb @@ -0,0 +1 @@ +ActsAsTaggableOn.delimiter = ',' \ No newline at end of file diff --git a/db/migrate/20150718075238_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb b/db/migrate/20150718075238_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb new file mode 100644 index 000000000..2cf5741f8 --- /dev/null +++ b/db/migrate/20150718075238_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb @@ -0,0 +1,25 @@ +# This migration comes from acts_as_taggable_on_engine (originally 1) +class ActsAsTaggableOnMigration < ActiveRecord::Migration + def self.up + create_table :tags do |t| + t.string :name + end + + create_table :taggings do |t| + t.references :tag + t.references :taggable, polymorphic: true + t.references :tagger, polymorphic: true + t.string :context, limit: 128 + t.datetime :created_at + end + + add_index :tags, :name, unique: true + add_index :taggings, :tag_id + add_index :taggings, [:taggable_id, :taggable_type, :context] + end + + def self.down + drop_table :taggings + drop_table :tags + end +end diff --git a/db/migrate/20150718075337_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20150718075337_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb new file mode 100644 index 000000000..6bbd5ab3d --- /dev/null +++ b/db/migrate/20150718075337_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb @@ -0,0 +1,10 @@ +# This migration comes from acts_as_taggable_on_engine (originally 3) +class AddTaggingsCounterCacheToTags < ActiveRecord::Migration + def self.up + add_column :tags, :taggings_count, :integer, default: 0 + end + + def self.down + remove_column :tags, :taggings_count + end +end diff --git a/db/schema.rb b/db/schema.rb index 302566a2d..5a5c87ef2 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -38,6 +38,26 @@ ActiveRecord::Schema.define(version: 20150718091702) do t.datetime "updated_at", null: false end + create_table "taggings", force: :cascade do |t| + t.integer "tag_id" + t.integer "taggable_id" + t.string "taggable_type" + t.integer "tagger_id" + t.string "tagger_type" + t.string "context", limit: 128 + t.datetime "created_at" + end + + add_index "taggings", ["tag_id"], name: "index_taggings_on_tag_id" + add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context" + + create_table "tags", force: :cascade do |t| + t.string "name" + t.integer "taggings_count", default: 0 + end + + add_index "tags", ["name"], name: "index_tags_on_name", unique: true + create_table "users", force: :cascade do |t| t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false diff --git a/spec/features/tags_spec.rb b/spec/features/tags_spec.rb new file mode 100644 index 000000000..61376480d --- /dev/null +++ b/spec/features/tags_spec.rb @@ -0,0 +1,99 @@ +require 'rails_helper' + +feature 'Tags' do + + scenario 'Index' do + earth = create(:debate, tag_list: 'Medio Ambiente') + money = create(:debate, tag_list: 'Economía') + + visit debates_path + + within "#debate-#{earth.id}" do + expect(page).to have_content "Temas: Medio Ambiente" + end + + within "#debate-#{money.id}" do + expect(page).to have_content "Temas: Economía" + end + end + + scenario 'Filtered' do + 2.times { create(:debate, tag_list: 'Salud') } + 2.times { create(:debate, tag_list: 'Hacienda') } + + visit debates_path + first(:link, "Salud").click + + expect(page).to have_css('.debate', count: 2) + expect(page).to have_content('Temas: Salud') + expect(page).to_not have_content('Temas: Hacienda') + end + + scenario 'Show' do + debate = create(:debate, tag_list: 'Hacienda, Economía') + + visit debate_path(debate) + + expect(page).to have_content "Temas: Hacienda, Economía" + end + + scenario 'Tag Cloud' do + 1.times { create(:debate, tag_list: 'Medio Ambiente') } + 5.times { create(:debate, tag_list: 'Corrupción') } + 10.times { create(:debate, tag_list: 'Economía') } + + visit debates_path + + within "#tag-cloud" do + expect(page).to have_css(".s", text: "Medio Ambiente(1)") + expect(page).to have_css(".m", text: "Corrupción(5)") + expect(page).to have_css(".l", text: "Economía(10)") + end + end + + scenario 'Create' do + user = create(:user) + login_as(user) + + visit new_debate_path + fill_in 'debate_title', with: 'Title' + fill_in 'debate_description', with: 'Description' + check 'debate_terms_of_service' + + fill_in 'debate_tag_list', with: "Impuestos, Economía, Hacienda" + + click_button 'Crear Debate' + + expect(page).to have_content 'Debate creado correctamente' + expect(page).to have_content 'Temas: Impuestos, Economía, Hacienda' + end + + scenario 'Update' do + debate = create(:debate, tag_list: 'Economía') + + login_as(debate.author) + visit edit_debate_path(debate) + + expect(page).to have_selector("input[value='Economía']") + + fill_in 'debate_tag_list', with: "Economía, Hacienda" + click_button 'Actualizar Debate' + + expect(page).to have_content 'Debate actualizado correctamente' + expect(page).to have_content 'Temas: Economía, Hacienda' + end + + scenario 'Delete' do + debate = create(:debate, tag_list: 'Economía') + + login_as(debate.author) + visit edit_debate_path(debate) + + fill_in 'debate_tag_list', with: "" + click_button 'Actualizar Debate' + + expect(page).to have_content 'Debate actualizado correctamente' + expect(page).to_not have_content 'Temas:' + end + +end \ No newline at end of file