Refactoring to add helper method (#16064)

* Refactoring to add helper method

Prior to this commit, we made view level calls to service modules.  This
refactor provides convenience methods on the model.

Furthermore, it addresses a few Rubocop violations that "come along for
the ride."

* Ensuring cached entity squaks like User

* Fixing broken spec

* Fixing typo
This commit is contained in:
Jeremy Friesen 2022-01-12 11:21:44 -05:00 committed by GitHub
parent c489971ecf
commit a65954107f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
54 changed files with 144 additions and 85 deletions

View file

@ -43,7 +43,7 @@ class AsyncInfoController < ApplicationController
id: @user.id,
name: @user.name,
username: @user.username,
profile_image_90: Images::Profile.call(@user.profile_image_url, length: 90),
profile_image_90: @user.profile_image_url_for(length: 90),
followed_tags: @user.cached_followed_tags.to_json(only: %i[id name bg_color_hex text_color_hex hotness_score],
methods: [:points]),
followed_podcast_ids: @user.cached_following_podcasts_ids,

View file

@ -47,7 +47,16 @@ class NotificationsController < ApplicationController
# the first few notifications. After that the JS frontend code (see `initNotification.js`)
# will call this action again by sending the offset id for the last known notifications, the result
# will be the partial rendering of only the list of notifications that will be attached to the DOM by JS
render partial: "notifications_list" if notified_at_offset
if notified_at_offset
render partial: "notifications_list"
else
# [@jeremyf] I added an explicit render. Before adding the explicit render, we relied on the
# implicit render cycle of Rails. Which is fine, but it's very disarming to read `render
# partial: "notifications_list" if notified_at_offset` as the last line of the method.
#
# My hope is that this explicit render removes at least one future head scratch.
render "index"
end
end
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity

View file

@ -337,11 +337,11 @@ class StoriesController < ApplicationController
},
url: URL.user(@user),
sameAs: user_same_as,
image: Images::Profile.call(@user.profile_image_url, length: 320),
image: @user.profile_image_url_for(length: 320),
name: @user.name,
email: decorated_user.profile_email,
description: decorated_user.profile_summary
}.reject { |_, v| v.blank? }
}.compact_blank
end
def set_article_json_ld
@ -399,7 +399,7 @@ class StoriesController < ApplicationController
"@id": URL.organization(@organization)
},
url: URL.organization(@organization),
image: Images::Profile.call(@organization.profile_image_url, length: 320),
image: @organization.profile_image_url_for(length: 320),
name: @organization.name,
description: @organization.summary.presence || "404 bio not found"
}
@ -412,6 +412,6 @@ class StoriesController < ApplicationController
@user.twitter_username.present? ? "https://twitter.com/#{@user.twitter_username}" : nil,
@user.github_username.present? ? "https://github.com/#{@user.github_username}" : nil,
@user.profile.website_url,
].reject(&:blank?)
].compact_blank
end
end

View file

@ -1,6 +1,8 @@
module Articles
# NOTE: articles cache either users or organizations, but they have the same attributes.
CachedEntity = Struct.new(:name, :username, :slug, :profile_image_90, :profile_image_url) do
include Images::Profile.for(:profile_image_url)
def self.from_object(object)
new(
object.name,

View file

@ -1,6 +1,8 @@
class Organization < ApplicationRecord
include CloudinaryHelper
include Images::Profile.for(:profile_image_url)
COLOR_HEX_REGEXP = /\A#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})\z/
INTEGER_REGEXP = /\A\d+\z/
SLUG_REGEXP = /\A[a-zA-Z0-9\-_]+\z/
@ -103,7 +105,7 @@ class Organization < ApplicationRecord
end
def profile_image_90
Images::Profile.call(profile_image_url, length: 90)
profile_image_url_for(length: 90)
end
def enough_credits?(num_credits_needed)

View file

@ -1,6 +1,8 @@
class Podcast < ApplicationRecord
resourcify
include Images::Profile.for(:profile_image_url)
belongs_to :creator, class_name: "User", inverse_of: :created_podcasts, optional: true
has_many :podcast_episodes, dependent: :destroy
@ -50,7 +52,7 @@ class Podcast < ApplicationRecord
end
def image_90
Images::Profile.call(profile_image_url, length: 90)
profile_image_url_for(length: 90)
end
private

View file

@ -4,6 +4,8 @@ class User < ApplicationRecord
include CloudinaryHelper
include Images::Profile.for(:profile_image_url)
# NOTE: we are using an inline module to keep profile related things together.
concerning :Profiles do
included do
@ -507,7 +509,7 @@ class User < ApplicationRecord
end
def profile_image_90
Images::Profile.call(profile_image_url, length: 90)
profile_image_url_for(length: 90)
end
def unsubscribe_from_newsletters

View file

@ -1,7 +1,7 @@
module Search
class PodcastEpisodeSerializer < ApplicationSerializer
def self.podcast_image_url(podcast_episode)
Images::Profile.call(podcast_episode.podcast.profile_image_url, length: 90)
podcast_episode.podcast.profile_image_url_for(length: 90)
end
attribute :id, &:search_id

View file

@ -1,5 +1,22 @@
module Images
module Profile
# A convenience module for wrapping the Profile::Images logic.
#
# @param attribute [Symbol] named attribute that is an image_url
#
# @return [Module] for inclusion into the given class
#
# @example
# class User
# include Images::Profile.for(:image_url)
# end
def self.for(attribute)
Module.new do
define_method("#{attribute}_for") do |length:|
Images::Profile.call(public_send(attribute), length: length)
end
end
end
BACKUP_LINK = "https://thepracticaldev.s3.amazonaws.com/i/99mvlsfu5tfj9m7ku25d.png".freeze
def self.call(image_url, length: 120)

View file

@ -19,7 +19,7 @@
<h5 class="card-title text-center">
<% if comment.user %>
<a href="<%= comment.user.path %>" target="_blank" rel="noopener">
<img class="rounded" height="30" src="<%= Images::Profile.call(comment.user.profile_image_url, length: 50) %>" alt="<%= comment.user.username %> profile" loading="lazy" /> <%= comment.user.username %>
<img class="rounded" height="30" src="<%= comment.user.profile_image_url_for(length: 50) %>" alt="<%= comment.user.username %> profile" loading="lazy" /> <%= comment.user.username %>
</a>
<% end %>
<% if comment.user && comment.user.twitter_username.present? %>

View file

@ -13,6 +13,6 @@ json.array! @articles do |article|
json.user do
json.name article.user.name
json.profile_image_url Images::Profile.call(article.user.profile_image_url, length: 90)
json.profile_image_url article.user.profile_image_url_for(length: 90)
end
end

View file

@ -15,4 +15,4 @@ json.extract!(
)
json.joined_at utc_iso_timestamp(@organization.created_at)
json.profile_image Images::Profile.call(@organization.profile_image_url, length: 640)
json.profile_image @organization.profile_image_url_for(length: 640)

View file

@ -1,5 +1,5 @@
json.type_of "profile_image"
json.image_of @profile_image_owner.class.name.downcase
json.profile_image Images::Profile.call(@profile_image_owner.profile_image_url, length: 640)
json.profile_image_90 Images::Profile.call(@profile_image_owner.profile_image_url, length: 90)
json.profile_image @profile_image_owner.profile_image_url_for(length: 640)
json.profile_image_90 @profile_image_owner.profile_image_url_for(length: 90)

View file

@ -1,4 +1,4 @@
json.name user.name
json.path "/#{user.path.delete_prefix('/')}"
json.username user.try(:username) || user.name
json.profile_image Images::Profile.call(user.profile_image_url, length: 60)
json.profile_image user.profile_image_url_for(length: 60)

View file

@ -1,6 +1,6 @@
json.organization do
json.extract!(organization, :name, :username, :slug)
json.profile_image Images::Profile.call(organization.profile_image_url, length: 640)
json.profile_image_90 Images::Profile.call(organization.profile_image_url, length: 90)
json.profile_image organization.profile_image_url_for(length: 640)
json.profile_image_90 organization.profile_image_url_for(length: 90)
end

View file

@ -2,6 +2,6 @@ json.user do
json.extract!(user, :name, :username, :twitter_username, :github_username)
json.website_url user.processed_website_url
json.profile_image Images::Profile.call(user.profile_image_url, length: 640)
json.profile_image_90 Images::Profile.call(user.profile_image_url, length: 90)
json.profile_image user.profile_image_url_for(length: 640)
json.profile_image_90 user.profile_image_url_for(length: 90)
end

View file

@ -14,4 +14,4 @@ Profile.static_fields.each do |attr|
end
json.joined_at I18n.l(user.created_at, format: :json)
json.profile_image Images::Profile.call(user.profile_image_url, length: 320)
json.profile_image user.profile_image_url_for(length: 320)

View file

@ -10,9 +10,9 @@
<% if article.organization %>
<a href='<%= article.organization.path %>' class='ltag__link__link'>
<div class='ltag__link__org__pic'>
<img src='<%= Images::Profile.call(article.organization.profile_image_url, length: 150) %>' alt='<%= article.organization.name.to_s %>'>
<img src='<%= article.organization.profile_image_url_for(length: 150) %>' alt='<%= article.organization.name.to_s %>'>
<div class='ltag__link__user__pic'>
<img src='<%= Images::Profile.call(article.user.profile_image_url, length: 150) %>' alt=''>
<img src='<%= article.user.profile_image_url_for(length: 150) %>' alt=''>
</div>
</div>
</a>
@ -30,7 +30,7 @@
<% else %>
<a href='<%= article.user.path %>' class='ltag__link__link'>
<div class='ltag__link__pic'>
<img src='<%= Images::Profile.call(article.user.profile_image_url, length: 150) %>' alt='<%= article.user.username.to_s %>'>
<img src='<%= article.user.profile_image_url_for(length: 150) %>' alt='<%= article.user.username.to_s %>'>
</div>
</a>
<a href='<%= article.path %>' class='ltag__link__link'>

View file

@ -30,7 +30,7 @@
<% end %>
<a href="/<%= story.cached_user.username %>" class="crayons-avatar <% if story.cached_organization && !@organization_article_index %> crayons-avatar--s absolute -right-2 -bottom-2 border-solid border-2 border-base-inverted <% else %> crayons-avatar--l <% end %> ">
<img src="<%= Images::Profile.call(story.cached_user.profile_image_url, length: 90) %>" alt="<%= story.cached_user.username %> profile" class="crayons-avatar__image" loading="lazy" />
<img src="<%= story.cached_user.profile_image_url_for(length: 90) %>" alt="<%= story.cached_user.username %> profile" class="crayons-avatar__image" loading="lazy" />
</a>
</div>
<div>
@ -54,7 +54,7 @@
<a href="/<%= story.cached_user.username %>" class="flex">
<span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0">
<img
src="<%= Images::Profile.call(story.cached_user.profile_image_url, length: 90) %>"
src="<%= story.cached_user.profile_image_url_for(length: 90) %>"
class="crayons-avatar__image"
alt=""
loading="lazy" />

View file

@ -37,7 +37,7 @@
<% sticky_articles.each_with_index do |article, index| %>
<a class="crayons-link crayons-link--contentful flex" href="<%= article.path %>">
<span class="crayons-avatar mr-2 shrink-0">
<img src="<%= Images::Profile.call(article.cached_user.profile_image_url, length: 90) %>" class="crayons-avatar__image" loading="lazy" alt="<%= article.cached_user.name %> profile image">
<img src="<%= article.cached_user.profile_image_url_for(length: 90) %>" class="crayons-avatar__image" loading="lazy" alt="<%= article.cached_user.name %> profile image">
</span>
<div>
<%= article.title %>

View file

@ -103,12 +103,12 @@
<div class="flex flex-1 mb-5 items-start">
<div class="relative">
<% if @organization %>
<a href="<%= @organization.path %>"><img src="<%= Images::Profile.call(@organization.profile_image_url, length: 50) %>" class="radius-default align-middle" width="40" height="40" alt="<%= @organization.name %> profile image"></a>
<a href="<%= @organization.path %>"><img src="<%= @organization.profile_image_url_for(length: 50) %>" class="radius-default align-middle" width="40" height="40" alt="<%= @organization.name %> profile image"></a>
<a href="/<%= @user.username %>" class="absolute -right-2 -bottom-2 radius-full border border-solid border-2 border-base-inverted inline-flex">
<img class="radius-full align-middle" src="<%= Images::Profile.call(@user.profile_image_url, length: 50) %>" width="24" height="24" alt="<%= @user.name %>" />
<img class="radius-full align-middle" src="<%= @user.profile_image_url_for(length: 50) %>" width="24" height="24" alt="<%= @user.name %>" />
</a>
<% else %>
<a href="/<%= @user.username %>"><img class="radius-full align-middle" src="<%= Images::Profile.call(@user.profile_image_url, length: 50) %>" width="40" height="40" alt="<%= @user.name %>" /></a>
<a href="/<%= @user.username %>"><img class="radius-full align-middle" src="<%= @user.profile_image_url_for(length: 50) %>" width="40" height="40" alt="<%= @user.name %>" /></a>
<% end %>
</div>
<div class="pl-3 flex-1">

View file

@ -12,7 +12,7 @@ json.user do
json.id current_user.id
json.username current_user.username
json.name current_user.name
json.profile_pic Images::Profile.call(current_user.profile_image_url, length: 50)
json.profile_pic current_user.profile_image_url_for(length: 50)
json.twitter_username current_user.twitter_username
json.github_username current_user.github_username
end

View file

@ -4,6 +4,6 @@
</span>
<% else %>
<a href="<%= URL.user(comment.user) %>" class="shrink-0 crayons-avatar <% if comment.depth == 0 %>m:crayons-avatar--l mt-4 m:mt-3<% else %>mt-4<% end %>">
<img class="crayons-avatar__image" width="32" height="32" src="<%= Images::Profile.call(comment.user.profile_image_url, length: 50) %>" alt="<%= comment.user.username %> profile image" loading="lazy" />
<img class="crayons-avatar__image" width="32" height="32" src="<%= comment.user.profile_image_url_for(length: 50) %>" alt="<%= comment.user.username %> profile image" loading="lazy" />
</a>
<% end %>

View file

@ -2,7 +2,7 @@
<% if comment %>
<div class="details">
<a href="/<%= comment.user.username %>">
<img class="profile-pic" src="<%= Images::Profile.call(comment.user.profile_image_url, length: 50) %>" alt="<%= comment.user.username %> profile image" />
<img class="profile-pic" src="<%= comment.user.profile_image_url_for(length: 50) %>" alt="<%= comment.user.username %> profile image" />
</a>
<a href="/<%= comment.user.username %>">
<span class="comment-username"><%= comment.user.name %></span>

View file

@ -20,7 +20,7 @@
<% if user %>
<div class="crayons-card p-4 m:p-6 flex s:grid single-article break-word content-center" id="follows-<%= follow.id %>">
<a href="<%= user.path %>" class="crayons-avatar crayons-avatar--2xl s:mb-2 s:mx-auto">
<img alt="<%= user.username %> profile image" class="crayons-avatar__image" src="<%= Images::Profile.call(user.profile_image_url, length: 60) %>" loading="lazy" />
<img alt="<%= user.username %> profile image" class="crayons-avatar__image" src="<%= user.profile_image_url_for(length: 60) %>" loading="lazy" />
</a>
<div class="pl-4 s:pl-0 self-center">

View file

@ -18,7 +18,7 @@
<% organization = follow.followable %>
<div class="crayons-card p-4 m:p-6 flex s:grid single-article break-word content-center" id="follows-<%= follow.id %>">
<a href="<%= organization.path %>" class="crayons-logo crayons-logo--2xl s:mb-2 s:mx-auto">
<img alt="<%= organization.name %> logo" class="crayons-logo__image" src="<%= Images::Profile.call(organization.profile_image_url, length: 60) %>" loading="lazy" />
<img alt="<%= organization.name %> logo" class="crayons-logo__image" src="<%= organization.profile_image_url_for(length: 60) %>" loading="lazy" />
</a>
<div class="pl-4 s:pl-0 self-center">

View file

@ -20,7 +20,7 @@
<% if user %>
<div class="crayons-card p-4 m:p-6 flex s:grid single-article break-word content-center" id="follows-<%= follow.id %>">
<a href="<%= user.path %>" class="crayons-avatar crayons-avatar--2xl s:mb-2 s:mx-auto">
<img alt="<%= user.username %> profile image" class="crayons-avatar__image" src="<%= Images::Profile.call(user.profile_image_url, length: 60) %>" loading="lazy" />
<img alt="<%= user.username %> profile image" class="crayons-avatar__image" src="<%= user.profile_image_url_for(length: 60) %>" loading="lazy" />
</a>
<div class="pl-4 s:pl-0 self-center">

View file

@ -3,7 +3,7 @@
<% user = User.find_by(id: json_data["user"]["id"]) %>
<% cache "broadcast-html-#{notification.json_data['broadcast']['title']}" do %>
<a href="<%= json_data["user"]["path"] %>" class="crayons-avatar crayons-avatar--2xl m:crayons-avatar--3xl shrink-0 mb-4 m:mb-6">
<img src="<%= Images::Profile.call(user.profile_image_url) %>" class="crayons-avatar__image" alt="link to <%= json_data["user"]["username"] %>'s profile" width="128" height="128">
<img src="<%= user.profile_image_url %>" class="crayons-avatar__image" alt="link to <%= json_data["user"]["username"] %>'s profile" width="128" height="128">
</a>
<div class="fs-base m:fs-l broadcast-content" id="<%= sanitized_broadcast_id(json_data["broadcast"]["title"]) %>">
<%= json_data["broadcast"]["processed_html"].html_safe %>

View file

@ -6,6 +6,7 @@
</div>
<% rescue => e %>
<% Honeybadger.notify(e, context: { notification_id: notification.id }) %>
<div class="align-center p-9 py-10 color-base-80 crayons-card mb-2">

View file

@ -13,7 +13,7 @@
<header class="profile-header crayons-card mt-2">
<div class="relative profile-header__top">
<span class="crayons-logo crayons-logo--3xl">
<img src="<%= Images::Profile.call(@user.profile_image_url, length: 320) %>" alt="<%= @user.name %> logo" width="128" height="128" title="<%= t("views.organizations.logo", org: @user.name) %>" class="crayons-logo__image">
<img src="<%= @user.profile_image_url_for(length: 320) %>" alt="<%= @user.name %> logo" width="128" height="128" title="<%= t("views.organizations.logo", org: @user.name) %>" class="crayons-logo__image">
</span>
<div class="profile-header__actions">

View file

@ -8,7 +8,7 @@
</style>
<a href="<%= organization.path %>" class="ltag__user__link profile-image-link">
<div class="ltag__user__pic">
<img src="<%= Images::Profile.call(organization.profile_image_url, length: 150) %>" alt="<%= "#{organization.slug} image" %>" />
<img src="<%= organization.profile_image_url_for(length: 150) %>" alt="<%= "#{organization.slug} image" %>" />
</div>
</a>
<div class="ltag__user__content">

View file

@ -18,7 +18,7 @@
<% @organization.users.find_each do |user| %>
<div class="widget-user-pic">
<a href="/<%= user.username %>">
<img src="<%= Images::Profile.call(user.profile_image_url, length: 90) %>" alt="<%= user.username %> profile image" loading="lazy" />
<img src="<%= user.profile_image_url_for(length: 90) %>" alt="<%= user.username %> profile image" loading="lazy" />
</a>
</div>
<% end %>

View file

@ -1,7 +1,7 @@
<div class="-mt-4">
<a href="<%= actor.path %>" class="flex">
<span class="<% if actor.class.name == "User" %>crayons-avatar crayons-avatar--xl<% elsif actor.class.name == "Organization" %>crayons-logo crayons-logo--xl<% end %> mr-2 shrink-0">
<img src="<%= Images::Profile.call(actor.profile_image_url, length: 90) %>" class="<% if actor.class.name == "User" %>crayons-avatar__image<% elsif actor.class.name == "Organization" %>crayons-logo__image<% end %>" alt="" loading="lazy" />
<img src="<%= actor.profile_image_url_for(length: 90) %>" class="<% if actor.class.name == "User" %>crayons-avatar__image<% elsif actor.class.name == "Organization" %>crayons-logo__image<% end %>" alt="" loading="lazy" />
</span>
<span class="crayons-link crayons-subtitle-2 mt-5"><%= actor.name %></span>
</a>

View file

@ -123,7 +123,7 @@
<h1 style="font-size:<%= font_size %>vw;"><%= @article.title %></h1>
</div>
<div class="preview-user">
<img src="<%= Images::Profile.call(@article.user.profile_image_url, length: 90) %>" />
<img src="<%= @article.user.profile_image_url_for(length: 90) %>" />
<%= truncate @article.user.name, length: 28 %>・<%= @article.readable_publish_date %>
</div>
<div class="badge-images">

View file

@ -120,7 +120,7 @@
<h1 style="font-size:<%= font_size %>vw;"><%= @comment.title %></h1>
</div>
<div class="preview-user">
<img src="<%= Images::Profile.call(@comment.user.profile_image_url, length: 90) %>" />
<img src="<%= @comment.user.profile_image_url_for(length: 90) %>" />
<%= truncate @comment.user.name, length: 28 %>・<%= @comment.readable_publish_date %>
</div>
<div class="badge-images">

View file

@ -110,7 +110,7 @@
<% font_size = 4.6 %>
<% end %>
<h1 style="font-size:<%= font_size %>vw;">
<img src="<%= Images::Profile.call(@user.profile_image_url, length: 640) %>" alt="<%= @user.name %> profile image">
<img src="<%= @user.profile_image_url_for(length: 640) %>" alt="<%= @user.name %> profile image">
<%= truncate @user.name, length: 32 %>
<br />
<span style="font-size: 0.4em;display: inline-block; margin-left: 5.4em; margin-top: -1.7em">@<%= @user.username %></span>

View file

@ -44,7 +44,7 @@
<% @moderators.each do |user| %>
<div class="widget-user-pic">
<a href="/<%= user.username %>" title="<%= user.username %>">
<img src="<%= Images::Profile.call(user.profile_image_url, length: 90) %>" alt="<%= user.username %> profile image">
<img src="<%= user.profile_image_url_for(length: 90) %>" alt="<%= user.username %> profile image">
</a>
</div>
<% end %>

View file

@ -9,12 +9,12 @@
<% if user_path.present? %>
<a href="<%= user_path %>" class="ltag__user__link profile-image-link">
<div class="ltag__user__pic">
<img src="<%= Images::Profile.call(user.profile_image_url, length: 150) %>" alt="<%= "#{user.username} image" %>" />
<img src="<%= user.profile_image_url_for(length: 150) %>" alt="<%= "#{user.username} image" %>" />
</div>
</a>
<% else %>
<div class="ltag__user__pic">
<img src="<%= Images::Profile.call(user.profile_image_url, length: 150) %>" alt="<%= "#{user.username} image" %>" />
<img src="<%= user.profile_image_url_for(length: 150) %>" alt="<%= "#{user.username} image" %>" />
</div>
<% end %>
<div class="ltag__user__content">

View file

@ -45,7 +45,7 @@
<div class="flex items-center">
<% if @user.profile_image_url.present? %>
<span class="crayons-avatar crayons-avatar--xl mr-2">
<img alt="<%= @user.username %> profile image" src="<%= Images::Profile.call(@user.profile_image_url, length: 50) %>" class="crayons-avatar__image" loading="lazy" />
<img alt="<%= @user.username %> profile image" src="<%= @user.profile_image_url_for(length: 50) %>" class="crayons-avatar__image" loading="lazy" />
</span>
<% end %>
<%= f.file_field "user[profile_image]", accept: "image/*", class: "crayons-card crayons-card--secondary p-3 flex items-center flex-1 w-100" %>
@ -164,13 +164,13 @@
</label>
<p class="crayons-field__description"><%= t("views.logo.color_1.description") %></p>
<div class="flex items-center w-100 m:w-50">
<%= f.public_send("text_field", "users_setting[brand_color1]",
value: users_setting.public_send("brand_color1"),
<%= f.public_send(:text_field, "users_setting[brand_color1]",
value: users_setting.public_send(:brand_color1),
placeholder: "#000000",
class: "crayons-textfield js-color-field") %>
<%= f.public_send("color_field",
<%= f.public_send(:color_field,
"users_setting[brand_color1]",
value: users_setting.public_send("brand_color1"),
value: users_setting.public_send(:brand_color1),
class: "crayons-color-selector js-color-field ml-2") %>
</div>
</div>
@ -181,13 +181,13 @@
</label>
<p class="crayons-field__description"><%= t("views.logo.color_2.description_html") %></p>
<div class="flex items-center w-100 m:w-50">
<%= f.public_send("text_field", "users_setting[brand_color2]",
value: users_setting.public_send("brand_color2"),
<%= f.public_send(:text_field, "users_setting[brand_color2]",
value: users_setting.public_send(:brand_color2),
placeholder: "#000000",
class: "crayons-textfield js-color-field") %>
<%= f.public_send("color_field",
<%= f.public_send(:color_field,
"users_setting[brand_color2]",
value: users_setting.public_send("brand_color2"),
value: users_setting.public_send(:brand_color2),
class: "crayons-color-selector js-color-field ml-2") %>
</div>
</div>

View file

@ -11,7 +11,7 @@
<% @user.organizations.each do |organization| %>
<a href="/<%= organization.slug %>" class="flex items-center crayons-link crayons-link--contentful">
<span class="crayons-logo crayons-logo--l mr-2 shrink-0">
<img src="<%= Images::Profile.call(organization.profile_image_url, length: 90) %>" alt="<%= organization.name %> profile image" class="crayons-logo__image" loading="lazy" />
<img src="<%= organization.profile_image_url_for(length: 90) %>" alt="<%= organization.name %> profile image" class="crayons-logo__image" loading="lazy" />
</span>
<h4 class="fs-base fw-medium"><%= organization.name %></h4>
</a>

View file

@ -2,6 +2,6 @@ json.array! @users.each do |user|
json.extract!(user, :id, :name, :username)
json.summary truncate(user.tag_line || t("json.author", community: community_name), length: 100)
json.profile_image_url Images::Profile.call(user.profile_image_url, length: 90)
json.profile_image_url user.profile_image_url_for(length: 90)
json.following false
end

View file

@ -28,7 +28,7 @@
<header class="profile-header crayons-card mt-2">
<div class="relative profile-header__top">
<span class="crayons-avatar crayons-avatar--3xl">
<img src="<%= Images::Profile.call(@user.profile_image_url, length: 320) %>" width="128" height="128" alt="<%= @user.name %> profile picture" class="crayons-avatar__image">
<img src="<%= @user.profile_image_url_for(length: 320) %>" width="128" height="128" alt="<%= @user.name %> profile picture" class="crayons-avatar__image">
</span>
<div class="profile-header__actions">

View file

@ -35,7 +35,7 @@ RSpec.describe LinkTag, type: :liquid_tag do
<div class='ltag__link'>
<a href='#{article.user.path}' class='ltag__link__link'>
<div class='ltag__link__pic'>
<img src='#{Images::Profile.call(article.user.profile_image_url, length: 150)}' alt='#{article.user.username}'>
<img src='#{article.user.profile_image_url_for(length: 150)}' alt='#{article.user.username}'>
</div>
</a>
<a href='#{article.path}' class='ltag__link__link'>
@ -58,9 +58,9 @@ RSpec.describe LinkTag, type: :liquid_tag do
<div class='ltag__link'>
<a href='#{article.organization.path}' class='ltag__link__link'>
<div class='ltag__link__org__pic'>
<img src='#{Images::Profile.call(article.organization.profile_image_url, length: 150)}' alt='#{CGI.escapeHTML(article.organization.name)}'>
<img src='#{article.organization.profile_image_url_for(length: 150)}' alt='#{CGI.escapeHTML(article.organization.name)}'>
<div class='ltag__link__user__pic'>
<img src='#{Images::Profile.call(article.user.profile_image_url, length: 150)}' alt=''>
<img src='#{article.user.profile_image_url_for(length: 150)}' alt=''>
</div>
</div>
</a>

View file

@ -42,7 +42,7 @@ RSpec.describe "Api::V0::FollowersController", type: :request do
expect(response_follower["name"]).to eq(follower.name)
expect(response_follower["path"]).to eq(follower.path)
expect(response_follower["username"]).to eq(follower.username)
expect(response_follower["profile_image"]).to eq(Images::Profile.call(follower.profile_image_url, length: 60))
expect(response_follower["profile_image"]).to eq(follower.profile_image_url_for(length: 60))
expect(response_follower["created_at"]).to be_an_instance_of(String)
end

View file

@ -68,7 +68,7 @@ RSpec.describe "Api::V0::Organizations", type: :request do
end
expect(response_org_users["joined_at"]).to eq(org_user.created_at.strftime("%b %e, %Y"))
expect(response_org_users["profile_image"]).to eq(Images::Profile.call(org_user.profile_image_url, length: 320))
expect(response_org_users["profile_image"]).to eq(org_user.profile_image_url_for(length: 320))
end
end

View file

@ -17,8 +17,8 @@ RSpec.describe "Api::V0::ProfileImages", type: :request do
expect(response.parsed_body).to eq(
"type_of" => "profile_image",
"image_of" => "user",
"profile_image" => profile_image(user.profile_image_url, 640),
"profile_image_90" => profile_image(user.profile_image_url, 90),
"profile_image" => user.profile_image_url_for(length: 640),
"profile_image_90" => user.profile_image_url_for(length: 90),
)
end
end
@ -42,14 +42,10 @@ RSpec.describe "Api::V0::ProfileImages", type: :request do
expect(response.parsed_body).to eq(
"type_of" => "profile_image",
"image_of" => "organization",
"profile_image" => profile_image(organization.profile_image_url, 640),
"profile_image_90" => profile_image(organization.profile_image_url, 90),
"profile_image" => organization.profile_image_url_for(length: 640),
"profile_image_90" => organization.profile_image_url_for(length: 90),
)
end
end
end
def profile_image(url, length)
Images::Profile.call(url, length: length)
end
end

View file

@ -53,7 +53,7 @@ RSpec.describe "Api::V0::Users", type: :request do
end
expect(response_user["joined_at"]).to eq(user.created_at.strftime("%b %e, %Y"))
expect(response_user["profile_image"]).to eq(Images::Profile.call(user.profile_image_url, length: 320))
expect(response_user["profile_image"]).to eq(user.profile_image_url_for(length: 320))
end
end
@ -84,7 +84,7 @@ RSpec.describe "Api::V0::Users", type: :request do
end
expect(response_user["joined_at"]).to eq(user.created_at.strftime("%b %e, %Y"))
expect(response_user["profile_image"]).to eq(Images::Profile.call(user.profile_image_url, length: 320))
expect(response_user["profile_image"]).to eq(user.profile_image_url_for(length: 320))
end
it "returns 200 if no authentication and the Forem instance is set to private but user is authenticated" do
@ -104,7 +104,7 @@ RSpec.describe "Api::V0::Users", type: :request do
end
expect(response_user["joined_at"]).to eq(user.created_at.strftime("%b %e, %Y"))
expect(response_user["profile_image"]).to eq(Images::Profile.call(user.profile_image_url, length: 320))
expect(response_user["profile_image"]).to eq(user.profile_image_url_for(length: 320))
end
end
end

View file

@ -70,7 +70,7 @@ RSpec.describe "ArticlesShow", type: :request do
"@id" => URL.organization(organization)
},
"url" => URL.organization(organization),
"image" => Images::Profile.call(organization.profile_image_url, length: 320),
"image" => organization.profile_image_url_for(length: 320),
"name" => organization.name,
"description" => organization.summary
},

View file

@ -35,7 +35,7 @@ RSpec.describe "FollowingsController", type: :request do
expect(response_following["name"]).to eq(followed.name)
expect(response_following["path"]).to eq(followed.path)
expect(response_following["username"]).to eq(followed.username)
expect(response_following["profile_image"]).to eq(Images::Profile.call(followed.profile_image_url, length: 60))
expect(response_following["profile_image"]).to eq(followed.profile_image_url_for(length: 60))
end
end
end
@ -111,7 +111,7 @@ RSpec.describe "FollowingsController", type: :request do
expect(response_following["name"]).to eq(followed.name)
expect(response_following["path"]).to eq(followed.path)
expect(response_following["username"]).to eq(followed.username)
expect(response_following["profile_image"]).to eq(Images::Profile.call(followed.profile_image_url, length: 60))
expect(response_following["profile_image"]).to eq(followed.profile_image_url_for(length: 60))
end
end
end
@ -148,7 +148,7 @@ RSpec.describe "FollowingsController", type: :request do
expect(response_following["name"]).to eq(followed.name)
expect(response_following["path"]).to eq("/#{followed.path}")
expect(response_following["username"]).to eq(followed.name)
expect(response_following["profile_image"]).to eq(Images::Profile.call(followed.profile_image_url, length: 60))
expect(response_following["profile_image"]).to eq(followed.profile_image_url_for(length: 60))
end
end
end

View file

@ -35,7 +35,7 @@ RSpec.describe "UserShow", type: :request do
"https://github.com/#{user.github_username}",
"http://example.com",
],
"image" => Images::Profile.call(user.profile_image_url, length: 320),
"image" => user.profile_image_url_for(length: 320),
"name" => user.name,
"email" => user.email,
"description" => user.tag_line,

View file

@ -39,7 +39,7 @@ RSpec.describe "Users", type: :request do
"name" => suggested_user.name,
"username" => suggested_user.username,
"summary" => suggested_user.profile.summary,
"profile_image_url" => Images::Profile.call(suggested_user.profile_image_url, length: 90),
"profile_image_url" => suggested_user.profile_image_url_for(length: 90),
"following" => false,
)
end
@ -87,7 +87,7 @@ RSpec.describe "Users", type: :request do
"name" => suggested_user.name,
"username" => suggested_user.username,
"summary" => suggested_user.profile.summary,
"profile_image_url" => Images::Profile.call(suggested_user.profile_image_url, length: 90),
"profile_image_url" => suggested_user.profile_image_url_for(length: 90),
"following" => false,
)
end

View file

@ -16,7 +16,7 @@ RSpec.describe Search::PodcastEpisodeSerializer do
podcast = described_class.new(pce).serializable_hash.dig(:data, :attributes, :podcast)
expect(podcast.keys).to include(:slug, :image_url, :title)
expect(podcast[:slug]).to eq(pce.podcast_slug)
expect(podcast[:image_url]).to eq(Images::Profile.call(pce.podcast.profile_image_url, length: 90))
expect(podcast[:image_url]).to eq(pce.podcast.profile_image_url_for(length: 90))
expect(podcast[:title]).to eq(pce.title)
end
end

View file

@ -1,7 +1,35 @@
require "rails_helper"
RSpec.describe Images::Profile, type: :services do
describe "#get" do
describe ".for" do
subject(:returned_value) { described_class.for(:work) }
it { is_expected.to be_a(Module) }
context "when mixed in" do
subject(:object) { klass.new.tap { |k| k.the_image_url = "https://forem.com/image" } }
let(:klass) do
Class.new do
attr_accessor :the_image_url
include Images::Profile.for(:the_image_url)
end
end
it "creates a method" do
expect(object).to respond_to(:the_image_url_for)
end
it "forward delegate the method to Images::Profile.call" do
allow(described_class).to receive(:call)
object.the_image_url_for(length: 90)
expect(described_class).to have_received(:call).with(object.the_image_url, length: 90)
end
end
end
describe ".get" do
it "returns user profile_image_url" do
user = build_stubbed(:user)
expect(described_class.call(user.profile_image_url)).to eq(user.profile_image_url)

View file

@ -85,7 +85,7 @@ RSpec.describe Search::PodcastEpisode, type: :service do
expect(podcast[:slug]).to eq(podcast_episode.podcast_slug)
image_url = Images::Profile.call(podcast_episode.podcast.profile_image_url, length: 90)
image_url = podcast_episode.podcast.profile_image_url_for(length: 90)
expect(podcast[:image_url]).to eq(image_url)
expect(podcast[:title]).to eq(podcast_episode.title)