保存!使用Serializer时不保存更新的值对象

问题描述 投票:0回答:1

我有一个事件对象,它是ruby中哈希的包装器。我用它来存储已经发生但尚未发生的事件。信息包括计划日期,事件的实际日期事件类型模式等。

我在Active Record中使用了serialize方法来加载事件对象。它被存储为posgresql中的jsonb。

当我打电话保存!或者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
ruby-on-rails ruby serializer
1个回答
0
投票

见doc:https://maxivak.com/update_attribute-and-update_attributes-ruby-on-rails/

见链接:Rails: update_column works, but not update_attributes

update_column不验证记录,不调用回调,不调用save方法,虽然它确实更新了数据库中的记录。

可能是某些回调限制使用update_attribute来保存它。

只需使用update_attributes,因为update_attributes尝试验证记录,调用回调和保存。您可以检查错误。

update_attribute不验证记录,调用回调和保存;

您应该使用update_attributes并避免使用其他两种方法,除非您确切知道自己在做什么。如果稍后向模型添加验证和回调,则使用update_attribute和update_column会导致难以调试的令人讨厌的行为。

© www.soinside.com 2019 - 2024. All rights reserved.