<commit_before>require 'cgi'
require 'addressable/uri'
require "builder"

class Work < ActiveRecord::Base
  # include HTTP request helpers
  include Networkable

  # include helper module for DOI resolution
  include Resolvable

  # store blank values as nil
  nilify_blanks

  belongs_to :publisher, primary_key: :member_id
  belongs_to :work_type
  has_many :retrieval_statuses, :dependent => :destroy
  has_many :sources, :through => :retrieval_statuses
  has_many :alerts, :dependent => :destroy
  has_many :api_responses
  has_many :relationships, :dependent => :destroy
  has_many :related_works, :through => :relationships
  has_many :similar_works, :through => :relationships

  validates :pid_type, :pid, :title, presence: true
  validates :doi, uniqueness: true, format: { with: DOI_FORMAT }, allow_blank: true
  validates :canonical_url, uniqueness: true, format: { with: URL_FORMAT }, allow_blank: true
  validates :ark, uniqueness: true, format: { with: ARK_FORMAT }, allow_blank: true
  validates :pid, :pmid, :pmcid, :wos, :scp, uniqueness: true, allow_blank: true
  validates :year, numericality: { only_integer: true }
  validate :validate_published_on

  before_validation :sanitize_title, :normalize_url, :set_pid
  after_create :create_retrievals, if: :tracked

  scope :query, ->(query) { where("pid like ?", "#{query}%") }
  scope :last_x_days, ->(duration) { where("created_at > ?", Time.zone.now.beginning_of_day - duration.days) }
  scope :has_events, -> { includes(:retrieval_statuses)
    .where("retrieval_statuses.total > ?", 0)
    .references(:retrieval_statuses) }
  scope :by_source, ->(source_id) { joins(:retrieval_statuses)
    .where("retrieval_statuses.source_id = ?", source_id) }
  scope :tracked, -> { where("works.tracked = ?", true) }

  serialize :csl, JSON

  # this is faster than first_or_create
  def self.find_or_create(params)
    work = self.create!(params.except(:related_works))
    work.update_relations(params[:related_works])
    work
  rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => e
    # update title and/or date if work exists
    # raise an error for other RecordInvalid errors such as missing title
    if e.message.start_with?("Validation failed: Doi has already been taken") || e.message.include?("key 'index_works_on_doi'")
      work = Work.where(doi: params[:doi]).first
      work.update_attributes(params.except(:doi)) unless work.nil?
      work.update_relations(params[:related_works])
      work
    elsif e.message.start_with?("Validation failed: Canonical url has already been taken") || e.message.include?("key 'index_works_on_url'")
      work = Work.where(canonical_url: params[:canonical_url]).first
      work.update_attributes(params.except(:canonical_url)) unless work.nil?
      work.update_relations(params[:related_works])
      work<commit_msg>handle missing related_works. #213<commit_after>require 'cgi'
require 'addressable/uri'
require "builder"

class Work < ActiveRecord::Base
  # include HTTP request helpers
  include Networkable

  # include helper module for DOI resolution
  include Resolvable

  # store blank values as nil
  nilify_blanks

  belongs_to :publisher, primary_key: :member_id
  belongs_to :work_type
  has_many :retrieval_statuses, :dependent => :destroy
  has_many :sources, :through => :retrieval_statuses
  has_many :alerts, :dependent => :destroy
  has_many :api_responses
  has_many :relationships, :dependent => :destroy
  has_many :related_works, :through => :relationships
  has_many :similar_works, :through => :relationships

  validates :pid_type, :pid, :title, presence: true
  validates :doi, uniqueness: true, format: { with: DOI_FORMAT }, allow_blank: true
  validates :canonical_url, uniqueness: true, format: { with: URL_FORMAT }, allow_blank: true
  validates :ark, uniqueness: true, format: { with: ARK_FORMAT }, allow_blank: true
  validates :pid, :pmid, :pmcid, :wos, :scp, uniqueness: true, allow_blank: true
  validates :year, numericality: { only_integer: true }
  validate :validate_published_on

  before_validation :sanitize_title, :normalize_url, :set_pid
  after_create :create_retrievals, if: :tracked

  scope :query, ->(query) { where("pid like ?", "#{query}%") }
  scope :last_x_days, ->(duration) { where("created_at > ?", Time.zone.now.beginning_of_day - duration.days) }
  scope :has_events, -> { includes(:retrieval_statuses)
    .where("retrieval_statuses.total > ?", 0)
    .references(:retrieval_statuses) }
  scope :by_source, ->(source_id) { joins(:retrieval_statuses)
    .where("retrieval_statuses.source_id = ?", source_id) }
  scope :tracked, -> { where("works.tracked = ?", true) }

  serialize :csl, JSON

  # this is faster than first_or_create
  def self.find_or_create(params)
    work = self.create!(params.except(:related_works))
    work.update_relations(params.fetch(:related_works, []))
    work
  rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotUnique => e
    # update title and/or date if work exists
    # raise an error for other RecordInvalid errors such as missing title
    if e.message.start_with?("Validation failed: Doi has already been taken") || e.message.include?("key 'index_works_on_doi'")
      work = Work.where(doi: params[:doi]).first
      work.update_attributes(params.except(:doi)) unless work.nil?
      work.update_relations(params.fetch(:related_works, []))
      work
    elsif e.message.start_with?("Validation failed: Canonical url has already been taken") || e.message.include?("key 'index_works_on_url'")
      work = Work.where(canonical_url: params[:canonical_url]).first
      work.update_attributes(params.except(:canonical_url)) unless work.nil?
      work.update_relations(params.fetch(:related_works, []))
      work
{'fraction_non_alphanumeric': 0.11954821894005213, 'fraction_numerical': 0.0008688097306689834, 'mean_word_length': 5.014629049111807, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 31, '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': '7441996', 'n_tokens_mistral': 1864, 'n_tokens_neox': 1801, 'n_words': 442}