diff --git a/app/models/concerns/searchable.rb b/app/models/concerns/searchable.rb index 06cefe8a7..ad675ecdc 100644 --- a/app/models/concerns/searchable.rb +++ b/app/models/concerns/searchable.rb @@ -24,6 +24,6 @@ module Searchable end def sync_related_elasticsearch_docs - self.class::DATA_SYNC_CLASS.new(self, saved_changes).call + self.class::DATA_SYNC_CLASS.new(self).call end end diff --git a/app/models/organization.rb b/app/models/organization.rb index 34c33bcd2..517bb2559 100644 --- a/app/models/organization.rb +++ b/app/models/organization.rb @@ -142,6 +142,6 @@ class Organization < ApplicationRecord end def sync_related_elasticsearch_docs - DataSync::Elasticsearch::Organization.new(self, saved_changes).call + DataSync::Elasticsearch::Organization.new(self).call end end diff --git a/app/services/data_sync/elasticsearch/article.rb b/app/services/data_sync/elasticsearch/article.rb index ee4cdffb8..b6a3c1105 100644 --- a/app/services/data_sync/elasticsearch/article.rb +++ b/app/services/data_sync/elasticsearch/article.rb @@ -1,11 +1,11 @@ module DataSync module Elasticsearch - class Article + class Article < Base RELATED_DOCS = %i[ reactions ].freeze - SHARED_ARTICLE_FIELDS = %i[ + SHARED_FIELDS = %i[ body_markdown path published @@ -14,18 +14,11 @@ module DataSync title ].freeze - attr_accessor :article, :updated_fields - - def initialize(article, updated_fields) - @article = article - @updated_fields = updated_fields.deep_symbolize_keys - end - - def call - return unless sync_needed? + private + def sync_related_documents RELATED_DOCS.each do |relation_name| - if article.published + if updated_record.published send(relation_name).find_each(&:index_to_elasticsearch) elsif updated_fields.key?(:published) send(relation_name).find_each(&:remove_from_elasticsearch) @@ -33,14 +26,12 @@ module DataSync end end - private - def sync_needed? - updated_fields.slice(*SHARED_ARTICLE_FIELDS).any? && reactions.any? + updated_fields.slice(*SHARED_FIELDS).any? && reactions.any? end def reactions - article.reactions.readinglist + updated_record.reactions.readinglist end end end diff --git a/app/services/data_sync/elasticsearch/base.rb b/app/services/data_sync/elasticsearch/base.rb new file mode 100644 index 000000000..9918d89fe --- /dev/null +++ b/app/services/data_sync/elasticsearch/base.rb @@ -0,0 +1,33 @@ +module DataSync + module Elasticsearch + class Base + attr_reader :updated_record + + def initialize(updated_record) + @updated_record = updated_record + end + + def call + return unless sync_needed? + + sync_related_documents + end + + private + + def sync_needed? + updated_fields.slice(*self.class::SHARED_FIELDS).any? + end + + def sync_related_documents + self.class::RELATED_DOCS.each do |relation_name| + send(relation_name).find_each(&:index_to_elasticsearch) + end + end + + def updated_fields + updated_record.saved_changes + end + end + end +end diff --git a/app/services/data_sync/elasticsearch/organization.rb b/app/services/data_sync/elasticsearch/organization.rb index d18393242..94e06e684 100644 --- a/app/services/data_sync/elasticsearch/organization.rb +++ b/app/services/data_sync/elasticsearch/organization.rb @@ -1,38 +1,17 @@ module DataSync module Elasticsearch - class Organization + class Organization < Base RELATED_DOCS = %i[ articles ].freeze - SHARED_TAG_FIELDS = %i[ + SHARED_FIELDS = %i[ slug name profile_image ].freeze - attr_accessor :organization, :updated_fields - - delegate :articles, to: :@organization - - def initialize(organization, updated_fields) - @organization = organization - @updated_fields = updated_fields.deep_symbolize_keys - end - - def call - return unless sync_needed? - - RELATED_DOCS.each do |relation_name| - send(relation_name).find_each(&:index_to_elasticsearch) - end - end - - private - - def sync_needed? - updated_fields.slice(*SHARED_TAG_FIELDS).any? - end + delegate :articles, to: :@updated_record end end end diff --git a/app/services/data_sync/elasticsearch/user.rb b/app/services/data_sync/elasticsearch/user.rb index 08ea9d73e..a2514fc48 100644 --- a/app/services/data_sync/elasticsearch/user.rb +++ b/app/services/data_sync/elasticsearch/user.rb @@ -1,6 +1,6 @@ module DataSync module Elasticsearch - class User + class User < Base RELATED_DOCS = %i[ articles reactions @@ -9,42 +9,23 @@ module DataSync comments ].freeze - SHARED_USER_FIELDS = %i[ + SHARED_FIELDS = %i[ username name pro profile_image_url ].freeze - attr_accessor :user, :updated_fields - - delegate :articles, :chat_channel_memberships, :comments, to: :@user - - def initialize(user, updated_fields) - @user = user - @updated_fields = updated_fields.deep_symbolize_keys - end - - def call - return unless sync_needed? - - RELATED_DOCS.each do |relation_name| - send(relation_name).find_each(&:index_to_elasticsearch) - end - end + delegate :articles, :chat_channel_memberships, :comments, to: :@updated_record private - def sync_needed? - updated_fields.slice(*SHARED_USER_FIELDS).any? - end - def reactions - user.reactions.readinglist + updated_record.reactions.readinglist end def podcast_episodes - PodcastEpisode.for_user(user) + PodcastEpisode.for_user(updated_record) end end end diff --git a/spec/services/data_sync/elasticsearch/article_spec.rb b/spec/services/data_sync/elasticsearch/article_spec.rb index d463cc5a4..cd11b65d9 100644 --- a/spec/services/data_sync/elasticsearch/article_spec.rb +++ b/spec/services/data_sync/elasticsearch/article_spec.rb @@ -3,35 +3,21 @@ require "rails_helper" RSpec.describe DataSync::Elasticsearch::Article, type: :service do let(:article) { create(:article) } - describe "#call" do - it "reindexes RELATED_DOCS when sync is needed " do - syncer = described_class.new(article, title: %w[old_title new_title]) - described_class::RELATED_DOCS.each do |method_name| - allow(syncer).to receive(method_name).and_call_original - end - syncer.call - described_class::RELATED_DOCS.each do |method_name| - expect(syncer).to have_received(method_name) - end - end - - it "does not reindex when sync is not needed" do - syncer = described_class.new(article, page_views_count: [nil, 1]) - described_class::RELATED_DOCS.each { |method_name| allow(syncer).to receive(method_name) } - syncer.call - described_class::RELATED_DOCS.each do |method_name| - expect(syncer).not_to have_received(method_name) - end - end + it "defines necessary constants" do + expect(described_class::RELATED_DOCS).not_to be_nil + expect(described_class::SHARED_FIELDS).not_to be_nil + end + describe "#sync_related_documents" do it "removes docs from elasticsearch if article is unpublished" do + allow(article).to receive(:saved_changes).and_return(published: [true, false]) reaction = create(:reaction, reactable: article, category: "readinglist") sidekiq_perform_enqueued_jobs expect(reaction.elasticsearch_doc).not_to be_nil article.update_column(:published, false) - described_class.new(article, published: [true, false]).call + described_class.new(article).call sidekiq_perform_enqueued_jobs expect { reaction.elasticsearch_doc }.to raise_error(Search::Errors::Transport::NotFound) end diff --git a/spec/services/data_sync/elasticsearch/base_spec.rb b/spec/services/data_sync/elasticsearch/base_spec.rb new file mode 100644 index 000000000..e965793d6 --- /dev/null +++ b/spec/services/data_sync/elasticsearch/base_spec.rb @@ -0,0 +1,24 @@ +require "rails_helper" + +RSpec.describe DataSync::Elasticsearch::Base, type: :service do + let!(:updated_record) { instance_double("Record", saved_changes: { name: %w[name1 name2] }) } + let(:syncer) { described_class.new(updated_record) } + + describe "#call" do + before do + stub_const("#{described_class}::SHARED_FIELDS", %i[name]) + allow(syncer).to receive(:sync_related_documents) + end + + it "syncs related_documents when sync is needed " do + syncer.call + expect(syncer).to have_received(:sync_related_documents) + end + + it "does not sync related_documents when sync is not needed" do + allow(updated_record).to receive(:saved_changes).and_return(twitter_url: %w[url1 url2]) + syncer.call + expect(syncer).not_to have_received(:sync_related_documents) + end + end +end diff --git a/spec/services/data_sync/elasticsearch/organization_spec.rb b/spec/services/data_sync/elasticsearch/organization_spec.rb index 94d4d90a4..cab5d2e6d 100644 --- a/spec/services/data_sync/elasticsearch/organization_spec.rb +++ b/spec/services/data_sync/elasticsearch/organization_spec.rb @@ -1,27 +1,8 @@ require "rails_helper" RSpec.describe DataSync::Elasticsearch::Organization, type: :service do - let!(:organization) { create(:organization) } - - describe "#call" do - it "reindexes RELATED_DOCS when sync is needed " do - syncer = described_class.new(organization, name: %w[name1 name2]) - described_class::RELATED_DOCS.each do |method_name| - allow(syncer).to receive(method_name).and_call_original - end - syncer.call - described_class::RELATED_DOCS.each do |method_name| - expect(syncer).to have_received(method_name) - end - end - - it "does not reindex when sync is not needed" do - syncer = described_class.new(organization, articles_count: [0, 1]) - described_class::RELATED_DOCS.each { |method_name| allow(syncer).to receive(method_name) } - syncer.call - described_class::RELATED_DOCS.each do |method_name| - expect(syncer).not_to have_received(method_name) - end - end + it "defines necessary constants" do + expect(described_class::RELATED_DOCS).not_to be_nil + expect(described_class::SHARED_FIELDS).not_to be_nil end end diff --git a/spec/services/data_sync/elasticsearch/user_spec.rb b/spec/services/data_sync/elasticsearch/user_spec.rb index 8228a79cb..3320d7a93 100644 --- a/spec/services/data_sync/elasticsearch/user_spec.rb +++ b/spec/services/data_sync/elasticsearch/user_spec.rb @@ -1,27 +1,8 @@ require "rails_helper" RSpec.describe DataSync::Elasticsearch::User, type: :service do - let!(:user) { create(:user) } - - describe "#call" do - it "reindexes RELATED_DOCS when sync is needed " do - syncer = described_class.new(user, username: %w[name1 name2]) - described_class::RELATED_DOCS.each do |method_name| - allow(syncer).to receive(method_name).and_call_original - end - syncer.call - described_class::RELATED_DOCS.each do |method_name| - expect(syncer).to have_received(method_name) - end - end - - it "does not reindex when sync is not needed" do - syncer = described_class.new(user, stackoverflow_url: [nil, "url"]) - described_class::RELATED_DOCS.each { |method_name| allow(syncer).to receive(method_name) } - syncer.call - described_class::RELATED_DOCS.each do |method_name| - expect(syncer).not_to have_received(method_name) - end - end + it "defines necessary constants" do + expect(described_class::RELATED_DOCS).not_to be_nil + expect(described_class::SHARED_FIELDS).not_to be_nil end end