diff --git a/app/controllers/services_controller.rb b/app/controllers/services_controller.rb index 5e6823a2..72032d39 100644 --- a/app/controllers/services_controller.rb +++ b/app/controllers/services_controller.rb @@ -28,6 +28,17 @@ class ServicesController < ApplicationController end end + def update + service = current_user.services.find(params[:id]) + service.post_tag = params[:service][:post_tag].tr('@', '') + if service.save + flash[:success] = "Service updated successfully" + else + flash[:error] = "Failed to update service" + end + redirect_to services_path + end + def failure Rails.logger.info "oauth error: #{params.inspect}" flash[:error] = t('flash.service.failure') diff --git a/app/helpers/social_helper/twitter_methods.rb b/app/helpers/social_helper/twitter_methods.rb index 03a473e8..ce0b605d 100644 --- a/app/helpers/social_helper/twitter_methods.rb +++ b/app/helpers/social_helper/twitter_methods.rb @@ -3,7 +3,7 @@ require 'cgi' module SocialHelper::TwitterMethods include MarkdownHelper - def prepare_tweet(answer) + def prepare_tweet(answer, post_tag = nil) question_content = twitter_markdown answer.question.content.gsub(/\@(\w+)/, '\1') original_question_length = question_content.length answer_content = twitter_markdown answer.content @@ -19,8 +19,16 @@ module SocialHelper::TwitterMethods tweet_text = "" until parsed_tweet[:valid] - tweet_text = "#{question_content[0..122]}#{'…' if original_question_length > [123, question_content.length].min}" \ - " — #{answer_content[0..123]}#{'…' if original_answer_length > [124, answer_content.length].min} #{answer_url}" + shortened_question = "#{question_content[0..122]}#{'…' if original_question_length > [123, question_content.length].min}" + shortened_answer = "#{answer_content[0..123]}#{'…' if original_answer_length > [124, answer_content.length].min}" + components = [ + shortened_question, + '—', + shortened_answer, + post_tag, + answer_url + ] + tweet_text = components.compact.join(' ') parsed_tweet = Twitter::TwitterText::Validation::parse_tweet(tweet_text) diff --git a/app/models/service.rb b/app/models/service.rb index 46bd234a..7cdf4524 100644 --- a/app/models/service.rb +++ b/app/models/service.rb @@ -3,6 +3,7 @@ class Service < ApplicationRecord belongs_to :user validates_uniqueness_of :uid, scope: :type + validates_length_of :post_tag, maximum: 20 class << self diff --git a/app/models/services/twitter.rb b/app/models/services/twitter.rb index 53ae7b2a..388c316d 100644 --- a/app/models/services/twitter.rb +++ b/app/models/services/twitter.rb @@ -23,6 +23,6 @@ class Services::Twitter < Service end def post_tweet(answer) - client.update! prepare_tweet(answer) + client.update! prepare_tweet(answer, self.post_tag) end end diff --git a/app/views/settings/_services.haml b/app/views/settings/_services.haml index ebec715c..24087517 100644 --- a/app/views/settings/_services.haml +++ b/app/views/settings/_services.haml @@ -20,3 +20,9 @@ service_path(service), data: { confirm: t('views.settings.service.confirm', service: service.provider.capitalize) }, method: :delete + + .col-md-6.mt-2 + = bootstrap_form_for(service, as: 'service', url: update_service_path(service)) do |f| + = f.text_field :post_tag, class: 'form-control', label: 'tag', label_as_placeholder: true, + append: f.submit('Update', class: 'btn btn-primary'), maxlength: 20, pattern: '^[^@]*$', + help: "Automatically append a tag to your shared answers. #{'A # symbol is not automatically prepended.' if service.provider == 'twitter'}" diff --git a/config/routes.rb b/config/routes.rb index 6ff41bee..5bb7241e 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -77,6 +77,7 @@ Rails.application.routes.draw do # resources :services, only: [:index, :destroy] match '/settings/services', to: 'services#index', via: 'get', as: :services + match '/settings/services/:id', to: 'services#update', via: 'patch', as: :update_service match '/settings/services/:id', to: 'services#destroy', via: 'delete', as: :service controller :services do scope "/auth", as: "auth" do diff --git a/db/migrate/20220104180510_add_post_tag_to_services.rb b/db/migrate/20220104180510_add_post_tag_to_services.rb new file mode 100644 index 00000000..ab09c201 --- /dev/null +++ b/db/migrate/20220104180510_add_post_tag_to_services.rb @@ -0,0 +1,5 @@ +class AddPostTagToServices < ActiveRecord::Migration[5.2] + def change + add_column :services, :post_tag, :string, limit: 20 + end +end diff --git a/db/schema.rb b/db/schema.rb index 0e3d2915..525becf1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -192,6 +192,7 @@ ActiveRecord::Schema.define(version: 2022_01_05_171216) do t.string "nickname" t.datetime "created_at" t.datetime "updated_at" + t.string "post_tag", limit: 20 t.index ["user_id"], name: "index_services_on_user_id" end diff --git a/spec/controllers/services_controller_spec.rb b/spec/controllers/services_controller_spec.rb index 112e97e1..13f8b04c 100644 --- a/spec/controllers/services_controller_spec.rb +++ b/spec/controllers/services_controller_spec.rb @@ -38,4 +38,45 @@ describe ServicesController, type: :controller do end end end + + context '#update' do + subject { patch :update, params: params } + + context 'not signed in' do + let(:params) { { id: 1 } } + + it 'redirects to sign in page' do + subject + expect(response).to redirect_to(new_user_session_path) + end + end + + context 'user with Twitter connection' do + before { sign_in user } + + let(:user) { FactoryBot.create(:user) } + let(:service) { Services::Twitter.create(user: user, uid: 12) } + let(:params) { { id: service.id, service: { post_tag: post_tag } } } + + context 'tag is valid' do + let(:post_tag) { '#askaraccoon' } + + it 'updates a service connection' do + expect { subject }.to change { service.reload.post_tag }.to('#askaraccoon') + expect(response).to redirect_to(services_path) + expect(flash[:success]).to eq("Service updated successfully") + end + end + + context 'tag is too long' do + let(:post_tag) { 'a' * 21 } # 1 character over the limit + + it 'shows an error' do + subject + expect(response).to redirect_to(services_path) + expect(flash[:error]).to eq("Failed to update service") + end + end + end + end end diff --git a/spec/helpers/social_helper/twitter_methods_spec.rb b/spec/helpers/social_helper/twitter_methods_spec.rb index 7a2e8afe..71a5eb60 100644 --- a/spec/helpers/social_helper/twitter_methods_spec.rb +++ b/spec/helpers/social_helper/twitter_methods_spec.rb @@ -4,9 +4,11 @@ require 'rails_helper' describe SocialHelper::TwitterMethods, :type => :helper do let(:user) { FactoryBot.create(:user) } + let(:question_content) { 'q' * 255 } + let(:answer_content) { 'a' * 255 } let(:answer) { FactoryBot.create(:answer, user: user, - content: 'a' * 255, - question_content: 'q' * 255) } + content: answer_content, + question_content: question_content) } before do stub_const("APP_CONFIG", { @@ -25,6 +27,25 @@ describe SocialHelper::TwitterMethods, :type => :helper do end end + context 'when a suffix has been passed' do + let(:question_content) { 'question' } + let(:answer_content) { 'answer' } + + subject { prepare_tweet(answer, '#askracc') } + + it 'should include the suffix after the link' do + expect(subject).to eq("question — answer #askracc https://example.com/#{user.screen_name}/a/#{answer.id}") + end + end + + context 'when a suffix has been passed and the tweet needs to be shortened' do + subject { prepare_tweet(answer, '#askracc') } + + it 'should shorten the tweet while keeping the suffix intact' do + expect(subject).to eq("#{'q' * 120}… — #{'a' * 120}… #askracc https://example.com/#{user.screen_name}/a/#{answer.id}") + end + end + context 'when the question and answer are short' do before do answer.question.content = 'Why are raccoons so good?'