4

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 = 'john@email.com'

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

UserRepository.update(user_instance2)
#expected: UPDATE USER SET EMAIL = 'john@email.com' 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?

Luiz A.
  • 43
  • 1
  • 5
  • Any specific reason why you can't upgrade to v0.7.0? This way you could use update with the id and data to be updated. – Rodrigo Vasconcelos May 03 '18 at 10:21
  • The software is big monolith and it is not so easy to upgrade it, given that this upgrade requires handling with some new concepts, such as immutable entities. We are working on it, but I would like to know if there was an alternative for this problem. The solution is to upgrade. – Luiz A. May 18 '18 at 16:24

1 Answers1

7

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"
Anton
  • 287
  • 2
  • 9