ruby-on-railshashactionpackrails-flash

`flash.discard` in Rails 2.3 fails because flash is a Hash, not a FlashHash


Given a functional test such as:

def test_exciting_rails_upgrades
    login(m=users(:manager))

    post :import_users_map_fields, :csv_file => fixture_file_upload('/users.csv', 'text/csv')
    assert flash.empty?
    flash.discard
    # other goodies omitted

end

In Rails 2.3.2 there are no errors, however in 2.3.15 the error is:

    NoMethodError: undefined method `discard' for {}:Hash
    /test/functional/broken_upgrades.rb:119:in `test_exciting_rails_upgrades'

Why is flash a Hash class instead of a FlashHash?

From the source it looks like both 2.3.2 and 2.3.15 ActionPack files lib/action_controller/flash.rb create the FlashHash class and inherit from Hash. However what is shown in this functional test in both 2.3.2 and 2.3.15 is a Hash class, not a HashFlash, so one cannot call discard on it.

Can anyone else reproduce this error with 2.3.15 and flash.discard?


Solution

  • Here are two test cases you can use to prove ActionController changes the type of 'flash' depending on whether or not it is already set.

    In my app, you cannot see :index unless you're logged in, so in test_flash_is_now_a_flashhash you see that flash was set by the backend properly, while in test_flash_is_a_plain_hash it was not.

    def test_flash_is_a_plain_hash
      login(users(:permitted_user))
      get :index
      assert flash.instance_of?(Hash)
    end
    
    def test_flash_is_now_a_flashhash
      get :index
      assert_redirected_to :controller => "login"
      assert flash.instance_of?(ActionController::Flash::FlashHash)
    end
    

    You can see this for yourself in the ActionController::TestRequest code:

    def flash
        session['flash'] || {}
    end
    

    Update: This has been fixed in Rails branch 2-3-stable.