Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should a model method call 'save' itself?

Let's say that we have a method inside a model that

  1. needs to called only on saved records
  2. may update the model itself and thus the model needs to be saved again afterwords

Should the "save" calls happen inside the method itself like the following code

def result
  save! if new_record?

  # do some funky stuff here that may also change the model state
  # ...
  # And calculate the return value
  search_result = "foo" # Let's say "foo" is the value we calculated

  save! if changed?
  search_result # return
end

Or should the external observer (the controller) be responsible for calling save as needed?

like image 501
Nikos D Avatar asked Oct 09 '10 16:10

Nikos D


3 Answers

If your method really, really needs to do all that, so be it.

However, I would make it clear from looking at the method why you're doing that (comments might be good here), and would definitely make this a bang_method! so that it is clear to whoever invokes it that this method is liable to mess with the object as much as it likes.

Also, the method name result (which, I know, probably isn't your real method name) somewhat implies that you're just fetching data, and little more. Maybe load_result! would be more appropriate here, to make it clearer that you're not just accessing an attribute, but are, in fact, performing heavy operations to get it.

like image 52
Matchu Avatar answered Sep 21 '22 14:09

Matchu


There are definitely times when it is necessary for a model to persist itself. But it's worth considering whether save is the best method for your application.

In a current example, we have a model that processes a file asynchronously in a long-running method (we are spinning the process off using sidekiq.) Inside the method, a persistent attribute is updated regularly so the status information is available to other requests.

We're using update_column rather than save, because

  1. We don't want or need the overhead of the AR callbacks, and we particularly want to skip validation to ensure the update occurs surely and immediately.
  2. We only need to update a single attribute. Using update_column avoids the need to determine whether any other attributes need to be saved (or not saved.)

Inside the model, methods like

  • update_column
  • save(:validate => false) (granted, same method, but different options)
  • touch

etc, may often be a more appropriate way to persist changes than a plain save.

like image 21
Tom Wilson Avatar answered Sep 20 '22 14:09

Tom Wilson


When does a program save data on a file?

a) Only when user requires it (directly or indirectly)? -- this is controller case

b) Only when the program achieves part of its correctness and data integrity? -- this is model case

c) Both.

I would vote for (c). I hope this discrimination straightens things a bit.

Additionally, from a object-oriented design point of view, method save() belongs to the public contract of its class; it can be invoked by anyone. Given this, a class is responsible for its public contract and, if needed, an object can invoke its own methods at will.

like image 36
Ioannis Avatar answered Sep 18 '22 14:09

Ioannis