aboutsummaryrefslogtreecommitdiffstats
path: root/activesupport/lib/active_support/core_ext
Commit message (Collapse)AuthorAgeFilesLines
...
| * | This PR speeds up Nil#try by avoiding an allocation when only one argument ↵schneems2018-10-031-2/+2
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | is passed: ```ruby class FooNew def try(method_name = nil, *args) nil end end class FooOld def try(*args) nil end end require 'benchmark/ips' foo_new = FooNew.new foo_old = FooOld.new Benchmark.ips do |x| x.report("new") { foo_new.try(:anything) } x.report("old") { foo_old.try(:anything) } x.compare! end # Warming up -------------------------------------- # new 250.633k i/100ms # old 232.322k i/100ms # Calculating ------------------------------------- # new 6.476M (± 4.8%) i/s - 32.332M in 5.005777s # old 5.258M (± 3.2%) i/s - 26.485M in 5.042589s # Comparison: # new: 6476002.5 i/s # old: 5257912.5 i/s - 1.23x slower ``` It's worth noting that checking for nil separately as in https://github.com/rails/rails/pull/34067 seems to be MUCH faster. It might be worth it to apply a blanket `&.` to every internal `try` call.
* | | Prefix Module#parent, Module#parents, and Module#parent_name with moduleGannon McGibbon2018-10-021-13/+37
| | |
* | | Merge pull request #33058 from gmcgibbon/string_first_last_negative_deprecationRafael França2018-10-021-0/+8
|\ \ \ | |_|/ |/| | Add deprecation warning when String#first and String#last receive neg…
| * | Add deprecation warning when String#first and String#last receive negative ↵Gannon McGibbon2018-09-281-0/+8
| | | | | | | | | | | | | | | | | | integers [Gannon McGibbon + Eric Turner]
* | | Add `Style/RedundantFreeze` to remove redudant `.freeze`Yasuo Honda2018-09-292-2/+2
|/ / | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Since Rails 6.0 will support Ruby 2.4.1 or higher `# frozen_string_literal: true` magic comment is enough to make string object frozen. This magic comment is enabled by `Style/FrozenStringLiteralComment` cop. * Exclude these files not to auto correct false positive `Regexp#freeze` - 'actionpack/lib/action_dispatch/journey/router/utils.rb' - 'activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb' It has been fixed by https://github.com/rubocop-hq/rubocop/pull/6333 Once the newer version of RuboCop released and available at Code Climate these exclude entries should be removed. * Replace `String#freeze` with `String#-@` manually if explicit frozen string objects are required - 'actionpack/test/controller/test_case_test.rb' - 'activemodel/test/cases/type/string_test.rb' - 'activesupport/lib/active_support/core_ext/string/strip.rb' - 'activesupport/test/core_ext/string_ext_test.rb' - 'railties/test/generators/actions_test.rb'
* / Handle more unsafe String methods (#33990)Janosch Müller2018-09-271-2/+15
|/ | | | | | | | | | * Handle more unsafe String methods * Fix codeclimate issue * Revert stylistic change [Janosch Müller + Rafael Mendonça França]
* Change the empty block style to have space inside of the blockRafael Mendonça França2018-09-251-1/+1
|
* Merge pull request #33800 from aeroastro/feature/doc-change-for-blankXavier Noria2018-09-131-1/+1
|\ | | | | Improve API document on Object#blank?
| * Revert falsey with example reorderedTakumasa Ochi2018-09-141-2/+2
| |
| * Improve API document on Object#blank?Takumasa Ochi2018-09-061-2/+2
| | | | | | | | | | * Introduce `falsey` to represent both `nil` and `false`. * Keep consistent order between abstract description and examples.
* | Faster multiple_of? methodrigani2018-09-121-1/+1
| |
* | SafeBuffer should maintain safety upon getting a slice via a range if ↵Yumin Wong2018-08-311-3/+1
|/ | | | | | original buffer was safe. Co-Authored-By: no-itsbackpack <no-itsbackpack@github.com>
* 20% faster `try`Sean Griffin2018-08-291-8/+7
| | | | | | | | | | | | | | | | | | | | | | | | Following up on #33747, this takes things a step further by pulling out the method name from the arguments array, letting us skip an allocation in the case where there are no arguments -- notably, this also no longer *requires* the splat to be an array, allowing us to benefit from optimizations in Jruby (and maybe MRI in the future) of skipping the array allocation entirely. Benchmark results: ``` Warming up -------------------------------------- old 179.987k i/100ms new 199.201k i/100ms Calculating ------------------------------------- old 3.029M (± 1.6%) i/s - 15.299M in 5.052417s new 3.657M (± 1.2%) i/s - 18.326M in 5.012648s Comparison: new: 3656620.7 i/s old: 3028848.3 i/s - 1.21x slower ```
* 32% Faster Object#tryschneems2018-08-291-1/+10
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Here’s the micro benchmark: ```ruby module ActiveSupport module NewTryable #:nodoc: def try(*a, &b) return unless a.empty? || respond_to?(a.first) return public_send(*a, &b) unless a.empty? return nil unless block_given? return instance_eval(&b) if b.arity == 0 yield self end def try!(*a, &b) return public_send(*a, &b) if !a.empty? return nil unless block_given? return instance_eval(&b) if b.arity == 0 yield self end end end module ActiveSupport module OldTryable #:nodoc: def try(*a, &b) try!(*a, &b) if a.empty? || respond_to?(a.first) end def try!(*a, &b) if a.empty? && block_given? if b.arity == 0 instance_eval(&b) else yield self end else public_send(*a, &b) end end end end class FooNew include ActiveSupport::NewTryable def foo end end class FooOld include ActiveSupport::OldTryable def foo end end foo_new = FooNew.new foo_old = FooOld.new require 'benchmark/ips' Benchmark.ips do |x| x.report("old") { foo_old.try(:foo) } x.report("new") { foo_new.try(:foo) } x.compare! end # Warming up -------------------------------------- # old 144.178k i/100ms # new 172.371k i/100ms # Calculating ------------------------------------- # old 2.181M (± 8.0%) i/s - 10.813M in 5.001419s # new 2.889M (± 7.7%) i/s - 14.479M in 5.051760s # Comparison: # new: 2888691.7 i/s # old: 2180740.7 i/s - 1.32x slower ``` Also reduces memory. On https://www.codetriage.com i’m seeing 1.5% fewer object allocations per request (in object count). Before: Total allocated: 1014475 bytes (8525 objects) After: Total allocated: 1015499 bytes (8389 objects)
* Refactor `Array#extract!`bogdanvlviv2018-08-141-7/+7
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Avoid allocating the second array by using `Array#reject!` instead of `Enumerable#partition` in `Array#extract!`. There are benchmarks in order to ensure that the changes speed up the method: ``` begin require "bundler/inline" rescue LoadError => e $stderr.puts "Bundler version 1.10 or later is required. Please update your Bundler" raise e end class Array def extract_v1!(&block) unless block_given? to_enum(:extract!) { size } else extracted_elements, other_elements = partition(&block) replace(other_elements) extracted_elements end end def extract_v2! return to_enum(:extract!) { size } unless block_given? extracted_elements = [] reject! do |element| extracted_elements << element if yield(element) end extracted_elements end end gemfile(true) do source "https://rubygems.org" gem "benchmark-ips" end arrays_for_partition = Array.new(1000) { (0..10000).to_a } arrays_for_extract_v1 = Array.new(1000) { (0..10000).to_a } arrays_for_extract_v2 = Array.new(1000) { (0..10000).to_a } Benchmark.ips do |x| x.report("Array#partition") do arrays_for_partition.each do |numbers| odd_numbers, numbers = numbers.partition { |number| number.odd? } numbers end end x.report("Array#extract_v1!") do arrays_for_extract_v1.each do |numbers| odd_numbers = numbers.extract_v1! { |number| number.odd? } numbers end end x.report("Array#extract_v2!") do arrays_for_extract_v2.each do |numbers| odd_numbers = numbers.extract_v2! { |number| number.odd? } numbers end end x.compare! end ``` The result of the benchmarks: ``` ruby -v ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux] ``` ``` Fetching gem metadata from https://rubygems.org/. Resolving dependencies... Using benchmark-ips 2.7.2 Using bundler 1.16.1 Warming up -------------------------------------- Array#partition 1.000 i/100ms Array#extract_v1! 1.000 i/100ms Array#extract_v2! 1.000 i/100ms Calculating ------------------------------------- Array#partition 1.390 (± 0.0%) i/s - 7.000 in 5.044843s Array#extract_v1! 2.781 (± 0.0%) i/s - 14.000 in 5.050589s Array#extract_v2! 3.151 (± 0.0%) i/s - 16.000 in 5.080608s Comparison: Array#extract_v2!: 3.2 i/s Array#extract_v1!: 2.8 i/s - 1.13x slower Array#partition: 1.4 i/s - 2.27x slower ``` Avoid `unless`/`else` in favour of an early return. The double-negative of that `else` can be confusing, even though the code layout is nearly the same. Also using of early return would improve `git diff` if we needed to change this method.
* Add `Array#extract!`bogdanvlviv2018-08-142-0/+22
| | | | | | | | | | | The method removes and returns the elements for which the block returns a true value. If no block is given, an Enumerator is returned instead. ``` numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] odd_numbers = numbers.extract! { |number| number.odd? } # => [1, 3, 5, 7, 9] numbers # => [0, 2, 4, 6, 8] ```
* Fix example in thread_mattr_accessor documentationFabian Mersch2018-07-311-1/+1
|
* Remove unused `require "active_support/core_ext/regexp"`Ryuta Kamizono2018-07-294-4/+0
| | | | | | | | Ruby 2.4 has native `Regexp#match?`. https://ruby-doc.org/core-2.4.0/Regexp.html#method-i-match-3F Related #32034.
* Update with_options.rbDaniel Amireh2018-07-251-1/+1
| | | explicit mapping for enum accepts a Hash not an Array, plus the example is using `.keys` which also exists on hash
* e4e1b62 broke `to_param` handling:Edouard CHIN2018-07-121-2/+5
| | | | | | | | | | | | | | | | | | | - There was an issue inside controller tests where order params were not respected, the reason was because we were calling `Hash#to_query` which sorts the results lexicographically. 1e4e1b62 fixed that issue by not using `to_query` but instead a utility function provided by rack. - However with the fix came another issue where it's now no longer possible to do this ``` post :foo, params: { user: User.first } # Prior to the patch the controller will receive { "user" => "1" } # Whereas now you get { "user": "#<User: ...>" } ``` The fix in this PR is to modify `Hash#to_query` to sort only when it doesn't contain an array structure that looks something like "bar[]" Ref https://github.com/rails/rails/pull/33341#issuecomment-404039396
* Merge pull request #33106 from marcandre/datecalcRafael Mendonça França2018-06-111-15/+12
|\ | | | | | | Improve some DateAndTime calculations
| * Use fetch for better error handlingMarc-Andre Lafortune2018-06-091-2/+2
| |
| * Use same weekday correspondance as Date#wday.Marc-Andre Lafortune2018-06-091-13/+10
|/ | | | | | | | | DeepCover revealed that most of these `wday != 0 ? wday - 1 : 6` were not entirely covered, i.e. the case of `wday == 0` was not tested: https://deep-cover.github.io/rails-cover/activesupport/activesupport/lib/active_support/core_ext/date_and_time/calculations.rb.html#L351 There's actually no valid reason to consider Sunday a special case, so this commit simply reajusts the values used for calculations.
* Add `ActiveSupport::CompareWithRange` to API docsbogdanvlviv2018-06-071-1/+1
| | | | | | | | Since it is documented in the guides http://edgeguides.rubyonrails.org/active_support_core_extensions.html#include-questionmark-and-cover-questionmark we can add it to API docs http://edgeapi.rubyonrails.org too. [ci skip]
* Don't expose `Enumerable#_original_sum_with_required_identity` which is ↵yuuji.yaginuma2018-06-041-1/+5
| | | | | | | | | | internal API [ci skip] `:nodoc:` is specified, but unfortunately, it is exposed in the API doc. http://edgeapi.rubyonrails.org/classes/Enumerable.html#method-i-_original_sum_with_required_identity If the method of the `alias` destination is public, the specification of `:nodoc:` does not seem to work.
* Improve grammar for DateAndTime before? and after? calculations [ci skip]Aaron Sumner2018-05-241-2/+2
|
* Allow Range#=== and Range#cover? on Rangeutilum2018-05-223-23/+68
| | | | | | | | | | | ruby/ruby@989e07c features switching `Range#===` to use internal `r_cover_p` instead of rubyland `include?`. This breaks expected behavior of `ActiveSupport::CoreExt::Range` documented since at least 8b67a02. This patch adds overrides on `Range#cover?` and `Range#===` and places all three in a single module, `CompareWithRange`. *Requiring core_ext/range/include_range now causes a deprecation warnning*
* Add Enumerable#index_with.Kasper Timm Hansen2018-05-211-1/+25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In the app I'm working on I've wished that index_by had a buddy that would assign the hash value instead of the key multiple times. Enter index_with. Useful when building a hash from a static list of symbols. Before you'd do: ```ruby POST_ATTRIBUTES.map { |attr_name| [ attr_name, public_send(attr_name) ] }.to_h ``` But now that's a little clearer and faster with: ````ruby POST_ATTRIBUTES.index_with { |attr_name| public_send(attr_name) } ``` It's also useful when you have an enumerable that should be converted to a hash, but you don't want to muddle the code up with the overhead that it takes to create that hash. So before, that's: ```ruby WEEKDAYS.each_with_object(Hash.new) do |day, intervals| intervals[day] = [ Interval.all_day ] end ``` And now it's just: ```ruby WEEKDAYS.index_with([ Interval.all_day ]) ``` It's also nice to quickly get a hash with either nil, [], or {} as the value.
* Fix #29632 - nil #path leads to NoMethodError in LoadError#is_missing?Neil Souza2018-05-041-1/+1
| | | | | | | | See #29632 for details. In short, it's possible to enter `LoadError#is_missing?` when `LoadError#path` returns `nil`, leading to `path.sub` throwing an none-to-helpful `NoMethodError`. This tiniest of patch inserts `#to_s` before the `sub` call to make sure it succeeds. Affected surface area should be just as tiny since something has already gone wrong to get us into `#is_missing?` and the current behavior when `#path` returns `nil` seems clearly not intended. [Gannon McGibbon + Neil Souza]
* Inclusive Language in Documentation Examples [ci skip]Cassidy Kobewka2018-04-151-2/+2
|
* Don't doc _original_sum_with_required_identityChris Arcand2018-04-121-1/+1
| | | | It's not public API so don't document it.
* [ci skip] Add :private option to delegation docYoshiyuki Hirano2018-04-051-1/+2
|
* Move implementation of `before?` and `after?` to `DateAndTime::Calculations`bogdanvlviv2018-03-314-6/+10
| | | | | | | | This prevents duplication of code. Prevent duplication of tests by moving them to `DateAndTimeBehavior`. Related to #32185.
* Merge pull request #32185 from nholden/human_readable_date_time_comparisonsRafael França2018-03-263-0/+6
|\ | | | | Add `before?` and `after?` methods to date and time classes
| * Add `before?` and `after?` methods to date and time classesNick Holden2018-03-063-0/+6
| | | | | | | | | | | | | | | | Equality comparisons between dates and times can take some extra time to comprehend. I tend to think of a date or time as "before" or "after" another date or time, but I naturally read `<` and `>` as "less than" and "greater than." This change seeks to make date/time comparisons more human readable.
* | Remove unused variableRafael Mendonça França2018-03-221-1/+0
| |
* | Ruby 2.6 will not require monkey patched `URI#unescape`Yasuo Honda2018-03-221-9/+1
| | | | | | | | since revision 62897 https://github.com/ruby/ruby/commit/234a30459cdae6aa7da6e28a1082d9c11f315696
* | Only apply monkey-patch if detected to be requiredAshe Connor2018-03-091-2/+9
| | | | | | | | | | | | | | | | | | | | We test the failing case we're trying to patch; only if it throws an Exception do we patch. Currently this will *always* throw, but upstream Ruby has patched this bug: https://git.io/vAxKB Signed-off-by: Ashe Connor <ashe@kivikakk.ee>
* | Merge pull request #32183 from kivikakk/uri-ext-fixEileen M. Uchitelle2018-03-071-1/+1
|\ \ | |/ |/| URI.unescape "extension" fails with Unicode input
| * URI.unescape handles mixed Unicode/escaped inputAshe Connor2018-03-071-1/+1
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, URI.enscape could handle Unicode input (without any actual escaped characters), or input with escaped characters (but no actual Unicode characters) - not both. URI.unescape("\xe3\x83\x90") # => "バ" URI.unescape("%E3%83%90") # => "バ" URI.unescape("\xe3\x83\x90%E3%83%90") # => # Encoding::CompatibilityError We need to let `gsub` handle this for us, and then force back to the original encoding of the input. The result String will be mangled if the percent-encoded characters don't conform to the encoding of the String itself, but that goes without saying. Signed-off-by: Ashe Connor <ashe@kivikakk.ee>
* | [ci skip] Hide internal docs from root AS moduleAshe Connor2018-03-061-0/+1
|/ | | | | | | | | We have a bunch of documentation in lib/active_support/core_ext/object/json.rb which is currently appearing as documentation for the top-level ActiveSupport module. We hide it from rdoc here. Signed-off-by: Ashe Connor <ashe@kivikakk.ee>
* [ci skip] Fix grammar in delegate, private: true docs.Kasper Timm Hansen2018-03-041-5/+4
| | | | | | | | | Convert the user to atheism by ditching the extra example that demonstrates the same thing as date_of_birth. Demonstrate the NoMethodError on date_of_birth first, then call age that uses date_of_birth internally. Thus showing that accessing it publicly fails, but using it internally succeeds.
* Deprecate "active_support/core_ext/numeric/inquiry"bogdanvlviv2018-03-022-26/+2
| | | | | | Numeric#positive? and Numeric#negative? was added to Ruby since 2.3, see https://github.com/ruby/ruby/blob/ruby_2_3/NEWS Rails 6 requires Ruby 2.4.1+ since https://github.com/rails/rails/pull/32034
* Deprecate `active_support/core_ext/hash/compact`yuuji.yaginuma2018-03-022-27/+2
| | | | | Ruby 2.4+ provides `Hash#compact` and `Hash#compact!` natively, so `active_support/core_ext/hash/compact` is no longer necessary.
* Add separate test to ensure that `delegate` with `:private` option returns ↵bogdanvlviv2018-02-281-5/+5
| | | | | | | | correct value Remove extra comments `# Asking for private method` in activesupport/test/core_ext/module_test.rb Improve docs of using `delegate` with `:private` Update changelog of #31944
* add private: true option for ActiveSupport delegateTomas Valent2018-02-261-2/+23
|
* Remove native `Array#sum` and `Enumerable#sum` detection (#32102)Ryuta Kamizono2018-02-261-63/+44
| | | Since #32034, Rails 6 requires Ruby 2.4.1+.
* String#truncate_bytes: limit to N bytes without breaking multibyte charsJeremy Daer2018-02-181-0/+41
| | | | | This faithfully preserves grapheme clusters (characters composed of other characters and combining marks) and other multibyte characters.
* `String#strip_heredoc` preserves frozennessJeremy Daer2018-02-171-1/+3
| | | | | | | | | | | | | | | | | | ```ruby "foo".freeze.strip_heredoc.frozen? # => true ``` Fixes the case where frozen string literals would inadvertently become unfrozen: ```ruby foo = <<-MSG.strip_heredoc la la la MSG foo.frozen? # => false !?? ```
* Rails 6 requires Ruby 2.4.1+Jeremy Daer2018-02-176-46/+12
| | | | | | Skipping over 2.4.0 to sidestep the `"symbol_from_string".to_sym.dup` bug. References #32028