Skip to content

Commit 794c759

Browse files
committed
Social media profiles to conferences
1 parent 2125bb3 commit 794c759

12 files changed

+127
-28
lines changed

app/avo/resources/event.rb

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ class Avo::Resources::Event < Avo::BaseResource
77
if id.is_a?(Array)
88
query.where(slug: id)
99
else
10-
query.find_by(slug: id)
10+
query.find_by(slug: id) || query.find_by(id:)
1111
end
1212
}
1313
self.external_link = -> {
@@ -27,6 +27,7 @@ def fields
2727
field :talks, as: :has_many
2828
field :speakers, as: :has_many, through: :talks
2929
field :topics, as: :has_many
30+
field :social_profiles, as: :has_many, use_resource: "Avo::Resources::SocialProfile"
3031
end
3132

3233
def actions

app/avo/resources/social_profile.rb

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Avo::Resources::SocialProfile < Avo::BaseResource
2+
def fields
3+
field :id, as: :id
4+
field :provider, enum: ::SocialProfile.providers, as: :select, required: true
5+
field :value, as: :text
6+
field :sociable, as: :belongs_to, polymorphic_as: :sociable, types: [::Speaker, ::Event], foreign_key: :slug
7+
end
8+
end

app/avo/resources/speaker.rb

+2-8
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ class Avo::Resources::Speaker < Avo::BaseResource
44
if id.is_a?(Array)
55
query.where(slug: id)
66
else
7-
query.find_by(slug: id)
7+
query.find_by(slug: id) || query.find_by(id:)
88
end
99
}
1010
self.search = {
@@ -17,19 +17,13 @@ class Avo::Resources::Speaker < Avo::BaseResource
1717
def fields
1818
field :id, as: :id, link_to_record: true
1919
field :name, as: :text, link_to_record: true, sortable: true
20-
field :twitter, as: :text
21-
field :github, as: :text
22-
field :speakerdeck, as: :text
23-
field :mastodon, as: :text, hide_on: :index
24-
field :linkedin, as: :text, hide_on: :index
25-
field :bsky, as: :text, hide_on: :index
2620
field :bio, as: :textarea, hide_on: :index
27-
field :website, as: :text, hide_on: :index
2821
field :slug, as: :text, hide_on: :index
2922
field :talks_count, as: :number, sortable: true
3023
field :canonical, as: :belongs_to, hide_on: :index
3124
# field :suggestions, as: :has_many
3225
# field :speaker_talks, as: :has_many
26+
field :social_profiles, as: :has_many, use_resource: "Avo::Resources::SocialProfile"
3327
field :talks, as: :has_many, use_resource: "Avo::Resources::Talk", attach_scope: -> { query.order(title: :asc) }, searchable: true
3428
end
3529

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# This controller has been generated to enable Rails' resource routes.
2+
# More information on https://docs.avohq.io/3.0/controllers.html
3+
class Avo::SocialProfilesController < Avo::ResourcesController
4+
end

app/models/concerns/sociable.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
module Sociable
2+
extend ActiveSupport::Concern
3+
4+
included do
5+
has_many :social_profiles, as: :sociable, dependent: :destroy
6+
end
7+
end

app/models/event.rb

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
class Event < ApplicationRecord
3333
include Suggestable
3434
include Sluggable
35+
include Sociable
3536
slug_from :name
3637

3738
# associations

app/models/social_profile.rb

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# == Schema Information
2+
#
3+
# Table name: social_profiles
4+
#
5+
# id :integer not null, primary key
6+
# provider :integer
7+
# sociable_type :string indexed => [sociable_id]
8+
# value :string
9+
# created_at :datetime not null
10+
# updated_at :datetime not null
11+
# sociable_id :integer indexed => [sociable_type]
12+
#
13+
# Indexes
14+
#
15+
# index_social_profiles_on_sociable (sociable_type,sociable_id)
16+
#
17+
class SocialProfile < ApplicationRecord
18+
belongs_to :sociable, polymorphic: true
19+
20+
enum :provider, {
21+
github: 0,
22+
twitter: 1,
23+
linkedin: 2,
24+
bsky: 3,
25+
mastadon: 4
26+
},
27+
suffix: true,
28+
validate: {presence: true}
29+
30+
before_save do
31+
self.value = self.class.normalize_value_for(provider.to_sym, value)
32+
end
33+
34+
# normalizes
35+
normalizes :github, with: ->(value) { value.gsub(/^(?:https?:\/\/)?(?:www\.)?github\.com\//, "").gsub(/^@/, "") }
36+
normalizes :twitter, with: ->(value) { value.gsub(%r{https?://(?:www\.)?(?:x\.com|twitter\.com)/}, "").gsub(/@/, "") }
37+
normalizes :linkedin, with: ->(value) { value.gsub(%r{https?://(?:www\.)?(?:linkedin\.com/in)/}, "") }
38+
normalizes :bsky, with: ->(value) { value.gsub(%r{https?://(?:www\.)?(?:[^\/]+\.com)/}, "").gsub(/@/, "") }
39+
normalizes :mastodon, with: ->(value) {
40+
return value if value&.match?(URI::DEFAULT_PARSER.make_regexp)
41+
return "" unless value.count("@") == 2
42+
43+
_, handle, instance = value.split("@")
44+
45+
"https://#{instance}/@#{handle}"
46+
}
47+
end

app/models/speaker.rb

+1-18
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class Speaker < ApplicationRecord
3838
include ActionView::RecordIdentifier
3939
include Sluggable
4040
include Suggestable
41+
include Sociable
4142
include Speaker::Searchable
4243
slug_from :name
4344

@@ -72,24 +73,6 @@ class Speaker < ApplicationRecord
7273
scope :canonical, -> { where(canonical_id: nil) }
7374
scope :not_canonical, -> { where.not(canonical_id: nil) }
7475

75-
# normalizes
76-
normalizes :github, with: ->(value) { value.gsub(/^(?:https?:\/\/)?(?:www\.)?github\.com\//, "").gsub(/^@/, "") }
77-
normalizes :twitter, with: ->(value) { value.gsub(%r{https?://(?:www\.)?(?:x\.com|twitter\.com)/}, "").gsub(/@/, "") }
78-
normalizes :bsky, with: ->(value) {
79-
value.gsub(%r{https?://(?:www\.)?(?:x\.com|bsky\.app/profile)/}, "").gsub(/@/, "")
80-
}
81-
normalizes :linkedin, with: ->(value) { value.gsub(%r{https?://(?:www\.)?(?:linkedin\.com/in)/}, "") }
82-
normalizes :bsky, with: ->(value) { value.gsub(%r{https?://(?:www\.)?(?:[^\/]+\.com)/}, "").gsub(/@/, "") }
83-
84-
normalizes :mastodon, with: ->(value) {
85-
return value if value&.match?(URI::DEFAULT_PARSER.make_regexp)
86-
return "" unless value.count("@") == 2
87-
88-
_, handle, instance = value.split("@")
89-
90-
"https://#{instance}/@#{handle}"
91-
}
92-
9376
def title
9477
name
9578
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class CreateSocialProfiles < ActiveRecord::Migration[8.0]
2+
def change
3+
create_table :social_profiles do |t|
4+
t.string :value
5+
t.integer :provider
6+
t.belongs_to :sociable, polymorphic: true
7+
t.timestamps
8+
end
9+
end
10+
end

db/schema.rb

+11-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/fixtures/social_profiles.yml

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html
2+
3+
# This model initially had no columns defined. If you add columns to the
4+
# model remove the "{}" from the fixture names and add the columns immediately
5+
# below each fixture, per the syntax in the comments below
6+
#
7+
# == Schema Information
8+
#
9+
# Table name: social_profiles
10+
#
11+
# id :integer not null, primary key
12+
# provider :integer
13+
# sociable_type :string indexed => [sociable_id]
14+
# value :string
15+
# created_at :datetime not null
16+
# updated_at :datetime not null
17+
# sociable_id :integer indexed => [sociable_type]
18+
#
19+
# Indexes
20+
#
21+
# index_social_profiles_on_sociable (sociable_type,sociable_id)
22+
#
23+
one: {}
24+
# column: value
25+
#
26+
two: {}
27+
# column: value

test/models/social_profile_test.rb

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require "test_helper"
2+
3+
class SocialProfileTest < ActiveSupport::TestCase
4+
# test "the truth" do
5+
# assert true
6+
# end
7+
end

0 commit comments

Comments
 (0)