th-downstream
commit
ea8802a05a
@ -0,0 +1,21 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class Api::V1::Instances::LanguagesController < Api::BaseController
|
||||||
|
skip_before_action :require_authenticated_user!, unless: :limited_federation_mode?
|
||||||
|
skip_around_action :set_locale
|
||||||
|
|
||||||
|
before_action :set_languages
|
||||||
|
|
||||||
|
vary_by ''
|
||||||
|
|
||||||
|
def show
|
||||||
|
cache_even_if_authenticated!
|
||||||
|
render json: @languages, each_serializer: REST::LanguageSerializer
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def set_languages
|
||||||
|
@languages = LanguagesHelper::SUPPORTED_LOCALES.keys.map { |code| LanguagePresenter.new(code) }
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class LanguagePresenter < ActiveModelSerializers::Model
|
||||||
|
attributes :code, :name, :native_name
|
||||||
|
|
||||||
|
def initialize(code)
|
||||||
|
super()
|
||||||
|
|
||||||
|
@code = code
|
||||||
|
@item = LanguagesHelper::SUPPORTED_LOCALES[code]
|
||||||
|
end
|
||||||
|
|
||||||
|
def name
|
||||||
|
@item[0]
|
||||||
|
end
|
||||||
|
|
||||||
|
def native_name
|
||||||
|
@item[1]
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,5 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class REST::LanguageSerializer < ActiveModel::Serializer
|
||||||
|
attributes :code, :name
|
||||||
|
end
|
@ -0,0 +1,39 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddUniqueIndexOnPreviewCardsStatuses < ActiveRecord::Migration[6.1]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_index :preview_cards_statuses, [:status_id, :preview_card_id], name: :preview_cards_statuses_pkey, algorithm: :concurrently, unique: true
|
||||||
|
rescue ActiveRecord::RecordNotUnique
|
||||||
|
deduplicate_and_reindex!
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_index :preview_cards_statuses, name: :preview_cards_statuses_pkey
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def deduplicate_and_reindex!
|
||||||
|
deduplicate_preview_cards!
|
||||||
|
|
||||||
|
safety_assured { execute 'REINDEX INDEX preview_cards_statuses_pkey' }
|
||||||
|
rescue ActiveRecord::RecordNotUnique
|
||||||
|
retry
|
||||||
|
end
|
||||||
|
|
||||||
|
def deduplicate_preview_cards!
|
||||||
|
# Statuses should have only one preview card at most, even if that's not the database
|
||||||
|
# constraint we will end up with
|
||||||
|
duplicate_ids = select_all('SELECT status_id FROM preview_cards_statuses GROUP BY status_id HAVING count(*) > 1;').rows
|
||||||
|
|
||||||
|
duplicate_ids.each_slice(1000) do |ids|
|
||||||
|
# This one is tricky: since we don't have primary keys to keep only one record,
|
||||||
|
# use the physical `ctid`
|
||||||
|
safety_assured do
|
||||||
|
execute "DELETE FROM preview_cards_statuses p WHERE p.status_id IN (#{ids.join(', ')}) AND p.ctid NOT IN (SELECT q.ctid FROM preview_cards_statuses q WHERE q.status_id = p.status_id LIMIT 1)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,20 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddPrimaryKeyToPreviewCardsStatusesJoinTable < ActiveRecord::Migration[6.1]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
safety_assured do
|
||||||
|
execute 'ALTER TABLE preview_cards_statuses ADD PRIMARY KEY USING INDEX preview_cards_statuses_pkey'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
safety_assured do
|
||||||
|
# I have found no way to demote the primary key to an index, instead, re-create the index
|
||||||
|
execute 'CREATE UNIQUE INDEX CONCURRENTLY preview_cards_statuses_pkey_tmp ON preview_cards_statuses (status_id, preview_card_id)'
|
||||||
|
execute 'ALTER TABLE preview_cards_statuses DROP CONSTRAINT preview_cards_statuses_pkey'
|
||||||
|
execute 'ALTER INDEX preview_cards_statuses_pkey_tmp RENAME TO preview_cards_statuses_pkey'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -0,0 +1,19 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
RSpec.describe 'Languages' do
|
||||||
|
describe 'GET /api/v1/instance/languages' do
|
||||||
|
before do
|
||||||
|
get '/api/v1/instance/languages'
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns http success' do
|
||||||
|
expect(response).to have_http_status(200)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'returns the supported languages' do
|
||||||
|
expect(body_as_json.pluck(:code)).to match_array LanguagesHelper::SUPPORTED_LOCALES.keys.map(&:to_s)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in new issue