views:

27

answers:

2

I'm trying to keep model logic within my model, but I can't get it to perform modifications on itself and have them persist in the database.

In my controller:

@article.perform_some_calulcations!

In my model:

def perform_some_calculations!
  self.foo.gsub!(/regexp/, 'string')
  self.save
end

If I drop debugger statements into my method and after my call to it in the controller, @article.foo has the correct value. However, when I continue, it doesn't persist in the database and webrick doesn't report any UPDATE statements.

What's going wrong? I don't know if I've ever had to do this before, but surely it's possible right?

+1  A: 

Your attributes might be protected. Check your log. IF that is the case then

self.save! 

or

self.save(false)

try taking the exclamation point off your definition.


self.foo = self.foo.gsub!(/regexp/, 'string')
Sam
Good idea, but `self.save!` and `self.save(false)` both have the same result. No sign of `attr_protected` anywhere or any warnings in the webrick log.
nfm
try taking the exclamation point off your definition.
Sam
No dice with removing the `!` from the method name
nfm
haha, your not setting the variable! check code
Sam
that will do it :)
Sam
heh, I just discovered that independently :P Why does it need explicit assignment if you use `gsub!`?
nfm
I see what you mean because you are doing it in place, but apparently it doesn't work like that in this case.
Sam
+1  A: 

Your problem was that if you modify an attribute "in place", this means: without assigning it a new value, then Rails will think that there is nothing new to be saved, so it "optimizes" the save away.

Each write accessor of your attribute will set a flag, so the save method will know that it should check whether the current value really differs from the value read from the database. That's why self.foo = self.foo.gsub(/regexp/, 'string') works (note that the exclamation mark is not necessary here).

If you need to modify an attribute "in place", for example with gsub! or replace, use:

def perform_some_calculations!
  foo_will_change!
  self.foo.gsub!(/regexp/, 'string')
  self.save
end
Arsen7
Thanks for the extra info
nfm