1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00
rails--rails/actionpack/test/controller/parameters/accessors_test.rb
Ricardo Díaz 93cbc30f34 Use Enumerator#all? and Enumerator#any? with classes instead of iterations
These methods have changed in Ruby 2.5 to be more akin to grep:

https://bugs.ruby-lang.org/issues/11286

Using classes seems to be faster (and a bit more expressive) than iterating over
the collection items:

```
Warming up --------------------------------------
    #all? with class   504.000  i/100ms
     #all? with proc   189.000  i/100ms
Calculating -------------------------------------
    #all? with class      4.960k (± 1.6%) i/s -     25.200k in   5.082049s
     #all? with proc      1.874k (± 2.8%) i/s -      9.450k in   5.047866s

Comparison:
    #all? with class:     4959.9 i/s
     #all? with proc:     1873.8 i/s - 2.65x  (± 0.00) slower
```

Benchmark script:

```ruby
require "minitest/autorun"
require "benchmark/ips"

class BugTest < Minitest::Test
  def test_enumerators_with_classes
    arr = (1..10000).to_a << nil

    assert_equal arr.all?(Integer), arr.all? { |v| v.is_a?(Integer) }

    Benchmark.ips do |x|
      x.report("#all? with class") do
        arr.all?(Integer)
      end

      x.report("#all? with proc") do
        arr.all? { |v| v.is_a?(Integer) }
      end

      x.compare!
    end
  end
end
```
2021-02-07 01:29:50 -05:00

405 lines
13 KiB
Ruby

# frozen_string_literal: true
require "abstract_unit"
require "action_controller/metal/strong_parameters"
class ParametersAccessorsTest < ActiveSupport::TestCase
setup do
ActionController::Parameters.permit_all_parameters = false
@params = ActionController::Parameters.new(
person: {
age: "32",
name: {
first: "David",
last: "Heinemeier Hansson"
},
addresses: [{ city: "Chicago", state: "Illinois" }]
}
)
end
test "each returns self" do
assert_same @params, @params.each { |_| _ }
end
test "each_pair returns self" do
assert_same @params, @params.each_pair { |_| _ }
end
test "each_value returns self" do
assert_same @params, @params.each_value { |_| _ }
end
test "[] retains permitted status" do
@params.permit!
assert_predicate @params[:person], :permitted?
assert_predicate @params[:person][:name], :permitted?
end
test "[] retains unpermitted status" do
assert_not_predicate @params[:person], :permitted?
assert_not_predicate @params[:person][:name], :permitted?
end
test "as_json returns the JSON representation of the parameters hash" do
assert_not @params.as_json.key? "parameters"
assert_not @params.as_json.key? "permitted"
assert @params.as_json.key? "person"
end
test "to_s returns the string representation of the parameters hash" do
assert_equal '{"person"=>{"age"=>"32", "name"=>{"first"=>"David", "last"=>"Heinemeier Hansson"}, ' \
'"addresses"=>[{"city"=>"Chicago", "state"=>"Illinois"}]}}', @params.to_s
end
test "each carries permitted status" do
@params.permit!
@params.each { |key, value| assert(value.permitted?) if key == "person" }
end
test "each carries unpermitted status" do
@params.each { |key, value| assert_not(value.permitted?) if key == "person" }
end
test "each returns key,value array for block with arity 1" do
@params.each do |arg|
assert_kind_of Array, arg
assert_equal "person", arg[0]
assert_kind_of ActionController::Parameters, arg[1]
end
end
test "each without a block returns an enumerator" do
assert_kind_of Enumerator, @params.each
assert_equal @params, @params.each.to_h
end
test "each_pair carries permitted status" do
@params.permit!
@params.each_pair { |key, value| assert(value.permitted?) if key == "person" }
end
test "each_pair carries unpermitted status" do
@params.each_pair { |key, value| assert_not(value.permitted?) if key == "person" }
end
test "each_pair returns key,value array for block with arity 1" do
@params.each_pair do |arg|
assert_kind_of Array, arg
assert_equal "person", arg[0]
assert_kind_of ActionController::Parameters, arg[1]
end
end
test "each_pair without a block returns an enumerator" do
assert_kind_of Enumerator, @params.each_pair
assert_equal @params, @params.each_pair.to_h
end
test "each_value carries permitted status" do
@params.permit!
@params.each_value do |value|
assert_predicate(value, :permitted?)
end
end
test "each_value carries unpermitted status" do
@params.each_value do |value|
assert_not_predicate(value, :permitted?)
end
end
test "each_value without a block returns an enumerator" do
assert_kind_of Enumerator, @params.each_value
assert_equal @params.values, @params.each_value.to_a
end
test "each_key converts to hash for permitted" do
@params.permit!
@params.each_key { |key| assert_kind_of(String, key) if key == "person" }
end
test "each_key converts to hash for unpermitted" do
@params.each_key { |key| assert_kind_of(String, key) if key == "person" }
end
test "each_key without a block returns an enumerator" do
assert_kind_of Enumerator, @params.each_key
assert_equal @params.keys, @params.each_key.to_a
end
test "empty? returns true when params contains no key/value pairs" do
params = ActionController::Parameters.new
assert_empty params
end
test "empty? returns false when any params are present" do
assert_not_empty @params
end
test "except retains permitted status" do
@params.permit!
assert_predicate @params.except(:person), :permitted?
assert_predicate @params[:person].except(:name), :permitted?
end
test "except retains unpermitted status" do
assert_not_predicate @params.except(:person), :permitted?
assert_not_predicate @params[:person].except(:name), :permitted?
end
test "fetch retains permitted status" do
@params.permit!
assert_predicate @params.fetch(:person), :permitted?
assert_predicate @params[:person].fetch(:name), :permitted?
end
test "fetch retains unpermitted status" do
assert_not_predicate @params.fetch(:person), :permitted?
assert_not_predicate @params[:person].fetch(:name), :permitted?
end
test "has_key? returns true if the given key is present in the params" do
assert @params.has_key?(:person)
end
test "has_key? returns false if the given key is not present in the params" do
assert_not @params.has_key?(:address)
end
test "has_value? returns true if the given value is present in the params" do
params = ActionController::Parameters.new(city: "Chicago", state: "Illinois")
assert params.has_value?("Chicago")
end
test "has_value? returns false if the given value is not present in the params" do
params = ActionController::Parameters.new(city: "Chicago", state: "Illinois")
assert_not params.has_value?("New York")
end
test "include? returns true if the given key is present in the params" do
assert @params.include?(:person)
end
test "include? returns false if the given key is not present in the params" do
assert_not @params.include?(:address)
end
test "key? returns true if the given key is present in the params" do
assert @params.key?(:person)
end
test "key? returns false if the given key is not present in the params" do
assert_not @params.key?(:address)
end
test "member? returns true if the given key is present in the params" do
assert @params.member?(:person)
end
test "member? returns false if the given key is not present in the params" do
assert_not @params.member?(:address)
end
test "keys returns an array of the keys of the params" do
assert_equal ["person"], @params.keys
assert_equal ["age", "name", "addresses"], @params[:person].keys
end
test "reject retains permitted status" do
assert_not_predicate @params.reject { |k| k == "person" }, :permitted?
end
test "reject retains unpermitted status" do
@params.permit!
assert_predicate @params.reject { |k| k == "person" }, :permitted?
end
test "select retains permitted status" do
@params.permit!
assert_predicate @params.select { |k| k == "person" }, :permitted?
end
test "select retains unpermitted status" do
assert_not_predicate @params.select { |k| k == "person" }, :permitted?
end
test "slice retains permitted status" do
@params.permit!
assert_predicate @params.slice(:person), :permitted?
end
test "slice retains unpermitted status" do
assert_not_predicate @params.slice(:person), :permitted?
end
test "transform_keys retains permitted status" do
@params.permit!
assert_predicate @params.transform_keys { |k| k }, :permitted?
end
test "transform_keys retains unpermitted status" do
assert_not_predicate @params.transform_keys { |k| k }, :permitted?
end
test "transform_keys without a block returns an enumerator" do
assert_kind_of Enumerator, @params.transform_keys
assert_kind_of ActionController::Parameters, @params.transform_keys.each { |k| k }
end
test "transform_keys! without a block returns an enumerator" do
assert_kind_of Enumerator, @params.transform_keys!
assert_kind_of ActionController::Parameters, @params.transform_keys!.each { |k| k }
end
test "deep_transform_keys retains permitted status" do
@params.permit!
assert_predicate @params.deep_transform_keys { |k| k }, :permitted?
end
test "deep_transform_keys retains unpermitted status" do
assert_not_predicate @params.deep_transform_keys { |k| k }, :permitted?
end
test "transform_values retains permitted status" do
@params.permit!
assert_predicate @params.transform_values { |v| v }, :permitted?
end
test "transform_values retains unpermitted status" do
assert_not_predicate @params.transform_values { |v| v }, :permitted?
end
test "transform_values converts hashes to parameters" do
@params.transform_values do |value|
assert_kind_of ActionController::Parameters, value
value
end
end
test "transform_values without a block returns an enumerator" do
assert_kind_of Enumerator, @params.transform_values
assert_kind_of ActionController::Parameters, @params.transform_values.each { |v| v }
end
test "transform_values! converts hashes to parameters" do
@params.transform_values! do |value|
assert_kind_of ActionController::Parameters, value
end
end
test "transform_values! without a block returns an enumerator" do
assert_kind_of Enumerator, @params.transform_values!
assert_kind_of ActionController::Parameters, @params.transform_values!.each { |v| v }
end
test "value? returns true if the given value is present in the params" do
params = ActionController::Parameters.new(city: "Chicago", state: "Illinois")
assert params.value?("Chicago")
end
test "value? returns false if the given value is not present in the params" do
params = ActionController::Parameters.new(city: "Chicago", state: "Illinois")
assert_not params.value?("New York")
end
test "values returns an array of the values of the params" do
params = ActionController::Parameters.new(city: "Chicago", state: "Illinois")
assert_equal ["Chicago", "Illinois"], params.values
end
test "values_at retains permitted status" do
@params.permit!
assert_predicate @params.values_at(:person).first, :permitted?
assert_predicate @params[:person].values_at(:name).first, :permitted?
end
test "values_at retains unpermitted status" do
assert_not_predicate @params.values_at(:person).first, :permitted?
assert_not_predicate @params[:person].values_at(:name).first, :permitted?
end
test "is equal to Parameters instance with same params" do
params1 = ActionController::Parameters.new(a: 1, b: 2)
params2 = ActionController::Parameters.new(a: 1, b: 2)
assert(params1 == params2)
assert(params1.hash == params2.hash)
end
test "is equal to Parameters instance with same permitted params" do
params1 = ActionController::Parameters.new(a: 1, b: 2).permit(:a)
params2 = ActionController::Parameters.new(a: 1, b: 2).permit(:a)
assert(params1 == params2)
assert(params1.hash == params2.hash)
end
test "is equal to Parameters instance with same different source params, but same permitted params" do
params1 = ActionController::Parameters.new(a: 1, b: 2).permit(:a)
params2 = ActionController::Parameters.new(a: 1, c: 3).permit(:a)
assert(params1 == params2)
assert(params2 == params1)
assert(params1.hash == params2.hash)
assert(params2.hash == params1.hash)
end
test "is not equal to an unpermitted Parameters instance with same params" do
params1 = ActionController::Parameters.new(a: 1).permit(:a)
params2 = ActionController::Parameters.new(a: 1)
assert(params1 != params2)
assert(params2 != params1)
assert(params1.hash != params2.hash)
assert(params2.hash != params1.hash)
end
test "is not equal to Parameters instance with different permitted params" do
params1 = ActionController::Parameters.new(a: 1, b: 2).permit(:a, :b)
params2 = ActionController::Parameters.new(a: 1, b: 2).permit(:a)
assert(params1 != params2)
assert(params2 != params1)
assert(params1.hash != params2.hash)
assert(params2.hash != params1.hash)
end
test "equality with simple types works" do
assert(@params != "Hello")
assert(@params != 42)
assert(@params != false)
end
test "inspect shows both class name, parameters and permitted flag" do
assert_equal(
'#<ActionController::Parameters {"person"=>{"age"=>"32", '\
'"name"=>{"first"=>"David", "last"=>"Heinemeier Hansson"}, ' \
'"addresses"=>[{"city"=>"Chicago", "state"=>"Illinois"}]}} permitted: false>',
@params.inspect
)
end
test "inspect prints updated permitted flag in the output" do
assert_match(/permitted: false/, @params.inspect)
@params.permit!
assert_match(/permitted: true/, @params.inspect)
end
test "#dig delegates the dig method to its values" do
assert_equal "David", @params.dig(:person, :name, :first)
assert_equal "Chicago", @params.dig(:person, :addresses, 0, :city)
end
test "#dig converts hashes to parameters" do
assert_kind_of ActionController::Parameters, @params.dig(:person)
assert_kind_of ActionController::Parameters, @params.dig(:person, :addresses, 0)
assert @params.dig(:person, :addresses).all?(ActionController::Parameters)
end
test "mutating #dig return value mutates underlying parameters" do
@params.dig(:person, :name)[:first] = "Bill"
assert_equal "Bill", @params.dig(:person, :name, :first)
@params.dig(:person, :addresses)[0] = { city: "Boston", state: "Massachusetts" }
assert_equal "Boston", @params.dig(:person, :addresses, 0, :city)
end
end