LWRP notifying on changed resources

Opscode Chef's light-weight resource providers are awesome. They allow you to compose a more complex resource from simpler resources. The one thing that has always annoyed me is that you can no longer use notifications to indicate which resources are actually changed or so I thought. Then along came a post at a gist by yfeldblum that demonstrated how to do this.

Of course I wanted to simplify this as almost all of our LWRPs will need this so I converted it into a method that can be added in the library directory.

def notifying_action(key, &block)
  action key do
    # So that we can refer to these within the sub-run-context
    # block.
    cached_new_resource = new_resource
    cached_current_resource = current_resource

    # Setup a sub-run-context.
    sub_run_context = @run_context.dup
    sub_run_context.resource_collection =
       Chef::ResourceCollection.new

    # Declare sub-resources within the sub-run-context. Since they
    # are declared here, they do not pollute the parent run-context.
    begin
      original_run_context, @run_context =
          @run_context, sub_run_context
      instance_eval(&block)
    ensure
      @run_context = original_run_context
    end

    # Converge the sub-run-context inside the provider action.
    # Make sure to mark the resource as updated-by-last-action if
    # any sub-run-context resources were updated (any actual
    # actions taken against the system) during the
    # sub-run-context convergence.
    begin
      Chef::Runner.new(sub_run_context).converge
    ensure
      if sub_run_context.resource_collection.any?(&:updated?)
        new_resource.updated_by_last_action(true)
      end
    end
  end
end

Now all the providers can simply use something like the following to define your actions in your provider. This will propagate notifications if any sub-resources have changed.

notifying_action :run do
  file "/tmp/something" do
    owner "root"
    group "root"
    mode "0755"
    action :create
  end
end