class LegalEntity end
Merchant#owner_first_name
, then the data were simultaneously recorded in LegalEntity#first_name
. At this point, the old data in LegalEntity has not yet been migrated, so the Merchant and AccountApplication tables remained the “source of truth”. class Merchant # Each Merchant has a LegalEntity prop :legal_entity, foreign: LegalEntity def self.legal_entity_proxy(merchant_prop_name, legal_entity_prop_name) # Redefine the Merchant setter method to also write to the LegalEntity merchant_prop_name_set = :"#{merchant_prop_name}=" original_merchant_prop_name_set = :"original_#{merchant_prop_name_set}" alias_method original_merchant_prop_name_set, merchant_prop_name_set if method_defined?(merchant_prop_name_set) define_method(merchant_prop_name_set) do |val| self.public_send(original_merchant_prop_name_set, val) self.legal_entity.public_send(:"#{legal_entity_prop_name}=", val) end end legal_entity_proxy :owner_first_name, :first_name before_save do # Make sure that we actually save our LegalEntity double-write. # This "multi-save" can cause confusion and unnecessary database calls, # but is a necessary evil and will be unwound later self.legal_entity.save end end merchant.owner_first_name = 'Barry' merchant.save merchant.legal_entity.first_name # => Also 'Barry'
class Merchant prop :legal_entity, foreign: LegalEntity def self.legal_entity_proxy(merchant_prop_name, legal_entity_prop_name) # # UPDATED: Now we also redefine the Merchant getter method to read from the LegalEntity # alias_method :"original_#{merchant_prop_name}", merchant_prop_name if method_defined?(merchant_prop_name) define_method(merchant_prop_name) do self.legal_entity.public_send(legal_entity_prop_name) end # We continue to write to both tables for safety merchant_prop_name_set = :"#{merchant_prop_name}=" original_merchant_prop_name_set = :"original_#{merchant_prop_name_set}" alias_method original_merchant_prop_name_set, merchant_prop_name_set if method_defined?(merchant_prop_name_set) define_method(merchant_prop_name_set) do |val| self.public_send(original_merchant_prop_name_set, val) self.legal_entity.public_send(:"#{legal_entity_prop_name}=", val) end end legal_entity_proxy :owner_first_name, :first_name before_save do self.legal_entity.save end end merchant.owner_first_name # => calls legal_entity.first_name, which should be the same as Merchant#owner_first_name anyway
merchant.owner_first_name
written and read only to and from the LegalEntity table, and there is no longer an owner_first_name
entity in the Merchant table.merchant.owner_first_name = 'Barry'
legal_entity.first_name = 'Barry'
class Merchant prop :legal_entity, foreign: LegalEntity def self.legal_entity_proxy(merchant_prop_name, legal_entity_prop_name) alias_method :"original_#{merchant_prop_name}", merchant_prop_name if method_defined?(merchant_prop_name) define_method(merchant_prop_name) do # # UPDATED: We add in logging # log.info('Deprecated method called') self.legal_entity.public_send(legal_entity_prop_name) end merchant_prop_name_set = :"#{merchant_prop_name}=" original_merchant_prop_name_set = :"original_#{merchant_prop_name_set}" alias_method original_merchant_prop_name_set, merchant_prop_name_set if method_defined?(merchant_prop_name_set) define_method(merchant_prop_name_set) do |val| # # UPDATED: We add in logging # log.info('Deprecated method called') self.legal_entity.public_send(:"#{legal_entity_prop_name}=", val) end end end
class Merchant prop :legal_entity, foreign: LegalEntity # REMOVED # # def self.legal_entity_proxy(merchant_prop_name, legal_entity_prop_name) # # etc # end # # legal_entity_proxy :owner_first_name, :first_name before_save do self.legal_entity.save end end
legal_entity.first_name = 'Barry' merchant.save
merchant.save
(or similar things) somehow affect the change of fields in legal_entity, and change the before_save
sections as follows: class Merchant prop :legal_entity, foreign: LegalEntity before_save do # Our ORM's implementation of "dirty" fields unless self.legal_entity.updated_fields.empty? self.legal_entity.save log.info('Multi-saved an updated model') end end end
'Multi-saved an updated model'
in order to find out all the places where saving Merchant and AccountApplicaion also affects saving New Data to LegalEntity. This table is saved before changes are saved in another model, which leads to setting an empty value in the field legal_entity.updated_fields
- in such a situation nothing will appear in the logs. And here is the code: legal_entity.first_name = 'Barry' merchant.business_url = 'http://foobar.com' merchant.save
LegalEntity#owner_name
. It needs to be changed to: legal_entity.first_name = 'Barry' legal_entity.save merchant.business_url = 'http://foobar.com' merchant.save
legal_entity
save itself previously. class Merchant prop :legal_entity, foreign: LegalEntity end
If you ever want to write one huge pull request to migrate a huge amount of anything, think twice about whether there is any possibility to make the whole process not so terribly dependent on luck. If the answer is “no”, before starting the process, you should take care of false documents and credit history, which will help you to leave the country (and most likely you will have to do it soon) and start a new life in Brazil.
Source: https://habr.com/ru/post/266111/
All Articles