Add profile_updated_at and github_repos_updated_at to avoid extra fet… (#1754)

* Add profile_updated_at and github_repos_updated_at to avoid extra fetches

* Fix variant_number issue

* Fix test
This commit is contained in:
Ben Halpern 2019-02-06 20:39:15 -04:00 committed by GitHub
parent 7d6c85a294
commit 71a419e5ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 181 additions and 158 deletions

View file

@ -15,6 +15,7 @@ module Api
def update_or_create
@client = create_octokit_client
@repo = GithubRepo.find_or_create(fetched_repo_params)
current_user.touch(:github_repos_updated_at)
if @repo.valid?
render json: { featured: @repo.featured }
else

View file

@ -5,6 +5,7 @@ class GithubReposController < ApplicationController
authorize GithubRepo
@client = create_octokit_client
@repo = GithubRepo.find_or_create(fetched_repo_params)
current_user.touch(:github_repos_updated_at)
if @repo.valid?
redirect_to "/settings/integrations", notice: "GitHub repo added"
else
@ -15,6 +16,7 @@ class GithubReposController < ApplicationController
def update
@repo = GithubRepo.find(params[:id])
current_user.touch(:github_repos_updated_at)
authorize @repo
if @repo.update(featured: false)
redirect_to "/settings/integrations", notice: "GitHub repo added"

View file

@ -18,7 +18,6 @@ class OrganizationsController < ApplicationController
end
end
# GET /users/:id/edit
def update
@user = current_user
@tab = "organization"
@ -27,6 +26,7 @@ class OrganizationsController < ApplicationController
authorize @organization
if @organization.update(organization_params)
@organization.touch(:profile_updated_at)
redirect_to "/settings/organization", notice: "Your organization was successfully updated."
else
render template: "users/edit"

View file

@ -196,7 +196,7 @@ class StoriesController < ApplicationController
def handle_article_show
@article_show = true
@variant_number = params[:variant_version] || rand(2)
@variant_number = params[:variant_version] || (user_signed_in? ? 0 : rand(2))
assign_user_and_org
@comments_to_show_count = @article.cached_tag_list_array.include?("discuss") ? 50 : 30
assign_second_and_third_user

View file

@ -32,6 +32,7 @@ class UsersController < ApplicationController
end
follow_hiring_tag(@user)
@user.touch(:profile_updated_at)
redirect_to "/settings/#{@tab}", notice: notice
else
render :edit

View file

@ -25,10 +25,4 @@ class OrganizationDecorator < ApplicationDecorator
text: "#ffffff"
}
end
def key_profile_attributes
"#{bg_color_hex}-#{text_color_hex}-#{path}-#{tag_line}-
#{email}-#{company_size}-#{location}-#{summary}-#{cta_processed_html}-
#{cta_button_url}-#{cta_button_text}-#{profile_image_url}-#{name}"
end
end

View file

@ -76,11 +76,4 @@ class UserDecorator < ApplicationDecorator
]
colors[id % 10]
end
def key_profile_attributes
"#{bg_color_hex}-#{text_color_hex}-#{path}-#{tag_line}-
#{email}-#{email_public}-#{employer_name}-#{employment_title}-
#{employer_url}-#{location}-#{education}-#{summary}-
#{looking_for_work_publicly}-#{created_at}-#{profile_image_url}-#{name}"
end
end

View file

@ -34,6 +34,7 @@ class GithubRepo < ApplicationRecord
stargazers_count: fetched_repo.stargazers_count,
info_hash: fetched_repo.to_hash,
)
repo.user&.touch(:github_repos_updated_at)
rescue StandardError => e
repo.destroy if e.message.include?("404 - Not Found")
end

View file

@ -61,7 +61,7 @@
</div>
<% end %>
</div>
<% if @variant_number.to_i == 1 && !user_signed_in? %>
<% if @variant_number.to_i == 1 %>
<% cache("html-variant-sidebar#{rand(20)}", :expires_in => 8.hours) do %>
<% @html_variant = HtmlVariant.find_for_test(@article.cached_tag_list_array) %>
<% if @html_variant %>
@ -71,7 +71,7 @@
<% end %>
<% end %>
<% else %>
<% cache("article-sticky-nav-articles-#{@article.id}-#{@actor.last_article_at}", :expires_in => 36.hours) do %>
<% cache("article-sticky-nav-articles-#{@article.id}-#{@actor.last_article_at}", :expires_in => 48.hours) do %>
<% @sticky_collection = StickyArticleCollection.new(@article, @organization || @user) %>
<% @sticky_articles = @sticky_collection.suggested_stickies %>
<% @user_stickies = @sticky_collection.user_stickies %>

View file

@ -222,7 +222,7 @@
</div>
</div>
<% cache("sticky-sidebar-#{@article.id}-#{(@organization || @user).decorate.key_profile_attributes}-#{(@organization || @user).last_article_at}-#{user_signed_in?}-#{@variant_number}", :expires_in => 24.hours) do %>
<% cache("sticky-sidebar-#{@article.id}-#{(@organization || @user).profile_updated_at}-#{(@organization || @user).last_article_at}-#{@variant_number}", :expires_in => 50.hours) do %>
<%= render "articles/sticky_nav" %>
<% end %>

View file

@ -2,57 +2,61 @@
<div class="sidebar-bg" id="sidebar-bg-left"></div>
<div class="side-bar">
<div class="user-sidebar">
<% if @user.mostly_work_with.present? %>
<div class="widget">
<header>
<h4>skills/languages</h4>
</header>
<div class="widget-body">
<%= sanitized_sidebar @user.mostly_work_with %>
<% cache "user-profile-sidebar-profile-details-#{@user.profile_updated_at}", expires_in: 10.days do %>
<% if @user.mostly_work_with.present? %>
<div class="widget">
<header>
<h4>skills/languages</h4>
</header>
<div class="widget-body">
<%= sanitized_sidebar @user.mostly_work_with %>
</div>
</div>
<% end %>
<% if @user.currently_learning.present? %>
<div class="widget">
<header>
<h4>learning/trying</h4>
</header>
<div class="widget-body">
<%= sanitized_sidebar @user.currently_learning %>
</div>
</div>
<% end %>
<% if @user.currently_hacking_on.present? %>
<div class="widget">
<header>
<h4>projects and hacks</h4>
</header>
<div class="widget-body">
<%= sanitized_sidebar @user.currently_hacking_on %>
</div>
</div>
<% end %>
<% if @user.available_for.present? %>
<div class="widget">
<header>
<h4>available for</h4>
</header>
<div class="widget-body">
<%= sanitized_sidebar @user.available_for %>
</div>
</div>
<% end %>
<% end %>
<% cache "user-profile-sidebar-stats-#{@user.last_article_at}-#{@user.last_comment_at}-#{@user.last_followed_at}", expires_in: 10.days do %>
<div class="sidebar-data">
<div>
<%= pluralize @user.articles.where(published: true).size, "Post" %> Published
</div>
<div>
<%= pluralize @user.comments.where(deleted: false).size, "Comment" %> Written
</div>
<div>
<%= pluralize @user.decorate.cached_followed_tags.size, "Tag" %> Followed
</div>
</div>
<% end %>
<% if @user.currently_learning.present? %>
<div class="widget">
<header>
<h4>learning/trying</h4>
</header>
<div class="widget-body">
<%= sanitized_sidebar @user.currently_learning %>
</div>
</div>
<% end %>
<% if @user.currently_hacking_on.present? %>
<div class="widget">
<header>
<h4>projects and hacks</h4>
</header>
<div class="widget-body">
<%= sanitized_sidebar @user.currently_hacking_on %>
</div>
</div>
<% end %>
<% if @user.available_for.present? %>
<div class="widget">
<header>
<h4>available for</h4>
</header>
<div class="widget-body">
<%= sanitized_sidebar @user.available_for %>
</div>
</div>
<% end %>
<div class="sidebar-data">
<div>
<%= pluralize @user.articles.where(published: true).size, "Post" %> Published
</div>
<div>
<%= pluralize @user.comments.where(deleted: false).size, "Comment" %> Written
</div>
<div>
<%= pluralize @user.decorate.cached_followed_tags.size, "Tag" %> Followed
</div>
</div>
</div>
</div>
</div>

View file

@ -4,97 +4,99 @@
<%= render "users/meta" %>
<% end %>
<style>
.widget header{
color: <%= HexComparer.new([user_colors(@user)[:bg], user_colors(@user)[:text]]).brightness(0.88) %>;
}
<% if user_colors(@user)[:bg].downcase.start_with?("#fff") %>
.user-profile-follow-button {
border: 1px solid <%= user_colors(@user)[:text] %> !important;
<% cache "main-user-profile-header-area-#{@user.profile_updated_at}", expires_in: 10.days do %>
<style>
.widget header{
color: <%= HexComparer.new([user_colors(@user)[:bg], user_colors(@user)[:text]]).brightness(0.88) %>;
}
<% end %>
</style>
<div class="user-profile-header" style="<%= user_colors_style(@user) %>" itemscope itemtype="http://schema.org/Person" itemprop="mainEntityOfPage">
<meta itemprop="url" content="https://dev.to/<%=@user.username%>">
<div class="user-profile-header-container">
<div class="profile-pic-wrapper">
<img class="profile-pic" src="<%= ProfileImage.new(@user).get(320) %>" itemprop="image" alt="<%= @user.username %> profile" style="border-color:<%=user_colors(@user)[:bg] %>;background:<%=user_colors(@user)[:bg] %>"/>
</div>
<div class="profile-details">
<h1 style="color:<%= HexComparer.new([user_colors(@user)[:bg], user_colors(@user)[:text]]).brightness(0.78) %>"><span itemprop="name"><%= @user.name %></span>
<span class="user-profile-follow-button-wrapper">
<button id="user-follow-butt" class="cta follow-action-button user-profile-follow-button" style="color:<%= user_colors(@user)[:text] %>;background-color:<%=user_colors(@user)[:bg] %>" data-info='{"id":<%= @user.id%>,"className":"<%= @user.class.name %>"}'>&nbsp;</button>
</span>
</h1>
<p class="profile-description" itemprop="description">
<%= @user.summary.presence || ["404 bio not found"].sample %>
</p>
<style>
.profile-details .social .icon-img path{
fill: <%= HexComparer.new([user_colors(@user)[:bg], user_colors(@user)[:text]]).brightness(0.78) %> !important;
}
</style>
<p class="social">
<% if @user.twitter_username? %>
<a href="https://twitter.com/<%= @user.twitter_username %>" target="_blank" rel="noopener me">
<%= inline_svg("twitter-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.github_username? %>
<a href="https://github.com/<%= @user.github_username %>" target="_blank" rel="noopener me">
<%= inline_svg("github-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.mastodon_url? %>
<a href="<%= @user.mastodon_url %>" target="_blank" rel="noopener">
<%= inline_svg("mastodon-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.facebook_url? %>
<a href="<%= @user.facebook_url %>" target="_blank" rel="noopener me">
<%= inline_svg("facebook-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.linkedin_url? %>
<a href="<%= @user.linkedin_url %>" target="_blank" rel="noopener me">
<%= inline_svg("linkedin_icon.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.behance_url? %>
<a href="<%= @user.behance_url %>" target="_blank" rel="noopener me">
<%= inline_svg("behance_icon.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.stackoverflow_url? %>
<a href="<%= @user.stackoverflow_url %>" target="_blank" rel="noopener me">
<%= inline_svg("stackoverflow-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.dribbble_url? %>
<a href="<%= @user.dribbble_url %>" target="_blank" rel="noopener me">
<%= inline_svg("dribbble_icon.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.medium_url? %>
<a href="<%= @user.medium_url %>" target="_blank" rel="noopener nofollow me">
<%= inline_svg("medium_icon.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.gitlab_url? %>
<a href="<%= @user.gitlab_url %>" target="_blank" rel="noopener nofollow me">
<%= inline_svg("gitlab.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.website_url? %>
<a href="<%= @user.website_url %>" target="_blank" rel="noopener nofollow me">
<%= inline_svg("external-link-logo.svg", class:"icon-img") %>
</a>
<% end %>
</p>
<% if user_colors(@user)[:bg].downcase.start_with?("#fff") %>
.user-profile-follow-button {
border: 1px solid <%= user_colors(@user)[:text] %> !important;
}
<% end %>
</style>
<div class="user-profile-header" style="<%= user_colors_style(@user) %>" itemscope itemtype="http://schema.org/Person" itemprop="mainEntityOfPage">
<meta itemprop="url" content="https://dev.to/<%=@user.username%>">
<div class="user-profile-header-container">
<div class="profile-pic-wrapper">
<img class="profile-pic" src="<%= ProfileImage.new(@user).get(320) %>" itemprop="image" alt="<%= @user.username %> profile" style="border-color:<%=user_colors(@user)[:bg] %>;background:<%=user_colors(@user)[:bg] %>"/>
</div>
<div class="profile-details">
<h1 style="color:<%= HexComparer.new([user_colors(@user)[:bg], user_colors(@user)[:text]]).brightness(0.78) %>"><span itemprop="name"><%= @user.name %></span>
<span class="user-profile-follow-button-wrapper">
<button id="user-follow-butt" class="cta follow-action-button user-profile-follow-button" style="color:<%= user_colors(@user)[:text] %>;background-color:<%=user_colors(@user)[:bg] %>" data-info='{"id":<%= @user.id%>,"className":"<%= @user.class.name %>"}'>&nbsp;</button>
</span>
</h1>
<p class="profile-description" itemprop="description">
<%= @user.summary.presence || ["404 bio not found"].sample %>
</p>
<style>
.profile-details .social .icon-img path{
fill: <%= HexComparer.new([user_colors(@user)[:bg], user_colors(@user)[:text]]).brightness(0.78) %> !important;
}
</style>
<p class="social">
<% if @user.twitter_username? %>
<a href="https://twitter.com/<%= @user.twitter_username %>" target="_blank" rel="noopener me">
<%= inline_svg("twitter-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.github_username? %>
<a href="https://github.com/<%= @user.github_username %>" target="_blank" rel="noopener me">
<%= inline_svg("github-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.mastodon_url? %>
<a href="<%= @user.mastodon_url %>" target="_blank" rel="noopener">
<%= inline_svg("mastodon-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.facebook_url? %>
<a href="<%= @user.facebook_url %>" target="_blank" rel="noopener me">
<%= inline_svg("facebook-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.linkedin_url? %>
<a href="<%= @user.linkedin_url %>" target="_blank" rel="noopener me">
<%= inline_svg("linkedin_icon.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.behance_url? %>
<a href="<%= @user.behance_url %>" target="_blank" rel="noopener me">
<%= inline_svg("behance_icon.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.stackoverflow_url? %>
<a href="<%= @user.stackoverflow_url %>" target="_blank" rel="noopener me">
<%= inline_svg("stackoverflow-logo.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.dribbble_url? %>
<a href="<%= @user.dribbble_url %>" target="_blank" rel="noopener me">
<%= inline_svg("dribbble_icon.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.medium_url? %>
<a href="<%= @user.medium_url %>" target="_blank" rel="noopener nofollow me">
<%= inline_svg("medium_icon.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.gitlab_url? %>
<a href="<%= @user.gitlab_url %>" target="_blank" rel="noopener nofollow me">
<%= inline_svg("gitlab.svg", class:"icon-img") %>
</a>
<% end %>
<% if @user.website_url? %>
<a href="<%= @user.website_url %>" target="_blank" rel="noopener nofollow me">
<%= inline_svg("external-link-logo.svg", class:"icon-img") %>
</a>
<% end %>
</p>
</div>
</div>
<%= render "articles/user_metadata", context: "profile" %>
</div>
<%= render "articles/user_metadata", context: "profile" %>
</div>
<% end %>
<div class="home sub-home" id="index-container"
data-params="<%= params.to_json(only: [:tag,:username,:q]) %>" data-which="<%=@list_of%>"
@ -123,7 +125,9 @@
loading...
</div>
</div>
<%= render "users/sidebar_additional" %>
<% cache "user-profile-sidebar-additional-#{@user.github_repos_updated_at}-#{@user.badge_achievements_count}", expires_in: 2.days do %>
<%= render "users/sidebar_additional" %>
<% end %>
</div>
<%= render "stories/narrow_nav_menu" %>

View file

@ -0,0 +1,7 @@
class AddProfileUpdatedAtToUsers < ActiveRecord::Migration[5.1]
def change
add_column :users, :profile_updated_at, :datetime, default: "2017-01-01 05:00:00"
add_column :organizations, :profile_updated_at, :datetime, default: "2017-01-01 05:00:00"
add_column :users, :github_repos_updated_at, :datetime, default: "2017-01-01 05:00:00"
end
end

View file

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20190206164319) do
ActiveRecord::Schema.define(version: 20190206222055) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@ -496,6 +496,7 @@ ActiveRecord::Schema.define(version: 20190206164319) do
t.string "old_old_slug"
t.string "old_slug"
t.string "profile_image"
t.datetime "profile_updated_at", default: "2017-01-01 05:00:00"
t.text "proof"
t.string "secret"
t.string "slug"
@ -755,6 +756,7 @@ ActiveRecord::Schema.define(version: 20190206164319) do
t.integer "following_tags_count", default: 0, null: false
t.integer "following_users_count", default: 0, null: false
t.datetime "github_created_at"
t.datetime "github_repos_updated_at", default: "2017-01-01 05:00:00"
t.string "github_username"
t.string "gitlab_url"
t.jsonb "language_settings", default: {}, null: false
@ -792,6 +794,7 @@ ActiveRecord::Schema.define(version: 20190206164319) do
t.boolean "permit_adjacent_sponsors", default: true
t.datetime "personal_data_updated_at"
t.string "profile_image"
t.datetime "profile_updated_at", default: "2017-01-01 05:00:00"
t.integer "reactions_count", default: 0, null: false
t.datetime "remember_created_at"
t.string "remember_token"

View file

@ -11,7 +11,7 @@ RSpec.describe "OrganizationsUpdate", type: :request do
sign_in user
end
it "updates ordinary article with proper params" do
it "updates org color with proper params" do
put "/organizations/#{organization.id}", params: {
organization: { text_color_hex: "#111111" }
}
@ -23,4 +23,11 @@ RSpec.describe "OrganizationsUpdate", type: :request do
post "/organizations/generate_new_secret"
expect(Organization.last.secret).not_to eq(secret)
end
it "updates profile_updated_at" do
organization.update_column(:profile_updated_at, 2.weeks.ago)
put "/organizations/#{organization.id}", params: { organization: { text_color_hex: "#111111" } }
expect(organization.reload.profile_updated_at).to be > 2.minutes.ago
end
end

View file

@ -47,7 +47,7 @@ RSpec.describe "StoriesShow", type: :request do
it "does not render html variant when user logged in" do
html_variant = create(:html_variant, published: true, approved: true)
sign_in user
get article.path + "?variant_version=1"
get article.path
expect(response.body).not_to include html_variant.html
end

View file

@ -58,6 +58,12 @@ RSpec.describe "UserSettings", type: :request do
expect(user.summary).to eq("Hello new summary")
end
it "updates profile_updated_at" do
user.update_column(:profile_updated_at, 2.weeks.ago)
put "/users/#{user.id}", params: { user: { tab: "profile", summary: "Hello new summary" } }
expect(user.reload.profile_updated_at).to be > 2.minutes.ago
end
it "updates username to too short username" do
put "/users/#{user.id}", params: { user: { tab: "profile", username: "h" } }
expect(response.body).to include("Username is too short")