├── .gitignore ├── .travis.yml ├── Gemfile ├── LICENSE.txt ├── README.md ├── Rakefile ├── gemfiles ├── Gemfile.rails-2.3.x ├── Gemfile.rails-2.3.x.lock ├── Gemfile.rails-3.0.x ├── Gemfile.rails-3.0.x.lock ├── Gemfile.rails-3.1.x ├── Gemfile.rails-3.1.x.lock ├── Gemfile.rails-3.2.x ├── Gemfile.rails-3.2.x.lock ├── Gemfile.rails-4.0.x ├── Gemfile.rails-4.0.x.lock ├── Gemfile.rails-4.1.x ├── Gemfile.rails-4.1.x.lock ├── Gemfile.rails-4.2.x └── Gemfile.rails-4.2.x.lock ├── lib ├── rails_4_session_flash_backport.rb └── rails_4_session_flash_backport │ ├── rails2 │ ├── flash_hash.rb │ └── session_with_indifferent_access.rb │ ├── rails3-0 │ └── flash_hash.rb │ ├── rails3-1 │ └── flash_hash.rb │ ├── rails4 │ └── flash_hash.rb │ └── version.rb ├── rails_4_session_flash_backport.gemspec ├── script └── update-lockfiles └── spec ├── rails2 └── flash_hash_spec.rb ├── rails3-0 └── flash_hash_spec.rb ├── rails3-1 └── flash_hash_spec.rb └── rails4 └── flash_hash_spec.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | .yardoc 6 | Gemfile.lock 7 | InstalledFiles 8 | _yardoc 9 | coverage 10 | doc/ 11 | lib/bundler/man 12 | pkg 13 | rdoc 14 | spec/reports 15 | test/tmp 16 | test/version_tmp 17 | tmp 18 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | before_install: 3 | - gem install bundler -v 1.16.0 4 | rvm: 5 | - 1.9.3 6 | - 2.0.0 7 | - 2.1.5 8 | - 2.2.0 9 | gemfile: 10 | - gemfiles/Gemfile.rails-2.3.x 11 | - gemfiles/Gemfile.rails-3.0.x 12 | - gemfiles/Gemfile.rails-3.1.x 13 | - gemfiles/Gemfile.rails-3.2.x 14 | - gemfiles/Gemfile.rails-4.0.x 15 | - gemfiles/Gemfile.rails-4.1.x 16 | - gemfiles/Gemfile.rails-4.2.x 17 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gemspec 4 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012 Envato, Lucas Parry, Jack Chen (chendo) 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Rails4SessionFlashBackport 2 | [![Gem Version](https://badge.fury.io/rb/rails_4_session_flash_backport.png)](http://badge.fury.io/rb/rails_4_session_flash_backport) 3 | [![Build Status](https://travis-ci.org/envato/rails_4_session_flash_backport.png)](https://travis-ci.org/envato/rails_4_session_flash_backport) 4 | 5 | Different versions of Rails have stored flash messages in different objects in 6 | the session, making it a pain to upgrade without nuking everyones session. The 7 | good ol' `ActionDispatch::Session::SessionRestoreError` making life difficult. 8 | 9 | This gem was created because we wanted to be able to keep our users Rails 2 10 | sessions working on Rails 3, and we figured as long as we're going to be doing 11 | crazy stuff we might as well go and use the far more sensible practice from 12 | Rails 4 of storing the flash as basic ruby types and sweeping the flash before 13 | persisting into the session. 14 | 15 | For more details of the how and why, check out our blog post [Happily upgrading 16 | Ruby on Rails at production scale][blog-post]. 17 | 18 | [blog-post]: http://webuild.envato.com/blog/upgrading-ruby-on-rails-at-production-scale/ 19 | 20 | When using this gem on a Rails 2.3, 3.1+ or 4 app: 21 | 22 | * Flash messages are stored as basic objects in the Rails 4 style, pre-swept. 23 | * Flash messages in the Rails 2 format can be successfully decoded. 24 | * Flash messages in the Rails 3.1 format can be successfully decoded. 25 | * Flash messages in the Rails 4 format can be successfully decoded. 26 | 27 | This actually makes it possible to bounce requests from a Rails 2 server, to a 28 | Rails 3 server and back again so long as both servers are using this gem. Very 29 | helpful when you're doing a big Rails 2 => 3 upgrade and want to run a few 30 | Rails 3 servers concurrently with your Rails 2 cluster to verify everything is 31 | fine and performance is acceptable without having to do the all-in switch. 32 | 33 | ### Rails 2 34 | 35 | Additionally, on Rails 2 we include some patches for the SessionHash and 36 | CookieStore in order to make them act more like a HashWithIndifferentAccess, 37 | like the versions on Rails 3, so that your session_id can survive a trip to 38 | Rails 3 and back. 39 | 40 | ### Rails 3.0 41 | 42 | Rails 3.0 was a weird half-way house between 2.x and 3.1. The 3.0 to 3.1 43 | upgrade gave many of us an [Argument Error (dump format error) 44 | problem][argumenterror-so]. 45 | 46 | [argumenterror-so]: http://stackoverflow.com/questions/9120501/what-causes-the-argumenterror-dump-format-error 47 | 48 | Consequently rails 3.0 with this gem can decode a rails 2.3 flash and a rails 49 | 3.0 flash but not a rails 3.1+ or 4.x flash. 50 | 51 | Once this gem is installed, rails 3.0 flashes will be stored in the rails 4 52 | style simple format and can be used with any other rails version with this gem, 53 | and from rails 4 without the gem, so it actually alleviates the upgrade pain. 54 | Be aware that older sessions may still contain the older formatted hash if 55 | you've been running on rails 3.0 for some time. 56 | 57 | Using this gem from rails 2.3 will completely skip the issue. 58 | 59 | ### Rails 4 60 | 61 | This gem also now backports functionality for Rails 2, 3 and 4 which sweeps the 62 | flash before persisting it into the session. This means putting large objects 63 | into `flash.now` shouldn't cause `CookieOverflow` errors. 64 | 65 | ## Installation 66 | 67 | Add this line to your application's Gemfile: 68 | 69 | gem 'rails_4_session_flash_backport' 70 | 71 | And then execute: 72 | 73 | $ bundle 74 | 75 | Or install it yourself as: 76 | 77 | $ gem install rails_4_session_flash_backport 78 | 79 | ## Development 80 | 81 | If you update the Gem version or any of the Gemfiles, you'll need to update the 82 | Gemfile.locks, too. You can do this by running `./script/update-lockfiles` and 83 | checking the results into Git. 84 | 85 | ## Copyright 86 | 87 | Copyright (c) 2012 [Envato](http://envato.com), [Lucas Parry](http://github.com/lparry), [chendo](http://github.com/chendo), [sj26](http://github.com/sj26). See LICENSE.txt for further details. 88 | 89 | 90 | ## About 91 | 92 | This project is maintained by the [Envato engineering team][webuild] and funded by [Envato][envato]. 93 | 94 | [Envato logo][envato] 95 | 96 | Encouraging the use and creation of open source software is one of the ways we serve our community. See [our other projects][oss] or [come work with us][careers] where you'll find an incredibly diverse, intelligent and capable group of people who help make our company succeed and make our workplace fun, friendly and happy. 97 | 98 | [webuild]: http://webuild.envato.com?utm_source=github 99 | [envato]: https://envato.com?utm_source=github 100 | [oss]: http://opensource.envato.com//?utm_source=github 101 | [careers]: http://careers.envato.com/?utm_source=github 102 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'bundler/setup' 3 | require 'bundler/gem_tasks' 4 | 5 | desc "Run specs for loaded version of rails" 6 | task :spec do 7 | rails_version = Gem.loaded_specs["rails"].version.to_s 8 | 9 | spec_dir = 10 | case rails_version 11 | when /\A2\./ 12 | "spec/rails2" 13 | when /\A3\.0\./ 14 | "spec/rails3-0" 15 | when /\A3\./ 16 | "spec/rails3-1" 17 | when /\A4\./ 18 | "spec/rails4" 19 | else 20 | fail "rails_4_session_flash_backport doesnt yet do anything on Rails #{rails_version}" 21 | end 22 | 23 | system "bundle", "exec", "rspec", "--color", spec_dir or fail 24 | end 25 | 26 | task :default => :spec 27 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-2.3.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec :path => ".." 4 | 5 | group :development do 6 | gem "actionpack", "~> 2.3" 7 | gem "iconv" 8 | end 9 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-2.3.x.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rails_4_session_flash_backport (0.2.2) 5 | rails (>= 2.0, < 4.3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionmailer (2.3.18) 11 | actionpack (= 2.3.18) 12 | actionpack (2.3.18) 13 | activesupport (= 2.3.18) 14 | rack (~> 1.1.0) 15 | activerecord (2.3.18) 16 | activesupport (= 2.3.18) 17 | activeresource (2.3.18) 18 | activesupport (= 2.3.18) 19 | activesupport (2.3.18) 20 | coderay (1.1.0) 21 | diff-lcs (1.2.5) 22 | iconv (1.0.4) 23 | method_source (0.8.2) 24 | pry (0.10.1) 25 | coderay (~> 1.1.0) 26 | method_source (~> 0.8.1) 27 | slop (~> 3.4) 28 | rack (1.1.6) 29 | rails (2.3.18) 30 | actionmailer (= 2.3.18) 31 | actionpack (= 2.3.18) 32 | activerecord (= 2.3.18) 33 | activeresource (= 2.3.18) 34 | activesupport (= 2.3.18) 35 | rake (>= 0.8.3) 36 | rake (10.4.2) 37 | rspec (3.2.0) 38 | rspec-core (~> 3.2.0) 39 | rspec-expectations (~> 3.2.0) 40 | rspec-mocks (~> 3.2.0) 41 | rspec-core (3.2.0) 42 | rspec-support (~> 3.2.0) 43 | rspec-expectations (3.2.0) 44 | diff-lcs (>= 1.2.0, < 2.0) 45 | rspec-support (~> 3.2.0) 46 | rspec-mocks (3.2.0) 47 | diff-lcs (>= 1.2.0, < 2.0) 48 | rspec-support (~> 3.2.0) 49 | rspec-support (3.2.1) 50 | slop (3.6.0) 51 | 52 | PLATFORMS 53 | ruby 54 | 55 | DEPENDENCIES 56 | actionpack (~> 2.3) 57 | iconv 58 | pry 59 | rails_4_session_flash_backport! 60 | rake 61 | rspec 62 | 63 | BUNDLED WITH 64 | 1.16.1 65 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-3.0.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec :path => ".." 4 | 5 | group :development do 6 | gem "actionpack", "3.0.20" 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-3.0.x.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rails_4_session_flash_backport (0.2.2) 5 | rails (>= 2.0, < 4.3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | abstract (1.0.0) 11 | actionmailer (3.0.20) 12 | actionpack (= 3.0.20) 13 | mail (~> 2.2.19) 14 | actionpack (3.0.20) 15 | activemodel (= 3.0.20) 16 | activesupport (= 3.0.20) 17 | builder (~> 2.1.2) 18 | erubis (~> 2.6.6) 19 | i18n (~> 0.5.0) 20 | rack (~> 1.2.5) 21 | rack-mount (~> 0.6.14) 22 | rack-test (~> 0.5.7) 23 | tzinfo (~> 0.3.23) 24 | activemodel (3.0.20) 25 | activesupport (= 3.0.20) 26 | builder (~> 2.1.2) 27 | i18n (~> 0.5.0) 28 | activerecord (3.0.20) 29 | activemodel (= 3.0.20) 30 | activesupport (= 3.0.20) 31 | arel (~> 2.0.10) 32 | tzinfo (~> 0.3.23) 33 | activeresource (3.0.20) 34 | activemodel (= 3.0.20) 35 | activesupport (= 3.0.20) 36 | activesupport (3.0.20) 37 | arel (2.0.10) 38 | builder (2.1.2) 39 | coderay (1.1.0) 40 | diff-lcs (1.2.5) 41 | erubis (2.6.6) 42 | abstract (>= 1.0.0) 43 | i18n (0.5.4) 44 | json (1.8.6) 45 | mail (2.2.20) 46 | activesupport (>= 2.3.6) 47 | i18n (>= 0.4.0) 48 | mime-types (~> 1.16) 49 | treetop (~> 1.4.8) 50 | method_source (0.8.2) 51 | mime-types (1.25.1) 52 | polyglot (0.3.5) 53 | pry (0.10.1) 54 | coderay (~> 1.1.0) 55 | method_source (~> 0.8.1) 56 | slop (~> 3.4) 57 | rack (1.2.8) 58 | rack-mount (0.6.14) 59 | rack (>= 1.0.0) 60 | rack-test (0.5.7) 61 | rack (>= 1.0) 62 | rails (3.0.20) 63 | actionmailer (= 3.0.20) 64 | actionpack (= 3.0.20) 65 | activerecord (= 3.0.20) 66 | activeresource (= 3.0.20) 67 | activesupport (= 3.0.20) 68 | bundler (~> 1.0) 69 | railties (= 3.0.20) 70 | railties (3.0.20) 71 | actionpack (= 3.0.20) 72 | activesupport (= 3.0.20) 73 | rake (>= 0.8.7) 74 | rdoc (~> 3.4) 75 | thor (~> 0.14.4) 76 | rake (10.4.2) 77 | rdoc (3.12.2) 78 | json (~> 1.4) 79 | rspec (3.2.0) 80 | rspec-core (~> 3.2.0) 81 | rspec-expectations (~> 3.2.0) 82 | rspec-mocks (~> 3.2.0) 83 | rspec-core (3.2.0) 84 | rspec-support (~> 3.2.0) 85 | rspec-expectations (3.2.0) 86 | diff-lcs (>= 1.2.0, < 2.0) 87 | rspec-support (~> 3.2.0) 88 | rspec-mocks (3.2.0) 89 | diff-lcs (>= 1.2.0, < 2.0) 90 | rspec-support (~> 3.2.0) 91 | rspec-support (3.2.1) 92 | slop (3.6.0) 93 | thor (0.14.6) 94 | treetop (1.4.15) 95 | polyglot 96 | polyglot (>= 0.3.1) 97 | tzinfo (0.3.43) 98 | 99 | PLATFORMS 100 | ruby 101 | 102 | DEPENDENCIES 103 | actionpack (= 3.0.20) 104 | pry 105 | rails_4_session_flash_backport! 106 | rake 107 | rspec 108 | 109 | BUNDLED WITH 110 | 1.16.1 111 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-3.1.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec :path => ".." 4 | 5 | group :development do 6 | gem "actionpack", "3.1.12" 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-3.1.x.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rails_4_session_flash_backport (0.2.2) 5 | rails (>= 2.0, < 4.3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionmailer (3.1.12) 11 | actionpack (= 3.1.12) 12 | mail (~> 2.4.4) 13 | actionpack (3.1.12) 14 | activemodel (= 3.1.12) 15 | activesupport (= 3.1.12) 16 | builder (~> 3.0.0) 17 | erubis (~> 2.7.0) 18 | i18n (~> 0.6) 19 | rack (~> 1.3.6) 20 | rack-cache (~> 1.2) 21 | rack-mount (~> 0.8.2) 22 | rack-test (~> 0.6.1) 23 | sprockets (~> 2.0.4) 24 | activemodel (3.1.12) 25 | activesupport (= 3.1.12) 26 | builder (~> 3.0.0) 27 | i18n (~> 0.6) 28 | activerecord (3.1.12) 29 | activemodel (= 3.1.12) 30 | activesupport (= 3.1.12) 31 | arel (~> 2.2.3) 32 | tzinfo (~> 0.3.29) 33 | activeresource (3.1.12) 34 | activemodel (= 3.1.12) 35 | activesupport (= 3.1.12) 36 | activesupport (3.1.12) 37 | multi_json (~> 1.0) 38 | arel (2.2.3) 39 | builder (3.0.4) 40 | coderay (1.1.0) 41 | diff-lcs (1.2.5) 42 | erubis (2.7.0) 43 | hike (1.2.3) 44 | i18n (0.7.0) 45 | json (1.8.6) 46 | mail (2.4.4) 47 | i18n (>= 0.4.0) 48 | mime-types (~> 1.16) 49 | treetop (~> 1.4.8) 50 | method_source (0.8.2) 51 | mime-types (1.25.1) 52 | multi_json (1.10.1) 53 | polyglot (0.3.5) 54 | pry (0.10.1) 55 | coderay (~> 1.1.0) 56 | method_source (~> 0.8.1) 57 | slop (~> 3.4) 58 | rack (1.3.10) 59 | rack-cache (1.2) 60 | rack (>= 0.4) 61 | rack-mount (0.8.3) 62 | rack (>= 1.0.0) 63 | rack-ssl (1.3.4) 64 | rack 65 | rack-test (0.6.3) 66 | rack (>= 1.0) 67 | rails (3.1.12) 68 | actionmailer (= 3.1.12) 69 | actionpack (= 3.1.12) 70 | activerecord (= 3.1.12) 71 | activeresource (= 3.1.12) 72 | activesupport (= 3.1.12) 73 | bundler (~> 1.0) 74 | railties (= 3.1.12) 75 | railties (3.1.12) 76 | actionpack (= 3.1.12) 77 | activesupport (= 3.1.12) 78 | rack-ssl (~> 1.3.2) 79 | rake (>= 0.8.7) 80 | rdoc (~> 3.4) 81 | thor (~> 0.14.6) 82 | rake (10.4.2) 83 | rdoc (3.12.2) 84 | json (~> 1.4) 85 | rspec (3.2.0) 86 | rspec-core (~> 3.2.0) 87 | rspec-expectations (~> 3.2.0) 88 | rspec-mocks (~> 3.2.0) 89 | rspec-core (3.2.0) 90 | rspec-support (~> 3.2.0) 91 | rspec-expectations (3.2.0) 92 | diff-lcs (>= 1.2.0, < 2.0) 93 | rspec-support (~> 3.2.0) 94 | rspec-mocks (3.2.0) 95 | diff-lcs (>= 1.2.0, < 2.0) 96 | rspec-support (~> 3.2.0) 97 | rspec-support (3.2.1) 98 | slop (3.6.0) 99 | sprockets (2.0.5) 100 | hike (~> 1.2) 101 | rack (~> 1.0) 102 | tilt (~> 1.1, != 1.3.0) 103 | thor (0.14.6) 104 | tilt (1.4.1) 105 | treetop (1.4.15) 106 | polyglot 107 | polyglot (>= 0.3.1) 108 | tzinfo (0.3.53) 109 | 110 | PLATFORMS 111 | ruby 112 | 113 | DEPENDENCIES 114 | actionpack (= 3.1.12) 115 | pry 116 | rails_4_session_flash_backport! 117 | rake 118 | rspec 119 | 120 | BUNDLED WITH 121 | 1.16.1 122 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-3.2.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec :path => ".." 4 | 5 | group :development do 6 | gem "actionpack", "3.2.21" 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-3.2.x.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rails_4_session_flash_backport (0.2.2) 5 | rails (>= 2.0, < 4.3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionmailer (3.2.21) 11 | actionpack (= 3.2.21) 12 | mail (~> 2.5.4) 13 | actionpack (3.2.21) 14 | activemodel (= 3.2.21) 15 | activesupport (= 3.2.21) 16 | builder (~> 3.0.0) 17 | erubis (~> 2.7.0) 18 | journey (~> 1.0.4) 19 | rack (~> 1.4.5) 20 | rack-cache (~> 1.2) 21 | rack-test (~> 0.6.1) 22 | sprockets (~> 2.2.1) 23 | activemodel (3.2.21) 24 | activesupport (= 3.2.21) 25 | builder (~> 3.0.0) 26 | activerecord (3.2.21) 27 | activemodel (= 3.2.21) 28 | activesupport (= 3.2.21) 29 | arel (~> 3.0.2) 30 | tzinfo (~> 0.3.29) 31 | activeresource (3.2.21) 32 | activemodel (= 3.2.21) 33 | activesupport (= 3.2.21) 34 | activesupport (3.2.21) 35 | i18n (~> 0.6, >= 0.6.4) 36 | multi_json (~> 1.0) 37 | arel (3.0.3) 38 | builder (3.0.4) 39 | coderay (1.1.0) 40 | diff-lcs (1.2.5) 41 | erubis (2.7.0) 42 | hike (1.2.3) 43 | i18n (0.7.0) 44 | journey (1.0.4) 45 | json (1.8.6) 46 | mail (2.5.5) 47 | mime-types (~> 1.16) 48 | treetop (~> 1.4.8) 49 | method_source (0.8.2) 50 | mime-types (1.25.1) 51 | multi_json (1.10.1) 52 | polyglot (0.3.5) 53 | pry (0.10.1) 54 | coderay (~> 1.1.0) 55 | method_source (~> 0.8.1) 56 | slop (~> 3.4) 57 | rack (1.4.5) 58 | rack-cache (1.2) 59 | rack (>= 0.4) 60 | rack-ssl (1.3.4) 61 | rack 62 | rack-test (0.6.3) 63 | rack (>= 1.0) 64 | rails (3.2.21) 65 | actionmailer (= 3.2.21) 66 | actionpack (= 3.2.21) 67 | activerecord (= 3.2.21) 68 | activeresource (= 3.2.21) 69 | activesupport (= 3.2.21) 70 | bundler (~> 1.0) 71 | railties (= 3.2.21) 72 | railties (3.2.21) 73 | actionpack (= 3.2.21) 74 | activesupport (= 3.2.21) 75 | rack-ssl (~> 1.3.2) 76 | rake (>= 0.8.7) 77 | rdoc (~> 3.4) 78 | thor (>= 0.14.6, < 2.0) 79 | rake (10.4.2) 80 | rdoc (3.12.2) 81 | json (~> 1.4) 82 | rspec (3.2.0) 83 | rspec-core (~> 3.2.0) 84 | rspec-expectations (~> 3.2.0) 85 | rspec-mocks (~> 3.2.0) 86 | rspec-core (3.2.0) 87 | rspec-support (~> 3.2.0) 88 | rspec-expectations (3.2.0) 89 | diff-lcs (>= 1.2.0, < 2.0) 90 | rspec-support (~> 3.2.0) 91 | rspec-mocks (3.2.0) 92 | diff-lcs (>= 1.2.0, < 2.0) 93 | rspec-support (~> 3.2.0) 94 | rspec-support (3.2.1) 95 | slop (3.6.0) 96 | sprockets (2.2.3) 97 | hike (~> 1.2) 98 | multi_json (~> 1.0) 99 | rack (~> 1.0) 100 | tilt (~> 1.1, != 1.3.0) 101 | thor (0.20.0) 102 | tilt (1.4.1) 103 | treetop (1.4.15) 104 | polyglot 105 | polyglot (>= 0.3.1) 106 | tzinfo (0.3.53) 107 | 108 | PLATFORMS 109 | ruby 110 | 111 | DEPENDENCIES 112 | actionpack (= 3.2.21) 113 | pry 114 | rails_4_session_flash_backport! 115 | rake 116 | rspec 117 | 118 | BUNDLED WITH 119 | 1.16.1 120 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-4.0.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec :path => ".." 4 | 5 | group :development do 6 | gem "actionpack", "4.0.13" 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-4.0.x.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rails_4_session_flash_backport (0.2.2) 5 | rails (>= 2.0, < 4.3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionmailer (4.0.13) 11 | actionpack (= 4.0.13) 12 | mail (~> 2.5, >= 2.5.4) 13 | actionpack (4.0.13) 14 | activesupport (= 4.0.13) 15 | builder (~> 3.1.0) 16 | erubis (~> 2.7.0) 17 | rack (~> 1.5.2) 18 | rack-test (~> 0.6.2) 19 | activemodel (4.0.13) 20 | activesupport (= 4.0.13) 21 | builder (~> 3.1.0) 22 | activerecord (4.0.13) 23 | activemodel (= 4.0.13) 24 | activerecord-deprecated_finders (~> 1.0.2) 25 | activesupport (= 4.0.13) 26 | arel (~> 4.0.0) 27 | activerecord-deprecated_finders (1.0.4) 28 | activesupport (4.0.13) 29 | i18n (~> 0.6, >= 0.6.9) 30 | minitest (~> 4.2) 31 | multi_json (~> 1.3) 32 | thread_safe (~> 0.1) 33 | tzinfo (~> 0.3.37) 34 | arel (4.0.2) 35 | builder (3.1.4) 36 | coderay (1.1.0) 37 | concurrent-ruby (1.0.5) 38 | diff-lcs (1.2.5) 39 | erubis (2.7.0) 40 | i18n (0.7.0) 41 | mail (2.7.0) 42 | mini_mime (>= 0.1.1) 43 | method_source (0.8.2) 44 | mini_mime (1.0.0) 45 | minitest (4.7.5) 46 | multi_json (1.10.1) 47 | pry (0.10.1) 48 | coderay (~> 1.1.0) 49 | method_source (~> 0.8.1) 50 | slop (~> 3.4) 51 | rack (1.5.2) 52 | rack-test (0.6.3) 53 | rack (>= 1.0) 54 | rails (4.0.13) 55 | actionmailer (= 4.0.13) 56 | actionpack (= 4.0.13) 57 | activerecord (= 4.0.13) 58 | activesupport (= 4.0.13) 59 | bundler (>= 1.3.0, < 2.0) 60 | railties (= 4.0.13) 61 | sprockets-rails (~> 2.0) 62 | railties (4.0.13) 63 | actionpack (= 4.0.13) 64 | activesupport (= 4.0.13) 65 | rake (>= 0.8.7) 66 | thor (>= 0.18.1, < 2.0) 67 | rake (10.4.2) 68 | rspec (3.2.0) 69 | rspec-core (~> 3.2.0) 70 | rspec-expectations (~> 3.2.0) 71 | rspec-mocks (~> 3.2.0) 72 | rspec-core (3.2.0) 73 | rspec-support (~> 3.2.0) 74 | rspec-expectations (3.2.0) 75 | diff-lcs (>= 1.2.0, < 2.0) 76 | rspec-support (~> 3.2.0) 77 | rspec-mocks (3.2.0) 78 | diff-lcs (>= 1.2.0, < 2.0) 79 | rspec-support (~> 3.2.0) 80 | rspec-support (3.2.1) 81 | slop (3.6.0) 82 | sprockets (3.7.1) 83 | concurrent-ruby (~> 1.0) 84 | rack (> 1, < 3) 85 | sprockets-rails (2.3.3) 86 | actionpack (>= 3.0) 87 | activesupport (>= 3.0) 88 | sprockets (>= 2.8, < 4.0) 89 | thor (0.20.0) 90 | thread_safe (0.3.4) 91 | tzinfo (0.3.43) 92 | 93 | PLATFORMS 94 | ruby 95 | 96 | DEPENDENCIES 97 | actionpack (= 4.0.13) 98 | pry 99 | rails_4_session_flash_backport! 100 | rake 101 | rspec 102 | 103 | BUNDLED WITH 104 | 1.16.1 105 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-4.1.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec :path => ".." 4 | 5 | group :development do 6 | gem "actionpack", "4.1.9" 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-4.1.x.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rails_4_session_flash_backport (0.2.2) 5 | rails (>= 2.0, < 4.3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionmailer (4.1.9) 11 | actionpack (= 4.1.9) 12 | actionview (= 4.1.9) 13 | mail (~> 2.5, >= 2.5.4) 14 | actionpack (4.1.9) 15 | actionview (= 4.1.9) 16 | activesupport (= 4.1.9) 17 | rack (~> 1.5.2) 18 | rack-test (~> 0.6.2) 19 | actionview (4.1.9) 20 | activesupport (= 4.1.9) 21 | builder (~> 3.1) 22 | erubis (~> 2.7.0) 23 | activemodel (4.1.9) 24 | activesupport (= 4.1.9) 25 | builder (~> 3.1) 26 | activerecord (4.1.9) 27 | activemodel (= 4.1.9) 28 | activesupport (= 4.1.9) 29 | arel (~> 5.0.0) 30 | activesupport (4.1.9) 31 | i18n (~> 0.6, >= 0.6.9) 32 | json (~> 1.7, >= 1.7.7) 33 | minitest (~> 5.1) 34 | thread_safe (~> 0.1) 35 | tzinfo (~> 1.1) 36 | arel (5.0.1.20140414130214) 37 | builder (3.2.2) 38 | coderay (1.1.0) 39 | concurrent-ruby (1.0.5) 40 | diff-lcs (1.2.5) 41 | erubis (2.7.0) 42 | i18n (0.7.0) 43 | json (1.8.2) 44 | mail (2.7.0) 45 | mini_mime (>= 0.1.1) 46 | method_source (0.8.2) 47 | mini_mime (1.0.0) 48 | minitest (5.5.1) 49 | pry (0.10.1) 50 | coderay (~> 1.1.0) 51 | method_source (~> 0.8.1) 52 | slop (~> 3.4) 53 | rack (1.5.2) 54 | rack-test (0.6.3) 55 | rack (>= 1.0) 56 | rails (4.1.9) 57 | actionmailer (= 4.1.9) 58 | actionpack (= 4.1.9) 59 | actionview (= 4.1.9) 60 | activemodel (= 4.1.9) 61 | activerecord (= 4.1.9) 62 | activesupport (= 4.1.9) 63 | bundler (>= 1.3.0, < 2.0) 64 | railties (= 4.1.9) 65 | sprockets-rails (~> 2.0) 66 | railties (4.1.9) 67 | actionpack (= 4.1.9) 68 | activesupport (= 4.1.9) 69 | rake (>= 0.8.7) 70 | thor (>= 0.18.1, < 2.0) 71 | rake (10.4.2) 72 | rspec (3.2.0) 73 | rspec-core (~> 3.2.0) 74 | rspec-expectations (~> 3.2.0) 75 | rspec-mocks (~> 3.2.0) 76 | rspec-core (3.2.0) 77 | rspec-support (~> 3.2.0) 78 | rspec-expectations (3.2.0) 79 | diff-lcs (>= 1.2.0, < 2.0) 80 | rspec-support (~> 3.2.0) 81 | rspec-mocks (3.2.0) 82 | diff-lcs (>= 1.2.0, < 2.0) 83 | rspec-support (~> 3.2.0) 84 | rspec-support (3.2.1) 85 | slop (3.6.0) 86 | sprockets (3.7.1) 87 | concurrent-ruby (~> 1.0) 88 | rack (> 1, < 3) 89 | sprockets-rails (2.3.3) 90 | actionpack (>= 3.0) 91 | activesupport (>= 3.0) 92 | sprockets (>= 2.8, < 4.0) 93 | thor (0.20.0) 94 | thread_safe (0.3.4) 95 | tzinfo (1.2.2) 96 | thread_safe (~> 0.1) 97 | 98 | PLATFORMS 99 | ruby 100 | 101 | DEPENDENCIES 102 | actionpack (= 4.1.9) 103 | pry 104 | rails_4_session_flash_backport! 105 | rake 106 | rspec 107 | 108 | BUNDLED WITH 109 | 1.16.1 110 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-4.2.x: -------------------------------------------------------------------------------- 1 | source "https://rubygems.org" 2 | 3 | gemspec :path => ".." 4 | 5 | group :development do 6 | gem "actionpack", "4.2.0" 7 | end 8 | -------------------------------------------------------------------------------- /gemfiles/Gemfile.rails-4.2.x.lock: -------------------------------------------------------------------------------- 1 | PATH 2 | remote: .. 3 | specs: 4 | rails_4_session_flash_backport (0.2.2) 5 | rails (>= 2.0, < 4.3) 6 | 7 | GEM 8 | remote: https://rubygems.org/ 9 | specs: 10 | actionmailer (4.2.0) 11 | actionpack (= 4.2.0) 12 | actionview (= 4.2.0) 13 | activejob (= 4.2.0) 14 | mail (~> 2.5, >= 2.5.4) 15 | rails-dom-testing (~> 1.0, >= 1.0.5) 16 | actionpack (4.2.0) 17 | actionview (= 4.2.0) 18 | activesupport (= 4.2.0) 19 | rack (~> 1.6.0) 20 | rack-test (~> 0.6.2) 21 | rails-dom-testing (~> 1.0, >= 1.0.5) 22 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 23 | actionview (4.2.0) 24 | activesupport (= 4.2.0) 25 | builder (~> 3.1) 26 | erubis (~> 2.7.0) 27 | rails-dom-testing (~> 1.0, >= 1.0.5) 28 | rails-html-sanitizer (~> 1.0, >= 1.0.1) 29 | activejob (4.2.0) 30 | activesupport (= 4.2.0) 31 | globalid (>= 0.3.0) 32 | activemodel (4.2.0) 33 | activesupport (= 4.2.0) 34 | builder (~> 3.1) 35 | activerecord (4.2.0) 36 | activemodel (= 4.2.0) 37 | activesupport (= 4.2.0) 38 | arel (~> 6.0) 39 | activesupport (4.2.0) 40 | i18n (~> 0.7) 41 | json (~> 1.7, >= 1.7.7) 42 | minitest (~> 5.1) 43 | thread_safe (~> 0.3, >= 0.3.4) 44 | tzinfo (~> 1.1) 45 | arel (6.0.4) 46 | builder (3.2.2) 47 | coderay (1.1.0) 48 | concurrent-ruby (1.0.5) 49 | diff-lcs (1.2.5) 50 | erubis (2.7.0) 51 | globalid (0.4.1) 52 | activesupport (>= 4.2.0) 53 | i18n (0.7.0) 54 | json (1.8.2) 55 | loofah (2.0.1) 56 | nokogiri (>= 1.5.9) 57 | mail (2.7.0) 58 | mini_mime (>= 0.1.1) 59 | method_source (0.8.2) 60 | mini_mime (1.0.0) 61 | mini_portile (0.6.2) 62 | minitest (5.5.1) 63 | nokogiri (1.6.6.2) 64 | mini_portile (~> 0.6.0) 65 | pry (0.10.1) 66 | coderay (~> 1.1.0) 67 | method_source (~> 0.8.1) 68 | slop (~> 3.4) 69 | rack (1.6.0) 70 | rack-test (0.6.3) 71 | rack (>= 1.0) 72 | rails (4.2.0) 73 | actionmailer (= 4.2.0) 74 | actionpack (= 4.2.0) 75 | actionview (= 4.2.0) 76 | activejob (= 4.2.0) 77 | activemodel (= 4.2.0) 78 | activerecord (= 4.2.0) 79 | activesupport (= 4.2.0) 80 | bundler (>= 1.3.0, < 2.0) 81 | railties (= 4.2.0) 82 | sprockets-rails 83 | rails-deprecated_sanitizer (1.0.3) 84 | activesupport (>= 4.2.0.alpha) 85 | rails-dom-testing (1.0.5) 86 | activesupport (>= 4.2.0.beta, < 5.0) 87 | nokogiri (~> 1.6.0) 88 | rails-deprecated_sanitizer (>= 1.0.1) 89 | rails-html-sanitizer (1.0.1) 90 | loofah (~> 2.0) 91 | railties (4.2.0) 92 | actionpack (= 4.2.0) 93 | activesupport (= 4.2.0) 94 | rake (>= 0.8.7) 95 | thor (>= 0.18.1, < 2.0) 96 | rake (10.4.2) 97 | rspec (3.2.0) 98 | rspec-core (~> 3.2.0) 99 | rspec-expectations (~> 3.2.0) 100 | rspec-mocks (~> 3.2.0) 101 | rspec-core (3.2.0) 102 | rspec-support (~> 3.2.0) 103 | rspec-expectations (3.2.0) 104 | diff-lcs (>= 1.2.0, < 2.0) 105 | rspec-support (~> 3.2.0) 106 | rspec-mocks (3.2.0) 107 | diff-lcs (>= 1.2.0, < 2.0) 108 | rspec-support (~> 3.2.0) 109 | rspec-support (3.2.1) 110 | slop (3.6.0) 111 | sprockets (3.7.1) 112 | concurrent-ruby (~> 1.0) 113 | rack (> 1, < 3) 114 | sprockets-rails (3.2.1) 115 | actionpack (>= 4.0) 116 | activesupport (>= 4.0) 117 | sprockets (>= 3.0.0) 118 | thor (0.20.0) 119 | thread_safe (0.3.4) 120 | tzinfo (1.2.2) 121 | thread_safe (~> 0.1) 122 | 123 | PLATFORMS 124 | ruby 125 | 126 | DEPENDENCIES 127 | actionpack (= 4.2.0) 128 | pry 129 | rails_4_session_flash_backport! 130 | rake 131 | rspec 132 | 133 | BUNDLED WITH 134 | 1.16.1 135 | -------------------------------------------------------------------------------- /lib/rails_4_session_flash_backport.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require "rails_4_session_flash_backport/version" 3 | 4 | case Rails.version 5 | when /\A2\./ 6 | require 'rails_4_session_flash_backport/rails2/flash_hash' 7 | require 'rails_4_session_flash_backport/rails2/session_with_indifferent_access' 8 | when /\A3\.0\./ 9 | require 'rails_4_session_flash_backport/rails3-0/flash_hash' 10 | when /\A3\./ 11 | require 'rails_4_session_flash_backport/rails3-1/flash_hash' 12 | when /\A4\./ 13 | require 'rails_4_session_flash_backport/rails4/flash_hash' 14 | else 15 | Rails.logger.warn "rails_4_session_flash_backport doesnt yet do anything on Rails #{Rails.version}" 16 | end 17 | -------------------------------------------------------------------------------- /lib/rails_4_session_flash_backport/rails2/flash_hash.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'active_support' 3 | require 'action_controller/flash' 4 | require 'action_controller/test_process' 5 | # Backport Rails 4 style storing the flash as basic ruby types to Rails 2 6 | module ActionController #:nodoc: 7 | module Flash 8 | class FlashHash 9 | def self.from_session_value(value) 10 | case value 11 | when FlashHash # Rails 2.3 12 | value.tap(&:sweep) 13 | when ::ActionDispatch::Flash::FlashHash # Rails 3.2 14 | flashes = value.instance_variable_get(:@flashes) 15 | if discard = value.instance_variable_get(:@used).presence 16 | flashes.except!(*discard) 17 | end 18 | 19 | new_from_session(flashes) 20 | when Hash # Rails 4.0 21 | flashes = value['flashes'] || {} 22 | if discard = value['discard'].presence 23 | flashes.except!(*discard) 24 | end 25 | 26 | new_from_session(flashes) 27 | else 28 | new 29 | end 30 | end 31 | 32 | def to_session_value 33 | return nil if empty? 34 | discard = hashify(@used.select { |_, used| used }).keys 35 | {'flashes' => Hash[to_a].except(*discard)} 36 | end 37 | 38 | def hashify(selected) 39 | if selected.respond_to?(:to_h) 40 | selected.to_h 41 | else 42 | selected 43 | end 44 | end 45 | 46 | def store(session, key = "flash") 47 | session[key] = to_session_value 48 | end 49 | 50 | private 51 | 52 | def self.new_from_session(flashes) 53 | new.tap do |flash| 54 | flashes.each do |key, value| 55 | flash[key] = value 56 | flash.discard key 57 | end 58 | end 59 | end 60 | end 61 | 62 | module InstanceMethods #:nodoc: 63 | protected 64 | def flash #:doc: 65 | if !defined?(@_flash) 66 | @_flash = Flash::FlashHash.from_session_value(session["flash"]) 67 | end 68 | 69 | @_flash 70 | end 71 | end 72 | end 73 | module TestResponseBehavior #:nodoc: 74 | # A shortcut to the flash. 75 | def flash 76 | ActionController::Flash::FlashHash.from_session_value(session["flash"]) 77 | end 78 | end 79 | end 80 | 81 | # This magic here allows us to unmarshal a Rails 3.2 ActionDispatch::Flash::FlashHash 82 | module ActionDispatch 83 | class Flash 84 | class FlashHash 85 | def self._load(args) 86 | {} 87 | end 88 | end 89 | end 90 | end 91 | -------------------------------------------------------------------------------- /lib/rails_4_session_flash_backport/rails2/session_with_indifferent_access.rb: -------------------------------------------------------------------------------- 1 | # The SessionHash acts like a HashWithIndifferentAccess on Rails 3, which causes 2 | # problems with the session_id among other things. On Rails 2 the session_id is 3 | # stored as session[:session_id], if we take that session to Rails 3 it becomes 4 | # session["session_id"], and if we bring it back to Rails 2 it's still 5 | # session["session_id"], but Rails checks session[:session_id], finds nothing 6 | # and generates a new one. This is unacceptable. 7 | # 8 | # We've patched the SessionHash to #to_s keys before it stores them, and to 9 | # fall back from the string key to the symbol if needed. 10 | module ActionController::Session 11 | class AbstractStore 12 | class SessionHash < Hash 13 | def [](key) 14 | load! unless @loaded 15 | super(key.to_s) || super(key) 16 | end 17 | 18 | def has_key?(key) 19 | load! unless @loaded 20 | super(key.to_s) || super(key) 21 | end 22 | 23 | def []=(key, value) 24 | load! unless @loaded 25 | super(key.to_s, value) 26 | end 27 | 28 | def delete(key) 29 | value = super(key) 30 | string_value = super(key.to_s) 31 | value || string_value 32 | end 33 | end 34 | end 35 | end 36 | 37 | # We've also had to patch the cookie store, to make it use for the string 38 | # version of "session_id", again falling back to the symbol if needed. 39 | module ActionController 40 | module Session 41 | class CookieStore 42 | def load_session(env) 43 | data = unpacked_cookie_data(env) 44 | data = persistent_session_id!(data) 45 | [data["session_id"] || data[:session_id], data] 46 | end 47 | 48 | def extract_session_id(env) 49 | if data = unpacked_cookie_data(env) 50 | persistent_session_id!(data) unless data.empty? 51 | data["session_id"] || data[:session_id] 52 | else 53 | nil 54 | end 55 | end 56 | 57 | def inject_persistent_session_id(data) 58 | requires_session_id?(data) ? { "session_id" => generate_sid } : {} 59 | end 60 | 61 | def requires_session_id?(data) 62 | if data 63 | data.respond_to?(:key?) && !(data.key?("session_id") || data.key?(:session_id)) 64 | else 65 | true 66 | end 67 | end 68 | end 69 | end 70 | end 71 | 72 | -------------------------------------------------------------------------------- /lib/rails_4_session_flash_backport/rails3-0/flash_hash.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'active_support/core_ext/hash/except' 3 | require 'action_dispatch' 4 | require 'action_dispatch/middleware/flash' 5 | 6 | # Backport Rails 4 style storing the flash as basic ruby types to Rails 3.0 7 | module ActionDispatch 8 | class Request < Rack::Request 9 | def flash 10 | @env[Flash::KEY] ||= Flash::FlashHash.from_session_value(session["flash"]) 11 | end 12 | end 13 | 14 | class Flash 15 | KEY = 'action_dispatch.request.flash_hash'.freeze 16 | 17 | class FlashHash < Hash 18 | def self.from_session_value(value) 19 | flashes = discard = nil 20 | 21 | case value 22 | when ::ActionController::Flash::FlashHash # Rails 2.x 23 | flashes = Hash.new.update(value) 24 | discard = value.instance_variable_get(:@used).select{|a,b| b}.keys 25 | when ::ActionDispatch::Flash::FlashHash # Rails 3.1, 3.2 26 | flashes = value.tap(&:sweep).to_hash 27 | when Hash # Rails 4.0, we backported to 2.3 too 28 | flashes = value['flashes'] 29 | discard = value['discard'] 30 | end 31 | 32 | flashes ||= {} 33 | if discard 34 | flashes.except!(*discard) 35 | end 36 | 37 | new_from_session(flashes) 38 | end 39 | 40 | def to_session_value 41 | flashes_to_keep = except(*@used) 42 | return nil if flashes_to_keep.empty? 43 | {'flashes' => flashes_to_keep} 44 | end 45 | 46 | private 47 | 48 | def self.new_from_session(flashes) 49 | new.tap do |flash| 50 | flashes.each do |key, value| 51 | flash[key] = value 52 | flash.discard key 53 | end 54 | end 55 | end 56 | end 57 | 58 | def call(env) 59 | @app.call(env) 60 | ensure 61 | session = env['rack.session'] || {} 62 | flash_hash = env[KEY] 63 | 64 | if flash_hash 65 | if !flash_hash.empty? || session.key?('flash') 66 | session["flash"] = flash_hash.to_session_value 67 | new_hash = flash_hash.dup 68 | else 69 | new_hash = flash_hash 70 | end 71 | 72 | env[KEY] = new_hash 73 | end 74 | 75 | if session.key?('flash') && session['flash'].nil? 76 | session.delete('flash') 77 | end 78 | end 79 | end 80 | end 81 | 82 | # This magic here allows us to unmarshal the old Rails 2.x ActionController::Flash::FlashHash 83 | module ActionController 84 | module Flash 85 | class FlashHash < Hash 86 | def self._load(args) 87 | {} 88 | end 89 | end 90 | end 91 | end 92 | -------------------------------------------------------------------------------- /lib/rails_4_session_flash_backport/rails3-1/flash_hash.rb: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | require 'active_support/core_ext/hash/except' 3 | require 'action_dispatch' 4 | require 'action_dispatch/middleware/flash' 5 | 6 | # Backport Rails 4 style storing the flash as basic ruby types to Rails 3 7 | module ActionDispatch 8 | class Request < Rack::Request 9 | def flash 10 | @env[Flash::KEY] ||= Flash::FlashHash.from_session_value(session["flash"]) 11 | end 12 | end 13 | 14 | class Flash 15 | class FlashHash 16 | def self.from_session_value(value) 17 | flashes = discard = nil 18 | 19 | case value 20 | when ::ActionController::Flash::FlashHash # Rails 2.x 21 | flashes = Hash.new.update(value) 22 | discard = value.instance_variable_get(:@used).select{|a,b| b}.keys 23 | when ::ActionDispatch::Flash::FlashHash # Rails 3.1, 3.2 24 | flashes = value.instance_variable_get(:@flashes) 25 | discard = value.instance_variable_get(:@used) 26 | when Hash # Rails 4.0, we backported to 2.3 too 27 | flashes = value['flashes'] 28 | discard = value['discard'] 29 | end 30 | 31 | flashes ||= {} 32 | if discard 33 | flashes.except!(*discard) 34 | end 35 | 36 | new(flashes, flashes.keys) 37 | end 38 | 39 | def to_session_value 40 | flashes_to_keep = @flashes.except(*@used) 41 | return nil if flashes_to_keep.empty? 42 | {'flashes' => flashes_to_keep} 43 | end 44 | 45 | def initialize(flashes = {}, discard = []) #:nodoc: 46 | @used = Set.new(discard) 47 | @closed = false 48 | @flashes = flashes 49 | @now = nil 50 | end 51 | 52 | end 53 | 54 | def call(env) 55 | @app.call(env) 56 | ensure 57 | session = env['rack.session'] || {} 58 | flash_hash = env[KEY] 59 | 60 | if flash_hash 61 | if !flash_hash.empty? || session.key?('flash') 62 | session["flash"] = flash_hash.to_session_value 63 | new_hash = flash_hash.dup 64 | else 65 | new_hash = flash_hash 66 | end 67 | 68 | env[KEY] = new_hash 69 | end 70 | 71 | if session.key?('flash') && session['flash'].nil? 72 | session.delete('flash') 73 | end 74 | end 75 | end 76 | end 77 | 78 | # This magic here allows us to unmarshal the old Rails 2.x ActionController::Flash::FlashHash 79 | module ActionController 80 | module Flash 81 | class FlashHash < Hash 82 | def self._load(args) 83 | {} 84 | end 85 | end 86 | end 87 | end 88 | -------------------------------------------------------------------------------- /lib/rails_4_session_flash_backport/rails4/flash_hash.rb: -------------------------------------------------------------------------------- 1 | require 'active_support/core_ext/hash/except' 2 | require 'action_dispatch' 3 | require 'action_dispatch/middleware/flash' 4 | 5 | # Backport discarding before session persist to rails 4 6 | module ActionDispatch 7 | class Flash 8 | class FlashHash 9 | def self.from_session_value(value) 10 | flashes = discard = nil 11 | 12 | case value 13 | when ::ActionController::Flash::FlashHash # Rails 2.x 14 | flashes = Hash.new.update(value) 15 | discard = value.instance_variable_get(:@used).select{|a,b| b}.keys 16 | when ::ActionDispatch::Flash::FlashHash # Rails 3.1, 3.2 17 | flashes = value.instance_variable_get(:@flashes) 18 | discard = value.instance_variable_get(:@used) 19 | when Hash # Rails 4.0, we backported to 2.3 too 20 | flashes = value['flashes'] 21 | discard = value['discard'] 22 | end 23 | 24 | flashes ||= {} 25 | if discard 26 | flashes.except!(*discard) 27 | end 28 | 29 | new(flashes, flashes.keys) 30 | end 31 | 32 | def to_session_value 33 | flashes_to_keep = @flashes.except(*@discard) 34 | return nil if flashes_to_keep.empty? 35 | {'discard' => @discard.to_a, 'flashes' => flashes_to_keep} 36 | end 37 | end 38 | end 39 | end 40 | 41 | # This magic here allows us to unmarshal the old Rails 2.x ActionController::Flash::FlashHash 42 | module ActionController 43 | module Flash 44 | class FlashHash < Hash 45 | def self._load(args) 46 | {} 47 | end 48 | end 49 | end 50 | end 51 | 52 | -------------------------------------------------------------------------------- /lib/rails_4_session_flash_backport/version.rb: -------------------------------------------------------------------------------- 1 | module Rails4SessionFlashBackport 2 | VERSION = "0.2.2" 3 | end 4 | -------------------------------------------------------------------------------- /rails_4_session_flash_backport.gemspec: -------------------------------------------------------------------------------- 1 | # -*- encoding: utf-8 -*- 2 | lib = File.expand_path('../lib', __FILE__) 3 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 4 | require 'rails_4_session_flash_backport/version' 5 | 6 | Gem::Specification.new do |gem| 7 | gem.name = "rails_4_session_flash_backport" 8 | gem.version = Rails4SessionFlashBackport::VERSION 9 | gem.authors = ["Lucas Parry", "Samuel Cochran", "Pete Johns"] 10 | gem.email = ["lparry@gmail.com", "sj26@sj26.com", "paj+rubygems@johnsy.com"] 11 | gem.description = %q{Store flash in the session in Rails 4 style on Rails 2/3/4} 12 | gem.summary = %q{Backport of the way Rails 4 stores flash messages in the session to Rails 2/3/4, so you can safely take a session betweens Rails versions without things exploding.} 13 | gem.homepage = "https://github.com/envato/rails_4_session_flash_backport" 14 | 15 | gem.files = `git ls-files`.split($/) 16 | gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } 17 | gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) 18 | gem.require_paths = ["lib"] 19 | 20 | gem.add_runtime_dependency 'rails', '>= 2.0', '< 4.3' 21 | 22 | gem.add_development_dependency 'rake' 23 | gem.add_development_dependency 'rspec' 24 | gem.add_development_dependency 'pry' 25 | end 26 | -------------------------------------------------------------------------------- /script/update-lockfiles: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | for gemfile in ${PWD}/gemfiles/Gemfile.rails-?.?.x; do 4 | echo "Updating ${gemfile}.lock ..." 5 | export BUNDLE_GEMFILE="${gemfile}" 6 | bundle install --no-deployment 7 | done 8 | 9 | -------------------------------------------------------------------------------- /spec/rails2/flash_hash_spec.rb: -------------------------------------------------------------------------------- 1 | require 'base64' 2 | require 'action_controller' 3 | require 'rails_4_session_flash_backport/rails2/flash_hash' 4 | 5 | describe ActionController::Flash::FlashHash, "backport" do 6 | context "#from_session_value" do 7 | subject(:flash) { described_class.from_session_value(value) } 8 | 9 | context "with rails 4 style session value" do 10 | context "without discards" do 11 | let(:value) { {"flashes" => {"greeting" => "Hello"}} } 12 | 13 | it "is the expected flash" do 14 | expect(flash).to eq("greeting" => "Hello") 15 | end 16 | end 17 | 18 | context "with discards" do 19 | let(:value) { {"flashes" => {"greeting" => "Hello", "farewell" => "Goodbye"}, "discard" => ["farewell"]} } 20 | 21 | it "is the expected flash" do 22 | expect(flash).to eq("greeting" => "Hello") 23 | end 24 | end 25 | end 26 | 27 | context "with rails 3 style session value" do 28 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#, @closed=false, @flashes={"greeting"=>"Hello", "farewell"=>"Goodbye"}, @now=nil>} 29 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsARm86JUFjdGlvbkRpc3BhdGNoOjpGbGFzaDo6Rmxhc2hIYXNoCToKQHVzZWRvOghTZXQGOgpAaGFzaHsGSSINZmFyZXdlbGwGOwBUVDoMQGNsb3NlZEY6DUBmbGFzaGVzewdJIg1ncmVldGluZwY7AFRJIgpIZWxsbwY7AFRJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVDoJQG5vdzA=' } 30 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 31 | let(:value) { session["flash"] } 32 | 33 | it "is the expected flash" do 34 | expect(flash).to eq("greeting" => "Hello") 35 | end 36 | end 37 | 38 | context "with rails 2 style session value" do 39 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#true}, {"greeting"=>"Hello", "farewell"=>"Goodbye"}>} 40 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsAVElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewdJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVEkiDWdyZWV0aW5nBjsAVEkiCkhlbGxvBjsAVAY6CkB1c2VkewZJIg1mYXJld2VsbAY7AFRU' } 41 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 42 | let(:value) { session["flash"] } 43 | 44 | it "is the expected flash" do 45 | expect(flash).to eq("greeting" => "Hello") 46 | end 47 | end 48 | end 49 | 50 | context "#to_session_value" do 51 | subject(:flash) { described_class.new } 52 | 53 | before do 54 | flash["greeting"] = "Hello" 55 | flash.now["farewell"] = "Goodbye" 56 | end 57 | 58 | it "dumps to basic objects like rails 4" do 59 | expect(flash.to_session_value).to eq("flashes" => {"greeting" => "Hello"}) 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /spec/rails3-0/flash_hash_spec.rb: -------------------------------------------------------------------------------- 1 | require 'base64' 2 | 3 | require 'rails_4_session_flash_backport/rails3-0/flash_hash' 4 | 5 | describe ActionDispatch::Flash::FlashHash, "backport" do 6 | context "#from_session_value" do 7 | subject(:flash) { described_class.from_session_value(value) } 8 | 9 | context "with rails 4 style session value" do 10 | context "without discards" do 11 | let(:value) { {"flashes" => {"greeting" => "Hello"}} } 12 | 13 | it "is the expected flash" do 14 | expect(flash.to_hash).to eq("greeting" => "Hello") 15 | end 16 | end 17 | 18 | context "with discards" do 19 | let(:value) { {"flashes" => {"greeting" => "Hello", "farewell" => "Goodbye"}, "discard" => ["farewell"]} } 20 | 21 | it "is the expected flash" do 22 | expect(flash.to_hash).to eq("greeting" => "Hello") 23 | end 24 | end 25 | end 26 | 27 | context "with rails 3.1 style session value" do 28 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#, @closed=false, @flashes={"greeting"=>"Hello", "farewell"=>"Goodbye"}, @now=nil>} 29 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsARm86JUFjdGlvbkRpc3BhdGNoOjpGbGFzaDo6Rmxhc2hIYXNoCToKQHVzZWRvOghTZXQGOgpAaGFzaHsGSSINZmFyZXdlbGwGOwBUVDoMQGNsb3NlZEY6DUBmbGFzaGVzewdJIg1ncmVldGluZwY7AFRJIgpIZWxsbwY7AFRJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVDoJQG5vdzA=' } 30 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 31 | 32 | it "is breaks spectacularly" do 33 | expect { session }.to raise_error(/dump format error/) 34 | end 35 | end 36 | 37 | context "with rails 3.0 style session value" do 38 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>{"greeting"=>"Hello", "farewell"=>"Goodbye"}} # <= (actually a FlashHash < Hash) 39 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsAVElDOiVBY3Rpb25EaXNwYXRjaDo6Rmxhc2g6OkZsYXNoSGFzaHsHSSINZ3JlZXRpbmcGOwBUSSIKSGVsbG8GOwBUSSINZmFyZXdlbGwGOwBUSSIMR29vZGJ5ZQY7AFQGOgpAdXNlZG86CFNldAY6CkBoYXNoewZJIg1mYXJld2VsbAY7AFRU' } 40 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 41 | let(:value) { session["flash"] } 42 | 43 | it "is the expected flash" do 44 | expect(flash.to_hash).to eq("greeting" => "Hello") 45 | end 46 | end 47 | 48 | context "with rails 2 style session value" do 49 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#true}, {"greeting"=>"Hello", "farewell"=>"Goodbye"}>} 50 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsAVElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewdJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVEkiDWdyZWV0aW5nBjsAVEkiCkhlbGxvBjsAVAY6CkB1c2VkewZJIg1mYXJld2VsbAY7AFRU' } 51 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 52 | let(:value) { session["flash"] } 53 | 54 | it "is the expected flash" do 55 | expect(flash.to_hash).to eq("greeting" => "Hello") 56 | end 57 | end 58 | end 59 | 60 | context "#to_session_value" do 61 | subject(:flash) { described_class.new } 62 | 63 | before do 64 | flash["greeting"] = "Hello" 65 | flash.now["farewell"] = "Goodbye" 66 | end 67 | 68 | it "dumps to basic objects like rails 4" do 69 | expect(flash.to_session_value).to eq("flashes" => {"greeting" => "Hello"}) 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /spec/rails3-1/flash_hash_spec.rb: -------------------------------------------------------------------------------- 1 | require 'base64' 2 | 3 | require 'rails_4_session_flash_backport/rails3-1/flash_hash' 4 | 5 | describe ActionDispatch::Flash::FlashHash, "backport" do 6 | context "#from_session_value" do 7 | subject(:flash) { described_class.from_session_value(value) } 8 | 9 | context "with rails 4 style session value" do 10 | context "without discards" do 11 | let(:value) { {"flashes" => {"greeting" => "Hello"}} } 12 | 13 | it "is the expected flash" do 14 | expect(flash.to_hash).to eq("greeting" => "Hello") 15 | end 16 | end 17 | 18 | context "with discards" do 19 | let(:value) { {"flashes" => {"greeting" => "Hello", "farewell" => "Goodbye"}, "discard" => ["farewell"]} } 20 | 21 | it "is the expected flash" do 22 | expect(flash.to_hash).to eq("greeting" => "Hello") 23 | end 24 | end 25 | end 26 | 27 | context "with rails 3.1 style session value" do 28 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#, @closed=false, @flashes={"greeting"=>"Hello", "farewell"=>"Goodbye"}, @now=nil>} 29 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsARm86JUFjdGlvbkRpc3BhdGNoOjpGbGFzaDo6Rmxhc2hIYXNoCToKQHVzZWRvOghTZXQGOgpAaGFzaHsGSSINZmFyZXdlbGwGOwBUVDoMQGNsb3NlZEY6DUBmbGFzaGVzewdJIg1ncmVldGluZwY7AFRJIgpIZWxsbwY7AFRJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVDoJQG5vdzA=' } 30 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 31 | let(:value) { session["flash"] } 32 | 33 | it "is the expected flash" do 34 | expect(flash.to_hash).to eq("greeting" => "Hello") 35 | end 36 | end 37 | 38 | context "with rails 3.0 style session value" do 39 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>{"greeting"=>"Hello", "farewell"=>"Goodbye"}} # <= (actually a FlashHash < Hash) 40 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsAVElDOiVBY3Rpb25EaXNwYXRjaDo6Rmxhc2g6OkZsYXNoSGFzaHsHSSINZ3JlZXRpbmcGOwBUSSIKSGVsbG8GOwBUSSINZmFyZXdlbGwGOwBUSSIMR29vZGJ5ZQY7AFQGOgpAdXNlZG86CFNldAY6CkBoYXNoewZJIg1mYXJld2VsbAY7AFRU' } 41 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 42 | 43 | it "is breaks spectacularly" do 44 | expect { session }.to raise_error(/dump format error/) 45 | end 46 | end 47 | 48 | context "with rails 2 style session value" do 49 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#true}, {"greeting"=>"Hello", "farewell"=>"Goodbye"}>} 50 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsAVElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewdJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVEkiDWdyZWV0aW5nBjsAVEkiCkhlbGxvBjsAVAY6CkB1c2VkewZJIg1mYXJld2VsbAY7AFRU' } 51 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 52 | let(:value) { session["flash"] } 53 | 54 | it "is the expected flash" do 55 | expect(flash.to_hash).to eq("greeting" => "Hello") 56 | end 57 | end 58 | end 59 | 60 | context "#to_session_value" do 61 | subject(:flash) { described_class.new } 62 | 63 | before do 64 | flash["greeting"] = "Hello" 65 | flash.now["farewell"] = "Goodbye" 66 | end 67 | 68 | it "dumps to basic objects like rails 4" do 69 | expect(flash.to_session_value).to eq("flashes" => {"greeting" => "Hello"}) 70 | end 71 | end 72 | end 73 | -------------------------------------------------------------------------------- /spec/rails4/flash_hash_spec.rb: -------------------------------------------------------------------------------- 1 | require 'base64' 2 | 3 | require 'rails_4_session_flash_backport/rails4/flash_hash' 4 | 5 | describe ActionDispatch::Flash::FlashHash, "backport" do 6 | context "#from_session_value" do 7 | subject(:flash) { described_class.from_session_value(value) } 8 | 9 | context "with rails 4 style session value" do 10 | context "without discards" do 11 | let(:value) { {"flashes" => {"greeting" => "Hello"}} } 12 | 13 | it "is the expected flash" do 14 | expect(flash.to_hash).to eq("greeting" => "Hello") 15 | end 16 | end 17 | 18 | context "with discards" do 19 | let(:value) { {"flashes" => {"greeting" => "Hello", "farewell" => "Goodbye"}, "discard" => ["farewell"]} } 20 | 21 | it "is the expected flash" do 22 | expect(flash.to_hash).to eq("greeting" => "Hello") 23 | end 24 | end 25 | end 26 | 27 | context "with rails 3.1 style session value" do 28 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#, @closed=false, @flashes={"greeting"=>"Hello", "farewell"=>"Goodbye"}, @now=nil>} 29 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFRkkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsARm86JUFjdGlvbkRpc3BhdGNoOjpGbGFzaDo6Rmxhc2hIYXNoCToKQHVzZWRvOghTZXQGOgpAaGFzaHsGSSINZmFyZXdlbGwGOwBUVDoMQGNsb3NlZEY6DUBmbGFzaGVzewdJIg1ncmVldGluZwY7AFRJIgpIZWxsbwY7AFRJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVDoJQG5vdzA=' } 30 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 31 | let(:value) { session["flash"] } 32 | 33 | it "is the expected flash" do 34 | expect(flash.to_hash).to eq("greeting" => "Hello") 35 | end 36 | end 37 | 38 | context "with rails 3.0 style session value" do 39 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>{"greeting"=>"Hello", "farewell"=>"Goodbye"}} # <= (actually a FlashHash < Hash) 40 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsAVElDOiVBY3Rpb25EaXNwYXRjaDo6Rmxhc2g6OkZsYXNoSGFzaHsHSSINZ3JlZXRpbmcGOwBUSSIKSGVsbG8GOwBUSSINZmFyZXdlbGwGOwBUSSIMR29vZGJ5ZQY7AFQGOgpAdXNlZG86CFNldAY6CkBoYXNoewZJIg1mYXJld2VsbAY7AFRU' } 41 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 42 | 43 | it "is breaks spectacularly" do 44 | expect { session }.to raise_error(/dump format error/) 45 | end 46 | end 47 | 48 | context "with rails 2 style session value" do 49 | # {"session_id"=>"f8e1b8152ba7609c28bbb17ec9263ba7", "flash"=>#true}, {"greeting"=>"Hello", "farewell"=>"Goodbye"}>} 50 | let(:cookie) { 'BAh7B0kiD3Nlc3Npb25faWQGOgZFVEkiJWY4ZTFiODE1MmJhNzYwOWMyOGJiYjE3ZWM5MjYzYmE3BjsAVEkiCmZsYXNoBjsAVElDOidBY3Rpb25Db250cm9sbGVyOjpGbGFzaDo6Rmxhc2hIYXNoewdJIg1mYXJld2VsbAY7AFRJIgxHb29kYnllBjsAVEkiDWdyZWV0aW5nBjsAVEkiCkhlbGxvBjsAVAY6CkB1c2VkewZJIg1mYXJld2VsbAY7AFRU' } 51 | let(:session) { Marshal.load(Base64.decode64(cookie)) } 52 | let(:value) { session["flash"] } 53 | 54 | it "is the expected flash" do 55 | expect(flash.to_hash).to eq("greeting" => "Hello") 56 | end 57 | end 58 | end 59 | 60 | context "#to_session_value" do 61 | subject(:flash) { described_class.new } 62 | 63 | before do 64 | flash["greeting"] = "Hello" 65 | flash.now["farewell"] = "Goodbye" 66 | end 67 | 68 | it "dumps to basic objects like rails 4" do 69 | expect(flash.to_session_value).to eq("discard" => ["farewell"], "flashes" => {"greeting" => "Hello"}) 70 | end 71 | end 72 | end 73 | --------------------------------------------------------------------------------