diff --git a/Gemfile b/Gemfile index 65d1af1d..a9128224 100644 --- a/Gemfile +++ b/Gemfile @@ -94,6 +94,9 @@ gem 'foreman' # Better logging gem 'awesome_print' +# Tagging +gem 'acts-as-taggable-on', '~> 3.4' + gem 'faraday', '~> 0.8.1' gem 'metamagic' @@ -135,9 +138,6 @@ gem 'mongoid' gem 'mongo' gem 'mongoid_taggable' gem 'bson_ext' -#Tagging -gem 'rocket_tag' -gem 'squeel', '1.0.1' gem 'strong_parameters' gem 'postgres_ext' # ElasticSearch client diff --git a/Gemfile.lock b/Gemfile.lock index 56f70053..22e5e9bb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -81,6 +81,8 @@ GEM activesupport (3.2.21) i18n (~> 0.6, >= 0.6.4) multi_json (~> 1.0) + acts-as-taggable-on (3.4.2) + activerecord (>= 3.2, < 5) acts_as_commentable (2.0.1) acts_as_follower (0.1.1) addressable (2.3.6) @@ -475,8 +477,6 @@ GEM cliver (~> 0.3.1) multi_json (~> 1.0) websocket-driver (>= 0.2.0) - polyamorous (0.5.0) - activerecord (~> 3.0) polyglot (0.3.5) poro_plus (1.0.2) posix-spawn (0.3.9) @@ -593,9 +593,6 @@ GEM rest-client (1.7.2) mime-types (>= 1.16, < 3.0) netrc (~> 0.7) - rocket_tag (0.5.6) - activerecord (>= 3.2.0) - squeel (~> 1.0.0) rspec (3.1.0) rspec-core (~> 3.1.0) rspec-expectations (~> 3.1.0) @@ -688,10 +685,6 @@ GEM multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) - squeel (1.0.1) - activerecord (~> 3.0) - activesupport (~> 3.0) - polyamorous (~> 0.5.0) strong_parameters (0.2.3) actionpack (~> 3.0) activemodel (~> 3.0) @@ -763,6 +756,7 @@ PLATFORMS ruby DEPENDENCIES + acts-as-taggable-on (~> 3.4) acts_as_commentable (= 2.0.1) acts_as_follower (= 0.1.1) airbrake @@ -855,7 +849,6 @@ DEPENDENCIES redcarpet redis-rails (~> 3.2) rest-client - rocket_tag rspec-rails rubocop ruby-progressbar @@ -872,7 +865,6 @@ DEPENDENCIES slim-rails spring spring-commands-rspec - squeel (= 1.0.1) stripe! stripe-ruby-mock! strong_parameters diff --git a/app/controllers/networks_controller.rb b/app/controllers/networks_controller.rb index 656db6c8..db5946fe 100644 --- a/app/controllers/networks_controller.rb +++ b/app/controllers/networks_controller.rb @@ -41,7 +41,7 @@ def members def show @protips = [] - @topics = @network.tags + @topics = @network.tag_list if (params[:sort].blank? && params[:filter].blank?) || params[:sort] == 'upvotes' @protips = @network.most_upvoted_protips(@per_page, @page) @@ -141,7 +141,7 @@ def destroy def add_tag tag = params[:tag] - @network.tags << tag + @network.tag_list.add(tag) respond_to do |format| if @network.save @@ -155,8 +155,8 @@ def add_tag end def remove_tag - tag = params[:tag] - @network.tags = @network.tags.delete(tag) + tag = params[:tag] + @network.tag_list.remove(tag) respond_to do |format| if @network.save @@ -171,7 +171,7 @@ def remove_tag def update_tags tags = params[:tags][:tags] - @network.tags = tags.split(',').map(&:strip).select { |tag| Tag.exists?(name: tag) } + @network.tag_list = tags.split(',').map(&:strip).select { |tag| Tag.exists?(name: tag) } respond_to do |format| if @network.save diff --git a/app/controllers/opportunities_controller.rb b/app/controllers/opportunities_controller.rb index 785d82e0..812613d8 100644 --- a/app/controllers/opportunities_controller.rb +++ b/app/controllers/opportunities_controller.rb @@ -1,7 +1,7 @@ class OpportunitiesController < ApplicationController before_action :lookup_team, only: [:activate, :deactivate, :new, :create, :edit, :update, :visit] before_action :lookup_opportunity, only: [:edit, :update, :activate, :deactivate, :visit] - before_action :cleanup_params_to_prevent_rocket_tag_error + before_action :cleanup_params_to_prevent_tagging_error before_action :validate_permissions, only: [:new, :edit, :create, :update, :activate, :deactivate] before_action :verify_payment, only: [:new, :create] before_action :stringify_location, only: [:create, :update] @@ -29,7 +29,7 @@ def edit end def create - opportunity_create_params = params.require(:opportunity).permit(:name, :team_id, :opportunity_type, :description, :tags, :location, :link, :salary, :apply, :remote) + opportunity_create_params = params.require(:opportunity).permit(:name, :team_id, :opportunity_type, :description, :tag_list, :location, :link, :salary, :apply, :remote) @job = Opportunity.new(opportunity_create_params) respond_to do |format| if @job.save @@ -42,7 +42,7 @@ def create end def update - opportunity_update_params = params.require(:opportunity).permit(:id, :name, :team_id, :opportunity_type, :description, :tags, :location, :link, :salary, :apply) + opportunity_update_params = params.require(:opportunity).permit(:id, :name, :team_id, :opportunity_type, :description, :tag_list, :location, :link, :salary, :apply) respond_to do |format| if @job.update_attributes(opportunity_update_params) format.html { redirect_to teamname_path(@team.slug), notice: "#{@job.name} updated" } @@ -131,10 +131,10 @@ def header_ok end end - def cleanup_params_to_prevent_rocket_tag_error - if params[:opportunity] && params[:opportunity][:tags] - params[:opportunity][:tags] = "#{params[:opportunity][:tags]}".split(',').map(&:strip).reject(&:empty?).join(",") - params[:opportunity][:tags] = nil if params[:opportunity][:tags].strip.blank? + def cleanup_params_to_prevent_tagging_error + if params[:opportunity] && params[:opportunity][:tag_list] + params[:opportunity][:tag_list] = "#{params[:opportunity][:tag_list]}".split(',').map(&:strip).reject(&:empty?).join(",") + params[:opportunity][:tag_list] = nil if params[:opportunity][:tag_list].strip.blank? end end @@ -151,7 +151,7 @@ def all_job_locations end def all_job_skills - Rails.cache.fetch('job_skills', expires_in: 23.hours) { Opportunity.all.flat_map(&:tags).uniq.compact } + Rails.cache.fetch('job_skills', expires_in: 23.hours) { Opportunity.all.flat_map(&:tag_list).uniq.compact } end def closest_to_user(user) diff --git a/app/controllers/protips_controller.rb b/app/controllers/protips_controller.rb index ad105111..3122fd49 100644 --- a/app/controllers/protips_controller.rb +++ b/app/controllers/protips_controller.rb @@ -152,10 +152,10 @@ def random end def new - new_params = params.permit(:topics) + new_params = params.permit(:topic_list) - prefilled_topics = (new_params[:topics] || '').split('+').collect(&:strip) - @protip = Protip.new(topics: prefilled_topics) + prefilled_topics = (new_params[:topic_list] || '').split('+').collect(&:strip) + @protip = Protip.new(topic_list: prefilled_topics) respond_with @protip end @@ -165,7 +165,7 @@ def edit def create create_params = if params[:protip] && params[:protip].keys.present? - params.require(:protip).permit(:title, :body, :user_id, topics: []) + params.require(:protip).permit(:title, :body, :user_id, :topic_list) else {} end @@ -187,7 +187,7 @@ def create def update # strong_parameters will intentionally fail if a key is present but has an empty hash. :( update_params = if params[:protip] && params[:protip].keys.present? - params.require(:protip).permit(:title, :body, :user_id, topics: []) + params.require(:protip).permit(:title, :body, :user_id, :topic_list) else {} end @@ -233,8 +233,8 @@ def upvote end def tag - tag_params = params.permit(:topics) - @protip.topics << tag_params[:topics] unless tag_params[:topics].nil? + tag_params = params.permit(:topic_list) + @protip.topic_list.add(tag_params[:topic_list]) unless tag_params[:topic_list].nil? end def subscribe @@ -316,7 +316,7 @@ def feature end def delete_tag - @protip.topics.delete(CGI.unescape(params.permit(:topic))) + @protip.topic_list.remove(params.permit(:topic)) respond_to do |format| if @protip.save format.html { redirect_to protip_path(@protip) } @@ -349,7 +349,7 @@ def by_tags def preview preview_params = params.require(:protip).permit(:title, :body) - preview_params.delete(:topics) if preview_params[:topics].blank? + preview_params.delete(:topic_list) if preview_params[:topic_list].blank? protip = Protip.new(preview_params) protip.updated_at = protip.created_at = Time.now protip.user = current_user diff --git a/app/models/network.rb b/app/models/network.rb index f2525ab4..e3f86271 100644 --- a/app/models/network.rb +++ b/app/models/network.rb @@ -17,7 +17,7 @@ class Network < ActiveRecord::Base profile_url: { type: 'string', index: 'not_analyzed' }, } } } } - attr_taggable :tags + acts_as_taggable acts_as_followable attr_accessor :resident_expert has_many :network_experts, autosave: true, dependent: :destroy @@ -61,7 +61,7 @@ def top_tags_not_networks end def top_tags_not_in_any_networks - top_tags.where('tags.name NOT IN (?)', Network.all.map(&:tags).flatten) + top_tags.where('tags.name NOT IN (?)', Network.all.map(&:tag_list).flatten) end def top_tags @@ -82,21 +82,17 @@ def create_slug! end def tag_with_name! - unless self.tags.include? self.name - self.tags = (self.tags + [self.name, self.slug]) + unless self.tag_list.include? self.name + self.tag_list = (self.tag_list + [self.name, self.slug]) end end def correct_tags - if self.tags_changed? - self.tags = self.tags.uniq.select { |tag| Tag.exists?(name: tag) }.reject { |tag| (tag != self.name) && Network.exists?(name: tag) } + if self.tag_list_changed? + self.tags_list = self.tag_list.uniq.select { |tag| Tag.exists?(name: tag) }.reject { |tag| (tag != self.name) && Network.exists?(name: tag) } end end - def tags_changed? - self.tags_tags.map(&:name) != self.tags - end - def protips_tags_with_count self.protips.joins("inner join taggings on taggings.taggable_id = protips.id").joins('inner join tags on taggings.tag_id = tags.id').where("taggings.taggable_type = 'Protip' AND taggings.context = 'topics'").select('tags.name, count(tags.name)').group('tags.name').order('count(tags.name) DESC') end @@ -117,7 +113,7 @@ def assign_mayor! candidate = self.in_line_to_the_throne.first unless candidate.nil? - Rails.logger.debug "finding a mayor among: #{self.tags}" if ENV['DEBUG'] + Rails.logger.debug "finding a mayor among: #{self.tag_list}" if ENV['DEBUG'] person_with_most_upvoted_protips_on_topic = User.find(candidate.user_id) Rails.logger.debug "mayor for #{name} found: #{person_with_most_upvoted_protips_on_topic.username}" if ENV['DEBUG'] @@ -163,7 +159,7 @@ def to_public_hash end def protips - @protips ||= Protip.tagged_with(self.tags, on: :topics) + @protips ||= Protip.tagged_with(self.tag_list, on: :topics) end def upvotes @@ -171,33 +167,33 @@ def upvotes end def most_upvoted_protips(limit = nil, offset = 0) - Protip.search_trending_by_topic_tags("sort:upvotes desc", self.tags, offset, limit) + Protip.search_trending_by_topic_tags("sort:upvotes desc", self.tag_list, offset, limit) end def new_protips(limit = nil, offset = 0) - Protip.search("sort:created_at desc", self.tags, page: offset, per_page: limit) + Protip.search("sort:created_at desc", self.tag_list, page: offset, per_page: limit) end def featured_protips(limit = nil, offset = 0) #self.protips.where(:featured => true) - Protip.search("featured:true", self.tags, page: offset, per_page: limit) + Protip.search("featured:true", self.tag_list, page: offset, per_page: limit) end def flagged_protips(limit = nil, offset = 0) - Protip.search("flagged:true", self.tags, page: offset, per_page: limit) + Protip.search("flagged:true", self.tag_list, page: offset, per_page: limit) end def highest_scored_protips(limit=nil, offset =0, field=:trending_score) - Protip.search("sort:#{field} desc", self.tags, page: offset, per_page: limit) + Protip.search("sort:#{field} desc", self.tag_list, page: offset, per_page: limit) end def mayor_protips(limit=nil, offset =0) - Protip.search_trending_by_user(self.mayor.username, nil, self.tags, offset, limit) + Protip.search_trending_by_user(self.mayor.username, nil, self.tag_list, offset, limit) end def expert_protips(limit=nil, offset =0) - Protip.search_trending_by_user(self.resident_expert.username, nil, self.tags, offset, limit) + Protip.search_trending_by_user(self.resident_expert.username, nil, self.tag_list, offset, limit) end def members(limit = -1, offset = 0) @@ -226,7 +222,7 @@ def resident_expert_from_env end def assign_members - Skill.where(name: self.tags).select('DISTINCT(user_id)').map(&:user).each do |member| + Skill.where(name: self.tag_list).select('DISTINCT(user_id)').map(&:user).each do |member| member.join(self) end end diff --git a/app/models/opportunity.rb b/app/models/opportunity.rb index 98666fd1..29d49d54 100644 --- a/app/models/opportunity.rb +++ b/app/models/opportunity.rb @@ -6,7 +6,7 @@ class Opportunity < ActiveRecord::Base include SearchModule include OpportunityMapping - attr_taggable :tags + acts_as_taggable OPPORTUNITY_TYPES = %w(full-time part-time contract internship) @@ -16,7 +16,7 @@ class Opportunity < ActiveRecord::Base validates :name, presence: true, allow_blank: false validates :opportunity_type, inclusion: { in: OPPORTUNITY_TYPES } validates :description, length: { minimum: 100, maximum: 2000 } - validates :tags, with: :tags_within_length + validates :tag_list, with: :tags_within_length validates :location, presence: true, allow_blank: false validates :location_city, presence: true, allow_blank: false, unless: lambda { location && anywhere?(location) } validates :salary, presence: true, numericality: true, inclusion: 0..800_000, allow_blank: true @@ -76,13 +76,13 @@ def self.random end def tags_within_length - tags_string = tags.join(',') + tags_string = tag_list.join(',') errors.add(:skill_tags, 'are too long(Maximum is 250 characters)') if tags_string.length > 250 errors.add(:base, 'You need to specify at least one skill tag') if tags_string.length == 0 end def update_cached_tags - self.cached_tags = tags.join(',') + self.cached_tags = tag_list.join(',') end def seize_by(user) diff --git a/app/models/protip.rb b/app/models/protip.rb index 0210ed16..26dc8c80 100644 --- a/app/models/protip.rb +++ b/app/models/protip.rb @@ -39,7 +39,7 @@ class Protip < ActiveRecord::Base user_ip: proc { self.user.last_ip }, user_agent: proc { self.user.last_ua } - attr_taggable :topics, :users + acts_as_taggable_on :topics, :users attr_accessor :upvotes DEFAULT_IP_ADDRESS = '0.0.0.0' @@ -73,7 +73,7 @@ class Protip < ActiveRecord::Base validates :title, presence: true, length: { minimum: 5, maximum: MAX_TITLE_LENGTH } validates :body, presence: true validates :kind, presence: true, inclusion: { in: KINDS } - validates :topics, length: { minimum: 1 } + validates :topic_list, length: { minimum: 1 } after_validation :tag_user before_create :assign_random_id @@ -345,7 +345,7 @@ def index_search_after_destroy def networks - Network.tagged_with(self.topics) + Network.tagged_with(self.topic_list) end def orphan? @@ -357,7 +357,7 @@ def update_network(event=:new_protip) end def generate_event(options={}) - unless self.created_automagically? and self.topics.include?("github") + unless self.created_automagically? and self.topic_list.include?("github") event_type = self.event_type(options) GenerateEventJob.perform_in(10.minutes, event_type, event_audience(event_type), self.to_event_hash(options), 1.minute) end @@ -389,7 +389,7 @@ def event_audience(event_type) end def slideshare? - self.topics.count == 1 && self.topics.include?("slideshare") + self.topics.count == 1 && self.topic_list.include?("slideshare") end def event_type(options={}) @@ -403,7 +403,7 @@ def event_type(options={}) end def topic_ids - self.taggings.joins('inner join tags on taggings.tag_id = tags.id').select('tags.id').map(&:id) + topics.pluck(:id) end def to_indexed_json @@ -459,7 +459,7 @@ def to_public_hash title: Sanitize.clean(title), body: body, html: Sanitize.clean(to_html), - tags: topics, + tags: topic_list, upvotes: upvotes, url: path, upvote_path: upvote_path, @@ -518,7 +518,7 @@ def original? end def tokenized_skills - @tokenized_skills ||= self.topics.collect { |tag| Skill.tokenize(tag) } + @tokenized_skills ||= self.topic_list.collect { |tag| Skill.tokenize(tag) } end def to_param @@ -844,7 +844,7 @@ def owned_by?(user) alias_method :owner?, :owned_by? def tag_user - self.users = [self.user.try(:username)] if self.users.blank? + self.user_list = [self.user.try(:username)] if self.users.blank? end def reassign_to(user) @@ -853,7 +853,7 @@ def reassign_to(user) end def tags - topics + users + topic_list + user_list end def link @@ -861,24 +861,20 @@ def link end def reformat_tags! - if self.topics.count == 1 && self.topics.first =~ /\s/ - self.topics = self.topics.first.split(/\s/) + if self.topic_list.count == 1 && self.topic_list.first =~ /\s/ + self.topic_list = self.topic_list.first.split(/\s/) end end def sanitize_tags! - new_topics = self.topics.reject { |tag| tag.blank? }.map do |topic| + new_topics = self.topic_list.reject { |tag| tag.blank? }.map do |topic| sanitized_topic = self.class.preprocess_tag(topic) invalid_topic = topic.match("^((?!#{VALID_TAG}).)*$") && $1 errors[:topics] << "The tag '#{topic}' has invalid characters: #{invalid_topic unless invalid_topic.nil?}" if sanitized_topic.nil? sanitized_topic end new_topics = new_topics.compact.uniq - self.topics = new_topics if topics.blank? or topics_changed? - end - - def topics_changed? - self.topics_tags.map(&:name) != self.topics + self.topic_list = new_topics if topic_list.blank? or topic_list_changed? end def viewed_by(viewer) @@ -954,7 +950,7 @@ def matching_jobs if self.user.team && self.user.team.hiring? self.user.team.best_positions_for(self.user) else - Opportunity.based_on(self.topics) + Opportunity.based_on(self.topic_list) end end @@ -973,7 +969,7 @@ def check_links private def need_to_extract_data_from_links - self.topics.blank? || self.title.blank? + self.topic_list.blank? || self.title.blank? end def adjust_like_value(user, like_value) diff --git a/app/views/opportunities/_form.html.haml b/app/views/opportunities/_form.html.haml index 61679239..7a8430b3 100644 --- a/app/views/opportunities/_form.html.haml +++ b/app/views/opportunities/_form.html.haml @@ -18,8 +18,8 @@ =j.text_area :description %fieldset - =j.label :tags, 'Primary skills the person will use. (comma separated)' - =j.text_field :tags, value: params[:tags] || @job.tags.join(",") + =j.label :tag_list, 'Primary skills the person will use. (comma separated)' + =j.text_field :tag_list, value: params[:tag_list] || @job.tag_list.join(",") %fieldset -if @team.locations.any? diff --git a/app/views/protips/_new_or_edit.html.haml b/app/views/protips/_new_or_edit.html.haml index 8ef32ed7..872cfd97 100644 --- a/app/views/protips/_new_or_edit.html.haml +++ b/app/views/protips/_new_or_edit.html.haml @@ -31,7 +31,7 @@ %li.full-list=link_to('How to write a great pro tip', 'https://coderwall.com/p/o42nvq', target: "_blank") .rule.edit-tags - = p.input :topics, placeholder: "Tags, comma separated", label: false, input_html: {class: "tags cf", value: @protip.topics.join(","), id: "protip_tags", :autocomplete=>'off'} + = p.input :topic_list, placeholder: "Tags, comma separated", label: false, input_html: {class: "tags cf", value: @protip.topic_list.join(","), id: "protip_tags", :autocomplete=>'off'} .x-tip-content.preview.back.side.cf#x-protip-preview diff --git a/app/views/protips/_protip.html.haml b/app/views/protips/_protip.html.haml index 3052503e..8a9d92ae 100644 --- a/app/views/protips/_protip.html.haml +++ b/app/views/protips/_protip.html.haml @@ -84,7 +84,7 @@ = protip.total_views views %ul#tags.cf{itemprop: :keywords} - - protip.topics.each do |tag| + - protip.topic_list.each do |tag| %li %a{ href: "/p/t/#{ tag.parameterize }" } = tag diff --git a/config/initializers/acts_as_taggable_on.rb b/config/initializers/acts_as_taggable_on.rb new file mode 100644 index 00000000..08d8aa67 --- /dev/null +++ b/config/initializers/acts_as_taggable_on.rb @@ -0,0 +1 @@ +ActsAsTaggableOn.force_lowercase = true diff --git a/db/migrate/20141231203425_replace_rocket_tag_with_aato.rb b/db/migrate/20141231203425_replace_rocket_tag_with_aato.rb new file mode 100644 index 00000000..6605de0c --- /dev/null +++ b/db/migrate/20141231203425_replace_rocket_tag_with_aato.rb @@ -0,0 +1,27 @@ +class ReplaceRocketTagWithAato < ActiveRecord::Migration + def up + # This was created by rocket_tag but not used anywhere. + drop_table :alias_tags + + # This is something that AATO has that rocket_tag doesn't. + add_column :tags, :taggings_count, :integer, default: 0 + + # Populate the taggings_count properly + ActsAsTaggableOn::Tag.reset_column_information + ActsAsTaggableOn::Tag.find_each do |tag| + ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) + end + + add_index 'tags', ['name'], name: 'index_tags_on_name', unique: true + + remove_index 'taggings', name: "index_taggings_on_tag_id" + remove_index 'taggings', name: "index_taggings_on_taggable_id_and_taggable_type_and_context" + add_index 'taggings', + ['tag_id', 'taggable_id', 'taggable_type', 'context', 'tagger_id', 'tagger_type'], + unique: true, name: 'taggings_idx' + end + + def down + raise ActiveRecord::IrreversibleMigration + end +end diff --git a/db/schema.rb b/db/schema.rb index 72eaee64..d3778e55 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,19 +11,11 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20141221211825) do +ActiveRecord::Schema.define(:version => 20141231203425) do add_extension "citext" add_extension "hstore" - create_table "alias_tags", :id => false, :force => true do |t| - t.integer "tag_id" - t.integer "alias_id" - end - - add_index "alias_tags", ["alias_id"], :name => "index_alias_tags_on_alias_id" - add_index "alias_tags", ["tag_id"], :name => "index_alias_tags_on_tag_id" - create_table "api_accesses", :force => true do |t| t.string "api_key" t.text "awards" @@ -352,13 +344,15 @@ 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" + add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], :name => "taggings_idx", :unique => true create_table "tags", :force => true do |t| - t.string "name" + t.string "name" + t.integer "taggings_count", :default => 0 end + add_index "tags", ["name"], :name => "index_tags_on_name", :unique => true + create_table "teams", :force => true do |t| t.datetime "created_at", :null => false t.datetime "updated_at", :null => false diff --git a/spec/fabricators/opportunity_fabricator.rb b/spec/fabricators/opportunity_fabricator.rb index 741c7a23..a062b9aa 100644 --- a/spec/fabricators/opportunity_fabricator.rb +++ b/spec/fabricators/opportunity_fabricator.rb @@ -2,7 +2,7 @@ salary 100_000 name 'Senior Rails Web Developer' description 'Architect and implement the Ruby and Javascript underpinnings of our various user-facing and internal web apps like api.heroku.com.' - tags ['rails', 'sinatra', 'JQuery', 'Clean, beautiful code'] + tag_list ['rails', 'sinatra', 'JQuery'] location 'San Francisco, CA' cached_tags 'java, python' team_id { Fabricate(:team, paid_job_posts: 1).id } diff --git a/spec/fabricators/protip_fabricator.rb b/spec/fabricators/protip_fabricator.rb index 6de898e6..80f94dd0 100644 --- a/spec/fabricators/protip_fabricator.rb +++ b/spec/fabricators/protip_fabricator.rb @@ -1,5 +1,5 @@ Fabricator(:protip) do - topics %w(Javascript CoffeeScript) + topic_list %w(Javascript CoffeeScript) title { Faker::Company.catch_phrase } body { Faker::Lorem.sentences(8).join(' ') } user { Fabricate.build(:user) } diff --git a/spec/mailers/abuse_mailer_spec.rb b/spec/mailers/abuse_mailer_spec.rb index f6c5631a..bcfae750 100644 --- a/spec/mailers/abuse_mailer_spec.rb +++ b/spec/mailers/abuse_mailer_spec.rb @@ -9,7 +9,7 @@ Protip.create!( title: 'hello world', body: "somethings that's meaningful and nice", - topics: %w(java javascript), + topic_list: %w(java javascript), user_id: current_user.id ) end diff --git a/spec/models/protip_spec.rb b/spec/models/protip_spec.rb index e79a466e..0fe492db 100644 --- a/spec/models/protip_spec.rb +++ b/spec/models/protip_spec.rb @@ -1,6 +1,6 @@ require 'vcr_helper' -RSpec.describe Protip, type: :model, skip: true do +RSpec.describe Protip, type: :model do describe 'indexing linked content' do it 'indexes page' @@ -74,6 +74,7 @@ end it 'is reindexed if username or team change' do + pending "Not implemented yet" team = Fabricate(:team, name: 'first-team') user = Fabricate(:user, username: 'initial-username') team.add_member(user) @@ -99,32 +100,40 @@ describe 'tagging protip' do it 'should sanitize tags into normalized form' do - protip = Fabricate(:protip, topics: %w(Javascript CoffeeScript), user: Fabricate(:user)) + protip = Fabricate(:protip, topic_list: %w(Javascript CoffeeScript), user: Fabricate(:user)) protip.save! - expect(protip.topics).to match_array(%w(javascript coffeescript)) + expect(protip.topic_list).to match_array(%w(javascript coffeescript)) expect(protip.topics.count).to eq(2) end it 'should sanitize empty tag' do - protip = Fabricate(:protip, topics: 'Javascript, ', user: Fabricate(:user)) + protip = Fabricate(:protip, topic_list: 'Javascript, ', user: Fabricate(:user)) protip.save! - expect(protip.topics).to match_array(['javascript']) + expect(protip.topic_list).to match_array(['javascript']) expect(protip.topics.count).to eq(1) end it 'should remove duplicate tags' do - protip = Fabricate(:protip, topics: %w(github github Github GitHub), user: Fabricate(:user)) + protip = Fabricate(:protip, topic_list: %w(github github Github GitHub), user: Fabricate(:user)) protip.save! - expect(protip.topics).to eq(['github']) + expect(protip.topic_list).to eq(['github']) expect(protip.topics.count).to eq(1) end - it 'should accept tags separated by spaces only' do - protip = Fabricate(:protip, topics: 'ruby python heroku', user: Fabricate(:user)) + it 'should accept tags separated by commas only' do + protip = Fabricate(:protip, topic_list: 'ruby, python, heroku', user: Fabricate(:user)) protip.save! - expect(protip.topics).to eq(%w(ruby python heroku)) + expect(protip.topic_list).to eq(%w(ruby python heroku)) expect(protip.topics.count).to eq(3) end + + it '#topic_ids should return ids of topics only' do + protip = Fabricate(:protip, topic_list: 'ruby, python', user: Fabricate(:user)) + protip.save! + ruby_id = Tag.find_by_name("ruby").id + python_id = Tag.find_by_name("python").id + expect(protip.topic_ids).to match_array([ruby_id, python_id]) + end end describe 'linking and featuring an image' do @@ -168,7 +177,7 @@ expect(wrapper.user.username).to eq(protip.user.username) expect(wrapper.user.profile_url).to eq(protip.user.avatar_url) expect(wrapper.upvotes).to eq(protip.upvotes) - expect(wrapper.topics).to eq(protip.topics) + expect(wrapper.topics).to eq(protip.topic_list) expect(wrapper.only_link?).to eq(protip.only_link?) expect(wrapper.link).to eq(protip.link) expect(wrapper.title).to eq(protip.title) @@ -193,7 +202,7 @@ expect(wrapper.user.username).to eq(protip.user.username) expect(wrapper.user.profile_url).to eq(protip.user.avatar_url) expect(wrapper.upvotes).to eq(protip.upvotes) - expect(wrapper.topics).to match_array(protip.topics) + expect(wrapper.topics).to match_array(protip.topic_list) expect(wrapper.only_link?).to eq(protip.only_link?) expect(wrapper.link).to eq(protip.link) expect(wrapper.title).to eq(protip.title) @@ -231,7 +240,7 @@ end describe 'upvotes' do - let(:protip) { Fabricate(:protip, user: Fabricate(:user)) } + let(:protip) { Fabricate(:protip) } let(:user) { Fabricate(:user) { score_cache 5 } } it 'should upvote by right amount' do @@ -251,14 +260,14 @@ end it 'should weigh team member upvotes less' do - protip.author.team_id = '4f271930973bf00004000001' + protip.author.team = Fabricate(:team) protip.author.save - team_member = Fabricate(:user, team_id: protip.author.team_id) + team_member = Fabricate(:user, team: protip.author.team) team_member.score_cache = 5 protip.upvote_by(team_member, team_member.tracking_code, Protip::DEFAULT_IP_ADDRESS) protip.reload expect(protip.upvotes_value).to eq(2) - non_team_member = Fabricate(:user, team_id: '4f271930973bf00004000002') + non_team_member = Fabricate(:user, team: Fabricate(:team)) non_team_member.score_cache = 5 protip.upvote_by(non_team_member, non_team_member.tracking_code, Protip::DEFAULT_IP_ADDRESS) protip.reload