Last active
April 6, 2023 20:40
-
-
Save kaspth/54c2541309704e054bca2be5ace3ebee to your computer and use it in GitHub Desktop.
A spike of an idea for https://twitter.com/joemasilotti/status/1643755888614965249
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Developer | |
has_object :search_scorer, after_save_commit: :rebuild_later # Forward callback onto context object. | |
end | |
# From my https://github.com/kaspth/active_record-associated_object gem. | |
# app/models/developer/search_scorer.rb | |
class Developer::SearchScorer < ActiveRecord::AssociatedObject | |
performs :rebuild # Adds `rebuild_later` to automatically generate a job to run the scoring calculation in. | |
def rebuild | |
record.update! search_score: new_score | |
end | |
private | |
def new_score | |
small, medium, large, x_large = 5, 10, 20, 30 | |
score = [] | |
score << medium if record.scheduling_link? | |
score << large if record.source_contributor? | |
score << x_large if record.recently_added? | |
score << medium if record.bio_length > 500 | |
score << -large if record.bio_length < 50 | |
score << large if record.profile_updated_at&.before? 1.months.ago | |
score << medium if record.profile_updated_at&.before? 3.months.ago | |
score << -medium if record.profile_updated_at&.after? 6.months.ago | |
score << large if record.conversations_count.positive? && record.response_rate >= Developer::HasBadges::HIGH_RESPONSE_RATE_CUTOFF | |
score << -large if record.conversations_count.positive? && record.response_rate <= Developer::HasBadges::LOW_RESPONSE_RATE_CUTOFF | |
score.sum | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# app/models/developers/search_score.rb | |
module Developers::SearchScore | |
extend ActiveSupport::Concern | |
included do | |
small, medium, large, x_large = 5, 10, 20, 30 | |
scores :scheduling_link?, by: medium, if: :present? | |
scores :source_contributor?, by: large, if: :present? | |
scores :recently_added?, by: x_large, if: :present? | |
scores :bio_length, by: medium, if: -> { _1 > 500 } | |
scores :bio_length, by: -large, if: -> { _1 < 50 } | |
scores :profile_updated_at, by: large, if: -> { _1&.before? 1.months.ago } | |
scores :profile_updated_at, by: medium, if: -> { _1&.before? 3.months.ago } | |
scores :profile_updated_at, by: -medium, if: -> { _1&.after? 6.months.ago } | |
scores :response_rate, by: large, if: -> { conversations_count.positive? && _1 >= HasBadges::HIGH_RESPONSE_RATE_CUTOFF } | |
scores :response_rate, by: -large, if: -> { conversations_count.positive? && _1 <= HasBadges::LOW_RESPONSE_RATE_CUTOFF } | |
before_save :recalculate_search_score | |
end | |
class_methods do | |
attr_reader :scorings | |
def scores(attribute, by:, **options) | |
(@scorings ||= []) << -> { by if instance_exec(public_send(attribute), &options.fetch(:if)) } } | |
end | |
end | |
private | |
def recalculate_search_score | |
self.search_score = self.class.scorings.filter_map(&:call).sum | |
end | |
end |
I wonder if the same
scores
could be a declarative approach to how each score contributes, then it is calculated fresh every time.
yeah, good point. I updated it to do that. Also added an alternate just because I was curious to see what it would look like modeled as a domain context object using a gem I've got for that.
Oh, nice! I might be missing something, but how does this line work?
self.search_score = self.class.scorings.filter_map(&:call).sum
It keeps trying to call, for example, scheduling_link
on the class, not the instance.
If I can get this to work with the existing tests then I'd love to merge it in!
Yeah, it's a little finicky unfortunately. I fixed it up here joemasilotti/railsdevs.com#858
Amazing, thanks @kaspth!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Ah, man! I really like this approach though.
I wonder if the same
scores
could be a declarative approach to how each score contributes, then it is calculated fresh every time.