aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel/lib/active_model/validations/callbacks.rb
Commit message (Collapse)AuthorAgeFilesLines
* Refactor to `Array(options[:on])` only once in defining validationsRyuta Kamizono2018-01-011-8/+10
|
* Fix validation callbacks on multiple contextYoshiyuki Hirano2017-12-201-9/+13
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I found a bug that validation callbacks don't fire on multiple context. So I've fixed it. Example: ```ruby class Dog include ActiveModel::Validations include ActiveModel::Validations::Callbacks attr_accessor :history def initialize @history = [] end before_validation :set_before_validation_on_a, on: :a before_validation :set_before_validation_on_b, on: :b after_validation :set_after_validation_on_a, on: :a after_validation :set_after_validation_on_b, on: :b def set_before_validation_on_a; history << "before_validation on a"; end def set_before_validation_on_b; history << "before_validation on b"; end def set_after_validation_on_a; history << "after_validation on a" ; end def set_after_validation_on_b; history << "after_validation on b" ; end end ``` Before: ``` d = Dog.new d.valid?([:a, :b]) d.history # [] ``` After: ``` d = Dog.new d.valid?([:a, :b]) d.history # ["before_validation on a", "before_validation on b", "after_validation on a", "after_validation on b"] ```
* Use frozen string literal in activemodel/Kir Shatrov2017-07-161-0/+2
|
* Revert "Merge pull request #29540 from kirs/rubocop-frozen-string"Matthew Draper2017-07-021-1/+0
| | | | | This reverts commit 3420a14590c0e6915d8b6c242887f74adb4120f9, reversing changes made to afb66a5a598ce4ac74ad84b125a5abf046dcf5aa.
* Enforce frozen string in RubocopKir Shatrov2017-07-011-0/+1
|
* Remove deprecated behavior that halts callbacks when the return is falseRafael Mendonça França2017-02-071-1/+0
|
* Privatize unneededly protected methods in Active ModelAkira Matsuda2016-12-241-2/+2
|
* - removing redundant 'happens' in documentation [ci skip]Mohit Natoo2016-05-191-4/+2
|
* Fix the AS::Callbacks terminator regression from 4.2.3Roque Pinel2015-09-221-0/+1
| | | | | | 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.
* Revert "Revert "Reduce allocations when running AR callbacks.""Guo Xiang Tan2015-07-161-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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}" ```
* Revert "Reduce allocations when running AR callbacks."Guo Xiang Tan2015-03-221-1/+1
| | | | This reverts commit 796cab45561fce268aa74e6587cdb9cae3bb243e.
* Deprecate `false` as the way to halt AM validation callbacksclaudiob2015-01-021-3/+2
| | | | | | | | | | Before this commit, returning `false` in an ActiveModel validation callback such as `before_validation` would halt the callback chain. After this commit, the behavior is deprecated: will still work until the next release of Rails but will also display a deprecation warning. The preferred way to halt a callback chain is to explicitly `throw(:abort)`.
* Throw :abort halts default CallbackChainsclaudiob2015-01-021-1/+1
| | | | | | | | | | | | | | 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`.
* Prefix internal method with _Rafael Mendonça França2014-10-251-1/+1
| | | | This will avoid naming clash with user defined methods
* Refactor callback setup in to use lambda instead of evalPablo Herrero2014-09-301-2/+4
|
* Reduce allocations when running AR callbacks.Pete Higgins2014-09-281-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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
* Adding missing backslashes in active_model files so as to avoid unwanted ↵aditya-kapoor2013-12-271-1/+1
| | | | links in rdoc [ci skip]
* remove evals from AM::Validations::CallbacksSteven Yang2013-06-301-1/+3
| | | | follow the same refactor at a63a964a5d1ed02cf0df1b1a33a96ed2a9fa987b
* deprecating string based terminatorsAaron Patterson2013-05-141-1/+4
|
* Convert ActiveModel to 1.9 hash syntax.Patrick Robertson2013-05-011-1/+1
| | | | | I also attempted to fix other styleguide violations such as { a: :b } over {a: :b} and foo(b: 'bar') over foo( b: 'bar' ).
* cleanup, removed dispensable `require` statements from `ActiveModel`Yves Senn2012-11-251-2/+0
|
* cleanup, remove broken whitespaceYves Senn2012-11-251-2/+2
|
* minor edits in AM documentation [ci skip]Francesco Rodriguez2012-10-211-1/+1
|
* Switch to using include? on validation callbacksJohn Foley2012-09-231-2/+2
|
* Fix collisions with before and after validation callbacks.John Foley2012-09-231-2/+6
| | | | | | This commit allows a user to do something like: before_validation :do_stuff, :on => [ :create, :update ] after_validation :do_more, :on => [ :create, :update ]
* fix #after_validation example [ci skip]Francesco Rodriguez2012-07-301-1/+1
|
* update ActiveModel::Validations::Callbacks documentation [ci skip]Francesco Rodriguez2012-07-291-18/+69
|
* fix ActiveModel::Validations::Callbacks docJan Xie2012-04-151-1/+2
|
* AS::Callbacks: :skip_after_callbacks_if_terminated optionBogdan Gusiev2012-02-031-2/+1
|
* Remove Array.wrap call in ActiveModelRafael Mendonça França2012-01-061-2/+2
|
* fix typoAditya Sanghi2011-04-291-1/+1
|
* :if should not fire on validations when not in context with :onAditya Sanghi2011-04-291-2/+2
|
* Use run_callbacks; the generated _run_<name>_callbacks method is not a ↵John Firebaugh2011-01-311-1/+1
| | | | | | public interface. Signed-off-by: Santiago Pastorino <santiago@wyeworks.com>
* type fixedSantiago Pastorino2010-08-221-1/+1
|
* after_validation should be called irrespective of the result of validation.Neeraj Singh2010-08-201-1/+1
| | | | | | | | I confirmed that this is the behavior on 2.3.x . [5419 state:resolved] Signed-off-by: José Valim <jose.valim@gmail.com>
* ActiveModel::Validations::Callbacks should not be required by default.José Valim2010-06-191-12/+5
|
* moving before_validation and after_validation functionality from ↵Neeraj Singh2010-06-191-0/+64
ActiveRecord to ActiveModel [#4653 state:resolved] Signed-off-by: José Valim <jose.valim@gmail.com>