zilverline / sequent

CQRS & event sourcing framework for Ruby
https://www.sequent.io
MIT License
541 stars 58 forks source link

What's a proper flow to rename attribute for command, event and aggregate? #379

Closed smilyalexey closed 1 year ago

smilyalexey commented 1 year ago

Hello @lvonk. Can you explain me the process of renaming fields in command, event and aggregate.

Let's imagine I have SearchSubmitted event:

class SearchSubmitted < Sequent::Event
    attrs start_at: Time, finish_at: Time
end

SubmitSearch command:

class SubmitSearch < Sequent::Command
  attrs start_at: Time, finish_at: Time
end

And finally there is aggregate Search:

class Search < Sequent::AggregateRoot
  def initialize(command)
    super(command.aggregate_id)

    apply SearchSubmitted, start_at: command.start_at, end_at: command.end_at
  end

  on SearchSubmitted do |event|
    @start_at = event.start_at
    @finish_at = event.end_at
  end    
end

Now I found that end_at is better than finish_at. What's a proper flow to rename it? In documentation I found upcasting, but it looks as if it's only for event. Also there is mentioning that it's possible to update EventRecord directly. What about commands and aggregate? How should I update them?

And regarding upcasting - should it be like in docs:

class SearchSubmitted < Sequent::Event
  attrs start_at: Time, end_at: Time

  upcast do |hash|
    hash['end_at'] = hash['finish_at']
  end
end

or we also need to check if there is no hash['end_at']? Something like this:

  upcast do |hash|
      hash['end_at'] = hash['finish_at']     if hash['finish_at'].present?
  end
lvonk commented 1 year ago

You found the proper flow to rename it. You need to:

  1. Change the event and use upcasting
  2. Change the Aggregate so it uses the new attribute and any other references to that attribute name that you changed like you would do when you rename a method or attribute in any ruby object.
  3. I would also change the command, but don't need to upcast since it is only stored for reference and never deserialized (at least not by sequent).
  upcast do |hash|
      hash['end_at'] = hash['finish_at'] if hash['finish_at'].present?
  end

This is indeed the proper way. Thanks for reporting this.

Also there is mentioning that it's possible to update EventRecord directly.

I actually don't think this is a good advice and will remove it from the docs.

smilyalexey commented 1 year ago

ok it's clear now. thanks 👍