Commit a341e67e6277ca5881be400a99bbbe90b8d3fda5

Authored by Antonio Terceiro
1 parent 912190c8

Checkpoint: validated the idea of keeping the cart in an indepent cookie

There are a couple of FIXME's there, plus the whole thing has to be
refactored:

  * the shopping cart controller must be moved out of the profile
    namespace, because we can't know to which profile we should make the
    AJAX request to load the cart

  * there are too many unecessary AJAX requests.

  * most of the cart functionality must probably be encapsulate into
  * proper objects.
plugins/shopping_cart/controllers/shopping_cart_plugin_profile_controller.rb
  1 +require 'base64'
  2 +
1 include ShoppingCartPlugin::CartHelper 3 include ShoppingCartPlugin::CartHelper
2 4
3 class ShoppingCartPluginProfileController < ProfileController 5 class ShoppingCartPluginProfileController < ProfileController
@@ -6,6 +8,12 @@ class ShoppingCartPluginProfileController &lt; ProfileController @@ -6,6 +8,12 @@ class ShoppingCartPluginProfileController &lt; ProfileController
6 8
7 before_filter :login_required, :only => [] 9 before_filter :login_required, :only => []
8 10
  11 + def get
  12 + has_products = !cart.nil? && (cart[:items].keys.size > 0) || false
  13 + config = { 'enterprise' => profile.identifier, 'hasProducts' => has_products }
  14 + render :text => config.to_json
  15 + end
  16 +
9 def add 17 def add
10 self.cart = { :enterprise_id => profile.id, :items => {} } if self.cart.nil? 18 self.cart = { :enterprise_id => profile.id, :items => {} } if self.cart.nil?
11 if validate_same_enterprise && product = validate_enterprise_has_product(params[:id]) 19 if validate_same_enterprise && product = validate_enterprise_has_product(params[:id])
@@ -85,6 +93,7 @@ class ShoppingCartPluginProfileController &lt; ProfileController @@ -85,6 +93,7 @@ class ShoppingCartPluginProfileController &lt; ProfileController
85 93
86 def buy 94 def buy
87 @environment = profile.environment 95 @environment = profile.environment
  96 + @cart = cart
88 render :layout => false 97 render :layout => false
89 end 98 end
90 99
@@ -249,10 +258,31 @@ class ShoppingCartPluginProfileController &lt; ProfileController @@ -249,10 +258,31 @@ class ShoppingCartPluginProfileController &lt; ProfileController
249 protected 258 protected
250 259
251 def cart 260 def cart
252 - session[:cart] 261 + @cart ||=
  262 + begin
  263 + cookies[cookie_key] && YAML.load(Base64.decode64(cookies[cookie_key])) || nil
  264 + end
  265 + @cart
253 end 266 end
254 267
255 def cart=(data) 268 def cart=(data)
256 - session[:cart] = data 269 + @cart = data
257 end 270 end
  271 +
  272 + after_filter :save_cookie
  273 + def save_cookie
  274 + if @cart.nil? && cookies[cookie_key]
  275 + cookies.delete(cookie_key)
  276 + else
  277 + cookies[cookie_key] = {
  278 + :value => Base64.encode64(@cart.to_yaml),
  279 + :path => "/profile/#{profile.identifier}/plugin/shopping_cart"
  280 + }
  281 + end
  282 + end
  283 +
  284 + def cookie_key
  285 + :_noosfero_session_shopping_cart
  286 + end
  287 +
258 end 288 end
plugins/shopping_cart/lib/shopping_cart_plugin.rb
@@ -35,7 +35,7 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin @@ -35,7 +35,7 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin
35 end 35 end
36 36
37 def body_beginning 37 def body_beginning
38 - expanded_template('cart.html.erb',{:cart => context.session[:cart]}) 38 + expanded_template('cart.html.erb')
39 end 39 end
40 40
41 def control_panel_buttons 41 def control_panel_buttons
plugins/shopping_cart/test/functional/shopping_cart_plugin_profile_controller_test.rb
@@ -48,7 +48,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase @@ -48,7 +48,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
48 end 48 end
49 49
50 should 'not try to remove a product if there is no cart' do 50 should 'not try to remove a product if there is no cart' do
51 - instantiate_session 51 + instantiate_cart
52 assert !cart? 52 assert !cart?
53 53
54 assert_nothing_raised { get :remove, :profile => enterprise.identifier, :id => 9999 } 54 assert_nothing_raised { get :remove, :profile => enterprise.identifier, :id => 9999 }
@@ -76,7 +76,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase @@ -76,7 +76,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
76 end 76 end
77 77
78 should 'not try to list the cart if there is no cart' do 78 should 'not try to list the cart if there is no cart' do
79 - instantiate_session 79 + instantiate_cart
80 assert !cart? 80 assert !cart?
81 81
82 assert_nothing_raised { get :list, :profile => enterprise.identifier } 82 assert_nothing_raised { get :list, :profile => enterprise.identifier }
@@ -100,7 +100,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase @@ -100,7 +100,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
100 end 100 end
101 101
102 should 'not try to update quantity the quantity of a product if there is no cart' do 102 should 'not try to update quantity the quantity of a product if there is no cart' do
103 - instantiate_session 103 + instantiate_cart
104 assert !cart? 104 assert !cart?
105 105
106 assert_nothing_raised { get :update_quantity, :profile => enterprise.identifier, :id => 9999, :quantity => 3 } 106 assert_nothing_raised { get :update_quantity, :profile => enterprise.identifier, :id => 9999, :quantity => 3 }
@@ -139,7 +139,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase @@ -139,7 +139,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
139 end 139 end
140 140
141 should 'not crash if there is no cart' do 141 should 'not crash if there is no cart' do
142 - instantiate_session 142 + instantiate_cart
143 assert !cart? 143 assert !cart?
144 assert_nothing_raised { get :clean, :profile => enterprise.identifier } 144 assert_nothing_raised { get :clean, :profile => enterprise.identifier }
145 end 145 end
@@ -147,7 +147,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase @@ -147,7 +147,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
147 should 'register order on send request' do 147 should 'register order on send request' do
148 product1 = fast_create(Product, :enterprise_id => enterprise.id, :price => 1.99) 148 product1 = fast_create(Product, :enterprise_id => enterprise.id, :price => 1.99)
149 product2 = fast_create(Product, :enterprise_id => enterprise.id, :price => 2.23) 149 product2 = fast_create(Product, :enterprise_id => enterprise.id, :price => 2.23)
150 - @controller.stubs(:session).returns({:cart => {:items => {product1.id => 1, product2.id => 2}}}) 150 + @controller.stubs(:cart).returns({:items => {product1.id => 1, product2.id => 2}})
151 assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do 151 assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do
152 post :send_request, 152 post :send_request,
153 :customer => {:name => "Manuel", :email => "manuel@ceu.com"}, 153 :customer => {:name => "Manuel", :email => "manuel@ceu.com"},
@@ -165,7 +165,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase @@ -165,7 +165,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
165 165
166 should 'register order on send request and not crash if product is not defined' do 166 should 'register order on send request and not crash if product is not defined' do
167 product1 = fast_create(Product, :enterprise_id => enterprise.id) 167 product1 = fast_create(Product, :enterprise_id => enterprise.id)
168 - @controller.stubs(:session).returns({:cart => {:items => {product1.id => 1}}}) 168 + @controller.stubs(:cart).returns({:items => {product1.id => 1}})
169 assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do 169 assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do
170 post :send_request, 170 post :send_request,
171 :customer => {:name => "Manuel", :email => "manuel@ceu.com"}, 171 :customer => {:name => "Manuel", :email => "manuel@ceu.com"},
@@ -184,15 +184,15 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase @@ -184,15 +184,15 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
184 end 184 end
185 185
186 def cart? 186 def cart?
187 - !session[:cart].nil? 187 + @controller.send(:cart).nil?
188 end 188 end
189 189
190 def product_in_cart?(product) 190 def product_in_cart?(product)
191 - session[:cart][:items].has_key?(product.id) 191 + @controller.send(:cart)[:items].has_key?(product.id)
192 end 192 end
193 193
194 def product_quantity(product) 194 def product_quantity(product)
195 - session[:cart][:items][product.id] 195 + @controller.send(:cart)[:items][product.id]
196 end 196 end
197 197
198 def response_ok? 198 def response_ok?
@@ -205,7 +205,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase @@ -205,7 +205,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
205 205
206 # temporary hack...if I don't do this the session stays as an Array instead 206 # temporary hack...if I don't do this the session stays as an Array instead
207 # of a TestSession 207 # of a TestSession
208 - def instantiate_session 208 + def instantiate_cart
209 get :add, :profile => enterprise.identifier, :id => product.id 209 get :add, :profile => enterprise.identifier, :id => product.id
210 get :remove, :profile => enterprise.identifier, :id => product.id 210 get :remove, :profile => enterprise.identifier, :id => product.id
211 end 211 end
plugins/shopping_cart/views/cart.html.erb
@@ -18,6 +18,19 @@ @@ -18,6 +18,19 @@
18 18
19 <script type="text/javascript"> 19 <script type="text/javascript">
20 //<![CDATA[ 20 //<![CDATA[
21 - new Cart({hasProducts:<%= !locals[:cart].nil? ? "true, enterprise:'#{Enterprise.find(locals[:cart][:enterprise_id]).identifier}'" : "false" %>}); 21 + jQuery(function($) {
  22 + var profile = 'foo'; // FIXME
  23 + $.ajax({
  24 + url: "/profile/" + profile + "/plugin/shopping_cart/get",
  25 + dataType: 'json',
  26 + success: function(data) {
  27 + new Cart(data);
  28 + },
  29 + cache: false,
  30 + error: function(ajax, status, errorThrown) {
  31 + alert('Error getting shopping cart - HTTP '+status+': '+errorThrown);
  32 + }
  33 + });
  34 + });
22 //]]> 35 //]]>
23 </script> 36 </script>
plugins/shopping_cart/views/shopping_cart_plugin_profile/buy.html.erb
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 <%= submit_button(:send, _('Send buy request')) %> 16 <%= submit_button(:send, _('Send buy request')) %>
17 </div> 17 </div>
18 <% end %> 18 <% end %>
19 - <%= items_table(session[:cart][:items], profile) %> 19 + <%= items_table(@cart[:items], profile) %>
20 <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %> 20 <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %>
21 </div> 21 </div>
22 22
vendor/plugins/noosfero_caching/init.rb
@@ -38,6 +38,8 @@ module NoosferoHttpCaching @@ -38,6 +38,8 @@ module NoosferoHttpCaching
38 def call(env) 38 def call(env)
39 status, headers, body = @app.call(env) 39 status, headers, body = @app.call(env)
40 if headers['X-Noosfero-Auth'] == 'false' 40 if headers['X-Noosfero-Auth'] == 'false'
  41 + # FIXME do not do this if there is any plugin cookie set (e.g.
  42 + # _noosfero_session_shopping_cart)
41 headers.delete('Set-Cookie') 43 headers.delete('Set-Cookie')
42 end 44 end
43 headers.delete('X-Noosfero-Auth') 45 headers.delete('X-Noosfero-Auth')