* Allowing VariantQuery for Feed Generation Apologies for the breadth of this pull request, I had considered many small commits, but felt that would've been more effort for the value provided. This commit includes the following: - Documentation updates to the feed variant (though not the final pass) - Renaming and adding RelevancyLevers that help differentiate - Adding RelevancyLever#range to provide documentation - Reducing redundent controller logic by making a `Articles::Feeds.feed_for` method. - Adding some configuration validation for RelevancyLevers - Adding constants for better clarification - Testing unhappy paths for feed configuration - Adjusting the module namespace of some objects - Exposing top-level configurations for variants (along with their defaults) - Creating the VariantyQuery that at present inherits from the `Articles::Feeds::WeightedQueryStrategy` As implemented, we can deploy this code to production without using the new VariantQuery. Once we toggle on the `:feed_uses_variant_query_feature` FeatureFlag, it will switch to using the VariantQuery. The VariantQuery's two variants and the internal configuration of `Articles::Feeds::WeightedQueryStrategy` produce the same query. The goal of this factor is to allow for a quick on and off toggle of the feed query; to ensure that what we introduce remains performant. - Closes forem/forem#17272 - Closes forem/forem#17276 - Closes forem/forem#17216 In addition, I will be recording a code-walkthrough and linking that recording to the pull request. * Apply suggestions from code review Co-authored-by: Mac Siri <krairit.siri@gmail.com> Co-authored-by: Mac Siri <krairit.siri@gmail.com>
60 lines
2.4 KiB
Ruby
60 lines
2.4 KiB
Ruby
require "rails_helper"
|
|
|
|
RSpec.describe Articles::Feeds::VariantQuery, type: :service do
|
|
# We're exercising each named feed variant to ensure that the queries are valid SQL.
|
|
describe ".build_for" do
|
|
Rails.root.glob(File.join(Articles::Feeds::VariantAssembler::DIRECTORY, "/*.json")).each do |pathname|
|
|
variant = pathname.basename(".json").to_s.to_sym
|
|
subject(:query_call) { variant_query.call }
|
|
|
|
let(:variant_query) { described_class.build_for(variant: variant, user: user) }
|
|
|
|
context "for #{variant.inspect} and user is nil" do
|
|
let(:user) { nil }
|
|
|
|
it "is a valid ActiveRecord::Relation" do
|
|
article = create(:article)
|
|
expect(query_call).to be_a(ActiveRecord::Relation)
|
|
expect(query_call.to_a).to match_array(article)
|
|
end
|
|
end
|
|
|
|
context "for #{variant.inspect} and a non-nil user" do
|
|
let(:user) { create(:user) }
|
|
|
|
it "is a valid ActiveRecord::Relation" do
|
|
article = create(:article)
|
|
expect(query_call).to be_a(ActiveRecord::Relation)
|
|
expect(query_call.to_a).to match_array(article)
|
|
end
|
|
end
|
|
end
|
|
|
|
Rails.root.glob("spec/fixtures/feed-variants/broken/*.json").each do |pathname|
|
|
variant = pathname.basename(".json").to_s.to_sym
|
|
|
|
let(:variant_config) do
|
|
# Assembling the config and not polluting the variant cache with broken levers.
|
|
Articles::Feeds::VariantAssembler.call(variant: variant, variants: {},
|
|
dir: "spec/fixtures/feed-variants/broken")
|
|
end
|
|
|
|
# We already assembled the variant's config, let's short circuit that for the query
|
|
let(:stubbed_assembler) { ->(*) { variant_config } }
|
|
|
|
context "for broken variant #{variant.inspect} and a non-nil user" do
|
|
let(:variant_query) { described_class.build_for(variant: variant, user: user, assembler: stubbed_assembler) }
|
|
let(:user) { create(:user) }
|
|
|
|
it { within_block_is_expected.to raise_error(Articles::Feeds::RelevancyLever::ConfigurationError) }
|
|
end
|
|
|
|
context "for broken variant #{variant.inspect} and a nil user" do
|
|
let(:variant_query) { described_class.build_for(variant: variant, user: user, assembler: stubbed_assembler) }
|
|
let(:user) { nil }
|
|
|
|
it { within_block_is_expected.to raise_error(Articles::Feeds::RelevancyLever::ConfigurationError) }
|
|
end
|
|
end
|
|
end
|
|
end
|