У меня есть объект событий, который является оболочкой для хэша в ruby.Я использую его для хранения событий, которые произошли и еще не произошли.Информация включает запланированную дату, фактическую дату, тип события, режим события и т. Д.
Я использовал метод сериализации в Active Record для загрузки объекта событий.Он сохраняется как jsonb в posgresql.
Когда я вызываю save!или update_attribute для него, он не добавляет к нему новое событие перегрузки, но когда я вызываю update_column, он дает желаемый результат.
вот мой код для обновления событий
serialize :events, Shipload::Events::Serializer
def add_transshipment_event
self.events.add_transshipment
# update_column(:events, self.events)
update_attribute(:events, self.events)
# save!
end
здесьevents.rb
class Shipload
class Events
attr_reader :events
# Takes a hash of events
#
# @param [Hash]
def initialize(events)
unless events.present?
events = {}
events[Shipload::Events::Event::GATE_IN_EVENT_KEY] = Shipload::Events::Event.new(event_type: Shipload::Events::Event::GATE_IN)
events[Shipload::Events::Event::ORIGIN_DEPARTURE_EVENT_KEY] = Shipload::Events::Event.new(event_type: Shipload::Events::Event::ORIGIN_DEPARTURE)
events[Shipload::Events::Event::ARRIVAL_EVENT_KEY] = Shipload::Events::Event.new(event_type: Shipload::Events::Event::ARRIVAL)
events[Shipload::Events::Event::GATE_OUT_EVENT_KEY] = Shipload::Events::Event.new(event_type: Shipload::Events::Event::GATE_OUT)
end
@events = events
end
# Takes in the event has received from HTTP request and translates it into {Shipload::Events} object
#
# @param events_hash [Hash]
# @return [Shipload::Events]
def self.parse(events_hash)
events_hash = events_hash["events"]
events = {}
events_hash.keys.each do |key|
event = events_hash[key]
event["mode"] = event["mode"].present? ? event["mode"].to_i : nil
event["planned_date"] = event["planned_date"].present? ? event["planned_date"].to_datetime : nil
event["original_planned_date"] = event["original_planned_date"].present? ? event["original_planned_date"].to_datetime : nil
event["actual_date"] = event["actual_date"].present? ? event["actual_date"].to_datetime : nil
event["event_type"] = event["event_type"].present? ? event["event_type"].to_i : nil
events[key] = Shipload::Events::Event.new(Util.to_h_with_symbol_keys(event))
end
new(events)
end
# Returns total number of events
#
# @return [Integer]
def count
@events.count
end
# Returns the arrival event if present, nil otherwise
#
# @return [Shipload::Events::Event]
def arrival_event
@events[Shipload::Events::Event::ARRIVAL_EVENT_KEY]
end
# Returns event identified by key
#
# @param key [String/ Float]
# @return [Shipload::Events::Event]
def [](key)
@events[key.to_s]
end
# Assigns Event to the key in events
#
# @param key [String/ Float]
# @return [Shipload::Events::Event]
def []=(key, event)
@events[key.to_s] = event
end
# Returns all the values of @events hash
#
# @return [Array]
def values
@events.values
end
# Returns all the keys in @events hash
#
# @return [Array]
def keys
@events.keys.sort
end
# # Returns the Events object in hash format
# #
# @return [Hash]
def to_h
@events.to_h
end
# Adds a transhipment arrival and departure event.
def add_transshipment
add_trans_arrival_event
add_trans_departure_event
end
# Deletes latest transhipment arrival and departure event.
def delete_transshipment
sorted_transshipment_keys = @events.keys.sort[2..-3]
2.times do
@events.except!(sorted_transshipment_keys.last) if sorted_transshipment_keys.present?
sorted_transshipment_keys -= [sorted_transshipment_keys.last]
end
end
# Returns the current event. The most latest event with actual date set is current event
#
# @return [Event]
def current_event
keys.sort.reverse.each do |key|
return self.events[key] if self.events[key].actual_date.present?
end
nil
end
# Returns the next event. It is the event after current event. In case of current_event being nil,
# it returns first event.
#
# @return [Event]
def next_event(current_event)
current_event.nil? ? @events.first.last : @events[keys[keys.index(@events.key(current_event)) + 1]]
end
# Sorts the events on basis of keys
def sort_on_keys!
@events = @events.sort.to_h
end
# Returns total events present
#
# @return [Integer]
def total_events
@events.length
end
# Returns total events yet to occur
#
# @return [Integer]
def pending_events
total_events - completed_events
end
# Returns total events which have occured
#
# @return [Integer]
def completed_events
keys.index(@events.key(current_event)).present? ? keys.index(@events.key(current_event)).to_i + 1 : 0
end
private
# Returns the next key to be
def generate_transshipment_event_key
key = @events.keys.sort[2..-3].last || Shipload::Events::Event::TRANS_SHIPMENT_MASTER_KEY
integer_part, fraction_part = key.split(".")
fraction_part = fraction_part.to_i + Shipload::Events::Event::TRANS_SHIPMENT_KEY_STEP
integer_part+"."+format("%02d",fraction_part)
end
def add_trans_arrival_event
key = generate_transshipment_event_key
trans_arrival = Shipload::Events::Event.new(event_type: Shipload::Events::Event::TRANS_SHIPMENT_ARRIVAL)
@events[key] = trans_arrival
end
def add_trans_departure_event
key = generate_transshipment_event_key
trans_departure = Shipload::Events::Event.new(event_type: Shipload::Events::Event::TRANS_SHIPMENT_DEPARTURE)
@events[key] = trans_departure
end
def latest_transshipment_event
@events[@events.keys.sort[2..-3].last] || nil
end
end
end
serializer.rb
class Shipload
class Events
class Serializer
# Translates events object to format which can be stored in DB
#
# @param [Shipload::Events]
# @return [Hash]
def self.dump(events)
byebug
events.to_h
end
def self.load(events_h)
events = {}
if events_h.present?
events_h.each do |key, value|
%w(planned_date actual_date original_planned_date).each do |date|
value[date] = value[date].to_datetime unless value[date].nil?
end
events[key] = Shipload::Events::Event.new(Util.to_h_with_symbol_keys(value))
end
end
Shipload::Events.new(events)
end
end
end
end