Hi
I remember once I read about to get only updated fields from an
update_attributes method. Means say I have a model user with
name,age,sex etc And when the user updates the information I have to
first check whether he actually updated anything(There is a chance that
update button from view simply being clicked) and if only any updates
happened I have to get that updated fields and send a mail stating that
these fields are updated. How can I do this. Suppose in the above
example if only name updated
Thanks
Tom
On Tue, Mar 2, 2010 at 8:54 PM, Tom M. [email protected] wrote:
Thanks
Tom
Tom, you should be able to do the following to get the attributes that
have
been changed:
model_instance.changed
Next, you’ll need to store this information prior to saving the changes
to the database. Otherwise, the above method will return an empty
array.
Good luck,
-Conrad
–
Hi Conrad
Thanks for your reply. But this is not working for
update_attributes. What I tried is in update action
@user = User.find(params[:id])
if @user.update_attributes(params[:user])
send_mail if @user.changed? #But this is always returns false Not
working
---------
else
end
Thanks
Tom
On 3 March 2010 11:51, Tom M. [email protected] wrote:
else
end
If you look at the source code for update_attributes, you’ll see it
does a “save” in the method, so once it’s finished, the are no changed
fields (because the record has already been updated).
You need a callback filter to run in your User model; and
“before_save” seems sensible to me:
def before_save
send_mail if self.changed?
end
Hi
Thank you. I have one more thing to clarify . If I write a
before_save filter as you suggested, then will mail be sent when ever
there is an update or save to this User model ? That is not what I want
if it behaves like that.Please excuse if I am wrong
Thanks
Tom
On 3 March 2010 12:47, Tom M. [email protected] wrote:
Hi
Thank you. I have one more thing to clarify . If I write a
before_save filter as you suggested, then will mail be sent when ever
there is an update or save to this User model ? That is not what I want
if it behaves like that.Please excuse if I am wrong
Whatever you want will happen whenever whatever conditions you set are
met.
If you send mail on any changes; then yes, mail will be sent on any
changes.
Reading your original post, that’s what you said you wanted…
On 3 March 2010 13:16, Andy J. [email protected] wrote:
if @user.changed?
@user.save
send_mail
end
… and repeat that in every method that makes any updates to your
user…
Whatever works for you, though… it’s your code after all.
Be DRY
:-/
If you look at the source code for update_attributes, you’ll see it
does a “save” in the method, so once it’s finished, the are no changed
fields (because the record has already been updated).
You need a callback filter to run in your User model; and
“before_save” seems sensible to me:
Or alternatively, as you’re looking at the source for ActiveRecord::Base
you’ll see that the update_attributes method simply does this:
def update_attributes(attributes)
self.attributes = attributes
save
end
So, instead of messing about with callbacks, you could simply amend your
original code to this (assigning to attributes rather than calling
update_attributes):
@user = User.find(params[:id])
if @user.attributes = params[:user]
send_mail if @user.changed? #But this is always returns false Not
working
@user.save
else
end
If your send_mail method relies on the user being saved you might need
to
alter it to be:
if @user.changed?
@user.save
send_mail
end
Cheers,
Andy
Be DRY
:-/
While technically you’re right (and therefore it may make more sense to
move
it to the model - @user.update_attributes_and_notify), it seems (from
reading between the OP’s lines) like there are a number of places where
he’d
want to update the user himself (and not send an email) and only have it
send the email from a particular place/action.
I completely agree about DRYness, but I was just offering an alternative
solution as we don’t know the full facts in what he’s trying to do.
Cheers,
Andy
While technically you’re right
Way to get me onside
I’m a part-time developer and part-time sleazy politician “I
completely
agree with you 100%, however…” (notice no “but”). j/k
Let’s split the difference…
Completely agree with the solution (and it’s what I had in mind during
my
last message).
Cheers,
Andy
On 3 March 2010 14:04, Andy J. [email protected] wrote:
While technically you’re right
Way to get me onside
we don’t know the full facts in what he’s trying to do.
Agreed - the “oh, but I didn’t tell you about this condition” syndrome.
Let’s split the difference… create a method on the user model that
checks for .changed? and sends the email, but rather than using it as
an AR callback to hook every update, call it from those controller
methods you want to, and use the default update_attributes
elsewhere… how’s that sound?
Something along the lines of:
User model
def update_attributes_and_notify
self.attributes = attributes
send_email if changed?
save
end
Users controller
@user = User.find(params[:id])
if @user.update_attributes_and_notify(params[:user])
working
else
end
Some other controller
@user = User.find(params[:user_id])
if @user.update_attributes(params[:user])
working
else
end
On 9 March 2010 08:31, Tom M. [email protected] wrote:
even if the validations fail, mail is sent to user (What I need is only
if update happens successfully on changed attributes then only mail to
be sent)
if changed? && save
deliver_user_edit_details!
else
return 'nochange'
end
Hi
I solved it as Michael suggested And it was working .But now i
notified another issue. That is why reopening the thread. The issue is,
even if the validations fail, mail is sent to user (What I need is only
if update happens successfully on changed attributes then only mail to
be sent)
controller code is
@user = User.find(params[:id])
res = @user.update_attributes_and_notify(params[:user])
if res == true
----do this
elsif res == false
----do this
elsif res == ‘nochange’
----do this
end
User model code is
def update_attributes_and_notify(attributes,user)
self.attributes = attributes
if changed?
deliver_user_edit_details!
save
else
return ‘nochange’
end
end
and if I change the line in model
deliver_user_edit_details! if save
I get error
undefined method `call’ for nil:NilClass
What would be the reason? Please help
Thanks
Tom