app/models/dataset/dataset_record.rb
# -*- 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 => "…") : 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