Skip to content

Instantly share code, notes, and snippets.

@Whatapalaver
Last active December 23, 2019 15:13
Show Gist options
  • Save Whatapalaver/24d4db7fee2a290ef0f04471b3d00953 to your computer and use it in GitHub Desktop.
Save Whatapalaver/24d4db7fee2a290ef0f04471b3d00953 to your computer and use it in GitHub Desktop.
Reflecting updates to primary object
class EnhancedObject < ActiveRecord::Base
def self.from_museum_object(parsed_museum_object, object_namer, object_locator)
logger.debug "Museum_Object_Data: #{parsed_museum_object}"
EnhancedObject.new.tap do |enhanced_object|
enhanced_object.attributes = {
museum_unique_id: parsed_museum_object.museum_unique_id,
museum_number: parsed_museum_object.museum_number,
object_type: parsed_museum_object.object_type,
object_data_id: parsed_museum_object.museum_object_id,
location_id: parsed_museum_object.location_id,
name: object_namer.name,
room: object_locator.display_name,
on_display: object_locator.on_display,
}
end
end
end
# EnhancedObjectNamer is responsible for building the name (caption) for an enhanced object
class EnhancedObjectNamer
READABLE_ASSOCIATION = {'commissioned by' => 'commissioned by',
'advertising agency' => 'commissioned by',
'art director' => 'commissioned by',
'commissioned' => 'commissioned by',
'commissioned and' => 'commissioned by',
'commissioner' => 'commissioned by',
'commissioners' => 'commissioned by',
'art directors' => 'designed by', 'artistic editor' => 'designed by',
'costume designer' => 'designed by', 'costume designers' => 'designed by',
'creative team' => 'designed by', 'design' => 'designed by',
'design agency' => 'designed by', 'design director' => 'designed by',
'design house' => 'designed by', 'design studio' => 'designed by',
'designed' => 'designed by', 'designed and engraved' => 'designed by',
'designed and made' => 'designed by',
'designed and made by' => 'designed by',
'designed and manufactured' => 'designed by',
'designed by' => 'designed by',
'designed under the direction of' => 'designed by',
'designer' => 'designed by',
'designer (pattern)' => 'designed by',
'designer (surface design)' => 'designed by',
'designer (textile)' => 'designed by',
'designer and engraver' => 'designed by',
'designer and etcher' => 'designed by',
'designer pattern' => 'designed by',
'designer shape' => 'designed by', 'designer, carver' => 'designed by',
'designers' => 'designed by', 'fashion designer' => 'designed by',
'set designer' => 'designed by', 'theatre designer' => 'designed by',
'theatre designers' => 'designed by',
'engraver' => 'engraved by', 'engravers' => 'engraved by',
'engraved by' => 'engraved by', 'engraved' => 'engraved by',
'wood-engraver' => 'engraved by', 'engraver (inciser)' => 'engraved by',
'issuer' => 'issued by', 'issued by' => 'issued by',
'factory' => 'made by', 'made by' => 'made by',
'manufactured' => 'manufactured by',
'manufactured by' => 'manufactured by',
'manufacturer' => 'manufactured by', 'manufacturers' => 'manufactured by',
'designed for' => 'made for', 'made for' => 'made for',
'retailer' => 'made for', 'retailers' => 'made for',
'painter' => 'painted by', 'painter (artist)' => 'painted by',
'printmaker' => 'printed by', 'printers' => 'printed by',
'printer' => 'printed by', 'printers (people)' => 'printed by',
'printer-maker' => 'printed by', 'print-makers' => 'printed by',
'producer' => 'produced by', 'producers' => 'produced by',
'commissioned and published' => 'published by',
'engraver and publisher' => 'published by',
'printed and published' => 'published by',
'printer and publisher' => 'published by',
'printers and publishers' => 'published by',
'published' => 'published by',
'published by' => 'published by', 'publisher' => 'published by',
'publishers' => 'published by', 'publishing' => 'published by',
'sculptor' => 'sculpted by',
'modelled by' => 'worn by'}.freeze
ASSOCIATION_PRIORITY = {'designed by' => 1, 'painted by' => 2, 'taken by' => 4,
'made by' => 3, 'sculpted by' => 5, 'printed by' => 6,
'produced by' => 7, 'published by' => 8, 'manufactured by' => 9,
'commissioned by' => 10, 'issued by' => 11,
'engraved by' => 13, 'cast by' => 14}.freeze
attr_accessor :parsed_museum_object, :name_attributes, :name
def initialize(parsed_museum_object)
@parsed_museum_object = parsed_museum_object
@name_attributes = name_attribute_constructor
@name = build_name
end
def build_name
name = name_attributes['title']
if name_attributes['title'].present? && name_attributes['object_type'].present?
name << ', ' + name_attributes['downcased_object_type']
elsif name_attributes['object_type'].present?
name << name_attributes['object_type'].capitalize
end
name.blank? ? name << 'Untitled' : nil
%w[artist date origin].each do |attrib|
name_attributes[attrib].present? ? name << ', ' + name_attributes[attrib] : nil
end
name
end
private
def name_attribute_constructor
{'title' => parsed_museum_object.first_title,
'artist' => extract_artists,
'date' => parsed_museum_object.clean_date,
'origin' => parsed_museum_object.origin,
'object_type' => object_included_in_title? ? '' : parsed_museum_object.object_type,
'downcased_object_type' => downcase_object_type}
end
def extract_artists
full_artists = artists_extract(parsed_museum_object.artist_maker_peoples) +
artists_extract(parsed_museum_object.artist_maker_persons) +
artists_extract(parsed_museum_object.artist_maker_organisations)
if full_artists.length >= 2
full_artists[0][:readable_association] + ' ' + full_artists[0][:name] +
', ' + full_artists[1][:readable_association] + ' ' + full_artists[1][:name]
elsif full_artists.length == 1
full_artists[0][:readable_association] + ' ' + full_artists[0][:name]
else ''
end
end
def artists_extract(artists_extract)
artists = []
artists_extract.each_with_index do |artist, index|
next if artist['name']['text'].blank?
next if unknown_artist?(artist)
hash = {name: artist['name']['text'],
association: artist['association'],
readable_association: READABLE_ASSOCIATION[artist['association'].downcase] || 'by'}
hash[:order] = ASSOCIATION_PRIORITY[hash[:readable_association]] || index
artists << hash
end
artists.sort_by { |k| k[:order] }
end
def unknown_artist?(artist)
artist['name']['text'].downcase.include?('unknown')
end
def downcase_object_type
return nil if parsed_museum_object.object_type.blank?
downcased_object_type = parsed_museum_object.object_type
downcased_object_type[0] = downcased_object_type[0].downcase
downcased_object_type
end
def object_included_in_title?
singular_object_type = parsed_museum_object.object_type.gsub(/s$/, '').downcase
parsed_museum_object.first_title.downcase.include?(singular_object_type)
end
end
# irb test
# namer = EnhancedObjectNamer.new(parse)
class Admin::EnhancedObjectsController < AdminController
def new
unless params[:enhanced_object]
# 0. Is there a museum_object sent to enhance?
if params[:mo].blank?
return redirect_to admin_museum_objects_path
end
# 1. check for existing enhanced object based on this unique_id
redirect_to_existing_museum_object(params[:mo]) && return
# 2. Get museum_object from object table (collection data in JSONB)
unparsed_museum_object = get_museum_object(params[:mo])
# 3. If museum_object returned then set up form content
if !unparsed_museum_object.nil?
@museum_object = MuseumObjectParser.new(unparsed_museum_object)
object_namer = EnhancedObjectNamer.new(@museum_object)
object_locator = ObjectLocation.new(@museum_object.location_id)
@enhanced_object = EnhancedObject.from_museum_object(
@museum_object,
object_namer,
object_locator
)
# 3. Otherwise redirect to search
else
return redirect_to admin_museum_objects_path(
museum_object: params[:mo],
)
end
end
end
def edit
@enhanced_object = enhanced_object
# update location elements on edit
if enhanced_object.museum_unique_id.present?
refreshed_enhanced_object = refreshed_enhanced_object(enhanced_object.museum_unique_id)
@enhanced_object.attributes = {
location_id: refreshed_enhanced_object.location_id,
room: refreshed_enhanced_object.room,
on_display: refreshed_enhanced_object.on_display,
object_type: refreshed_enhanced_object.object_type,
}
end
end
private
# This is extracting the object data based on the uniqueID
def get_museum_object(object_id)
query_results = MuseumObject.results('id', object_id)
logger.debug "Query Results: #{query_results}"
unless query_results.empty?
query_results[0]
end
end
# This recreates a temporary (non persisted) enhanced object to reflect potential changes to MuseumObject
def refreshed_enhanced_object(unique_id)
unparsed_museum_object = get_museum_object(unique_id)
parsed_museum_object = MuseumObjectParser.new(unparsed_museum_object)
object_namer = EnhancedObjectNamer.new(parsed_museum_object)
object_locator = ObjectLocation.new(parsed_museum_object.location_id)
EnhancedObject.from_museum_object(
parsed_museum_object,
object_namer,
object_locator
)
end
# Thinking to use this to test for changes that need to trigger an update attributes method
def attributes_changed?(eo_original)
refreshed_eo = refreshed_enhanced_object(eo_original.museum_unique_id)
eo_original.attributes == refresh_eo.attributes
end
end
# Responsible for extracting key fields from MuseumObject json data
class MuseumObjectParser
attr_accessor(
:object_type, :titles, :location_ids, :artist_maker_organisations,
:artist_maker_peoples, :artist_maker_persons, :dates, :origins, :first_title,
:museum_unique_id, :museum_number, :clean_date, :origin, :gallery_locations,
:location_id, :museum_object_id
)
def initialize(museum_object_data)
@object_type = museum_object_data['data']['object']
@museum_unique_id = museum_object_data['data']['uniqueID']
@museum_object_id = museum_object_data['id']
@museum_number = museum_object_data['data']['museumNumber']
@titles = museum_object_data['data']['title']
@location_ids = museum_object_data['data']['galleryLocation'] || []
@artist_maker_persons = museum_object_data['data']['artistMakerPerson'] || []
@artist_maker_peoples = museum_object_data['data']['artistMakerPeople'] || []
@artist_maker_organisations = museum_object_data['data']['artistMakerOrganisation'] || []
@dates = museum_object_data['data']['date'] || []
@origins = museum_object_data['data']['placeOfOrigin'] || []
@gallery_locations = museum_object_data['data']['galleryLocation'] || []
@location_id = extract_location_id
@first_title = extract_title
@clean_date = extract_clean_date
@origin = extract_origin
end
private
def extract_title
if titles.try(:first)
titles.first['title']
else ''
end
end
def extract_clean_date
# replacing circa or ca. with about
output_text = extract_date.gsub(/\bcirca\ |\bc\.|\bca\. |\bca\.\b/, 'about ')
# replacing hyphen with endash using unicode in gsub expression
output_text.gsub(/(\ds?)-/, "\\1 \u{2013} ")
end
def extract_date
if dates.try(:first)
dates.first['date']['text']
else ""
end
end
def extract_origin
if origins.try(:first)
origins.first['place']['text']
else ""
end
end
def extract_location_id
if gallery_locations.try(:first)
gallery_locations.first['current']['id']
else ''
end
end
end
# irb test
# query_results = MuseumObject.where("data ->> 'uniqueID' = ?", 'O1436889')
# mus_obj = query_results[0]
# parse = MuseumObjectParser.new(mus_obj)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment