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

Allow ActiveSupport::Deprecation features to be used by rails applications and library authors #6348

Merged
merged 2 commits into from Sep 13, 2012

Conversation

LTe
Copy link
Contributor

@LTe LTe commented May 16, 2012

Updated version of #2310

@rafaelfranca
Copy link
Member

cc @josevalim @jeremy

@jeremy
Copy link
Member

jeremy commented May 16, 2012

  1. If we're exposing this for reuse, we need docs! How should a library author use this?
  2. Feels like libraries using separate deprecators should be working with instances of a class rather than extending with a module that injects a bunch of behavior, including its internal state. Could make ActiveSupport::Deprecation a class (without breaking API) and delegate the existing toplevel methods to a singleton ActiveSupport::Deprecation.instance
  3. The #deprecator instance method may be unnecessary. Looks like the only reason we need it is so the deprecated method wrapper can refer to it. It'd be cleaner to pass a deprecator instance and reference it directly from the method wrapper (using define_method instead of class_eval)

@LTe
Copy link
Contributor Author

LTe commented May 18, 2012

@jeremy done :)


# Default warning behaviors per Rails.env.
DEFAULT_BEHAVIORS = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably leave these as a constant since it acts as public API now. People add behaviors to this hash directly.

@jeremy
Copy link
Member

jeremy commented May 18, 2012

@LTe Very nice! Looking good.

# Example
# OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST')
# Example with custom deprecator
# OLD_CONST = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('OLD_CONST', 'NEW_CONST'. deprecator_instance)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: . instead of , after NEW_CONST.

@LTe
Copy link
Contributor Author

LTe commented May 19, 2012

@carlosantoniodasilva @jeremy thanks for feedback!

@paneq
Copy link
Contributor

paneq commented May 20, 2012

What do you think about it:

module ActiveSupport
  class Deprecation
    def initialize(horizon = '3.2', gem_name = 'rails')
      self.deprecation_horizon = horizon
      self.gem_name = gem_name
    end
  end
end

For custom gems authors should create new instances of ActiveSupport::Deprecation to generate proper warning messages. If they use ActiveSupport::Deprecation.instance the message is going to say that something will be removed from rails which is in many cases not what the authors of gems would like to announce to the users.

These:

deprecator = ActiveSupport::Deprecation.new
deprecator.deprecation_horizon = "2.0.0"
ActiveSupport::Deprecation.new.tap{|d| d.deprecation_horizon = "2.0.0" }

seem to be unnecessary verbose to me.

ActiveSupport::Deprecation.new("2.0.0", "formtastic")

looks much better imho.

@paneq
Copy link
Contributor

paneq commented May 20, 2012

Science Fiction:

module ActiveSupport
  class Deprecation
    def initialize(horizon = default_horizon, gem_name = 'rails')
      self.deprecation_horizon = horizon
      self.gem_name = gem_name
    end

    def default_horizon
      "#{ActiveSupport::VERSION::MAJOR}.#{ActiveSupport::VERSION::MINOR + 1}"
    end
  end
end

because sometimes it should be major + 1. Or maybe it should be always major +1 and never minor + 1 ?

@LTe
Copy link
Contributor Author

LTe commented May 21, 2012

Now you can create instance of deprecator and create new object via new.
I like @paneq approach -- now this is simple to reuse.

About science fiction I think better solution is pass directly version to initialize method.

@paneq
Copy link
Contributor

paneq commented May 21, 2012

"About science fiction I think better solution is pass directly version to initialize method." - probably. Except for the fact that the core team needs to change this one line every time there is new rails version. I wanted to spare them this trouble in this science fiction solution :)

@LTe
Copy link
Contributor Author

LTe commented May 21, 2012

According to http://semver.org/ this always should be major +1

@LTe
Copy link
Contributor Author

LTe commented May 23, 2012

@jeremy what do you think? We can merge current implementation?

# [+log+] Log all deprecation warnings to +Rails.logger+.
# [+notify+] Use <tt>ActiveSupport::Notifications</tt> to notify +deprecation.rails+.
# [+notify] Use +ActiveSupport::Notifications+ to notify +deprecation.rails+.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[+notify+] formatting changed?

@LTe
Copy link
Contributor Author

LTe commented May 23, 2012

@jeremy updated and rebased

# Default warning behaviors per Rails.env.
DEFAULT_BEHAVIORS = {
:stderr => Proc.new { |message, callstack|
$stderr.puts(message)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra indentation here

@jeremy
Copy link
Member

jeremy commented May 23, 2012

@LTe some comments on the documentation :)

It covers how to give a custom deprecator object, but doesn't show how you can use ActiveSupport::Deprecation.new(version, libname) yourself.

When I read through the duck type for a deprecator, having to implement two methods seems wrong, too. We call deprecator.deprecated_method_warning then pass its return value to #warn -- we could just call one method and let the deprecator handle that internally.

@paneq
Copy link
Contributor

paneq commented May 23, 2012

@jeremy - I think that's because #warn has the logic for outputing to logger, stderr, output or whatever is configured in current development environment and #deprecated_method_warning is just responsible for generting the warning. One might want to generate different warnings for his own gem but keep the logic coherent with Rails as to where they are displayed. What do you think ?

@jeremy
Copy link
Member

jeremy commented May 23, 2012

@paneq definitely -- and a higher-level method like deprecation_warning(deprecated_method_name, message, caller_backtrace) could wrap that up. Then custom classes can implement that one method whereas subclasses of ActiveSupport::Deprecation can override just deprecated_method_warning if they like.

@LTe
Copy link
Contributor Author

LTe commented Jun 7, 2012

Updated

@LTe
Copy link
Contributor Author

LTe commented Jun 29, 2012

@jeremy what do you think about merge?

@steveklabnik
Copy link
Member

@LTe it needs rebased at least, it can't be merged cleanly anymore.

@LTe
Copy link
Contributor Author

LTe commented Jul 2, 2012

@steveklabnik rebased ;-)

@steveklabnik
Copy link
Member

Thanks. Let's see what @jeremy says.

@paneq
Copy link
Contributor

paneq commented Jul 9, 2012

What do you think @jeremy ?

@jeremy
Copy link
Member

jeremy commented Sep 11, 2012

👍

# Kernel.warn message
# end
#
# end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove whitespaces between the method and class declaration, there's no need for them ✂️

@carlosantoniodasilva
Copy link
Member

@LTe hey, could you please add a changelog entry for this, and check the minor comments I made, so that we can get this in master? Thanks!

@LTe
Copy link
Contributor Author

LTe commented Sep 12, 2012

@carlosantoniodasilva updated, rebased.

@carlosantoniodasilva
Copy link
Member

@LTe, great thanks. I'll have to ask you one more thing though, to review your commit message and improve the changelog a bit with an example of how to use this new feature. This will help others to understand the reasoning and how to use the feature at the same time when reading the commits or the changelog.

Here's an explanation about how to go with the commit message, and here's another about changelogs.

I'll merge it afterwards. Thanks!

paneq and others added 2 commits September 13, 2012 08:42
…xtend/include it also.

test local deprecation

deprecator object

Test ActiveSupport::Deprecation when included
ActiveSupport::Deprecation is now a class rather than a module. You can
get instance of ActiveSupport::Deprecation calling #instance method.

  ActiveSupport::Deprecation.instance

But when you need to get new object od ActiveSupport::Deprecation you
need to just call #new.

  @instance = ActiveSupport::Deprecation.new

Since you can create a new object, you can change the version and the
name of the library where the deprecator concerned.

  ActiveSupport::Deprecation.new('2.0', 'MyGem')

If you need use another deprecator instance you can select it in the
options of deprecate method.

  deprecate :method, :deprecator => deprecator_instance

Documentation has been updated.
@LTe
Copy link
Contributor Author

LTe commented Sep 13, 2012

@carlosantoniodasilva updated

@carlosantoniodasilva
Copy link
Member

@LTe great, thank you!

carlosantoniodasilva added a commit that referenced this pull request Sep 13, 2012
Allow ActiveSupport::Deprecation features to be used by rails applications and library authors
@carlosantoniodasilva carlosantoniodasilva merged commit 01ef633 into rails:master Sep 13, 2012
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants