Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The behavior of `attribute_changed?` inside of after callbacks will be changing #29035

Closed
pelcasandra opened this Issue May 10, 2017 · 11 comments

Comments

Projects
None yet
8 participants
@pelcasandra
Copy link

pelcasandra commented May 10, 2017

I just upgraded a project to Rails 5.1.0 and I'm seeing this deprecation warning.

DEPRECATION WARNING: The behavior of `attribute_changed?` 
inside of after callbacks will be changing in the next version of Rails.
The new return value will reflect the behavior of calling the method 
after `save` returned (e.g. the opposite of what it returns now). 
To maintain the current behavior, use `saved_change_to_attribute?` instead. 

My code looks like this

class MyClass
  before_valiadtion :my_method

  def my_method
    if name_changed?
      ...
    end
  end
end

I do not understand exactly the deprecation warning. If I use saved_change_to_name instead it will check it after it is saved but this is before validation callback.

I also noticed that if I change the name_changed? to saved_change_to_name my specs are not passing.

I'm having a hard time understanding what the appropriate way to this should be. It seems to me that how it was before it was doing the job okay, not fully understand the reason behind this change and how I should avoid these deprecation warnings.

@matthewd

This comment has been minimized.

Copy link
Member

matthewd commented May 11, 2017

Please use the mailing list or StackOverflow for questions/help, where a wider community will be able to help you. We reserve the issues tracker for issues only.

@matthewd matthewd closed this May 11, 2017

@m1neral

This comment has been minimized.

Copy link

m1neral commented May 22, 2017

According this comment #25337 (comment) attribute_changed? should be replaced to will_save_change_to_attribute?.

Why in the DEPRECATION WARNING is irrelevant information?

@dinatih

This comment has been minimized.

Copy link

dinatih commented Nov 1, 2017

@m1neral

Why in the DEPRECATION WARNING is irrelevant information?

The message says to use saved_change_to_attribute? in place of your will_save_change_to_attribute? (thank you, btw) that is correct when the attribute_changed? is called in an after_validation (not an after_save) callback, in my case.

The behavior of `attribute_changed?` inside of after callbacks will be changing in 
the next version of Rails. The new return value will reflect the behavior of calling 
the method after `save` returned (e.g. the opposite of what it returns now). 
To maintain the current behavior, use **`saved_change_to_attribute?`** instead.

@yoasyo25 yoasyo25 referenced this issue Apr 18, 2018

Open

rails 5.1 #11

@trezona-lecomte

This comment has been minimized.

Copy link
Contributor

trezona-lecomte commented Apr 20, 2018

I have just encountered this same issue, and do not believe it to be a matter for support as @matthewd stated. These are the facts:

  • We call attribute_changed? in a before_validation, not in any after callbacks.
  • The deprecation warning triggers, advising us to not to use attribute_changed? in after callbacks

How is this correct or sensible behaviour?

Further, the documentation for the (apparently) equivalent method of attribute_changed? in this context (i.e. not in an after callback) says simply:

Alias for attribute_changed?

This seems to be false. will_save_change_to_attribute?is not defined as an alias of any other method, and has provably different behaviour from attribute_changed?, e.g.:

(byebug) foo_changed?
true
(byebug) will_save_change_to_attribute?(:foo)
nil
(byebug) saved_change_to_attribute?(:account_type)
true

This is within the context of a before_validation.

How do we go about getting this issue re-opened? Or should I raise a new issue?

Thanks for your help.

@bborn

This comment has been minimized.

Copy link

bborn commented Jun 12, 2018

+1 I agree - this notice is showing up for me even when I'm using an attribute_changed? method in a before_save callback. So in that case, changing it to will_save_change_to_attribute? as suggested by the deprecation notice will break my code.

@trezona-lecomte

This comment has been minimized.

Copy link
Contributor

trezona-lecomte commented Jul 4, 2018

Note that the documentation discrepancy was addressed in #32835.

@bborn check whether you have some after callbacks that are causing your before callbacks to evaluate - in that context you will get the deprecation warning even though from reading your code it looks like you're only using the deprecated methods within before callbacks.

@joemsak

This comment has been minimized.

Copy link

joemsak commented Sep 13, 2018

@trezona-lecomte I've checked my callbacks and anything in after_* callbacks has been carefully coded to use update methods which skip callbacks, and my "*_changed?" calls are only in before_validation or in validates conditionals and I'm still getting this error, and it's pointing to the line of code that is part of the before_validation line

This deprecation error keeps coming back on me every couple months, I can't seem to stomp the wrinkle out of the rug over here

@joemsak

This comment has been minimized.

Copy link

joemsak commented Sep 13, 2018

In the end I changed the callbacks not to check if things changed since they will do the correct behavior either way

@ccelestial

This comment has been minimized.

Copy link

ccelestial commented Sep 20, 2018

I've done an upgrade to Rails 5.1.6 and have the same DEPRECATION warnings. If ever anyone still wants to solve this warning. Here are the steps I took:

Search all of your *_changed?

Changed this:

  if name_changed?
  ...
  if user_id_changed?

To this if it is inside after_* (after_save, after_commit, after_update, etc.) blocks:

  if saved_change_to_name?
  ...
  if saved_change_to_user_id?

AND to this if it is inside before_* (before_save, before_commit, before_update, etc.) blocks:

  if will_save_change_to_name?
  ...
  if will_save_change_to_user_id?

On my own opinion, this is quite tricky thing to change since we've been used to attribute_changed?. But change is good. The syntax also made more sense now.

@joemsak

This comment has been minimized.

Copy link

joemsak commented Sep 20, 2018

Thank you @ccelestial I will try this advice next time I run into it, and I agree the updated syntax makes a lot of sense but I think it's fair to say the change has been difficult to fully comprehend and work around, especially when we get these warnings in before_* callbacks, not just after ones, and that warning makes no mention of these new will_save_change_to_* methods

@ccelestial

This comment has been minimized.

Copy link

ccelestial commented Sep 20, 2018

You're right @joemsak, the warning should also specify/know the block that attribute_changed? was called. It'll be a time saver for all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.