<commit_before>class Project < ApplicationRecord
  include ArchivableModel
  include SearchableModel
  include SearchableByNameModel

  enum visibility: { hidden: 0, visible: 1 }

  auto_strip_attributes :name, nullify: false
  validates :name,
            length: { minimum: Constants::NAME_MIN_LENGTH,
                      maximum: Constants::NAME_MAX_LENGTH },
            uniqueness: { scope: :team, case_sensitive: false }
  validates :visibility, presence: true
  validates :team, presence: true

  belongs_to :created_by,
             foreign_key: 'created_by_id',
             class_name: 'User',
             optional: true
  belongs_to :last_modified_by,
             foreign_key: 'last_modified_by_id',
             class_name: 'User',
             optional: true
  belongs_to :archived_by,
             foreign_key: 'archived_by_id',
             class_name: 'User',
             optional: true
  belongs_to :restored_by,
             foreign_key: 'restored_by_id',
             class_name: 'User',
             optional: true
  belongs_to :team, inverse_of: :projects, touch: true, optional: true
  has_many :user_projects, inverse_of: :project
  has_many :users, through: :user_projects
  has_many :experiments, inverse_of: :project
  has_many :active_experiments, -> { where(archived: false) },
           class_name: 'Experiment'
  has_many :project_comments, foreign_key: :associated_id, dependent: :destroy
  has_many :activities, inverse_of: :project
  has_many :tags, inverse_of: :project
  has_many :reports, inverse_of: :project, dependent: :destroy
  has_many :report_elements, inverse_of: :project, dependent: :destroy

  scope :visible_to, (lambda do |user, team|
                        unless user.is_admin_of_team?(team)
                          left_outer_joins(:user_projects)
                          .where(
                            'visibility = 1 OR user_projects.user_id = :id',
                            id: user.id
                          )
                        end
                      end)

  scope :templates, -> { where(template: true) }

  def self.visible_from_user_by_name(user, team, name)
    projects = where(team: team).distinct
    if user.is_admin_of_team?(team)
      projects.where('projects.archived IS FALSE AND projects.name ILIKE ?', "%#{name}%")
    else
      projects.joins(:user_projects)
              .where('user_projects.user_id = ? OR projects.visibility = 1', user.id)
              .where('projects.archived IS FALSE AND projects.name ILIKE ?',
                     "%#{name}%")
    end
  end

  def self.search(
    user,
    include_archived,
    query = nil,
    page = 1,
    current_team = nil,
    options = {}
  )

    if current_team
      new_query =
        Project<commit_msg>Add distinct to #visible_to in project.rb<commit_after>class Project < ApplicationRecord
  include ArchivableModel
  include SearchableModel
  include SearchableByNameModel

  enum visibility: { hidden: 0, visible: 1 }

  auto_strip_attributes :name, nullify: false
  validates :name,
            length: { minimum: Constants::NAME_MIN_LENGTH,
                      maximum: Constants::NAME_MAX_LENGTH },
            uniqueness: { scope: :team, case_sensitive: false }
  validates :visibility, presence: true
  validates :team, presence: true

  belongs_to :created_by,
             foreign_key: 'created_by_id',
             class_name: 'User',
             optional: true
  belongs_to :last_modified_by,
             foreign_key: 'last_modified_by_id',
             class_name: 'User',
             optional: true
  belongs_to :archived_by,
             foreign_key: 'archived_by_id',
             class_name: 'User',
             optional: true
  belongs_to :restored_by,
             foreign_key: 'restored_by_id',
             class_name: 'User',
             optional: true
  belongs_to :team, inverse_of: :projects, touch: true, optional: true
  has_many :user_projects, inverse_of: :project
  has_many :users, through: :user_projects
  has_many :experiments, inverse_of: :project
  has_many :active_experiments, -> { where(archived: false) },
           class_name: 'Experiment'
  has_many :project_comments, foreign_key: :associated_id, dependent: :destroy
  has_many :activities, inverse_of: :project
  has_many :tags, inverse_of: :project
  has_many :reports, inverse_of: :project, dependent: :destroy
  has_many :report_elements, inverse_of: :project, dependent: :destroy

  scope :visible_to, (lambda do |user, team|
                        unless user.is_admin_of_team?(team)
                          left_outer_joins(:user_projects)
                          .where(
                            'visibility = 1 OR user_projects.user_id = :id',
                            id: user.id
                          ).distinct
                        end
                      end)

  scope :templates, -> { where(template: true) }

  def self.visible_from_user_by_name(user, team, name)
    projects = where(team: team).distinct
    if user.is_admin_of_team?(team)
      projects.where('projects.archived IS FALSE AND projects.name ILIKE ?', "%#{name}%")
    else
      projects.joins(:user_projects)
              .where('user_projects.user_id = ? OR projects.visibility = 1', user.id)
              .where('projects.archived IS FALSE AND projects.name ILIKE ?',
                     "%#{name}%")
    end
  end

  def self.search(
    user,
    include_archived,
    query = nil,
    page = 1,
    current_team = nil,
    options = {}
  )

    if current_team
      new_query =
        Project
{'fraction_non_alphanumeric': 0.09276870626233627, 'fraction_numerical': 0.0017943656917279742, 'mean_word_length': 2.2943262411347516, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1738485', 'n_tokens_mistral': 1647, 'n_tokens_neox': 1616, 'n_words': 391}