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 3 include ShoppingCartPlugin::CartHelper
2 4  
3 5 class ShoppingCartPluginProfileController < ProfileController
... ... @@ -6,6 +8,12 @@ class ShoppingCartPluginProfileController &lt; ProfileController
6 8  
7 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 17 def add
10 18 self.cart = { :enterprise_id => profile.id, :items => {} } if self.cart.nil?
11 19 if validate_same_enterprise && product = validate_enterprise_has_product(params[:id])
... ... @@ -85,6 +93,7 @@ class ShoppingCartPluginProfileController &lt; ProfileController
85 93  
86 94 def buy
87 95 @environment = profile.environment
  96 + @cart = cart
88 97 render :layout => false
89 98 end
90 99  
... ... @@ -249,10 +258,31 @@ class ShoppingCartPluginProfileController &lt; ProfileController
249 258 protected
250 259  
251 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 266 end
254 267  
255 268 def cart=(data)
256   - session[:cart] = data
  269 + @cart = data
257 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 288 end
... ...
plugins/shopping_cart/lib/shopping_cart_plugin.rb
... ... @@ -35,7 +35,7 @@ class ShoppingCartPlugin &lt; Noosfero::Plugin
35 35 end
36 36  
37 37 def body_beginning
38   - expanded_template('cart.html.erb',{:cart => context.session[:cart]})
  38 + expanded_template('cart.html.erb')
39 39 end
40 40  
41 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 48 end
49 49  
50 50 should 'not try to remove a product if there is no cart' do
51   - instantiate_session
  51 + instantiate_cart
52 52 assert !cart?
53 53  
54 54 assert_nothing_raised { get :remove, :profile => enterprise.identifier, :id => 9999 }
... ... @@ -76,7 +76,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
76 76 end
77 77  
78 78 should 'not try to list the cart if there is no cart' do
79   - instantiate_session
  79 + instantiate_cart
80 80 assert !cart?
81 81  
82 82 assert_nothing_raised { get :list, :profile => enterprise.identifier }
... ... @@ -100,7 +100,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
100 100 end
101 101  
102 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 104 assert !cart?
105 105  
106 106 assert_nothing_raised { get :update_quantity, :profile => enterprise.identifier, :id => 9999, :quantity => 3 }
... ... @@ -139,7 +139,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
139 139 end
140 140  
141 141 should 'not crash if there is no cart' do
142   - instantiate_session
  142 + instantiate_cart
143 143 assert !cart?
144 144 assert_nothing_raised { get :clean, :profile => enterprise.identifier }
145 145 end
... ... @@ -147,7 +147,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
147 147 should 'register order on send request' do
148 148 product1 = fast_create(Product, :enterprise_id => enterprise.id, :price => 1.99)
149 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 151 assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do
152 152 post :send_request,
153 153 :customer => {:name => "Manuel", :email => "manuel@ceu.com"},
... ... @@ -165,7 +165,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
165 165  
166 166 should 'register order on send request and not crash if product is not defined' do
167 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 169 assert_difference ShoppingCartPlugin::PurchaseOrder, :count, 1 do
170 170 post :send_request,
171 171 :customer => {:name => "Manuel", :email => "manuel@ceu.com"},
... ... @@ -184,15 +184,15 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
184 184 end
185 185  
186 186 def cart?
187   - !session[:cart].nil?
  187 + @controller.send(:cart).nil?
188 188 end
189 189  
190 190 def product_in_cart?(product)
191   - session[:cart][:items].has_key?(product.id)
  191 + @controller.send(:cart)[:items].has_key?(product.id)
192 192 end
193 193  
194 194 def product_quantity(product)
195   - session[:cart][:items][product.id]
  195 + @controller.send(:cart)[:items][product.id]
196 196 end
197 197  
198 198 def response_ok?
... ... @@ -205,7 +205,7 @@ class ShoppingCartPluginProfileControllerTest &lt; ActionController::TestCase
205 205  
206 206 # temporary hack...if I don't do this the session stays as an Array instead
207 207 # of a TestSession
208   - def instantiate_session
  208 + def instantiate_cart
209 209 get :add, :profile => enterprise.identifier, :id => product.id
210 210 get :remove, :profile => enterprise.identifier, :id => product.id
211 211 end
... ...
plugins/shopping_cart/views/cart.html.erb
... ... @@ -18,6 +18,19 @@
18 18  
19 19 <script type="text/javascript">
20 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 36 </script>
... ...
plugins/shopping_cart/views/shopping_cart_plugin_profile/buy.html.erb
... ... @@ -16,7 +16,7 @@
16 16 <%= submit_button(:send, _('Send buy request')) %>
17 17 </div>
18 18 <% end %>
19   - <%= items_table(session[:cart][:items], profile) %>
  19 + <%= items_table(@cart[:items], profile) %>
20 20 <%= link_to '', '#', :onclick => "Cart.colorbox_close(this);", :class => 'cart-box-close icon-cancel' %>
21 21 </div>
22 22  
... ...
vendor/plugins/noosfero_caching/init.rb
... ... @@ -38,6 +38,8 @@ module NoosferoHttpCaching
38 38 def call(env)
39 39 status, headers, body = @app.call(env)
40 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 43 headers.delete('Set-Cookie')
42 44 end
43 45 headers.delete('X-Noosfero-Auth')
... ...