aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/callbacks.rb
Commit message (Collapse)AuthorAgeFilesLines
* Eliminate instance level writers for class accessorsAaron Patterson2016-01-221-2/+2
| | | | | | | | | Instance level writers can have an impact on how the Active Model / Record objects are saved. Specifically, they can be used to bypass validations. This is a problem if mass assignment protection is disabled and specific attributes are passed to the constructor. CVE-2016-0753
* Deprecate passing string to define callback.yui-knk2015-12-161-1/+8
|
* nodoc for active support protected method [CI skip]Gaurav Sharma2015-10-041-3/+3
|
* Refactor AS::Callbacks halt config and fix the documentationRoque Pinel2015-10-011-7/+8
| | | | | | | | | Move from `AS::Callbacks::CallbackChain.halt_and_display_warning_on_return_false` to `AS::Callbacks.halt_and_display_warning_on_return_false` base on [this discussion](https://github.com/rails/rails/pull/21218#discussion_r39354580) Fix the documentation broken by 0a120a818d413c64ff9867125f0b03788fc306f8
* Fix the AS::Callbacks terminator regression from 4.2.3Roque Pinel2015-09-221-14/+28
| | | | | | Rails 4.2.3 AS::Callbacks will not halt chain if `false` is returned. That is the behavior of specific callbacks like AR::Callbacks and AM::Callbacks.
* Remove AS methods that are never invokedclaudiob2015-09-131-68/+6
| | | | | | | | | | | | | | | | | | | | Fixes #21122 - does not change any current behavior; simply reflects the fact that two conditions of the if/else statement are never reached. The reason is #17227 which adds a default terminator to AS::Callbacks. Therefore, even callback chains that do not define a terminator now have a terminator, and `chain_config.key?(:terminator)` is always true. Of course, if no terminator was defined, then we want this new default terminator not to do anything special. What the terminator actually does (or should do) is discussed in #21218 but the simple fact that a default terminator exists makes this current PR valid. *Note* that the conditional/simple methods have not been removed in AS::Conditionals::Filter::After because of `:skip_after_callbacks_if_terminated` which lets a user decide **not** to skip after callbacks even if the chain was terminated.
* [ci skip] Fix the AS::Callbacks terminator docsRoque Pinel2015-08-081-3/+3
| | | | | | | The second argument of the terminator lambda is no longer the result of the callback, but the result lambda. https://github.com/rails/rails/blob/3a7609e2bafee4b071fe35136274e6ccbae8cacd/activesupport/test/callbacks_test.rb#L553
* Revert "Revert "Reduce allocations when running AR callbacks.""Guo Xiang Tan2015-07-161-3/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This reverts commit bdc1d329d4eea823d07cf010064bd19c07099ff3. Before: Calculating ------------------------------------- 22.000 i/100ms ------------------------------------------------- 229.700 (± 0.4%) i/s - 1.166k Total Allocated Object: 9939 After: Calculating ------------------------------------- 24.000 i/100ms ------------------------------------------------- 246.443 (± 0.8%) i/s - 1.248k Total Allocated Object: 7939 ``` begin require 'bundler/inline' rescue LoadError => e $stderr.puts 'Bundler version 1.10 or later is required. Please update your Bundler' raise e end gemfile(true) do source 'https://rubygems.org' # gem 'rails', github: 'rails/rails', ref: 'bdc1d329d4eea823d07cf010064bd19c07099ff3' gem 'rails', github: 'rails/rails', ref: 'd2876141d08341ec67cf6a11a073d1acfb920de7' gem 'arel', github: 'rails/arel' gem 'sqlite3' gem 'benchmark-ips' end require 'active_record' require 'benchmark/ips' ActiveRecord::Base.establish_connection('sqlite3::memory:') ActiveRecord::Migration.verbose = false ActiveRecord::Schema.define do create_table :users, force: true do |t| t.string :name, :email t.boolean :admin t.timestamps null: false end end class User < ActiveRecord::Base default_scope { where(admin: true) } end admin = true 1000.times do attributes = { name: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", email: "foobar@email.com", admin: admin } User.create!(attributes) admin = !admin end GC.disable Benchmark.ips(5, 3) do |x| x.report { User.all.to_a } end key = if RUBY_VERSION < '2.2' :total_allocated_object else :total_allocated_objects end before = GC.stat[key] User.all.to_a after = GC.stat[key] puts "Total Allocated Object: #{after - before}" ```
* Fix grammar. [CI SKIP]Guo Xiang Tan2015-05-191-1/+1
|
* Merge pull request #19029 from iainbeeston/skipping-undefined-callbacksRafael Mendonça França2015-04-061-5/+13
|\ | | | | Raise ArgumentError if an unrecognised callback is skipped
| * Raise ArgumentError if an unrecognised callback is skippedIain Beeston2015-04-031-5/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | At present, if you skip a callback that hasn't been defined, activesupport callbacks silently does nothing. However, it's easy to mistype the name of a callback and mistakenly think that it's being skipped, when it is not. This problem even exists in the current test suite. CallbacksTest::SkipCallbacksTest#test_skip_person attempts to skip callbacks that were never set up. This PR changes `skip_callback` to raise an `ArgumentError` if the specified callback cannot be found.
* | Merge pull request #19448 from tgxworld/fix_activesupport_callbacks_clash_on_runRafael Mendonça França2015-04-061-12/+4
|\ \ | |/ |/| Fix AS::Callbacks raising an error when `:run` callback is defined.
| * Revert "Reduce allocations when running AR callbacks."Guo Xiang Tan2015-03-221-12/+4
| | | | | | | | This reverts commit 796cab45561fce268aa74e6587cdb9cae3bb243e.
* | Fix doc: set_callback also accepts an array of if:claudiob2015-03-311-4/+6
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When Active Record calls `set_callback` inside `after_commit`, [these lines of code](https://github.com/rails/rails/blob/master/activerecord/lib/active_record/transactions.rb#L276) pass an **array** of methods as the `:if` condition: ```ruby options[:if] = Array(options[:if]) options[:if] << "transaction_include_any_action?(#{fire_on})" ``` That made me realize that anyone could pass an **array** of `:if` and `:unless` conditions to `set_callback`, since Active Support transforms these conditions into an array anyways in [these lines of code](https://github.com/rails/rails/blob/master/activesupport/lib/active_support/callbacks.rb#L365): ```ruby @if = Array(options[:if]) @unless = Array(options[:unless]) ``` Long story short, this commit updates the documentation of the `set_callback` method to explain that arrays are also accepted. It also replaces +false+ and +true+ with false and true, since any _falsey_ or _truthy_ value will work. [ci skip]
* | Missing require 'active_support/deprecation'Akira Matsuda2015-03-271-0/+1
|/
* Change *args to arg in CallbackSequence#calleileencodes2015-03-051-7/+7
| | | | | | `CallbackSequence#call` can only ever take one argument. Using `*args` here produces unnecessary array allocations. Since it only ever takes one argument we should use `arg` instead of `*args`.
* Merge branch 'master' of github.com:rails/docrailsVijay Dev2015-02-141-2/+2
|\
| * Wording fixes for `:skip_after_callbacks_if_terminated` callbacks optionVipul A M2015-01-311-2/+2
| |
* | remove unnecessary assignment and parameter passing in ↵rxing2015-02-111-12/+7
| | | | | | | | ActiveSupport::Callbacks::Filters::Around
* | Use keyword argumentsRafael Mendonça França2015-02-051-4/+4
| | | | | | | | | | Also remove the default value since it will be always passed and Array(nil) returns an empty array
* | Callback#merge merges options for a callback skip instead of a callback. ↵Vipul A M2015-02-011-2/+2
|/ | | | Renamed it to indicate what it actually does.
* Add config to halt callback chain on return falseclaudiob2015-01-021-1/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This stems from [a comment](rails#17227 (comment)) by @dhh. In summary: * New Rails 5.0 apps will not accept `return false` as a way to halt callback chains, and will not display a deprecation warning. * Existing apps ported to Rails 5.0 will still accept `return false` as a way to halt callback chains, albeit with a deprecation warning. For this purpose, this commit introduces a Rails configuration option: ```ruby config.active_support.halt_callback_chains_on_return_false ``` For new Rails 5.0 apps, this option will be set to `false` by a new initializer `config/initializers/callback_terminator.rb`: ```ruby Rails.application.config.active_support.halt_callback_chains_on_return_false = false ``` For existing apps ported to Rails 5.0, the initializers above will not exist. Even running `rake rails:update` will not create this initializer. Since the default value of `halt_callback_chains_on_return_false` is set to `true`, these apps will still accept `return true` as a way to halt callback chains, displaying a deprecation warning. Developers will be able to switch to the new behavior (and stop the warning) by manually adding the line above to their `config/application.rb`. A gist with the suggested release notes to add to Rails 5.0 after this commit is available at https://gist.github.com/claudiob/614c59409fb7d11f2931
* Deprecate `false` as the way to halt AS callbacksclaudiob2015-01-021-2/+14
| | | | | | | | | | | | | | After this commit, returning `false` in a callback will display a deprecation warning to make developers aware of the fact that they need to explicitly `throw(:abort)` if their intention is to halt a callback chain. This commit also patches two internal uses of AS::Callbacks (inside ActiveRecord and ActionDispatch) which sometimes return `false` but whose returned value is not meaningful for the purpose of execution. In both cases, the returned value is set to `true`, which does not affect the execution of the callbacks but prevents unrequested deprecation warnings from showing up.
* Throw :abort halts default CallbackChainsclaudiob2015-01-021-5/+18
| | | | | | | | | | | | | | This commit changes arguments and default value of CallbackChain's :terminator option. After this commit, Chains of callbacks defined **without** an explicit `:terminator` option will be halted as soon as a `before_` callback throws `:abort`. Chains of callbacks defined **with** a `:terminator` option will maintain their existing behavior of halting as soon as a `before_` callback matches the terminator's expectation. For instance, ActiveModel's callbacks will still halt the chain when a `before_` callback returns `false`.
* Flatten the call stacks ActiveSupport::Callbacks produces, fix #18011.Jaroslaw Rzeszotko2014-12-271-74/+116
|
* Add test for `:skip_after_callbacks_if_terminated`claudiob2014-12-141-4/+5
| | | | | | | | | | `define_callbacks` from `ActiveSupport::Callbacks` accepts the `:skip_after_callbacks_if_terminated` option since #4866 but the option is not tested anywhere. This commit adds tests and fixes documentation for the option, making it clear that halting a callback chain only stops following `before_` and `around_` callbacks by default.
* Prefix internal method with _Rafael Mendonça França2014-10-251-2/+2
| | | | This will avoid naming clash with user defined methods
* Replace Enumerable#reverse.each with Enumerable#reverse_eachErik Michaels-Ober2014-10-131-1/+1
|
* fix typo in in define_model_callbacks comment [ci skip]Ryan Selk2014-10-031-1/+1
|
* add notes for `define_model_callbacks` [ci skip]Kuldeep Aggarwal2014-10-031-0/+3
|
* Reduce allocations when running AR callbacks.Pete Higgins2014-09-281-6/+15
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Inspired by @tenderlove's work in c363fff29f060e6a2effe1e4bb2c4dd4cd805d6e, this reduces the number of strings allocated when running callbacks for ActiveRecord instances. I measured that using this script: ``` require 'objspace' require 'active_record' require 'allocation_tracer' ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:" ActiveRecord::Base.connection.instance_eval do create_table(:articles) { |t| t.string :name } end class Article < ActiveRecord::Base; end a = Article.create name: "foo" a = Article.find a.id N = 10 result = ObjectSpace::AllocationTracer.trace do N.times { Article.find a.id } end result.sort.each do |k,v| p k => v end puts "total: #{result.values.map(&:first).inject(:+)}" ``` When I run this against master and this branch I get this output: ``` pete@balloon:~/projects/rails/activerecord$ git checkout master M Gemfile Switched to branch 'master' pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_before pete@balloon:~/projects/rails/activerecord$ git checkout remove-dynamic-send-on-built-in-callbacks M Gemfile Switched to branch 'remove-dynamic-send-on-built-in-callbacks' pete@balloon:~/projects/rails/activerecord$ bundle exec ruby benchmark_allocation_with_callback_send.rb > allocations_after pete@balloon:~/projects/rails/activerecord$ diff allocations_before allocations_after 39d38 < {["/home/pete/projects/rails/activesupport/lib/active_support/callbacks.rb", 81]=>[40, 0, 0, 0, 0, 0]} 42c41 < total: 630 --- > total: 590 ``` In addition to this, there are two micro-optimizations present: * Using `block.call if block` vs `yield if block_given?` when the block was being captured already. ``` pete@balloon:~/projects$ cat benchmark_block_call_vs_yield.rb require 'benchmark/ips' def block_capture_with_yield &block yield if block_given? end def block_capture_with_call &block block.call if block end def no_block_capture yield if block_given? end Benchmark.ips do |b| b.report("block_capture_with_yield") { block_capture_with_yield } b.report("block_capture_with_call") { block_capture_with_call } b.report("no_block_capture") { no_block_capture } end pete@balloon:~/projects$ ruby benchmark_block_call_vs_yield.rb Calculating ------------------------------------- block_capture_with_yield 124979 i/100ms block_capture_with_call 138340 i/100ms no_block_capture 136827 i/100ms ------------------------------------------------- block_capture_with_yield 5703108.9 (±2.4%) i/s - 28495212 in 4.999368s block_capture_with_call 6840730.5 (±3.6%) i/s - 34169980 in 5.002649s no_block_capture 5821141.4 (±2.8%) i/s - 29144151 in 5.010580s ``` * Defining and calling methods instead of using send. ``` pete@balloon:~/projects$ cat benchmark_method_call_vs_send.rb require 'benchmark/ips' class Foo def tacos nil end end my_foo = Foo.new Benchmark.ips do |b| b.report('send') { my_foo.send('tacos') } b.report('call') { my_foo.tacos } end pete@balloon:~/projects$ ruby benchmark_method_call_vs_send.rb Calculating ------------------------------------- send 97736 i/100ms call 151142 i/100ms ------------------------------------------------- send 2683730.3 (±2.8%) i/s - 13487568 in 5.029763s call 8005963.9 (±2.7%) i/s - 40052630 in 5.006604s ``` The result of this is making typical ActiveRecord operations slightly faster: https://gist.github.com/phiggins/e46e51dcc7edb45b5f98
* Fix ActiveSupport::Callbacks #set_callback docs.Nick Pellant2014-07-071-1/+1
| | | | | | A minor version breakage due to a rewrite of the callbacks code now requires an explicit block to be passed to #set_callback. This amends the documentation.
* :fire: these are lambdas now [ci skip]Godfrey Chan2014-07-031-9/+2
| | | This has changed since around 2b1500d6
* Tiny documentation fixes [ci skip]Robin Dupret2014-06-291-1/+1
|
* Update documentation for run_callbacksjamesprior2014-06-271-1/+2
| | | In some cases run_callbacks will return nil. I'm attempting to update the documentation for the method to clarify.
* remove deprecation warningeileencodes2014-05-131-6/+0
| | | | | This deprecation was released in 4.1.0 and can be removed for 4.2.0, deprecation message / handling is no longer necessary.
* flip conditional to use if/else instead of unless/elseeileencodes2014-05-121-3/+3
| | | | Use if/else instead of unless/else so conditional reads better.
* Merge pull request #11411 from dscataglini/masterAaron Patterson2014-04-091-6/+12
|\ | | | | Active support callback's before/after/around filters are not correctly making their singleton methods private
| * private method doesn't work for singleton methods defined this wayDiego Scataglini2013-07-121-6/+12
| |
* | Fix few typos in the documentation [ci skip]Robin Dupret2013-12-211-1/+1
| |
* | Merge pull request #13287 from aayushkhandelwal11/typo_rectifiedYves Senn2013-12-111-3/+3
|\ \ | | | | | | typos rectified lifecycle => life cycle
| * | typos rectified lifecycle => life cycleAayush khandelwal2013-12-121-3/+3
| | |
* | | typos rectified [ci skip]Aayush khandelwal2013-12-121-1/+1
|/ /
* / Fix typo in set_callback docs. [ci skip]Gilad Zohari2013-09-061-1/+1
|/
* Revert "remove string based terminators for `ActiveSupport::Callbacks`."Yves Senn2013-07-051-0/+6
| | | | | | | | This reverts commit d108672dada7ba97d3b3b56f0c6001cea621061e. Conflicts: activesupport/CHANGELOG.md
* remove string based terminators for `ActiveSupport::Callbacks`.Yves Senn2013-07-051-6/+0
|
* Further clean-up of ActiveSupport::CallbacksGenadi Samokovarov2013-07-011-10/+9
| | | | | | | | | | | | | | | | | In #11195 I noticed a trailing comma in the docs, but I decided to further clean it up. What I have done: * Clean up the trailing comma in the docs and some extra whitespace lines. * Used `Array#extract` options to factor the repetitive pattern of `args.last.is_a(Hash) ? ...` * Renamed the local var `config` to `options` in `define_callbacks`, as `options` seems to be the de facto name for the options objects. * Renamed the local var `l` to `line` in `define_callback` (maybe it meant `lambda` in the context) as single `l` may look like `1` in some fonts.
* unified the param names across all callbacks manipulation methodsSteven Yang2013-07-011-10/+10
| | | | | | | _ Rename the define_callbacks params to `names` - in order to match the naming conventions for `get_callbacks` and `set_callbacks` at https://github.com/rails/rails/blob/master/activesupport/lib/active_support/callbacks.rb#L736-743 - `define_callbacks` just register names(events), not define the real callback functions. - Rename the `reset_callbacks` params
* updated AS:Callbacks doc for terminator option in define_callbacks methodSteven Yang2013-06-301-3/+4
| | | | The change is commited at ba552764344bc0a3c25b8576ec11f127ceaa16da
* remove some evals from callback conditionalsAaron Patterson2013-06-111-0/+10
|