mirror of
https://github.com/Retrospring/retrospring.git
synced 2025-02-13 21:33:20 +01:00
Merge pull request #185 from Retrospring/feature/opengraph
Add OpenGraph metadata on user profiles and answers
This commit is contained in:
commit
1cf2733b69
7 changed files with 160 additions and 4 deletions
|
@ -1,4 +1,6 @@
|
|||
module ApplicationHelper
|
||||
include ApplicationHelper::GraphMethods
|
||||
|
||||
def nav_entry(body, path, options = {})
|
||||
options = {
|
||||
badge: nil,
|
||||
|
|
59
app/helpers/application_helper/graph_methods.rb
Normal file
59
app/helpers/application_helper/graph_methods.rb
Normal file
|
@ -0,0 +1,59 @@
|
|||
module ApplicationHelper::GraphMethods
|
||||
# Creates <meta> tags for OpenGraph properties from a hash
|
||||
# @param values [Hash]
|
||||
def opengraph_meta_tags(values)
|
||||
values.map { |name, content| tag(:meta, property: name, content: content) }.join("\n").html_safe
|
||||
end
|
||||
|
||||
# Creates <meta> tags from a hash
|
||||
# @param values [Hash]
|
||||
def meta_tags(values)
|
||||
values.map { |name, content| tag(:meta, name: name, content: content) }.join("\n").html_safe
|
||||
end
|
||||
|
||||
# @param user [User]
|
||||
def user_opengraph(user)
|
||||
opengraph_meta_tags({
|
||||
'og:title': user.safe_name,
|
||||
'og:type': 'profile',
|
||||
'og:image': full_profile_picture_url(user),
|
||||
'og:url': show_user_profile_url(user.screen_name),
|
||||
'og:description': user.bio,
|
||||
'og:site_name': APP_CONFIG['site_name'],
|
||||
'profile:username': user.screen_name
|
||||
})
|
||||
end
|
||||
|
||||
# @param user [User]
|
||||
def user_twitter_card(user)
|
||||
meta_tags({
|
||||
'twitter:card': 'summary',
|
||||
'twitter:site': '@retrospring',
|
||||
'twitter:title': user.motivation_header.presence || "Ask me anything!",
|
||||
'twitter:description': "Ask #{user.safe_name} anything on Retrospring",
|
||||
'twitter:image': full_profile_picture_url(user)
|
||||
})
|
||||
end
|
||||
|
||||
# @param answer [Answer]
|
||||
def answer_opengraph(answer)
|
||||
opengraph_meta_tags({
|
||||
'og:title': "#{answer.user.safe_name} answered: #{answer.question.content}",
|
||||
'og:type': 'article',
|
||||
'og:image': full_profile_picture_url(answer.user),
|
||||
'og:url': show_user_answer_url(answer.user.screen_name, answer.id),
|
||||
'og:description': answer.content,
|
||||
'og:site_name': APP_CONFIG['site_name']
|
||||
})
|
||||
end
|
||||
|
||||
def full_profile_picture_url(user)
|
||||
# @type [String]
|
||||
profile_picture_url = user.profile_picture.url(:large)
|
||||
if profile_picture_url.start_with? '/'
|
||||
"#{root_url}#{profile_picture_url[1..-1]}"
|
||||
else
|
||||
profile_picture_url
|
||||
end
|
||||
end
|
||||
end
|
|
@ -253,6 +253,10 @@ class User < ApplicationRecord
|
|||
!self.export_processing
|
||||
end
|
||||
|
||||
def safe_name
|
||||
self.display_name.presence || self.screen_name
|
||||
end
|
||||
|
||||
# %w[admin moderator].each do |m|
|
||||
# define_method(m) { raise "not allowed: #{m}" }
|
||||
# define_method(m+??) { raise "not allowed: #{m}?"}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
- provide(:title, answer_title(@answer))
|
||||
- provide(:og, answer_opengraph(@answer))
|
||||
.container.container--main
|
||||
= render 'answerbox', a: @answer, display_all: @display_all
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
!!! 5
|
||||
%html{ lang: 'en' }
|
||||
%html{ lang: 'en', prefix: 'og: https://ogp.me/ns#' }
|
||||
%head
|
||||
%meta{ charset: 'utf-8' }
|
||||
%meta{ 'http-equiv': 'X-UA-Compatible', content: 'IE=edge' }
|
||||
|
@ -17,6 +17,8 @@
|
|||
- if user_signed_in? && current_user.mod?
|
||||
= javascript_pack_tag 'legacy-moderation', data: { 'turbolinks-track': 'reload' }
|
||||
= csrf_meta_tags
|
||||
= yield(:og)
|
||||
= yield(:meta)
|
||||
%body
|
||||
- if user_signed_in?
|
||||
= render 'navigation/main'
|
||||
|
|
|
@ -10,5 +10,8 @@
|
|||
%button.btn.btn-light#load-more-btn{ type: :button, data: { last_id: @answers_last_id } }
|
||||
= t 'views.actions.load'
|
||||
|
||||
- provide(:title, user_title(@user))
|
||||
- parent_layout 'user/profile'
|
||||
:ruby
|
||||
provide(:title, user_title(@user))
|
||||
provide(:og, user_opengraph(@user))
|
||||
provide(:meta, user_twitter_card(@user))
|
||||
parent_layout 'user/profile'
|
||||
|
|
|
@ -3,6 +3,91 @@
|
|||
require "rails_helper"
|
||||
|
||||
describe ApplicationHelper, :type => :helper do
|
||||
describe "#bootstrap_color" do
|
||||
it 'should map error and alert to danger' do
|
||||
expect(bootstrap_color("error")).to eq("danger")
|
||||
expect(bootstrap_color("alert")).to eq("danger")
|
||||
end
|
||||
|
||||
it 'should map notice to info' do
|
||||
expect(bootstrap_color("notice")).to eq("info")
|
||||
end
|
||||
|
||||
it 'should return any uncovered value' do
|
||||
expect(bootstrap_color("success")).to eq("success")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#user_opengraph" do
|
||||
context "sample user" do
|
||||
let(:user) { FactoryBot.create(:user,
|
||||
display_name: 'Cunes',
|
||||
bio: 'A bunch of raccoons in a trenchcoat.',
|
||||
screen_name: 'raccoons') }
|
||||
|
||||
subject { user_opengraph(user) }
|
||||
|
||||
it 'should generate a matching OpenGraph structure for a user' do
|
||||
allow(APP_CONFIG).to receive(:[]).with('site_name').and_return('pineapplespring')
|
||||
expect(subject).to eq(<<-EOS.chomp)
|
||||
<meta property="og:title" content="Cunes" />
|
||||
<meta property="og:type" content="profile" />
|
||||
<meta property="og:image" content="http://test.host/images/large/no_avatar.png" />
|
||||
<meta property="og:url" content="http://test.host/raccoons" />
|
||||
<meta property="og:description" content="A bunch of raccoons in a trenchcoat." />
|
||||
<meta property="og:site_name" content="pineapplespring" />
|
||||
<meta property="profile:username" content="raccoons" />
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#user_twitter_card" do
|
||||
context "sample user" do
|
||||
let(:user) { FactoryBot.create(:user,
|
||||
display_name: '',
|
||||
bio: 'A bunch of raccoons in a trenchcoat.',
|
||||
screen_name: 'raccoons') }
|
||||
|
||||
subject { user_twitter_card(user) }
|
||||
|
||||
it 'should generate a matching OpenGraph structure for a user' do
|
||||
expect(subject).to eq(<<-EOS.chomp)
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<meta name="twitter:site" content="@retrospring" />
|
||||
<meta name="twitter:title" content="Ask me anything!" />
|
||||
<meta name="twitter:description" content="Ask raccoons anything on Retrospring" />
|
||||
<meta name="twitter:image" content="http://test.host/images/large/no_avatar.png" />
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#answer_opengraph" do
|
||||
context "sample user and answer" do
|
||||
let!(:user) { FactoryBot.create(:user,
|
||||
display_name: '',
|
||||
bio: 'A bunch of raccoons in a trenchcoat.',
|
||||
screen_name: 'raccoons') }
|
||||
let(:answer) { FactoryBot.create(:answer,
|
||||
user_id: user.id,) }
|
||||
|
||||
subject { answer_opengraph(answer) }
|
||||
|
||||
it 'should generate a matching OpenGraph structure for a user' do
|
||||
allow(APP_CONFIG).to receive(:[]).with('site_name').and_return('pineapplespring')
|
||||
expect(subject).to eq(<<-EOS.chomp)
|
||||
<meta property="og:title" content="raccoons answered: #{answer.question.content}" />
|
||||
<meta property="og:type" content="article" />
|
||||
<meta property="og:image" content="http://test.host/images/large/no_avatar.png" />
|
||||
<meta property="og:url" content="http://test.host/raccoons/a/#{answer.id}" />
|
||||
<meta property="og:description" content="#{answer.content}" />
|
||||
<meta property="og:site_name" content="pineapplespring" />
|
||||
EOS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "#rails_admin_path_for_resource" do
|
||||
context "user resource" do
|
||||
let(:resource) { FactoryBot.create(:user) }
|
||||
|
@ -13,4 +98,4 @@ describe ApplicationHelper, :type => :helper do
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue