diff --git a/app/models/profile_field.rb b/app/models/profile_field.rb index 623f2760f..0273ede16 100644 --- a/app/models/profile_field.rb +++ b/app/models/profile_field.rb @@ -11,7 +11,8 @@ class ProfileField < ApplicationRecord enum display_area: { header: 0, - left_sidebar: 1 + left_sidebar: 1, + settings_only: 2 } belongs_to :profile_field_group, optional: true diff --git a/app/services/profile_fields/field_definition.rb b/app/services/profile_fields/field_definition.rb index b2dd9b0af..d0a65a12f 100644 --- a/app/services/profile_fields/field_definition.rb +++ b/app/services/profile_fields/field_definition.rb @@ -32,7 +32,7 @@ module ProfileFields end def add_fields - self.class.fields.each { |field| ProfileField.create(field) } + self.class.fields.each { |field| ProfileField.find_or_create_by(field) } end end end diff --git a/app/services/profile_fields/import_from_csv.rb b/app/services/profile_fields/import_from_csv.rb index e8ebbb9d3..10a2aff44 100644 --- a/app/services/profile_fields/import_from_csv.rb +++ b/app/services/profile_fields/import_from_csv.rb @@ -1,6 +1,6 @@ module ProfileFields class ImportFromCsv - HEADERS = %i[label input_type placeholder_text description group].freeze + HEADERS = %i[label input_type placeholder_text description group display_area].freeze def self.call(file) CSV.foreach(file, headers: HEADERS, skip_blanks: true) do |row| diff --git a/lib/data/dev_profile_fields.csv b/lib/data/dev_profile_fields.csv index 6962c6221..731bf29d3 100644 --- a/lib/data/dev_profile_fields.csv +++ b/lib/data/dev_profile_fields.csv @@ -1,29 +1,29 @@ -Display email on profile,check_box,,,Basic -Name,text_field,John Doe,,Basic -Website URL,text_field,https://yoursite.com,,Basic -Summary,text_area,A short bio...,,Basic -Location,text_field,"Halifax, Nova Scotia",,Basic -Facebook URL,text_field,https://facebook.com/...,,Links -Youtube URL,text_field,https://www.youtube.com/channel/...,,Links -StackOverflow URL,text_field,https://stackoverflow.com/users/...,,Links -LinkedIn URL,text_field,https://www.linkedin.com/in/...,,Links -Behance URL,text_field,https://www.behance.net/...,,Links -Dribbble URL,text_field,https://dribbble.com/...,,Links -Medium URL,text_field,https://medium.com/@...,,Links -GitLab URL,text_field,https://gitlab.com/...,,Links -Instagram URL,text_field,https://www.instagram.com/...,,Links -Mastodon URL,text_field,https://...,,Links -Twitch URL,text_field,https://www.twitch.tv/...,,Links -Education,text_field,,,Work -Employer name,text_field,Acme Inc.,,Work -Employer URL,text_field,https://dev.com,,Work -Employment title,text_field,Junior Frontend Engineer,,Work -Looking for work,check_box,,,Work -"Display ""looking for work"" on profile",check_box,,,Work -Recruiters can contact me about job opportunities,check_box,,,Work -Skills/Languages,text_area,,What tools and languages are you most experienced with? Are you specialized or more of a generalist?,Coding -Currently learning,text_area,,"What are you learning right now? What are the new tools and languages you're picking up right now?",Coding -Currently hacking on,text_area,,What projects are currently occupying most of your time?,Coding -Available for,text_area,,"What kinds of collaborations or discussions are you available for? What's a good reason to say Hey! to you these days?",Coding -Brand color 1,color_field,#000000,"Used for backgrounds, borders etc.",Branding -Brand color 2,color_field,#000000,Used for texts (usually put on Brand color 1).,Branding +Display email on profile,check_box,,,Basic,settings_only +Name,text_field,John Doe,,Basic,header +Website URL,text_field,https://yoursite.com,,Basic,header +Summary,text_area,A short bio...,,Basic,header +Location,text_field,"Halifax, Nova Scotia",,Basic,header +Facebook URL,text_field,https://facebook.com/...,,Links,header +Youtube URL,text_field,https://www.youtube.com/channel/...,,Links,header +StackOverflow URL,text_field,https://stackoverflow.com/users/...,,Links,header +LinkedIn URL,text_field,https://www.linkedin.com/in/...,,Links,header +Behance URL,text_field,https://www.behance.net/...,,Links,header +Dribbble URL,text_field,https://dribbble.com/...,,Links,header +Medium URL,text_field,https://medium.com/@...,,Links,header +GitLab URL,text_field,https://gitlab.com/...,,Links,header +Instagram URL,text_field,https://www.instagram.com/...,,Links,header +Mastodon URL,text_field,https://...,,Links,header +Twitch URL,text_field,https://www.twitch.tv/...,,Links,header +Education,text_field,,,Work,header +Employer name,text_field,Acme Inc.,,Work,header +Employer URL,text_field,https://dev.com,,Work,header +Employment title,text_field,Junior Frontend Engineer,,Work,header +Looking for work,check_box,,,Work,settings_only +"Display ""looking for work"" on profile",check_box,,,Work,settings_only +Recruiters can contact me about job opportunities,check_box,,,Work,settings_only +Skills/Languages,text_area,,What tools and languages are you most experienced with? Are you specialized or more of a generalist?,Coding,left_sidebar +Currently learning,text_area,,"What are you learning right now? What are the new tools and languages you're picking up right now?",Coding,left_sidebar +Currently hacking on,text_area,,What projects are currently occupying most of your time?,Coding,left_sidebar +Available for,text_area,,"What kinds of collaborations or discussions are you available for? What's a good reason to say Hey! to you these days?",Coding,left_sidebar +Brand color 1,color_field,#000000,"Used for backgrounds, borders etc.",Branding,settings_only +Brand color 2,color_field,#000000,Used for texts (usually put on Brand color 1).,Branding,settings_only diff --git a/lib/data_update_scripts/20201103050112_prepare_for_profile_column_drop.rb b/lib/data_update_scripts/20201103050112_prepare_for_profile_column_drop.rb new file mode 100644 index 000000000..cccc11fe0 --- /dev/null +++ b/lib/data_update_scripts/20201103050112_prepare_for_profile_column_drop.rb @@ -0,0 +1,19 @@ +module DataUpdateScripts + class PrepareForProfileColumnDrop + def run + # Make sure all current DEV profile fields exist. The import task is + # idempotent so we don't need further checkes here. + dev_fields_csv = Rails.root.join("lib/data/dev_profile_fields.csv") + ProfileFields::ImportFromCsv.call(dev_fields_csv) + + # Make sure all current profile data is migrated before we remove the + # column from User. Also ensure we don't lose any data for custom fields, + # even if these got temporarily disabled by a feature flag. + User.includes(:profile).find_each do |user| + profile = user.profile + user_data = Profiles::ExtractData.call(user) + profile.update(data: profile.data.merge(user_data.compact)) + end + end + end +end diff --git a/lib/tasks/forem.rake b/lib/tasks/forem.rake index 8f6d75e8b..0c5e509c1 100644 --- a/lib/tasks/forem.rake +++ b/lib/tasks/forem.rake @@ -2,8 +2,6 @@ namespace :forem do desc "Performs basic setup for new Forem instances" task setup: :environment do puts "\n== Setting up profile fields ==" - # TODO: [@forem/oss] Remove the destroy_all call - ProfileField.destroy_all ProfileFields::AddBaseFields.call end diff --git a/spec/fixtures/files/profile_fields.csv b/spec/fixtures/files/profile_fields.csv index a309f3197..b0a22c986 100644 --- a/spec/fixtures/files/profile_fields.csv +++ b/spec/fixtures/files/profile_fields.csv @@ -1,4 +1,4 @@ -Name,text_field,John Doe,,Basic -Skills/Languages,text_area,,Programming languages,Coding +Name,text_field,John Doe,,Basic,header +Skills/Languages,text_area,,Programming languages,Coding,left_sidebar -Color,color_field,#000000,"Used for backgrounds, borders etc.",Branding +Color,color_field,#000000,"Used for backgrounds, borders etc.",Branding,settings_only diff --git a/spec/lib/data_update_scripts/prepare_for_profile_column_drop_spec.rb b/spec/lib/data_update_scripts/prepare_for_profile_column_drop_spec.rb new file mode 100644 index 000000000..42aab62b3 --- /dev/null +++ b/spec/lib/data_update_scripts/prepare_for_profile_column_drop_spec.rb @@ -0,0 +1,33 @@ +require "rails_helper" +require Rails.root.join( + "lib/data_update_scripts/20201103050112_prepare_for_profile_column_drop.rb", +) + +describe DataUpdateScripts::PrepareForProfileColumnDrop do + context "when using only DEV profile fields" do + it "migrates data from the user to the profile", :aggregate_failures do + summary = "I hack on profiles a lot" + user = create(:user, summary: summary) + + expect(user.profile).not_to respond_to(:summary) + described_class.new.run + expect(user.profile.reload.summary).to eq(summary) + end + end + + context "when a Forem used additional profile fields" do + let!(:user) { create(:user) } + + before do + create(:profile_field, label: "Doge Test") + Profile.refresh_attributes! + user.profile.update(doge_test: "Such update, much wow!") + end + + it "migrates data and keeps existing data intact", :aggregate_failures do + described_class.new.run + expect(user.profile.reload.data.keys.size).to eq(31) + expect(user.profile.data).to have_key("doge_test") + end + end +end