Skip to content
Snippets Groups Projects
Verified Commit ea5f1015 authored by Markus Koller's avatar Markus Koller Committed by Philip Cunningham
Browse files

Move data fields models to Integrations namespace

This moves the `*TrackerData` models into the `Integrations::` namespace
as part of #201855.

We also rename the related concerns to clarify their intent:

`app/models/concerns/services/data_fields.rb`:

- Renamed from `Services::DataFields` to `Integrations::BaseDataFields`.
- This is included in the models and acts as a sort of base class.
- It's still a module because converting it into an actual class
  changes some of the automatic Rails behaviour (such as inferring
  the table name).

`app/models/project_services/data_fields.rb`:

- Renamed from `DataFields` to `Integrations::HasDataFields`.
- This is included in the main `Integration` model and provides some
  helpers to access the associated data fields records.

Both of these are moved into `app/models/concerns/integrations`.
parent 9bbc6132
No related branches found
No related tags found
No related merge requests found
Showing
with 120 additions and 113 deletions
......@@ -1650,14 +1650,11 @@ Gitlab/NamespacedClass:
- 'app/models/project_services/chat_notification_service.rb'
- 'app/models/project_services/discord_service.rb'
- 'app/models/project_services/hangouts_chat_service.rb'
- 'app/models/project_services/issue_tracker_data.rb'
- 'app/models/project_services/jira_tracker_data.rb'
- 'app/models/project_services/mattermost_service.rb'
- 'app/models/project_services/mattermost_slash_commands_service.rb'
- 'app/models/project_services/microsoft_teams_service.rb'
- 'app/models/project_services/mock_monitoring_service.rb'
- 'app/models/project_services/monitoring_service.rb'
- 'app/models/project_services/open_project_tracker_data.rb'
- 'app/models/project_services/prometheus_service.rb'
- 'app/models/project_services/pushover_service.rb'
- 'app/models/project_services/slack_service.rb'
......@@ -2675,8 +2672,8 @@ Gitlab/DelegatePredicateMethods:
- 'app/models/clusters/platforms/kubernetes.rb'
- 'app/models/concerns/ci/metadatable.rb'
- 'app/models/concerns/diff_positionable_note.rb'
- 'app/models/concerns/integrations/base_data_fields.rb'
- 'app/models/concerns/resolvable_discussion.rb'
- 'app/models/concerns/services/data_fields.rb'
- 'app/models/project.rb'
- 'ee/app/models/concerns/ee/ci/metadatable.rb'
- 'ee/app/models/ee/group.rb'
......
# frozen_string_literal: true
module Services
module DataFields
module Integrations
module BaseDataFields
extend ActiveSupport::Concern
included do
belongs_to :integration, inverse_of: self.name.underscore.to_sym, foreign_key: :service_id
# TODO: Once we rename the tables we can't rely on `table_name` anymore.
# https://gitlab.com/gitlab-org/gitlab/-/issues/331953
belongs_to :integration, inverse_of: self.table_name.to_sym, foreign_key: :service_id
delegate :activated?, to: :integration, allow_nil: true
......
# frozen_string_literal: true
module Integrations
module HasDataFields
extend ActiveSupport::Concern
class_methods do
# Provide convenient accessor methods for data fields.
# TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
def data_field(*args)
args.each do |arg|
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
unless method_defined?(arg)
def #{arg}
data_fields.send('#{arg}') || (properties && properties['#{arg}'])
end
end
def #{arg}=(value)
@old_data_fields ||= {}
@old_data_fields['#{arg}'] ||= #{arg} # set only on the first assignment, IOW we remember the original value only
data_fields.send('#{arg}=', value)
end
def #{arg}_touched?
@old_data_fields ||= {}
@old_data_fields.has_key?('#{arg}')
end
def #{arg}_changed?
#{arg}_touched? && @old_data_fields['#{arg}'] != #{arg}
end
def #{arg}_was
return unless #{arg}_touched?
return if data_fields.persisted? # arg_was does not work for attr_encrypted
legacy_properties_data['#{arg}']
end
RUBY
end
end
end
included do
has_one :issue_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::IssueTrackerData'
has_one :jira_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::JiraTrackerData'
has_one :open_project_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id, class_name: 'Integrations::OpenProjectTrackerData'
def data_fields
raise NotImplementedError
end
def data_fields_present?
data_fields.present?
rescue NotImplementedError
false
end
end
end
end
......@@ -6,7 +6,7 @@ class Integration < ApplicationRecord
include Sortable
include Importable
include ProjectServicesLoggable
include DataFields
include Integrations::HasDataFields
include FromUnion
include EachBatch
......
# frozen_string_literal: true
module Integrations
class IssueTrackerData < ApplicationRecord
include BaseDataFields
attr_encrypted :project_url, encryption_options
attr_encrypted :issues_url, encryption_options
attr_encrypted :new_issue_url, encryption_options
end
end
# frozen_string_literal: true
module Integrations
class JiraTrackerData < ApplicationRecord
include BaseDataFields
attr_encrypted :url, encryption_options
attr_encrypted :api_url, encryption_options
attr_encrypted :username, encryption_options
attr_encrypted :password, encryption_options
enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
end
end
# frozen_string_literal: true
module Integrations
class OpenProjectTrackerData < ApplicationRecord
include BaseDataFields
# When the Open Project is fresh installed, the default closed status id is "13" based on current version: v8.
DEFAULT_CLOSED_STATUS_ID = "13"
attr_encrypted :url, encryption_options
attr_encrypted :api_url, encryption_options
attr_encrypted :token, encryption_options
def closed_status_id
super || DEFAULT_CLOSED_STATUS_ID
end
end
end
# frozen_string_literal: true
module DataFields
extend ActiveSupport::Concern
class_methods do
# Provide convenient accessor methods for data fields.
# TODO: Simplify as part of https://gitlab.com/gitlab-org/gitlab/issues/29404
def data_field(*args)
args.each do |arg|
self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
unless method_defined?(arg)
def #{arg}
data_fields.send('#{arg}') || (properties && properties['#{arg}'])
end
end
def #{arg}=(value)
@old_data_fields ||= {}
@old_data_fields['#{arg}'] ||= #{arg} # set only on the first assignment, IOW we remember the original value only
data_fields.send('#{arg}=', value)
end
def #{arg}_touched?
@old_data_fields ||= {}
@old_data_fields.has_key?('#{arg}')
end
def #{arg}_changed?
#{arg}_touched? && @old_data_fields['#{arg}'] != #{arg}
end
def #{arg}_was
return unless #{arg}_touched?
return if data_fields.persisted? # arg_was does not work for attr_encrypted
legacy_properties_data['#{arg}']
end
RUBY
end
end
end
included do
has_one :issue_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id
has_one :jira_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id
has_one :open_project_tracker_data, autosave: true, inverse_of: :integration, foreign_key: :service_id
def data_fields
raise NotImplementedError
end
def data_fields_present?
data_fields.present?
rescue NotImplementedError
false
end
end
end
# frozen_string_literal: true
class IssueTrackerData < ApplicationRecord
include Services::DataFields
attr_encrypted :project_url, encryption_options
attr_encrypted :issues_url, encryption_options
attr_encrypted :new_issue_url, encryption_options
end
# frozen_string_literal: true
class JiraTrackerData < ApplicationRecord
include Services::DataFields
attr_encrypted :url, encryption_options
attr_encrypted :api_url, encryption_options
attr_encrypted :username, encryption_options
attr_encrypted :password, encryption_options
enum deployment_type: { unknown: 0, server: 1, cloud: 2 }, _prefix: :deployment
end
# frozen_string_literal: true
class OpenProjectTrackerData < ApplicationRecord
include Services::DataFields
# When the Open Project is fresh installed, the default closed status id is "13" based on current version: v8.
DEFAULT_CLOSED_STATUS_ID = "13"
attr_encrypted :url, encryption_options
attr_encrypted :api_url, encryption_options
attr_encrypted :token, encryption_options
def closed_status_id
super || DEFAULT_CLOSED_STATUS_ID
end
end
......@@ -564,8 +564,8 @@ def merge_requests_with_overridden_project_rules(time_period = nil)
def projects_jira_issuelist_active
# rubocop: disable UsageData/LargeTable:
min_id = minimum_id(JiraTrackerData.where(issues_enabled: true), :service_id)
max_id = maximum_id(JiraTrackerData.where(issues_enabled: true), :service_id)
min_id = minimum_id(::Integrations::JiraTrackerData.where(issues_enabled: true), :service_id)
max_id = maximum_id(::Integrations::JiraTrackerData.where(issues_enabled: true), :service_id)
# rubocop: enable UsageData/LargeTable:
count(::Integrations::Jira.active.includes(:jira_tracker_data).where(jira_tracker_data: { issues_enabled: true }), start: min_id, finish: max_id)
end
......
......@@ -3,15 +3,15 @@
# These factories should not be called directly unless we are testing a _tracker_data model.
# The factories are used when creating integrations.
FactoryBot.define do
factory :jira_tracker_data do
factory :jira_tracker_data, class: 'Integrations::JiraTrackerData' do
integration factory: :jira_service
end
factory :issue_tracker_data do
factory :issue_tracker_data, class: 'Integrations::IssueTrackerData' do
integration
end
factory :open_project_tracker_data do
factory :open_project_tracker_data, class: 'Integrations::OpenProjectTrackerData' do
integration factory: :open_project_service
url { 'http://openproject.example.com'}
token { 'supersecret' }
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe DataFields do
RSpec.describe Integrations::HasDataFields do
let(:url) { 'http://url.com' }
let(:username) { 'username_one' }
let(:properties) do
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe IssueTrackerData do
RSpec.describe Integrations::IssueTrackerData do
describe 'associations' do
it { is_expected.to belong_to :integration }
end
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe JiraTrackerData do
RSpec.describe Integrations::JiraTrackerData do
describe 'associations' do
it { is_expected.to belong_to(:integration) }
end
......
......@@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe OpenProjectTrackerData do
RSpec.describe Integrations::OpenProjectTrackerData do
describe 'associations' do
it { is_expected.to belong_to(:integration) }
end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment