Giter Site home page Giter Site logo

Comments (6)

MatmaRex avatar MatmaRex commented on June 11, 2024

This is a two-part issue:

First, Camping overrides the session entirely on each request (killing, for example, rack-flash's data). There's a simple fix for that: change line 408 of camping-unabridged.rb (and similarly in camping.rb) to

@env['rack.session'].merge! Hash[@state]

(essentially, replace assignment with merging). However, I am afraid this might cause trouble with old code - if somebody was using Hash#delete to remove entries from @state, they wouldn't be removed now. Magnus - do we have a green light? ;)

Second, and worse, part, is that rack-flash uses some heavy metaprogramming just in order to define a flash method in the app which uses it. While its magic might work for some frameworks (Sinatra is, interestingly, apparently special-cased), it doesn't for camping and raises an exception. Workaround to this is to use Rack::Flash, :helper => false (and @env['x-rack.flash'] to access the notices) in Camping code, solution would be to get rack-flash guys to special-case Camping, too.

There's also third thing - Rack::Flash has to be used before you include Camping::Session (due to internal order of calling middlewares being in reverse). This could possibly be changed to be more intuitive, but would require some rewiring in Camping.

from camping.

MatmaRex avatar MatmaRex commented on June 11, 2024

(Here's a tiny app using rack-flash, for testing: https://gist.github.com/1304573)

from camping.

igravious avatar igravious commented on June 11, 2024

Wow :=)

First
The problem is that, if you delete keys in the state then rack.session still has them and merge won't get rid of them! I stumbled across your idea and I think it is half the battle. I'll post my attempt in my next post.

Second
I noticed this. I have had to use @env['x-rack.flash'] to access the FlashHash and it's ugly but notice that this is what you have to do for vanilla Rack apps per the Rack-Flash documentation so I guess Camping is considered vanilla :( heh

Third
I think this is why there is some weird metaprogramming on Rack::Builder in Rack-Flash in order to force it's way to the end of the middleware call chain, arguably their should be a Rack API for this (but what if two oh so special middlewares want to be on the tail end? Who wins?) Well spotted though. I have used it first in my app.

from camping.

igravious avatar igravious commented on June 11, 2024

Here is my attempt

  # diff two Hashes, er two Hs
  class Camping::H
    def diff(other)
      self.keys.inject({}) do |memo, key|
        unless self[key] == other[key]
          memo[key] = [self[key], other[key]] 
        end
        memo
      end
    end
  end

  def initialize(env, m) #:nodoc:
    .
    .
    # make a shallow copy
    @_state = @state.clone
    @cookies._p = self/"/"
  end

  def to_a
    # what is the diff between cloned and new?
    diff = @_state.diff(@state)
    # remove vanished keys from session
    diff.each {|k,v| @env['rack.session'].delete(k) }
    # merge what is left
    @env['rack.session'].merge! Hash[@state]
    .
    .
    .
  end

This solution seems to work for me with adding and deleting state entries. And seems to play nice wit Rack-Flash once you use it in the right order use( Rack::Flash, :flash_app_class => self, :accessorize => [:notice, :alert]) the first line in your app. It's verbose and slow but works for me (I think?).

from camping.

igravious avatar igravious commented on June 11, 2024

rewrite:

  module CampingFlash

    def self.included(base)
      Camping::H.class_eval do
        def diff(other)
          self.keys.inject({}) do |memo, key|
            unless self[key] == other[key]
              memo[key] = [self[key], other[key]] 
            end
            memo
          end
        end
      end
    end

    def to_a
      # overwrite the session with how @state is now
      # depeding on whether diff is defined for H or not
      if @state.respond_to? :diff
        diff = @_state.diff(@state)
        diff.each {|k,v| @env['rack.session'].delete(k) }
        @env['rack.session'].merge! Hash[@state]
      else
        @env['rack.session'] = Hash[@state]
      end
      .
      .
      .
    end

    def initialize(env, m) #:nodoc: 
      .
      .
      .
      @_state = @state.clone
      @cookies._p = self/"/"
    end

  end

from camping.

igravious avatar igravious commented on June 11, 2024

This rewrite means that we only need to touch Camping a tiny little bit. The rest remains the same from the previous post in this issue.

  # this goes into a possible module CampingFlash
  def to_a #:nodoc:
    if @state.respond_to? :diff
      diff = @_state.diff(@state)
      diff.each {|k,v| @env['rack.session'].delete(k) }
    end
    super
  end

  # this is the only change to Camping
  def to_a #:nodoc:
    # overwrite the session with how @state is now
    # depeding on whether diff is defined for H or not
    if @state.respond_to? :diff
      @env['rack.session'].merge! Hash[@state]
    else
      @env['rack.session'] = Hash[@state]
    end
    .
    .
    .
  end

  # this goes into a possible module CampingFlash
  def initialize(env, m) #:nodoc:
    super(env,m)
    @_state = @state.clone
  end

from camping.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.