fairplaysk/datacamp

View on GitHub
app/models/dataset/dataset_record.rb

Summary

Maintainability
D
1 day
Test Coverage
# -*- encoding : utf-8 -*-
class Dataset::DatasetRecord < ActiveRecord::Base
  include ActionView::Helpers::NumberHelper
  include ActionView::Helpers::TextHelper

  self.abstract_class = true

  establish_connection Rails.env + "_data"

  class_attribute :dataset, :derived_fields

  attr_accessor :handling_user, :is_part_of_import

  # FIXME: add this to initialize method, use datasetore manager!
  self.primary_key = '_record_id'

  def self.default_scope
    if derived_fields.present?
      select_columns = "`#{table_name}`.* , #{derived_fields.map{ |identifier, value| "#{value} as '#{identifier}'" }.join(",")}"
      select(select_columns)
    end
  end

  scope :active, lambda { where("record_status IS NULL OR record_status NOT IN ('#{Dataset::RecordStatus.find(:suspended)}', '#{Dataset::RecordStatus.find(:deleted)}')") }

  def active?
    record_status.nil? || [Dataset::RecordStatus.find(:suspended), Dataset::RecordStatus.find(:deleted)].exclude?(record_status)
  end

  IDENTIFIERS = [:name, :title, :original_name, :title_sk, :procurement_subject, :_record_id]

  def identifier
    IDENTIFIERS.each do |attribute|
      if self.attributes.include? attribute.to_s
        return self.attributes[attribute.to_s]
      end
    end
    nil
  end

  def to_param
    _record_id.to_s
  end

  def self.find_by_record_ids(ids)
    return [] if ids.empty?
    records = where(_record_id: ids).all.index_by(&:_record_id)
    ids.map { |id| records[id] }.compact
  end

  # Convenience shortcut
  def self.find_by_record_id! *args
    find_by__record_id! *args
  end

  def self.find_by_record_id *args
    find_by__record_id *args
  end

  def quality_status_messages
    # QualityStatus.find :all, :conditions => { :table_name => @@dataset.description.identifier.to_s.sub("ds_", ""), :record_id => id }
    # TODO this is not in QualityStatus model anymore, it should be done somehow else
    []
  end

  def record_status
    read_attribute(:record_status).blank? ? Dataset::RecordStatus.find(:absent) : read_attribute(:record_status)
  end

  def quality_status
    read_attribute(:quality_status).blank? ? Dataset::RecordStatus.find(:absent) : read_attribute(:quality_status)
  end


  def visible_fields
    fields_for_export = description.visible_field_descriptions(:export)
    # Put data into an array
    return fields_for_export.collect{ |description| description.identifier }
  end

  def values_for_fields(fields)
    values = fields.collect { |field| self[field]}
  end

  ########################################################################################
  # Getting different kinds of values

  def get_value(field_description)
    self[field_description.identifier.to_sym]
  end

  def formatted_values_for_fields(field_descriptions)
    field_descriptions.map {|fd| get_formatted_value(fd).to_s.force_encoding("utf-8") }
  end

  def get_formatted_value(field_description)
    value = get_value(field_description)
    # Apply format
    data_format = field_description.data_format
    if data_format
      # FIXME: get from system setup or localization
      # :separator =>, :delimiter =>
      # :precision => 0 get from argv

      format_arg =  field_description.data_format_argument
      format_arg = '' if format_arg.blank?
      case data_format.name
      when "number"
        value = (number_with_precision(value) rescue value)
      when "currency"
        # FIXME: Put format into argument 2
        value = number_to_currency(value, :unit => format_arg, :format => "%n %u")
      when "percentage"
        value = (number_to_percentage(value) rescue value)
      when "bytes"
        value = number_to_human_size(value)
      when 'zip'
        value = ("%05i" % value rescue value)
      when 'ico'
        value = value.present? ? '%08i' % value.to_i : value
      when 'history'
        value = YAML::load(value).map{|time, val| "#{time.strftime('%Y-%m-%d')}: #{val}"}.join("<br/>").html_safe if value.present?
      when "flag"
        if format_arg and format_arg != ""
          flag_values = format_arg.split(",")
          flag_values = flag_values.collect { |str| str.strip }
        end

        if not flag_values
          flag_values = [I18n.t("data_format_values.format_flag_true"), I18n.t("data_format_values.format_flag_false")]
        elsif flag_values.count == 1
          flag_values << I18n.t("data_format_values.format_flag_false")
        end

        if value
          value = flag_values[0]
        else
          value = flag_values[1]
        end
      end
    end
    value
  rescue
    nil
  end

  def get_html_value(field_description, length = nil)
    value = get_formatted_value(field_description)
    formatted_value = length.present? ? truncate(value.to_s, :length => length, :omission => "&hellip;") : value

    data_format = field_description.data_format
    if data_format.present?
     case data_format.name
     when "url"
       formatted_value = "<a href=\"#{value}\">#{formatted_value}</a>".html_safe
     when "email"
       formatted_value = "<a href=\"mailto:#{value}\">#{formatted_value}</a>".html_safe
     end
    end
    return formatted_value
  end

  def get_truncated_html_value(field_description)
    get_html_value(field_description, 100).html_safe
  end

  def search_string_for_field_description(field_description)
    search_string = "column:%s %s" % [field_description.reference, get_value(field_description)]
  end

  def self.table_exists?
    # not using cache
    connection.tables.include?(table_name)
  end

  ########################################################################################
  # Callbacks

  after_save :record_changes
  def record_changes
    if !self.class.table_name.match(/^(rel_|dc_)/) && !is_part_of_import
      change_details = []
      changed_attributes.each do |attribute, old_value|
        next if attribute == "updated_at"
        next if old_value == self[attribute]
        change_details << {changed_field: attribute, old_value: old_value, new_value: self[attribute]}
      end
      Change.create(record_id: self.id, change_type: changed.include?(self.class.primary_key) ? Change::RECORD_CREATE : Change::RECORD_UPDATE, dataset_description_id: (dataset.try(:id) rescue nil), user: User.current, change_details: change_details)
    end
  end

  before_save :record_updates
  def record_updates
    if !self.class.table_name.match(/^(rel_|dc_)/) && !self.new_record?
      change_hash = changed_attributes.map { |attribute, old_value| {updated_column: attribute, original_value: old_value, new_value: self[attribute]} }
      self.dc_updates.build(change_hash) if respond_to?(:dc_updates)
    end
  end

  before_destroy :record_destroy
  def record_destroy
    Change.create(change_type: Change::RECORD_DESTROY, dataset_description_cache: attributes, user: @handling_user)
  end
end