Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to update only changed attributes in Hanami Model?

Given I am using Hanami Model version 0.6.1, I would like the repository update only the changed attributes of an entity.

For example:

user_instance1 = UserRepository.find(1)
user_instance1.name = 'John'

user_instance2 = UserRepository.find(1)
user_instance2.email = '[email protected]'

UserRepository.update(user_instance1)
#expected: UPDATE USER SET NAME = 'John' WHERE ID = 1

UserRepository.update(user_instance2)
#expected: UPDATE USER SET EMAIL = '[email protected]' WHERE ID = 1

But what it happens is that the second command overrides all fields, including those which were not changed.

I know I can use the Hanami::Entity::DirtyTracking to get all changed attributes, but I do not know how to update an entity partially with these attributes.

Is there a way to do this?

like image 710
Luiz A. Avatar asked Mar 06 '23 17:03

Luiz A.


1 Answers

hanami entity is an immutable data structure. That's why you can't change data with setters:

>> account = AccountRepository.new.first
=> #<Account:0x00007ffbf3918010 @attributes={ name: 'Anton', ...}>

>> account.name
=> "Anton"

>> account.name = "Other"
        1: from /Users/anton/.rvm/gems/ruby-2.5.0/gems/hanami-model-1.2.0/lib/hanami/entity.rb:144:in `method_missing'
NoMethodError (undefined method `name=' for #<Account:0x00007ffbf3918010>)

Instead, you can create a new one entity, for example:

# will return a new account entity with updated attributes
>> Account.new(**account, name: 'A new one')

And also, you can use #update with old entity object:

>> AccountRepository.new.update(account.id, **account, name: 'A new name')
=> #<Account:0x00007ffbf3918010 @attributes={ name: 'Anton', ...}>

>> account = AccountRepository.new.first
=> #<Account:0x00007ffbf3918010 @attributes={ name: 'Anton', ...}>

>> account.name
=> "A new name"
like image 159
Anton Avatar answered Mar 23 '23 07:03

Anton