Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Rename all action callbacks from *_filter to *_action

  • Loading branch information...
commit 9d62e04838f01f5589fa50b0baa480d60c815e2c 1 parent c205284
@dhh dhh authored
View
27 actionpack/CHANGELOG.md
@@ -1,4 +1,31 @@
## Rails 4.0.0 (unreleased) ##
+
+* Rename all action callbacks from *_filter to *_action to avoid the misconception that these
+ callbacks are only suited for transforming or halting the response. With the new style,
+ it's more inviting to use them as they were intended, like setting shared ivars for views.
+
+ Example:
+
+ class PeopleController < ActionController::Base
+ before_action :set_person, except: [ :index, :new, :create ]
+ before_action :ensure_permission, only: [ :edit, :update ]
+
+ ...
+
+ private
+ def set_person
+ @person = current_account.people.find(params[:id])
+ end
+
+ def ensure_permission
+ current_person.change_change?(@person)

Should that read current_person.can_change?(@person)?

@dhh Owner
dhh added a note

No problem, nice change :+1:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ end
+ end
+
+ The old *_filter methods still work with no deprecation notice.
+
+ *DHH*
+
* Add :if / :unless conditions to fragment cache:
<%= cache @model, if: some_condition(@model) do %>
View
150 actionpack/lib/abstract_controller/callbacks.rb
@@ -40,18 +40,21 @@ def _normalize_callback_option(options, from, to) # :nodoc:
end
end
- # Skip before, after, and around filters matching any of the names
+ # Skip before, after, and around action callbacks matching any of the names
+ # Aliased as skip_filter.
#
# ==== Parameters
# * <tt>names</tt> - A list of valid names that could be used for
# callbacks. Note that skipping uses Ruby equality, so it's
# impossible to skip a callback defined using an anonymous proc
# using #skip_filter
- def skip_filter(*names)
- skip_before_filter(*names)
- skip_after_filter(*names)
- skip_around_filter(*names)
+ def skip_action_callback(*names)
+ skip_before_action(*names)
+ skip_after_action(*names)
+ skip_around_action(*names)
end
+
+ alias_method :skip_filter, :skip_action_callback
# Take callback names and an optional callback proc, normalize them,
# then call the block with each callback. This allows us to abstract
@@ -75,119 +78,138 @@ def _insert_callbacks(callbacks, block = nil)
end
##
- # :method: before_filter
+ # :method: before_action
#
- # :call-seq: before_filter(names, block)
+ # :call-seq: before_action(names, block)
#
- # Append a before filter. See _insert_callbacks for parameter details.
+ # Append a callback before actions. See _insert_callbacks for parameter details.
+ # Aliased as before_filter.
##
- # :method: prepend_before_filter
+ # :method: prepend_before_action
#
- # :call-seq: prepend_before_filter(names, block)
+ # :call-seq: prepend_before_action(names, block)
#
- # Prepend a before filter. See _insert_callbacks for parameter details.
+ # Prepend a callback before actions. See _insert_callbacks for parameter details.
+ # Aliased as prepend_before_action.
##
- # :method: skip_before_filter
+ # :method: skip_before_action
#
- # :call-seq: skip_before_filter(names)
+ # :call-seq: skip_before_action(names)
#
- # Skip a before filter. See _insert_callbacks for parameter details.
+ # Skip a callback before actions. See _insert_callbacks for parameter details.
+ # Aliased as skip_before_filter.
##
- # :method: append_before_filter
+ # :method: append_before_action
#
- # :call-seq: append_before_filter(names, block)
+ # :call-seq: append_before_action(names, block)
#
- # Append a before filter. See _insert_callbacks for parameter details.
+ # Append a callback before actions. See _insert_callbacks for parameter details.
+ # Aliased as append_before_filter.
##
- # :method: after_filter
+ # :method: after_action
#
- # :call-seq: after_filter(names, block)
+ # :call-seq: after_action(names, block)
#
- # Append an after filter. See _insert_callbacks for parameter details.
+ # Append a callback after actions. See _insert_callbacks for parameter details.
+ # Aliased as after_filter.
##
- # :method: prepend_after_filter
+ # :method: prepend_after_action
#
- # :call-seq: prepend_after_filter(names, block)
+ # :call-seq: prepend_after_action(names, block)
#
- # Prepend an after filter. See _insert_callbacks for parameter details.
+ # Prepend a callback after actions. See _insert_callbacks for parameter details.
+ # Aliased as prepend_after_filter.
##
- # :method: skip_after_filter
+ # :method: skip_after_action
#
- # :call-seq: skip_after_filter(names)
+ # :call-seq: skip_after_action(names)
#
- # Skip an after filter. See _insert_callbacks for parameter details.
+ # Skip a callback after actions. See _insert_callbacks for parameter details.
+ # Aliased as skip_after_filter.
##
- # :method: append_after_filter
+ # :method: append_after_action
#
- # :call-seq: append_after_filter(names, block)
+ # :call-seq: append_after_action(names, block)
#
- # Append an after filter. See _insert_callbacks for parameter details.
+ # Append a callback after actions. See _insert_callbacks for parameter details.
+ # Aliased as append_after_filter.
##
- # :method: around_filter
+ # :method: around_action
#
- # :call-seq: around_filter(names, block)
+ # :call-seq: around_action(names, block)
#
- # Append an around filter. See _insert_callbacks for parameter details.
+ # Append a callback around actions. See _insert_callbacks for parameter details.
+ # Aliased as around_filter.
##
- # :method: prepend_around_filter
+ # :method: prepend_around_action
#
- # :call-seq: prepend_around_filter(names, block)
+ # :call-seq: prepend_around_action(names, block)
#
- # Prepend an around filter. See _insert_callbacks for parameter details.
+ # Prepend a callback around actions. See _insert_callbacks for parameter details.
+ # Aliased as prepend_around_filter.
##
- # :method: skip_around_filter
+ # :method: skip_around_action
#
- # :call-seq: skip_around_filter(names)
+ # :call-seq: skip_around_action(names)
#
- # Skip an around filter. See _insert_callbacks for parameter details.
+ # Skip a callback around actions. See _insert_callbacks for parameter details.
+ # Aliased as skip_around_filter.
##
- # :method: append_around_filter
+ # :method: append_around_action
#
- # :call-seq: append_around_filter(names, block)
+ # :call-seq: append_around_action(names, block)
#
- # Append an around filter. See _insert_callbacks for parameter details.
+ # Append a callback around actions. See _insert_callbacks for parameter details.
+ # Aliased as append_around_filter.
- # set up before_filter, prepend_before_filter, skip_before_filter, etc.
+ # set up before_action, prepend_before_action, skip_before_action, etc.
# for each of before, after, and around.
- [:before, :after, :around].each do |filter|
+ [:before, :after, :around].each do |callback|
class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
- # Append a before, after or around filter. See _insert_callbacks
+ # Append a before, after or around callback. See _insert_callbacks
# for details on the allowed parameters.
- def #{filter}_filter(*names, &blk) # def before_filter(*names, &blk)
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
- set_callback(:process_action, :#{filter}, name, options) # set_callback(:process_action, :before, name, options)
- end # end
- end # end
+ def #{callback}_action(*names, &blk) # def before_action(*names, &blk)
+ _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
+ set_callback(:process_action, :#{callback}, name, options) # set_callback(:process_action, :before, name, options)
+ end # end
+ end # end
- # Prepend a before, after or around filter. See _insert_callbacks
+ alias_method :#{callback}_filter, :#{callback}_action
+
+ # Prepend a before, after or around callback. See _insert_callbacks
# for details on the allowed parameters.
- def prepend_#{filter}_filter(*names, &blk) # def prepend_before_filter(*names, &blk)
- _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
- set_callback(:process_action, :#{filter}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true))
- end # end
- end # end
+ def prepend_#{callback}_action(*names, &blk) # def prepend_before_action(*names, &blk)
+ _insert_callbacks(names, blk) do |name, options| # _insert_callbacks(names, blk) do |name, options|
+ set_callback(:process_action, :#{callback}, name, options.merge(:prepend => true)) # set_callback(:process_action, :before, name, options.merge(:prepend => true))
+ end # end
+ end # end
+
+ alias_method :prepend_#{callback}_filter, :prepend_#{callback}_action
- # Skip a before, after or around filter. See _insert_callbacks
+ # Skip a before, after or around callback. See _insert_callbacks
# for details on the allowed parameters.
- def skip_#{filter}_filter(*names) # def skip_before_filter(*names)
- _insert_callbacks(names) do |name, options| # _insert_callbacks(names) do |name, options|
- skip_callback(:process_action, :#{filter}, name, options) # skip_callback(:process_action, :before, name, options)
- end # end
- end # end
-
- # *_filter is the same as append_*_filter
- alias_method :append_#{filter}_filter, :#{filter}_filter # alias_method :append_before_filter, :before_filter
+ def skip_#{callback}_action(*names) # def skip_before_action(*names)
+ _insert_callbacks(names) do |name, options| # _insert_callbacks(names) do |name, options|
+ skip_callback(:process_action, :#{callback}, name, options) # skip_callback(:process_action, :before, name, options)
+ end # end
+ end # end
+
+ alias_method :skip_#{callback}_filter, :skip_#{callback}_action
+
+ # *_action is the same as append_*_action
+ alias_method :append_#{callback}_action, :#{callback}_action # alias_method :append_before_action, :before_action
+ alias_method :append_#{callback}_filter, :#{callback}_action # alias_method :append_before_filter, :before_action
RUBY_EVAL
end
end
View
10 actionpack/test/abstract/callbacks_test.rb
@@ -84,11 +84,11 @@ def setup
end
class Callback3 < ControllerWithCallbacks
- before_filter do |c|
+ before_action do |c|
c.instance_variable_set("@text", "Hello world")
end
- after_filter do |c|
+ after_action do |c|
c.instance_variable_set("@second", "Goodbye")
end
@@ -114,8 +114,8 @@ def setup
end
class CallbacksWithConditions < ControllerWithCallbacks
- before_filter :list, :only => :index
- before_filter :authenticate, :except => :index
+ before_action :list, :only => :index
+ before_action :authenticate, :except => :index
def index
self.response_body = @list.join(", ")
@@ -202,7 +202,7 @@ def setup
end
class ChangedConditions < Callback2
- before_filter :first, :only => :index
+ before_action :first, :only => :index
def not_index
@text ||= nil

34 comments on commit 9d62e04

@jeremy
Owner

:+1:

@luizkowalski

nice one!

@imkmf

Changing this to action makes a lot more sense for people learning these things (like me) in understanding that there's a verb going on here (as in :authenticate as an action). Thanks for this.
:thumbsup:

@josh
Collaborator

I dig it. :zap:

@natebird

Small changes like this is Rails that make it better semantically are what keep me using it. Great change.

@wildchild

I miss Merb's before and after.

@dvarelap

nice!

@AlexanderPavlenko

Does the return value (true or false) still control the flow?
It looks more natural for me to expect method with such a name before_action to raise exception or call some another method like halt!.

@glongman

works for me

@fxn
Owner

The return value was taken into account in the early days, but it's been a long time since filters are halted by rendering or redirecting.

@3den

@dhh why not just before :action, :do_something?

@dhh
Owner

Marcelo, because that's terribly ambiguous. before what? before rendering? before :authenticate "before authenticate"? before_action :authenticate is much clearer.

@mislav

I don't like the example in the documentation:

def set_person
  @person = current_account.people.find(params[:id])
end

Having a separate method just to set an ivar is an antipattern. I don't want to teach this to less experienced developer.

A much better implementation would be: (although, then it quits being an example for before_action)

def current_person
  @current_person ||= current_account.people.find(params[:id])
end
@qingwang

before_filter did confuse me a little bit at the beginning. Nice change. I was thinking before_do , after_do .

@dhh
Owner
@Dorian

Nice! Great to see that you can always change the API even if it's a popular method.

@3den

Hi @dhh, Thanks for your reply. One of the best thinks about rails is it clean and easy to read syntax. For sure _action is more meaningful than _filter but both add redundancy to de code. In plain english before :save, :calculate_total reads much cleaner than before_action :save, :calculate_total.

@dhh
Owner
@Dorian

@3den: Maybe before and after are too general words to be used here (they may be used in action names) but renaming to before/after would be better.

@matthewrobertson

I feel :neutral_face: about this. I think it would have been nice if it were called before_action from the beginning of time but I dunno if you actually get a lot of milage from the principle of least surprise . As someone thats been coding rails for a while I'm going to be like: "WTF is a before_action!?" If it aint broke, why fix it?

@muescha

why not an alias method which inform about the removing version - dont take all the old legacy code with every version. better clean it. too much similar methods also confuses newcomers

alias_deprecated_method 4.1, :old, :new

@steveklabnik
Collaborator

@muescha because it is not deprecated at this time. Just introducing a new name. If it's significantly nicer, we'll deprecate the old one.

@PikachuEXE

This name makes much more sense! :thumbsup:

@hpyhacking

对代码有洁癖

@knwang

Makes sense. +1

@kodemunki

I think _action is self-explanatory. It'd be nice though if we had a backport for 3.2.10, just one more thing we need to remember to do for the upgrade. Before you all retaliate I know before_filter and after_filter aren't deprecated yet, but most will want to use the new syntax, so moving to _action will become the norm.

@carlosantoniodasilva

@MeetDom sorry, no new features are backported to 3.2, only bug fixes. But it should be dead easy to alias the methods before/after filter in your application controller, and start using as before/after action.

@examplecode

good job ,it's more appropriate

@liuganggang

长姿势了:+1

Please sign in to comment.
Something went wrong with that request. Please try again.