docbrown/app/models/feed_event.rb
PJ 95ca9d37c5
Record feed events for public reactions (#20079)
* create feed event on feed reaction

* move feed event creation to feed event model

* tiny whoops

* fix failing specs

* slightly less flaky e2e spec (maybe)

* tiny fixes (couldn't resist)
2023-09-12 08:36:10 -04:00

45 lines
1.5 KiB
Ruby

class FeedEvent < ApplicationRecord
# These are "optional" mostly so that we can perform validated bulk inserts
# without triggering article/user validation.
# Since there are database-level constraints, it's fine to skip the automatic
# Rails-side association validation (which causes an N+1 query).
belongs_to :article, optional: true
belongs_to :user, optional: true
enum category: {
impression: 0,
click: 1,
reaction: 2,
comment: 3
}
CONTEXT_TYPE_HOME = "home".freeze
CONTEXT_TYPE_SEARCH = "search".freeze
CONTEXT_TYPE_TAG = "tag".freeze
VALID_CONTEXT_TYPES = [
CONTEXT_TYPE_HOME,
CONTEXT_TYPE_SEARCH,
CONTEXT_TYPE_TAG,
].freeze
DEFAULT_TIMEBOX = 5.minutes.freeze
validates :article_position, numericality: { only_integer: true, greater_than: 0 }
validates :context_type, inclusion: { in: VALID_CONTEXT_TYPES }, presence: true
# Since we have disabled association validation, this is handy to filter basic bad data
validates :article_id, presence: true, numericality: { only_integer: true }
validates :user_id, numericality: { only_integer: true }, allow_nil: true
def self.record_journey_for(user, article:, category:)
return unless %i[reaction comment].include?(category)
last_click = where(user: user, category: :click).last
return unless last_click&.article_id == article.id
create_with(last_click.slice(:article_position, :context_type))
.find_or_create_by(
category: category,
user: user,
article: article,
)
end
end