drapergem / draper

Decorators/View-Models for Rails Applications
MIT License
5.22k stars 527 forks source link

Virtual attributes and mass assignment #840

Closed lapitsky closed 2 weeks ago

lapitsky commented 5 years ago

I can define a virtual attribute in an ActiveRecord model class like

def virtual_attr
  ...
end

def virtual_attr=(val)
  ...
end

It allows me to make calls like model.update(virtual_attr: 'Hi!')

When I try to do the same for a decorated model class it fails in internal _assign_attribute method. I think the reason is that it tries to do send(:virtual_attr=) for the model object and does not find such a method there.

What is the recommended way to create virtual attributes in decorator classes so that I could do decorated_model.update(virtual_attr: 'Hi!')?

thaispeixoto commented 4 years ago

Any news on this? I'm having this same problem.

klyonrad commented 3 years ago

Honestly... isn't this a bit out of scope? What prevents you from accessing the non decorated record directly?

Alexander-Senko commented 2 weeks ago

What is the recommended way to create virtual attributes in decorator classes so that I could do decorated_model.update(virtual_attr: 'Hi!')?

I'm not sure if there could be any 🤔

Here, #update is called on an underlying model unless the method is explicitly defined in a decorator (in Darper, it's not). A model does (and should) know nothing about its decorator. Thus, its #update can't get access to decorator's attributes.

Another matter to be considered is separation of concerns. #update is a part of persistence interface, meanwhile decorators stand for representation which is the reverse side of a model. That's why it's hardly possible for that interface will ever be implemented here in Draper.

Alexander-Senko commented 2 weeks ago

…Unless the method is explicitly defined in a decorator…

Thus, if you still eager to, you may define #update for your basic decorator, based on the code from Active Record.