2017-06-23 21:19:08 +08:00
|
|
|
class Repository < ApplicationRecord
|
2017-06-23 22:06:11 +08:00
|
|
|
include SearchableModel
|
2018-03-02 20:39:22 +08:00
|
|
|
include RepositoryImportParser
|
2018-05-24 20:39:25 +08:00
|
|
|
include Discard::Model
|
2018-05-29 21:33:02 +08:00
|
|
|
|
|
|
|
attribute :discarded_by_id, :integer
|
|
|
|
|
2017-06-28 21:21:32 +08:00
|
|
|
belongs_to :team, optional: true
|
|
|
|
belongs_to :created_by,
|
|
|
|
foreign_key: :created_by_id,
|
|
|
|
class_name: 'User',
|
|
|
|
optional: true
|
2018-05-18 19:57:52 +08:00
|
|
|
has_many :repository_columns, dependent: :destroy
|
|
|
|
has_many :repository_rows, dependent: :destroy
|
2017-06-07 19:36:39 +08:00
|
|
|
has_many :repository_table_states,
|
|
|
|
inverse_of: :repository, dependent: :destroy
|
2017-06-05 18:24:06 +08:00
|
|
|
has_many :report_elements, inverse_of: :repository, dependent: :destroy
|
2018-02-09 21:11:56 +08:00
|
|
|
has_many :repository_list_items, inverse_of: :repository, dependent: :destroy
|
2017-05-16 21:27:36 +08:00
|
|
|
|
|
|
|
auto_strip_attributes :name, nullify: false
|
|
|
|
validates :name,
|
|
|
|
presence: true,
|
2017-06-05 16:38:04 +08:00
|
|
|
uniqueness: { scope: :team, case_sensitive: false },
|
2017-05-16 21:27:36 +08:00
|
|
|
length: { maximum: Constants::NAME_MAX_LENGTH }
|
|
|
|
validates :team, presence: true
|
|
|
|
validates :created_by, presence: true
|
2017-05-30 14:57:00 +08:00
|
|
|
|
2018-05-24 20:39:25 +08:00
|
|
|
default_scope -> { kept }
|
|
|
|
|
2017-06-23 22:06:11 +08:00
|
|
|
def self.search(
|
|
|
|
user,
|
|
|
|
query = nil,
|
|
|
|
page = 1,
|
2018-03-09 18:05:43 +08:00
|
|
|
repository = nil,
|
2017-06-23 22:06:11 +08:00
|
|
|
options = {}
|
|
|
|
)
|
2018-03-09 18:05:43 +08:00
|
|
|
repositories = repository ? repository : Repository.where(team: user.teams)
|
2017-06-23 22:06:11 +08:00
|
|
|
|
2018-03-09 18:05:43 +08:00
|
|
|
includes_json = { repository_cells: Extends::REPOSITORY_SEARCH_INCLUDES }
|
|
|
|
searchable_attributes = ['repository_rows.name', 'users.full_name'] +
|
|
|
|
Extends::REPOSITORY_EXTRA_SEARCH_ATTR
|
2017-06-23 22:06:11 +08:00
|
|
|
|
2018-03-09 18:05:43 +08:00
|
|
|
new_query = RepositoryRow
|
|
|
|
.left_outer_joins(:created_by)
|
|
|
|
.left_outer_joins(includes_json)
|
|
|
|
.where(repository: repositories)
|
|
|
|
.where_attributes_like(searchable_attributes, query, options)
|
2017-06-23 22:06:11 +08:00
|
|
|
|
|
|
|
# Show all results if needed
|
|
|
|
if page == Constants::SEARCH_NO_LIMIT
|
|
|
|
new_query
|
2018-03-09 18:05:43 +08:00
|
|
|
.joins(:repository)
|
|
|
|
.select(
|
|
|
|
'repositories.id AS id, COUNT(DISTINCT repository_rows.id) AS counter'
|
|
|
|
)
|
|
|
|
.group('repositories.id')
|
2017-06-23 22:06:11 +08:00
|
|
|
else
|
|
|
|
new_query
|
2018-03-09 18:05:43 +08:00
|
|
|
.distinct
|
2017-06-23 22:06:11 +08:00
|
|
|
.limit(Constants::SEARCH_LIMIT)
|
|
|
|
.offset((page - 1) * Constants::SEARCH_LIMIT)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-05-16 15:31:19 +08:00
|
|
|
def self.name_like(query)
|
|
|
|
where('repositories.name ILIKE ?', "%#{query}%")
|
|
|
|
end
|
2018-05-18 19:57:52 +08:00
|
|
|
|
2018-06-12 21:28:03 +08:00
|
|
|
def available_columns_ids
|
|
|
|
repository_columns.pluck(:id)
|
|
|
|
end
|
|
|
|
|
2018-03-13 18:36:05 +08:00
|
|
|
def importable_repository_fields
|
2017-06-13 14:10:10 +08:00
|
|
|
fields = {}
|
2017-06-21 23:39:20 +08:00
|
|
|
# First and foremost add record name
|
2017-06-21 20:45:50 +08:00
|
|
|
fields['-1'] = I18n.t('repositories.default_column')
|
2017-06-13 14:10:10 +08:00
|
|
|
# Add all other custom columns
|
|
|
|
repository_columns.order(:created_at).each do |rc|
|
2018-03-13 18:36:05 +08:00
|
|
|
next unless rc.importable?
|
2017-06-13 14:10:10 +08:00
|
|
|
fields[rc.id] = rc.name
|
|
|
|
end
|
|
|
|
fields
|
|
|
|
end
|
|
|
|
|
2017-05-30 14:57:00 +08:00
|
|
|
def copy(created_by, name)
|
|
|
|
new_repo = nil
|
|
|
|
|
|
|
|
begin
|
|
|
|
Repository.transaction do
|
|
|
|
# Clone the repository object
|
|
|
|
new_repo = dup
|
|
|
|
new_repo.created_by = created_by
|
|
|
|
new_repo.name = name
|
|
|
|
new_repo.save!
|
|
|
|
|
|
|
|
# Clone columns (only if new_repo was saved)
|
|
|
|
repository_columns.find_each do |col|
|
|
|
|
new_col = col.dup
|
|
|
|
new_col.repository = new_repo
|
|
|
|
new_col.created_by = created_by
|
|
|
|
new_col.save!
|
|
|
|
end
|
|
|
|
end
|
|
|
|
rescue ActiveRecord::RecordInvalid
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
|
|
|
# If everything is okay, return new_repo
|
|
|
|
new_repo
|
|
|
|
end
|
2017-06-13 14:10:10 +08:00
|
|
|
|
2017-06-19 20:05:37 +08:00
|
|
|
def import_records(sheet, mappings, user)
|
2018-03-02 20:39:22 +08:00
|
|
|
importer = RepositoryImportParser::Importer.new(sheet, mappings, user, self)
|
|
|
|
importer.run
|
2017-06-19 20:05:37 +08:00
|
|
|
end
|
2018-05-29 21:33:02 +08:00
|
|
|
|
|
|
|
def destroy_discarded(discarded_by_id = nil)
|
|
|
|
self.discarded_by_id = discarded_by_id
|
|
|
|
destroy
|
|
|
|
end
|
|
|
|
handle_asynchronously :destroy_discarded,
|
|
|
|
queue: :clear_discarded_repository,
|
|
|
|
priority: 20
|
2017-05-16 21:27:36 +08:00
|
|
|
end
|