aboutsummaryrefslogblamecommitdiffstats
path: root/actionpack/test/controller/parameters/nested_parameters_permit_test.rb
blob: 1403e224c0e4eb7f72ea98501e23b2a7f8f9df26 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                             

                                                   
 
                                                          
                                      
                                                                                   

     
                                       

                                              





                                      
            
                                            



                          

             
                   

         
                          
 
                                                                                                
 
                                           



                                                                            





                                                            

     
                                                                          

                                              


                                                              
         
        
 
                                                                  
 



                                                                             


                                                              



                                                                             

     
                                      

                                              
                           
        
 
                                                  



                                                       

                                              

                                     
        
                                    
 
                                                                       





                                                                 

                                              
                           
        





                                                                                 

                                              

                                  
        






                                                                 

                                              
                        
        



                                                    

                                          

                                              
                             


                                                                   
         
        
                                                                     
 




                                                                                            
 
                 
                                                                                                                                                         


                    
                                                                                 


                                                                

                                              
                             

                                                                    
         
        
                                                                   
 



                                                                                             
 
                                                                                  
     

                                

                                              
                     

                         
         
        
                                                               



                                                  
   
# frozen_string_literal: true

require "abstract_unit"
require "action_controller/metal/strong_parameters"

class NestedParametersPermitTest < ActiveSupport::TestCase
  def assert_filtered_out(params, key)
    assert_not params.has_key?(key), "key #{key.inspect} has not been filtered out"
  end

  test "permitted nested parameters" do
    params = ActionController::Parameters.new(
      book: {
        title: "Romeo and Juliet",
        authors: [{
          name: "William Shakespeare",
          born: "1564-04-26"
        }, {
          name: "Christopher Marlowe"
        }, {
          name: %w(malicious injected names)
        }],
        details: {
          pages: 200,
          genre: "Tragedy"
        },
        id: {
          isbn: "x"
        }
      },
      magazine: "Mjallo!")

    permitted = params.permit book: [ :title, { authors: [ :name ] }, { details: :pages }, :id ]

    assert_predicate permitted, :permitted?
    assert_equal "Romeo and Juliet", permitted[:book][:title]
    assert_equal "William Shakespeare", permitted[:book][:authors][0][:name]
    assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name]
    assert_equal 200, permitted[:book][:details][:pages]

    assert_filtered_out permitted, :magazine
    assert_filtered_out permitted[:book], :id
    assert_filtered_out permitted[:book][:details], :genre
    assert_filtered_out permitted[:book][:authors][0], :born
    assert_filtered_out permitted[:book][:authors][2], :name
  end

  test "permitted nested parameters with a string or a symbol as a key" do
    params = ActionController::Parameters.new(
      book: {
        "authors" => [
          { name: "William Shakespeare", born: "1564-04-26" },
          { name: "Christopher Marlowe" }
        ]
      })

    permitted = params.permit book: [ { "authors" => [ :name ] } ]

    assert_equal "William Shakespeare", permitted[:book]["authors"][0][:name]
    assert_equal "William Shakespeare", permitted[:book][:authors][0][:name]
    assert_equal "Christopher Marlowe", permitted[:book]["authors"][1][:name]
    assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name]

    permitted = params.permit book: [ { authors: [ :name ] } ]

    assert_equal "William Shakespeare", permitted[:book]["authors"][0][:name]
    assert_equal "William Shakespeare", permitted[:book][:authors][0][:name]
    assert_equal "Christopher Marlowe", permitted[:book]["authors"][1][:name]
    assert_equal "Christopher Marlowe", permitted[:book][:authors][1][:name]
  end

  test "nested arrays with strings" do
    params = ActionController::Parameters.new(
      book: {
        genres: ["Tragedy"]
      })

    permitted = params.permit book: { genres: [] }
    assert_equal ["Tragedy"], permitted[:book][:genres]
  end

  test "permit may specify symbols or strings" do
    params = ActionController::Parameters.new(
      book: {
        title: "Romeo and Juliet",
        author: "William Shakespeare"
      },
      magazine: "Shakespeare Today")

    permitted = params.permit({ book: ["title", :author] }, "magazine")
    assert_equal "Romeo and Juliet", permitted[:book][:title]
    assert_equal "William Shakespeare", permitted[:book][:author]
    assert_equal "Shakespeare Today", permitted[:magazine]
  end

  test "nested array with strings that should be hashes" do
    params = ActionController::Parameters.new(
      book: {
        genres: ["Tragedy"]
      })

    permitted = params.permit book: { genres: :type }
    assert_empty permitted[:book][:genres]
  end

  test "nested array with strings that should be hashes and additional values" do
    params = ActionController::Parameters.new(
      book: {
        title: "Romeo and Juliet",
        genres: ["Tragedy"]
      })

    permitted = params.permit book: [ :title, { genres: :type } ]
    assert_equal "Romeo and Juliet", permitted[:book][:title]
    assert_empty permitted[:book][:genres]
  end

  test "nested string that should be a hash" do
    params = ActionController::Parameters.new(
      book: {
        genre: "Tragedy"
      })

    permitted = params.permit book: { genre: :type }
    assert_nil permitted[:book][:genre]
  end

  test "fields_for-style nested params" do
    params = ActionController::Parameters.new(
      book: {
        authors_attributes: {
          '0': { name: "William Shakespeare", age_of_death: "52" },
          '1': { name: "Unattributed Assistant" },
          '2': { name: %w(injected names) }
        }
      })
    permitted = params.permit book: { authors_attributes: [ :name ] }

    assert_not_nil permitted[:book][:authors_attributes]["0"]
    assert_not_nil permitted[:book][:authors_attributes]["1"]
    assert_empty permitted[:book][:authors_attributes]["2"]
    assert_equal "William Shakespeare", permitted[:book][:authors_attributes]["0"][:name]
    assert_equal "Unattributed Assistant", permitted[:book][:authors_attributes]["1"][:name]

    assert_equal(
      { "book" => { "authors_attributes" => { "0" => { "name" => "William Shakespeare" }, "1" => { "name" => "Unattributed Assistant" }, "2" => {} } } },
      permitted.to_h
    )

    assert_filtered_out permitted[:book][:authors_attributes]["0"], :age_of_death
  end

  test "fields_for-style nested params with negative numbers" do
    params = ActionController::Parameters.new(
      book: {
        authors_attributes: {
          '-1': { name: "William Shakespeare", age_of_death: "52" },
          '-2': { name: "Unattributed Assistant" }
        }
      })
    permitted = params.permit book: { authors_attributes: [:name] }

    assert_not_nil permitted[:book][:authors_attributes]["-1"]
    assert_not_nil permitted[:book][:authors_attributes]["-2"]
    assert_equal "William Shakespeare", permitted[:book][:authors_attributes]["-1"][:name]
    assert_equal "Unattributed Assistant", permitted[:book][:authors_attributes]["-2"][:name]

    assert_filtered_out permitted[:book][:authors_attributes]["-1"], :age_of_death
  end

  test "nested number as key" do
    params = ActionController::Parameters.new(
      product: {
        properties: {
          "0" => "prop0",
          "1" => "prop1"
        }
      })
    params = params.require(:product).permit(properties: ["0"])
    assert_not_nil        params[:properties]["0"]
    assert_nil            params[:properties]["1"]
    assert_equal "prop0", params[:properties]["0"]
  end
end