micro_sessions 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Ben Hughes
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,72 @@
1
+ == Micro Sessions
2
+
3
+ In terms of passing data amongst HTTP requests there are really two options:
4
+ * Param or form data passing
5
+ * Storing in cookies
6
+ * Storing in server-side session, keyed off an ID stored as a cookie.
7
+
8
+ For a certain application where you're using number 3, this comes at a cost - the session is "global". In other words, in a single browser window with multiple tabs, the server side cannot distinguish between individual "sessions" *within* that browser session. This gem introduces a third, more granular method:
9
+ * Storing in server-side session, keyed off an ID stored as a cookie *and* keyed off a request parameter.
10
+
11
+ This could be useful in instances such as a very complex wizard where transmitting the entire history of data RESTfully via param passing may not be feasible, yet you'd still like to support multiple tabs within the same browser window separately.
12
+
13
+ == In-Progress
14
+
15
+ This gem is not useable and is being continually worked on. Will be released as 0.1.0 once reasonably working and stable.
16
+
17
+ DO NOT USE!
18
+
19
+ == Installation
20
+
21
+ This gem requires ActionPack and ActiveSupport 3.0 or greater.
22
+
23
+ Include the gem in your Gemfile:
24
+
25
+ gem "micro_sessions"
26
+
27
+ == Usage
28
+
29
+ Simply include the middleware in your controller:
30
+
31
+ class ApplicationController
32
+ micro_sessions
33
+ end
34
+
35
+ By default the name of the request parameter used to differentiate micro-sessions is "_msid", though this can be configured:
36
+
37
+ class ApplicationController
38
+ micro_sessions :key => "_msid"
39
+ end
40
+
41
+ By default the key generated will be a 10-digit random hash, though this can be configured as well:
42
+
43
+ class ApplicationController
44
+ micro_sessions :type => :integer, :length => 10
45
+ end
46
+
47
+ Valid values for +:type+: are:
48
+ * +:random_hash+
49
+ * +:integer+ (simply increments from one)
50
+ * +:random_integer+ (random integer with a maximum of +:length+ digits)
51
+
52
+ Session data is accessible to the controller and view through the +micro_session+ object, which works identically to the +session+ object but it specific to the micro-session:
53
+
54
+ micro_session[:key] = "Value"
55
+ micro_session[:key] # => "Value"
56
+
57
+ When transitioning between pages for which you'd like to keep the micro-session alive, the request parameter must be passed along with any link, form, or redirect. The preferred way is to make use of the new +:micro_session+ option on available on the +url_for+ helper, which will accept either a specific value or just "true" to use the "current" micro-session to this request:
58
+
59
+ link_to user_path(@user, :micro_session => true)
60
+ redirect_to user_project_path([@user, @project], :micro_session => true)
61
+
62
+ If you wish to transmit the identifier via a form, be sure to include the hidden field:
63
+
64
+ <% form_for(@user) do |f| %>
65
+ <%= micro_session_hidden_field %>
66
+ ...
67
+ <% end %>
68
+
69
+ Destroying a micro-session is as easy as:
70
+
71
+ micro_session.destroy
72
+
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ require "micro_sessions"
2
+
3
+ MicroSessions::Railtie.insert
@@ -0,0 +1,30 @@
1
+ module MicroSessions
2
+ module Controller
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def micro_sessions(options = {})
7
+ options.stringify_keys!
8
+ options.assert_valid_keys(:param, :param_type, :key, :length, :counter)
9
+
10
+ options[:param] ||= "_msid"
11
+ options[:key] ||= "_micro_sessions"
12
+ options[:param_type] ||= :hash
13
+ options[:length] ||= 10
14
+ options[:counter] ||= 1
15
+
16
+ class_inheritable_accessor :micro_session_options
17
+ self.micro_session_options = options
18
+
19
+ class_eval do
20
+ def micro_session
21
+ @micro_session ||= MicroSessions::MicroSession.new(self)
22
+ end
23
+
24
+ helper_method :micro_session
25
+ helper_method :micro_session_options
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,27 @@
1
+ module MicroSessions
2
+ module Helpers
3
+ module UrlHelper
4
+ extend ActiveSupport::Concern
5
+
6
+ module InstanceMethods
7
+ def url_for(options = {})
8
+ if options.is_a?(Hash) && ms_value = options.delete(:micro_sessions) && !micro_session.empty?
9
+ options[micro_session.options[:param]] = (ms_value == true ? micro_session.id : ms_value)
10
+ end
11
+
12
+ super
13
+ end
14
+ end
15
+ end
16
+
17
+ module FormTagHelper
18
+ extend ActiveSupport::Concern
19
+
20
+ module InstanceMethods
21
+ def micro_session_hidden_field
22
+ hidden_field_tag controller.class.micro_session_options[:param], micro_session.id
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,40 @@
1
+ module MicroSessions
2
+ class MicroSession
3
+ def initialize(controller)
4
+ @controller = controller
5
+ end
6
+
7
+ def options
8
+ @controller.class.micro_session_options
9
+ end
10
+
11
+ def data
12
+ @controller.session[options[:key]] ||= {}
13
+ @controller.session[options[:key]][id] ||= {}
14
+ end
15
+
16
+ delegate :empty?, :[], :[]=, :to_h, :to_hash, :to => :data
17
+
18
+ def id
19
+ @id ||= id_from_params || generate_id
20
+ end
21
+
22
+
23
+ protected
24
+
25
+ def id_from_params
26
+ @controller.params[options[:param]] if @controller.params
27
+ end
28
+
29
+ def generate_id
30
+ case options[:param_type]
31
+ when :hash
32
+ ActiveSupport::SecureRandom.hex(options[:length] / 2)
33
+ when :integer
34
+ self.counter += 1
35
+ when :random_integer
36
+ ActiveSupport::SecureRandom.integer
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,19 @@
1
+ module MicroSessions
2
+ if defined?(Rails::Railtie)
3
+ class Railtie < Rails::Railtie
4
+ initializer "micro_sessions.insert" do
5
+ ActiveSupport.on_load(:action_controller) do
6
+ MicroSessions::Railtie.insert
7
+ end
8
+ end
9
+ end
10
+ end
11
+
12
+ class Railtie
13
+ def self.insert
14
+ ActionController::Base.send(:include, MicroSessions::Controller)
15
+ ActionView::Helpers::UrlHelper.send(:include, MicroSessions::Helpers::UrlHelper)
16
+ ActionView::Helpers::FormTagHelper.send(:include, MicroSessions::Helpers::FormTagHelper)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,3 @@
1
+ module MicroSessions
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,25 @@
1
+ unless defined?(ActionController)
2
+ begin
3
+ require "action_pack"
4
+ require "action_controller"
5
+ require "action_view"
6
+ rescue LoadError
7
+ require "rubygems"
8
+ require_gem "actionpack"
9
+ end
10
+ end
11
+
12
+ module MicroSessions
13
+ extend ActiveSupport::Concern
14
+ extend ActiveSupport::Autoload
15
+
16
+ autoload :Controller
17
+ autoload :Helpers
18
+ autoload :MicroSession
19
+
20
+ included do
21
+ include MicroSessions::Controller
22
+ end
23
+ end
24
+
25
+ require "micro_sessions/railtie"
@@ -0,0 +1,80 @@
1
+ require "spec_helper"
2
+
3
+ describe MicroSessions::Controller do
4
+ context "with a controller" do
5
+ before do
6
+ @controller_class = class SampleController < ActionController::Base
7
+ micro_sessions
8
+ self
9
+ end
10
+ end
11
+
12
+ it "should default param to _msid" do
13
+ @controller_class.micro_session_options[:param].should == "_msid"
14
+ end
15
+
16
+ it "should default key to _micro_sessions" do
17
+ @controller_class.micro_session_options[:key].should == "_micro_sessions"
18
+ end
19
+
20
+ it "should default length to 10" do
21
+ @controller_class.micro_session_options[:length].should == 10
22
+ end
23
+
24
+ it "should default counter to 1" do
25
+ @controller_class.micro_session_options[:counter].should == 1
26
+ end
27
+
28
+ context "an instance of the controller" do
29
+ before do
30
+ @controller = @controller_class.new
31
+ @controller.stub(:params).and_return({})
32
+ end
33
+
34
+ it "should expose #micro_session as a method" do
35
+ @controller.micro_session.should be_an_instance_of(MicroSessions::MicroSession)
36
+ end
37
+
38
+ it "should generate a 10-character hash id" do
39
+ @controller.micro_session.id.should be_a(String)
40
+ @controller.micro_session.id.size.should == 10
41
+ end
42
+
43
+ context "with micro session data and another controller" do
44
+ before do
45
+ @micro_session_data = {
46
+ :integer => 1,
47
+ :string => "String"
48
+ }
49
+
50
+ @another_controller = @controller_class.new
51
+ @another_controller.stub(:params).and_return({})
52
+ @another_controller.stub(:session).and_return({
53
+ "_micro_sessions" => {@controller.micro_session.id => @micro_session_data}
54
+ })
55
+ end
56
+
57
+ context "without passing id" do
58
+ subject do
59
+ @another_controller.micro_session
60
+ end
61
+
62
+ it "should not have data" do
63
+ subject.data.should == {}
64
+ end
65
+ end
66
+
67
+ context "when passing id" do
68
+ subject do
69
+ @another_controller.stub(:params).and_return({"_msid" => @controller.micro_session.id})
70
+ @another_controller.micro_session
71
+ end
72
+
73
+ it "should have data" do
74
+ subject.data.should == @micro_session_data
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,24 @@
1
+ require "spec_helper"
2
+
3
+ describe MicroSessions::Helpers do
4
+ before do
5
+ @controller_class = Class.new(ActionController::Base)
6
+ @controller_class.stub(:micro_session_options).and_return(:param => "_msid")
7
+ @helpers = ActionView::Base.new
8
+ @helpers.stub(:controller).and_return(@controller_class.new)
9
+ @helpers.stub(:micro_session).and_return(mock(:id => "abc123"))
10
+ end
11
+
12
+ it "should respond to #micro_session_hidden_field" do
13
+ @helpers.should respond_to(:micro_session_hidden_field)
14
+ end
15
+
16
+ it "should render correct micro_session_hidden_field" do
17
+ @helpers.micro_session_hidden_field.should == %{<input id="_msid" name="_msid" type="hidden" value="abc123" />}
18
+ end
19
+
20
+ # TODO: This is way too complex to test, requires an enormous amount of stubbing... Need a real Rails app.
21
+ # it "should render correct link_to with :micro_sessions => true" do
22
+ # @helpers.url_for
23
+ # end
24
+ end
@@ -0,0 +1,10 @@
1
+ require "rubygems"
2
+ require "rspec"
3
+ require "active_support"
4
+ require "action_pack"
5
+
6
+ require File.dirname(__FILE__) + "/../init"
7
+
8
+ RSpec.configure do |c|
9
+
10
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: micro_sessions
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Ben Hughes
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-23 00:00:00 +03:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: actionpack
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 0
34
+ version: 3.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: activesupport
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 3
48
+ - 0
49
+ - 0
50
+ version: 3.0.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Provides 'micro-sessions' within the global sessions object keyed off an identifier.
54
+ email: ben@railsgarden.com
55
+ executables: []
56
+
57
+ extensions: []
58
+
59
+ extra_rdoc_files: []
60
+
61
+ files:
62
+ - lib/micro_sessions/controller.rb
63
+ - lib/micro_sessions/helpers.rb
64
+ - lib/micro_sessions/micro_session.rb
65
+ - lib/micro_sessions/railtie.rb
66
+ - lib/micro_sessions/version.rb
67
+ - lib/micro_sessions.rb
68
+ - spec/controller_spec.rb
69
+ - spec/helpers_spec.rb
70
+ - spec/spec_helper.rb
71
+ - LICENSE
72
+ - README.rdoc
73
+ - init.rb
74
+ has_rdoc: true
75
+ homepage: http://github.com/rubiety/micro_sessions
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 19
98
+ segments:
99
+ - 1
100
+ - 3
101
+ - 4
102
+ version: 1.3.4
103
+ requirements: []
104
+
105
+ rubyforge_project: micro_sessions
106
+ rubygems_version: 1.3.7
107
+ signing_key:
108
+ specification_version: 3
109
+ summary: Keyed sessions within the global sessions object.
110
+ test_files: []
111
+