Refactor admin/contact_version and admin/domain_version csv generation logic

This commit is contained in:
Thiago Youssef 2022-03-10 16:03:53 +02:00
parent 807419bc3a
commit 9fb4a6d7e6
19 changed files with 117 additions and 156 deletions

View file

@ -26,7 +26,7 @@ module Admin
respond_to do |format|
format.html { render page }
format.csv do
raw_csv = @q.result.to_csv
raw_csv = CsvGenerator.generate_csv(@q.result)
send_data raw_csv,
filename: "#{filename}_#{Time.zone.now.to_formatted_s(:number)}.csv",
type: "#{Mime[:csv]}; charset=utf-8"

View file

@ -1,13 +1,9 @@
module Admin
class ContactVersionsController < BaseController
include ApplicationHelper
include ObjectVersionsHelper
load_and_authorize_resource class: Version::ContactVersion
MODEL = Contact
CSV_HEADER = ['Name', 'ID', 'Ident', 'Registrar', 'Action', 'Created at'].freeze
def index
params[:q] ||= {}
@ -71,17 +67,5 @@ module Admin
params_copy
end
def render_by_format(page, filename)
respond_to do |format|
format.html { render page }
format.csv do
raw_csv = csv_generate(MODEL, CSV_HEADER, @q.result)
send_data raw_csv,
filename: "#{filename}_#{Time.zone.now.to_formatted_s(:number)}.csv",
type: "#{Mime[:csv]}; charset=utf-8"
end
end
end
end
end

View file

@ -1,12 +1,7 @@
module Admin
class DomainVersionsController < BaseController
include ObjectVersionsHelper
load_and_authorize_resource class: Version::DomainVersion
MODEL = Domain
CSV_HEADER = ['Name', 'Registrant', 'Registrar', 'Action', 'Created at'].freeze
def index
params[:q] ||= {}
@ -85,23 +80,10 @@ module Admin
def fix_date_params
params_copy = params[:q].deep_dup
if params_copy['created_at_lteq'].present?
params_copy['created_at_lteq'] = Date.parse(params_copy['created_at_lteq']) + 1.day
end
created_at = params_copy['created_at_lteq']
params_copy['created_at_lteq'] = Date.parse(created_at) + 1.day if created_at.present?
params_copy
end
def render_by_format(page, filename)
respond_to do |format|
format.html { render page }
format.csv do
raw_csv = csv_generate(MODEL, CSV_HEADER, @q.result)
send_data raw_csv,
filename: "#{filename}_#{Time.zone.now.to_formatted_s(:number)}.csv",
type: "#{Mime[:csv]}; charset=utf-8"
end
end
end
end
end

View file

@ -9,30 +9,6 @@ module ApplicationHelper
"background-image: url(#{image_path("#{unstable_env}.png")});"
end
def ident_for(contact)
if contact.is_a? Hash
ident_country_code = contact[:ident_country_code]
ident_type = contact[:ident_type]
ident = contact[:ident]
else
ident_country_code = contact.ident_country_code
ident_type = contact.ident_type
ident = contact.ident
end
case ident_type
when 'birthday'
"#{ident} [#{ident_country_code} #{ident_type}]"
else
if ident.present?
"#{ident} [#{ident_country_code} #{ident_type}]"
else
"[#{ident_country_code} #{ident_type}]"
end
end
end
def current_commit_link
hash = `git rev-parse --short HEAD`
current_repo = `git remote get-url origin`.gsub('com:', 'com/')

View file

@ -1,76 +0,0 @@
module ObjectVersionsHelper
CSV_HEADER = ['Name', 'Registrant', 'Registrar', 'Action', 'Created at'].freeze
def attach_existing_fields(version, new_object)
version.object_changes.to_h.each do |key, value|
method_name = "#{key}=".to_sym
new_object.public_send(method_name, event_value(version, value)) if new_object.respond_to?(method_name)
end
end
def only_present_fields(version, model)
field_names = model.column_names
version.object.to_h.select { |key, _value| field_names.include?(key) }
end
def csv_generate(model, header, versions)
CSV.generate do |csv|
csv << header
versions.each do |version|
attributes = only_present_fields(version, model)
history_object = model.new(attributes)
attach_existing_fields(version, history_object) unless version.event == 'destroy'
csv << create_row(history_object, version)
end
end
end
private
def event_value(version, val)
version.event == 'destroy' ? val.first : val.last
end
def registrant_name(domain, version)
return domain.registrant.name if domain.registrant
ver = Version::ContactVersion.where(item_id: domain.registrant_id).last
contact = Contact.all_versions_for([domain.registrant_id], version.created_at).first
if contact.nil? && ver
merged_obj = ver.object_changes.to_h.transform_values(&:last)
result = ver.object.to_h.merge(merged_obj)&.slice(*Contact&.column_names)
contact = Contact.new(result)
end
contact.try(:name) || 'Deleted'
end
def create_row(history_object, version)
if history_object.is_a?(Domain)
domain_history_row(history_object, version)
else
contact_history_row(history_object, version)
end
end
def contact_history_row(history_object, version)
name = history_object.name
code = history_object.code
ident = ident_for(history_object)
registrar = history_object.registrar
event = version.event
created_at = version.created_at.to_formatted_s(:db)
[name, code, ident, registrar, event, created_at]
end
def domain_history_row(history_object, version)
name = history_object.name
registrant = registrant_name(history_object, version)
registrar = history_object.registrar
event = version.event
created_at = version.created_at.to_formatted_s(:db)
[name, registrant, registrar, event, created_at]
end
end

View file

@ -569,4 +569,11 @@ class Contact < ApplicationRecord
def deletable?
!linked?
end
def ident_human_description
description = "[#{ident_country_code} #{ident_type}]"
description.prepend("#{ident} ") if ident.present?
description
end
end

View file

@ -4,4 +4,21 @@ class Version::ContactVersion < PaperTrail::Version
self.table_name = :log_contacts
self.sequence_name = :log_contacts_id_seq
def as_csv_row
contact = ObjectVersionsParser.new(self).parse
[
contact.name,
contact.code,
contact.ident_human_description,
contact.registrar,
event,
created_at.to_formatted_s(:db)
]
end
def self.csv_header
['Name', 'ID', 'Ident', 'Registrar', 'Action', 'Created at'].freeze
end
end

View file

@ -7,6 +7,18 @@ class Version::DomainVersion < PaperTrail::Version
scope :deleted, -> { where(event: 'destroy') }
def as_csv_row
domain = ObjectVersionsParser.new(self).parse
[
domain.name,
registrant_name(domain),
domain.registrar,
event,
created_at.to_formatted_s(:db)
]
end
def self.was_contact_linked?(contact_id)
sql = <<-SQL
SELECT
@ -43,4 +55,25 @@ class Version::DomainVersion < PaperTrail::Version
count_by_sql(sql).nonzero?
end
def self.csv_header
['Name', 'Registrant', 'Registrar', 'Action', 'Created at'].freeze
end
private
def registrant_name(domain)
return domain.registrant.name if domain.registrant
ver = Version::ContactVersion.where(item_id: domain.registrant_id).last
contact = Contact.all_versions_for([domain.registrant_id], created_at).first
if contact.nil? && ver
merged_obj = ver.object_changes.to_h.transform_values(&:last)
result = ver.object.to_h.merge(merged_obj)&.slice(*Contact&.column_names)
contact = Contact.new(result)
end
contact.try(:name) || 'Deleted'
end
end

View file

@ -0,0 +1,17 @@
class CsvGenerator
def self.generate_csv(objects)
class_name = objects.first.class
return objects.to_csv unless custom_csv(class_name)
CSV.generate do |csv|
csv << class_name.csv_header
objects.each { |object| csv << object.as_csv_row }
end
end
private
def self.custom_csv(class_name)
[Version::DomainVersion, Version::ContactVersion].include?(class_name)
end
end

View file

@ -0,0 +1,28 @@
class ObjectVersionsParser
def initialize(version)
@version = version
end
def parse
model = @version.item_type.constantize
attributes = only_present_fields(model)
history_object = model.new(attributes)
attach_existing_fields(history_object) unless @version.event == 'destroy'
history_object
end
private
def attach_existing_fields(history_object)
@version.object_changes.to_h.each do |key, value|
method_name = "#{key}=".to_sym
history_object.public_send(method_name, value.last) if history_object.respond_to?(method_name)
end
end
def only_present_fields(model)
field_names = model.column_names
@version.object.to_h.select { |key, _value| field_names.include?(key) }
end
end

View file

@ -64,14 +64,12 @@
%tbody
- @versions.each do |version|
- if version
- attributes = only_present_fields(version, Contact)
- contact = Contact.new(attributes)
- attach_existing_fields(version, contact)
- contact = ObjectVersionsParser.new(version).parse
%tr
%td= link_to(contact.name, admin_contact_version_path(version.id))
%td= contact.code
%td= ident_for(contact)
%td= contact.ident_human_description
%td
- if contact.registrar
= link_to(contact.registrar, admin_registrar_path(contact.registrar))

View file

@ -1,6 +1,5 @@
- attributes = only_present_fields(@version, Contact)
- contact = Contact.new(attributes)
- attach_existing_fields(@version, contact)
- contact = ObjectVersionsParser.new(@version).parse
= render 'shared/title', name: contact.name
.row
@ -23,7 +22,7 @@
%dt= t(:ident)
%dd{class: changing_css_class(@version,"ident_country_code", "ident_type", "ident")}
= ident_for(contact)
= contact.ident_human_description
- if contact.email.present?
%dt= t(:email)

View file

@ -100,7 +100,7 @@
%tr
%td= link_to(contact, admin_contact_path(contact))
%td= contact.code
%td= ident_for(contact)
%td= contact.ident_human_description
%td= contact.email
%td= l(contact.created_at, format: :short)
%td

View file

@ -14,7 +14,7 @@
%br
%dt.left_25= t(:ident)
%dd.left_25= ident_for(@contact)
%dd.left_25= @contact.ident_human_description
%dt.left_25= t(:email)
%dd.left_25= @contact.email

View file

@ -62,9 +62,7 @@
%tbody
- @versions.each do |version|
- if version
- attributes = only_present_fields(version, Domain)
- domain = Domain.new(attributes)
- attach_existing_fields(version, domain) unless version.event == 'destroy'
- domain = ObjectVersionsParser.new(version).parse
%tr
%td= link_to(domain.name, admin_domain_version_path(version.id))

View file

@ -1,6 +1,4 @@
- present_fields = only_present_fields(@version, Domain)
- domain = Domain.new(present_fields)
- attach_existing_fields(@version, domain) unless @version.event == 'destroy'
- domain = ObjectVersionsParser.new(@version).parse
- if @version
- children = HashWithIndifferentAccess.new(@version.children)

View file

@ -44,7 +44,7 @@
<%= contact.code %>
</td>
<td>
<%= ident_for(contact) %>
<%= contact.ident_human_description %>
</td>
<td>
<%= l(contact.created_at, format: :short) %>

View file

@ -20,7 +20,7 @@
<tr>
<td><%= contact %></td>
<td><%= contact.code %></td>
<td><%= ident_for(contact) %></td>
<td><%= contact.ident_human_description %></td>
<td><%= l(contact.created_at, format: :short) %></td>
<td><%= contact.registrar %></td>
</tr>

View file

@ -14,7 +14,7 @@
%br
%dt= t(:ident)
%dd= ident_for(@contact)
%dd= @contact.ident_human_description
%dt= t(:email)
%dd= @contact.email