From 46f94b135dd3f98fdbe55aab2b043f82c3403b1f Mon Sep 17 00:00:00 2001 From: Michael Kohl Date: Fri, 1 May 2020 05:57:01 +0700 Subject: [PATCH] [deploy] Classified listings refactor part 3 (#7498) * Ignore category column * Move view oriented class methods to helper * Start refactoring ClassifiedListingsToolkit * Add attr_accessor instead of category * Replace old category column with association * More cleanup * Trigger Travis * Don't rename associations, category_slug -> category * Indiana Kohl and the missing newline * More refactoring and spec fixes * Add dashboard for classified listing categories * Remove TODO comment Co-authored-by: rhymes --- ...lassified_listing_categories_controller.rb | 46 ++++++++++++ .../api/v0/classified_listings_controller.rb | 2 +- .../classified_listings_controller.rb | 17 ++++- .../concerns/classified_listings_toolkit.rb | 36 +++------ .../classified_listing_category_dashboard.rb | 73 +++++++++++++++++++ app/dashboards/dashboard_manifest.rb | 1 + app/helpers/classified_listing_helper.rb | 19 +++++ app/liquid_tags/classified_listing_tag.rb | 6 +- app/models/classified_listing.rb | 54 +++----------- app/views/classified_listings/_form.html.erb | 4 +- app/views/classified_listings/index.html.erb | 22 ++---- .../classified_listings/edit.html.erb | 2 +- .../classified_listings/index.html.erb | 2 +- db/schema.rb | 3 +- db/seeds.rb | 45 +++++++++++- .../classified_listing_categories.rb | 6 ++ .../helpers/classified_listing_helper_spec.rb | 41 +++++++++++ spec/labor/cache_buster_spec.rb | 2 +- .../classified_listing_tag_spec.rb | 3 - .../api/v0/classified_listings_spec.rb | 14 ++-- .../search/classified_listing_spec.rb | 14 ++-- 21 files changed, 303 insertions(+), 109 deletions(-) create mode 100644 app/controllers/admin/classified_listing_categories_controller.rb create mode 100644 app/dashboards/classified_listing_category_dashboard.rb create mode 100644 app/helpers/classified_listing_helper.rb create mode 100644 spec/helpers/classified_listing_helper_spec.rb diff --git a/app/controllers/admin/classified_listing_categories_controller.rb b/app/controllers/admin/classified_listing_categories_controller.rb new file mode 100644 index 000000000..d9b3b0ecd --- /dev/null +++ b/app/controllers/admin/classified_listing_categories_controller.rb @@ -0,0 +1,46 @@ +module Admin + class ClassifiedListingCategoriesController < Admin::ApplicationController + # Overwrite any of the RESTful controller actions to implement custom behavior + # For example, you may want to send an email after a foo is updated. + # + # def update + # super + # send_foo_updated_email(requested_resource) + # end + + # Override this method to specify custom lookup behavior. + # This will be used to set the resource for the `show`, `edit`, and `update` + # actions. + # + # def find_resource(param) + # Foo.find_by!(slug: param) + # end + + # The result of this lookup will be available as `requested_resource` + + # Override this if you have certain roles that require a subset + # this will be used to set the records shown on the `index` action. + # + # def scoped_resource + # if current_user.super_admin? + # resource_class + # else + # resource_class.with_less_stuff + # end + # end + + # Override `resource_params` if you want to transform the submitted + # data before it's persisted. For example, the following would turn all + # empty values into nil values. It uses other APIs such as `resource_class` + # and `dashboard`: + # + # def resource_params + # params.require(resource_class.model_name.param_key). + # permit(dashboard.permitted_attributes). + # transform_values { |value| value == "" ? nil : value } + # end + + # See https://administrate-prototype.herokuapp.com/customizing_controller_actions + # for more information + end +end diff --git a/app/controllers/api/v0/classified_listings_controller.rb b/app/controllers/api/v0/classified_listings_controller.rb index ddd101085..6e6957ab4 100644 --- a/app/controllers/api/v0/classified_listings_controller.rb +++ b/app/controllers/api/v0/classified_listings_controller.rb @@ -55,7 +55,7 @@ module Api ATTRIBUTES_FOR_SERIALIZATION = %i[ id user_id organization_id title slug body_markdown cached_tag_list - category classified_listing_category_id category processed_html published + classified_listing_category_id processed_html published ].freeze private_constant :ATTRIBUTES_FOR_SERIALIZATION diff --git a/app/controllers/classified_listings_controller.rb b/app/controllers/classified_listings_controller.rb index d7410670b..d5ae735b5 100644 --- a/app/controllers/classified_listings_controller.rb +++ b/app/controllers/classified_listings_controller.rb @@ -1,6 +1,15 @@ class ClassifiedListingsController < ApplicationController include ClassifiedListingsToolkit + JSON_OPTIONS = { + only: %i[ + title processed_html tag_list category id user_id slug contact_via_connect location + ], + include: { + author: { only: %i[username name], methods: %i[username profile_image_90] } + } + }.freeze + before_action :set_classified_listing, only: %i[edit update destroy] before_action :set_cache_control_headers, only: %i[index] before_action :raise_suspended, only: %i[new create update] @@ -13,18 +22,22 @@ class ClassifiedListingsController < ApplicationController if params[:view] == "moderate" not_found unless @displayed_classified_listing - return redirect_to "/internal/listings/#{@displayed_classified_listing.id}/edit" + return redirect_to edit_internal_listing_path(id: @displayed_classified_listing.id) end @classified_listings = if params[:category].blank? published_listings. order("bumped_at DESC"). - includes(:user, :organization, :taggings, :classified_listing_category). + includes(:user, :organization, :taggings). limit(12) else ClassifiedListing.none end + + @listings_json = @classified_listings.to_json(JSON_OPTIONS) + @displayed_listing_json = @displayed_classified_listing.to_json(JSON_OPTIONS) + set_surrogate_key_header "classified-listings-#{params[:category]}" end diff --git a/app/controllers/concerns/classified_listings_toolkit.rb b/app/controllers/concerns/classified_listings_toolkit.rb index ed95c863a..b27a8717a 100644 --- a/app/controllers/concerns/classified_listings_toolkit.rb +++ b/app/controllers/concerns/classified_listings_toolkit.rb @@ -4,33 +4,22 @@ module ClassifiedListingsToolkit MANDATORY_FIELDS_FOR_UPDATE = %i[body_markdown title tag_list].freeze def unpublish_listing - @classified_listing.published = false - @classified_listing.save + @classified_listing.update(published: false) end def publish_listing - @classified_listing.published = true - @classified_listing.save + @classified_listing.update(published: true) end - # TODO: why not just @classified_listing.update(listing_params)? def update_listing_details - @classified_listing.title = listing_params[:title] if listing_params[:title] - @classified_listing.body_markdown = listing_params[:body_markdown] if listing_params[:body_markdown] - @classified_listing.tag_list = listing_params[:tag_list] if listing_params[:tag_list] - if listing_params[:classified_listing_category_id] - @classified_listing.classified_listing_category_id = listing_params[:classified_listing_category_id] - end - @classified_listing.location = listing_params[:location] if listing_params[:location] - @classified_listing.expires_at = listing_params[:expires_at] if listing_params[:expires_at] - @classified_listing.contact_via_connect = listing_params[:contact_via_connect] if listing_params[:contact_via_connect] - @classified_listing.save + # [thepracticaldev/oss] Not entirely sure what the intention behind the + # original code was, but at least this is more compact. + filtered_params = listing_params.reject { |_k, v| v.nil? } + @classified_listing.update(filtered_params) end def bump_listing_success - @classified_listing.bumped_at = Time.current - saved = @classified_listing.save - saved + @classified_listing.update(bumped_at: Time.current) end def clear_listings_cache @@ -59,7 +48,6 @@ module ClassifiedListingsToolkit available_user_credits = current_user.credits.unspent unless @classified_listing.valid? - # TODO: [thepracticaldev/oss] For now the credits are needed in the view @credits = current_user.credits.unspent process_unsuccessful_creation return @@ -77,15 +65,15 @@ module ClassifiedListingsToolkit end ALLOWED_PARAMS = %i[ - title body_markdown category classified_listing_category_id tag_list + title body_markdown classified_listing_category_id tag_list expires_at contact_via_connect location organization_id action ].freeze - # Never trust parameters from the scary internet, only allow a specific list through. + # Filter for a set of known safe params def listing_params - if params["classified_listing"]["tags"].present? - params["classified_listing"]["tags"] = params["classified_listing"]["tags"].join(", ") - params["classified_listing"]["tag_list"] = params["classified_listing"].delete "tags" + tags = params["classified_listing"].delete("tags") + if tags.present? + params["classified_listing"]["tag_list"] = tags.join(", ") end params.require(:classified_listing).permit(ALLOWED_PARAMS) end diff --git a/app/dashboards/classified_listing_category_dashboard.rb b/app/dashboards/classified_listing_category_dashboard.rb new file mode 100644 index 000000000..ec436426c --- /dev/null +++ b/app/dashboards/classified_listing_category_dashboard.rb @@ -0,0 +1,73 @@ +require "administrate/base_dashboard" + +class ClassifiedListingCategoryDashboard < Administrate::BaseDashboard + # ATTRIBUTE_TYPES + # a hash that describes the type of each of the model's fields. + # + # Each different type represents an Administrate::Field object, + # which determines how the attribute is displayed + # on pages throughout the dashboard. + ATTRIBUTE_TYPES = { + classified_listings: Field::HasMany, + id: Field::Number, + cost: Field::Number, + created_at: Field::DateTime, + name: Field::String, + rules: Field::String, + slug: Field::String, + updated_at: Field::DateTime + }.freeze + + # COLLECTION_ATTRIBUTES + # an array of attributes that will be displayed on the model's index page. + # + # By default, it's limited to four items to reduce clutter on index pages. + # Feel free to add, remove, or rearrange items. + COLLECTION_ATTRIBUTES = %i[ + name + slug + rules + cost + ].freeze + + # SHOW_PAGE_ATTRIBUTES + # an array of attributes that will be displayed on the model's show page. + SHOW_PAGE_ATTRIBUTES = %i[ + id + name + slug + rules + cost + created_at + updated_at + ].freeze + + # FORM_ATTRIBUTES + # an array of attributes that will be displayed + # on the model's form (`new` and `edit`) pages. + FORM_ATTRIBUTES = %i[ + name + slug + rules + cost + ].freeze + + # COLLECTION_FILTERS + # a hash that defines filters that can be used while searching via the search + # field of the dashboard. + # + # For example to add an option to search for open resources by typing "open:" + # in the search field: + # + # COLLECTION_FILTERS = { + # open: ->(resources) { resources.where(open: true) } + # }.freeze + COLLECTION_FILTERS = {}.freeze + + # Overwrite this method to customize how classified listing categories are displayed + # across all pages of the admin dashboard. + # + # def display_resource(classified_listing_category) + # "ClassifiedListingCategory ##{classified_listing_category.id}" + # end +end diff --git a/app/dashboards/dashboard_manifest.rb b/app/dashboards/dashboard_manifest.rb index 70783832b..83eac66d6 100644 --- a/app/dashboards/dashboard_manifest.rb +++ b/app/dashboards/dashboard_manifest.rb @@ -30,6 +30,7 @@ class DashboardManifest html_variant_successes sponsorships pro_memberships + classified_listing_categories ].freeze # DASHBOARDS = [ # :users, diff --git a/app/helpers/classified_listing_helper.rb b/app/helpers/classified_listing_helper.rb new file mode 100644 index 000000000..4be490d94 --- /dev/null +++ b/app/helpers/classified_listing_helper.rb @@ -0,0 +1,19 @@ +module ClassifiedListingHelper + def select_options_for_categories + ClassifiedListingCategory.select(:id, :name, :cost).map do |cl| + ["#{cl.name} (#{cl.cost} #{'Credit'.pluralize(cl.cost)})", cl.id] + end + end + + def categories_for_display + ClassifiedListingCategory.pluck(:slug, :name).map do |slug, name| + { slug: slug, name: name } + end + end + + def categories_available + ClassifiedListingCategory.all.each_with_object({}) do |cat, h| + h[cat.slug] = cat.attributes.slice("cost", "name", "rules") + end.deep_symbolize_keys + end +end diff --git a/app/liquid_tags/classified_listing_tag.rb b/app/liquid_tags/classified_listing_tag.rb index f745dc209..405e8a065 100644 --- a/app/liquid_tags/classified_listing_tag.rb +++ b/app/liquid_tags/classified_listing_tag.rb @@ -2,8 +2,8 @@ class ClassifiedListingTag < LiquidTagBase PARTIAL = "classified_listings/liquid".freeze def initialize(_tag_name, slug_path_url, _tokens) - striped_path = ActionController::Base.helpers.strip_tags(slug_path_url).strip - @listing = get_listing(striped_path) + stripped_path = ActionController::Base.helpers.strip_tags(slug_path_url).strip + @listing = get_listing(stripped_path) end def render(_context) @@ -24,7 +24,7 @@ class ClassifiedListingTag < LiquidTagBase hash = get_hash(url) raise StandardError, "Invalid URL or slug. Listing not found." if hash.nil? - listing = ClassifiedListing.find_by(hash) + listing = ClassifiedListing.in_category(hash[:category]).find_by(slug: hash[:slug]) raise StandardError, "Invalid URL or slug. Listing not found." unless listing listing diff --git a/app/models/classified_listing.rb b/app/models/classified_listing.rb index f5c3e71db..e33b9d365 100644 --- a/app/models/classified_listing.rb +++ b/app/models/classified_listing.rb @@ -1,4 +1,6 @@ class ClassifiedListing < ApplicationRecord + self.ignored_columns = ["category"] + include Searchable SEARCH_SERIALIZER = Search::ClassifiedListingSerializer @@ -6,10 +8,9 @@ class ClassifiedListing < ApplicationRecord attr_accessor :action - # This allows to create a listing from a catgory string. - # TODO: [mkohl] refactor once column was dropped. - before_validation :assign_classified_listing_category - + # Note: categories were hardcoded at first and this model was only added later, + # so the association name is a bit verbose since the original "category" attribute + # was kept to minimize code changes. belongs_to :classified_listing_category belongs_to :user belongs_to :organization, optional: true @@ -29,38 +30,19 @@ class ClassifiedListing < ApplicationRecord validates :location, length: { maximum: 32 } validate :restrict_markdown_input validate :validate_tags - validate :validate_category scope :published, -> { where(published: true) } + scope :in_category, lambda { |slug| + joins(:classified_listing_category). + where("classified_listing_categories.slug" => slug) + } - # TODO: refactor this class method block - def self.select_options_for_categories - ClassifiedListingCategory.select(:id, :name, :cost).map do |cl| - ["#{cl.name} (#{cl.cost} #{'Credit'.pluralize(cl.cost)})", cl.id] - end - end - - def self.categories_for_display - ClassifiedListingCategory.pluck(:slug, :name).map do |slug, name| - { slug: slug, name: name } - end - end - - def self.categories_available - ClassifiedListingCategory.all.each_with_object({}) do |cat, h| - h[cat.slug] = cat.attributes.slice("cost", "name", "rules") - end.deep_symbolize_keys - end + delegate :cost, to: :classified_listing_category def category classified_listing_category&.slug end - def cost - @cost = classified_listing_category&.cost || - ClassifiedListingCategory.select(:cost).find_by(slug: category)&.cost - end - def author organization || user end @@ -82,7 +64,6 @@ class ClassifiedListing < ApplicationRecord def modify_inputs ActsAsTaggableOn::Taggable::Cache.included(ClassifiedListing) ActsAsTaggableOn.default_parser = ActsAsTaggableOn::TagParser - self.category = category.to_s.downcase self.body_markdown = body_markdown.to_s.gsub(/\r\n/, "\n") end @@ -93,11 +74,6 @@ class ClassifiedListing < ApplicationRecord errors.add(:body_markdown, "is not allowed to include liquid tags.") if markdown_string.include?("{% ") end - def validate_category - categories = ClassifiedListingCategory.pluck(:slug) - errors.add(:category, "not a valid category") unless category.in?(categories) - end - def validate_tags errors.add(:tag_list, "exceed the maximum of 8 tags") if tag_list.length > 8 end @@ -105,14 +81,4 @@ class ClassifiedListing < ApplicationRecord def create_slug self.slug = "#{title.downcase.parameterize.delete('_')}-#{rand(100_000).to_s(26)}" end - - def assign_classified_listing_category - return if classified_listing_category_id.present? - - category = ClassifiedListingCategory.find_by(slug: attributes["category"]) - return unless category - - self.category = category.slug - self.classified_listing_category_id = category.id - end end diff --git a/app/views/classified_listings/_form.html.erb b/app/views/classified_listings/_form.html.erb index a94677d39..b6e167234 100644 --- a/app/views/classified_listings/_form.html.erb +++ b/app/views/classified_listings/_form.html.erb @@ -9,8 +9,8 @@
+ data-categories-for-select="<%= select_options_for_categories.to_json %>" + data-categories-for-details="<%= categories_available.transform_values { |value_hash| value_hash.except(:cost) }.values.to_json %>">
<%= form.label "title" %> diff --git a/app/views/classified_listings/index.html.erb b/app/views/classified_listings/index.html.erb index ed43c7f6a..62af8ae3b 100644 --- a/app/views/classified_listings/index.html.erb +++ b/app/views/classified_listings/index.html.erb @@ -28,25 +28,19 @@
- data-displayedlisting="<%= @displayed_classified_listing.to_json( - only: %i[title processed_html tag_list category id user_id slug contact_via_connect location], - include: { - author: { only: %i[username name], methods: %i[username profile_image_90] } - }, - ) %> " + data-displayedlisting="<%= @displayed_listing_json %> " <% end %> >
- data-no-instant="true">all<% ClassifiedListing.categories_for_display.each do |cat| %> data-no-instant="true"><%= cat[:name] %><% end %>Create a Listing + data-no-instant="true">all + <% categories_for_display.each do |cat| %> + data-no-instant="true"><%= cat[:name] %> + <% end %> + Create a Listing <% if @displayed_classified_listing %> <% end %> diff --git a/app/views/internal/classified_listings/edit.html.erb b/app/views/internal/classified_listings/edit.html.erb index f7415fce7..84605e69a 100644 --- a/app/views/internal/classified_listings/edit.html.erb +++ b/app/views/internal/classified_listings/edit.html.erb @@ -18,7 +18,7 @@
<%= form.label :classified_listing_category_id %> - <%= form.select :classified_listing_category_id, ClassifiedListing.select_options_for_categories %> + <%= form.select :classified_listing_category_id, select_options_for_categories %>
<%= form.check_box :published, checked: @classified_listing.published? %> diff --git a/app/views/internal/classified_listings/index.html.erb b/app/views/internal/classified_listings/index.html.erb index d047c0ece..2436ed059 100644 --- a/app/views/internal/classified_listings/index.html.erb +++ b/app/views/internal/classified_listings/index.html.erb @@ -11,7 +11,7 @@
<%= label_tag(:filter, "Category") %> - <%= select_tag(:filter, options_for_select(ClassifiedListing.categories_available.keys, params[:filter]), include_blank: true) %> + <%= select_tag(:filter, options_for_select(categories_available.keys, params[:filter]), include_blank: true) %>
<%= label_tag(:include_unpublished, "Include unpublished listings") %> diff --git a/db/schema.rb b/db/schema.rb index 4bef0accf..0ec913ece 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -308,6 +308,7 @@ ActiveRecord::Schema.define(version: 2020_04_26_124118) do t.string "slug" t.string "status", default: "active" t.datetime "updated_at", null: false + t.index ["slug"], name: "index_chat_channels_on_slug", unique: true end create_table "classified_listing_categories", force: :cascade do |t| @@ -1216,9 +1217,9 @@ ActiveRecord::Schema.define(version: 2020_04_26_124118) do t.datetime "updated_at", null: false t.string "username" t.string "website_url" - t.string "youtube_url" t.boolean "welcome_notifications", default: true, null: false t.datetime "workshop_expiration" + t.string "youtube_url" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["created_at"], name: "index_users_on_created_at" t.index ["email"], name: "index_users_on_email", unique: true diff --git a/db/seeds.rb b/db/seeds.rb index 970f078da..d8e799f4c 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -4,7 +4,7 @@ SEEDS_MULTIPLIER = [1, ENV["SEEDS_MULTIPLIER"].to_i].max counter = 0 Rails.logger.info "Seeding with multiplication factor: #{SEEDS_MULTIPLIER}" -############################################################################## +##############################################################################/ counter += 1 Rails.logger.info "#{counter}. Creating Organizations" @@ -371,6 +371,49 @@ end ############################################################################## +counter += 1 +Rails.logger.info "#{counter}. Creating Classified Listings" + +users_in_random_order.each { |user| Credit.add_to(user, rand(100)) } +users = users_in_random_order.to_a + +listings_categories = ClassifiedListingCategory.pluck(:id) +listings_categories.each.with_index(1) do |category_id, index| + # rotate users if they are less than the categories + user = users.at(index % users.length) + 2.times do + ClassifiedListing.create!( + user: user, + title: Faker::Lorem.sentence, + body_markdown: Faker::Markdown.random, + location: Faker::Address.city, + organization_id: user.organizations.first&.id, + classified_listing_category_id: category_id, + contact_via_connect: true, + published: true, + bumped_at: Time.current, + tag_list: Tag.order(Arel.sql("RANDOM()")).first(2).pluck(:name), + ) + end +end + +############################################################################## + +counter += 1 +Rails.logger.info "#{counter}. Creating Pages" + +5.times do + Page.create!( + title: Faker::Hacker.say_something_smart, + body_markdown: Faker::Markdown.random, + slug: Faker::Internet.slug, + description: Faker::Books::Dune.quote, + template: %w[contained full_within_layout].sample, + ) +end + +############################################################################## + counter += 1 Rails.logger.info "#{counter}. Creating Classified Listing Categories" diff --git a/spec/factories/classified_listing_categories.rb b/spec/factories/classified_listing_categories.rb index f2a087659..0176c4a69 100644 --- a/spec/factories/classified_listing_categories.rb +++ b/spec/factories/classified_listing_categories.rb @@ -10,5 +10,11 @@ FactoryBot.define do slug { "cfp" } cost { 5 } end + + trait :jobs do + name { "Job Listings" } + slug { "jobs" } + cost { 1 } + end end end diff --git a/spec/helpers/classified_listing_helper_spec.rb b/spec/helpers/classified_listing_helper_spec.rb new file mode 100644 index 000000000..575023ab0 --- /dev/null +++ b/spec/helpers/classified_listing_helper_spec.rb @@ -0,0 +1,41 @@ +require "rails_helper" + +RSpec.describe ClassifiedListingHelper, type: :helper do + let_it_be_readonly(:cat1) { create(:classified_listing_category, cost: 1) } + let_it_be_readonly(:cat2) { create(:classified_listing_category, :cfp, cost: 5) } + + describe "select_options_for_categories" do + it "returns the correct options array" do + expect(helper.select_options_for_categories).to match_array( + [ + ["#{cat1.name} (1 Credit)", cat1.id], + ["#{cat2.name} (5 Credits)", cat2.id], + ] + ) + end + end + + describe "categories_for_display" do + it "return the correct hash of slug and name pairs" do + expect(helper.categories_for_display).to match_array( + [ + { slug: cat1.slug, name: cat1.name }, + { slug: cat2.slug, name: cat2.name }, + ] + ) + end + end + + describe "categories_available" do + it "returns a hash with slugs as keys" do + expected = [cat1.slug.to_sym, cat2.slug.to_sym] + expect(helper.categories_available.keys).to match_array(expected) + end + + it "categories have the correct keys" do + cfp_category = helper.categories_available[:cfp] + expect(cfp_category.keys).to match_array(%i[cost name rules]) + end + end +end + diff --git a/spec/labor/cache_buster_spec.rb b/spec/labor/cache_buster_spec.rb index 9081e1791..0dd2e8c3c 100644 --- a/spec/labor/cache_buster_spec.rb +++ b/spec/labor/cache_buster_spec.rb @@ -6,7 +6,7 @@ RSpec.describe CacheBuster, type: :labor do let(:article) { create(:article, user_id: user.id) } let(:comment) { create(:comment, user_id: user.id, commentable: article) } let(:organization) { create(:organization) } - let(:listing) { create(:classified_listing, user_id: user.id, category: "cfp") } + let(:listing) { create(:classified_listing, user_id: user.id) } let(:podcast) { create(:podcast) } let(:podcast_episode) { create(:podcast_episode, podcast_id: podcast.id) } let(:tag) { create(:tag) } diff --git a/spec/liquid_tags/classified_listing_tag_spec.rb b/spec/liquid_tags/classified_listing_tag_spec.rb index 5cbc0f1cc..e82787085 100644 --- a/spec/liquid_tags/classified_listing_tag_spec.rb +++ b/spec/liquid_tags/classified_listing_tag_spec.rb @@ -9,7 +9,6 @@ RSpec.describe ClassifiedListingTag, type: :liquid_tag do title: "save me pls", body_markdown: "sigh sigh sigh", processed_html: "

sigh sigh sigh

", - category: "cfp", tag_list: %w[a b c], organization_id: nil, ) @@ -22,7 +21,6 @@ RSpec.describe ClassifiedListingTag, type: :liquid_tag do title: "this old af", body_markdown: "exxpired", processed_html: "

exxpired

", - category: "cfp", tag_list: %w[x y z], organization_id: nil, bumped_at: datetime, @@ -43,7 +41,6 @@ RSpec.describe ClassifiedListingTag, type: :liquid_tag do title: "this is a job posting", body_markdown: "wow code lots get not only money but satisfaction from work", processed_html: "

wow code lots get not only money but satisfaction from work

", - category: "misc", tag_list: %w[a b c], organization_id: org.id, ) diff --git a/spec/requests/api/v0/classified_listings_spec.rb b/spec/requests/api/v0/classified_listings_spec.rb index e03ac2ce1..830f7b6bc 100644 --- a/spec/requests/api/v0/classified_listings_spec.rb +++ b/spec/requests/api/v0/classified_listings_spec.rb @@ -127,7 +127,7 @@ RSpec.describe "Api::V0::ClassifiedListings", type: :request do describe "GET /api/listings/:id" do include_context "with 7 listings and 2 user" - let(:listing) { ClassifiedListing.where(category: "cfp").last } + let(:listing) { ClassifiedListing.in_category("cfp").last } context "when unauthenticated" do it "returns a published listing" do @@ -293,7 +293,8 @@ RSpec.describe "Api::V0::ClassifiedListings", type: :request do it "fails if category is invalid" do post_classified_listing(title: "Title", body_markdown: "body", category: "unknown") expect(response).to have_http_status(:unprocessable_entity) - expect(response.parsed_body.dig("errors", "category").first).to match(/not a valid category/) + expect(response.parsed_body.dig("errors", "classified_listing_category").first). + to match(/must exist/) end it "does not subtract credits or create a listing if the listing is not valid" do @@ -312,8 +313,7 @@ RSpec.describe "Api::V0::ClassifiedListings", type: :request do post_classified_listing(listing_params) expect(response).to have_http_status(:created) - listing_cost = ClassifiedListing.categories_available[:cfp][:cost] - expect(user.credits.spent.size).to eq(listing_cost) + expect(user.credits.spent.size).to eq(cfp_category.cost) end it "creates a listing draft under the org" do @@ -357,7 +357,8 @@ RSpec.describe "Api::V0::ClassifiedListings", type: :request do it "cannot create a draft due to internal error" do allow(Organization).to receive(:find_by) post_classified_listing(draft_params.except(:classified_listing_category_id)) - expect(response.parsed_body["errors"]["category"]).to eq(["not a valid category"]) + expect(response.parsed_body.dig("errors", "classified_listing_category").first). + to match(/must exist/) expect(response).to have_http_status(:unprocessable_entity) end @@ -608,7 +609,8 @@ RSpec.describe "Api::V0::ClassifiedListings", type: :request do max_id = ClassifiedListingCategory.maximum(:id) put_classified_listing(listing.id, title: "New title", classified_listing_category_id: max_id + 1) expect(response).to have_http_status(:unprocessable_entity) - expect(response.parsed_body.dig("errors", "category").first).to match(/not a valid category/) + expect(response.parsed_body.dig("errors", "classified_listing_category").first). + to match(/must exist/) end it "updates the title of his listing" do diff --git a/spec/services/search/classified_listing_spec.rb b/spec/services/search/classified_listing_spec.rb index ac26a8a1f..d39e9920d 100644 --- a/spec/services/search/classified_listing_spec.rb +++ b/spec/services/search/classified_listing_spec.rb @@ -62,7 +62,7 @@ RSpec.describe Search::ClassifiedListing, type: :service do end it "searches by slug" do - slug_classified_listing = FactoryBot.create(:classified_listing, title: "A slug is created from this title in a callback") + slug_classified_listing = create(:classified_listing, title: "A slug is created from this title in a callback") index_documents(slug_classified_listing) params = { size: 5, slug: "slug" } @@ -136,7 +136,7 @@ RSpec.describe Search::ClassifiedListing, type: :service do it "sorts documents by bumped_at by default" do classified_listing.update(bumped_at: 1.year.ago) - classified_listing2 = FactoryBot.create(:classified_listing, bumped_at: Time.current) + classified_listing2 = create(:classified_listing, bumped_at: Time.current) index_documents([classified_listing, classified_listing2]) params = { size: 5 } @@ -148,7 +148,7 @@ RSpec.describe Search::ClassifiedListing, type: :service do it "paginates the results" do classified_listing.update(bumped_at: 1.year.ago) - classified_listing2 = FactoryBot.create(:classified_listing, bumped_at: Time.current) + classified_listing2 = create(:classified_listing, bumped_at: Time.current) index_documents([classified_listing, classified_listing2]) first_page_params = { page: 0, per_page: 1, sort_by: "bumped_at", order: "dsc" } @@ -162,8 +162,12 @@ RSpec.describe Search::ClassifiedListing, type: :service do end it "returns an empty Array if no results are found" do - classified_listing.update(category: "forhire") - classified_listing2 = FactoryBot.create(:classified_listing, category: "cfp") + jobs_category = create(:classified_listing_category, :jobs) + classified_listing.update(classified_listing_category: jobs_category) + + cfp_category = create(:classified_listing_category, :cfp) + classified_listing2 = create(:classified_listing, + classified_listing_category: cfp_category) index_documents([classified_listing, classified_listing2]) params = { page: 3, per_page: 1 }