Add couchbase with modifications, formalize broadcaster and make testable and some other stuff
This commit is contained in:
@@ -34,6 +34,11 @@ group :assets do
|
|||||||
end
|
end
|
||||||
|
|
||||||
#gem 'less-rails'
|
#gem 'less-rails'
|
||||||
|
# COUCHBASE GEMS
|
||||||
|
gem 'couchbase'
|
||||||
|
gem 'map'
|
||||||
|
gem 'couchbase-docstore'
|
||||||
|
gem 'couchbase-structures', github: 'bterkuile/couchbase-structures'
|
||||||
|
|
||||||
gem 'couch_potato' , github: 'bterkuile/couch_potato'
|
gem 'couch_potato' , github: 'bterkuile/couch_potato'
|
||||||
gem 'simply_stored', path: './../components/simply_stored' #, github: 'bterkuile/simply_stored'
|
gem 'simply_stored', path: './../components/simply_stored' #, github: 'bterkuile/simply_stored'
|
||||||
|
|||||||
+25
-1
@@ -7,6 +7,15 @@ GIT
|
|||||||
couchrest (>= 1.0.1)
|
couchrest (>= 1.0.1)
|
||||||
json (~> 1.6)
|
json (~> 1.6)
|
||||||
|
|
||||||
|
GIT
|
||||||
|
remote: git://github.com/bterkuile/couchbase-structures.git
|
||||||
|
revision: f6f7da685fd8bacd2bd05b55eac73e8b82a8078d
|
||||||
|
specs:
|
||||||
|
couchbase-structures (0.1.0)
|
||||||
|
couchbase (>= 1.2.0.z.beta3)
|
||||||
|
couchbase-docstore (>= 0.1.2)
|
||||||
|
couchbase-settings (>= 0.1.0)
|
||||||
|
|
||||||
GIT
|
GIT
|
||||||
remote: git://github.com/bterkuile/devise_simply_stored.git
|
remote: git://github.com/bterkuile/devise_simply_stored.git
|
||||||
revision: 8fdaed396a7e9566fe6cb59b64d950953c8506a6
|
revision: 8fdaed396a7e9566fe6cb59b64d950953c8506a6
|
||||||
@@ -120,7 +129,16 @@ GEM
|
|||||||
sass (~> 3.1)
|
sass (~> 3.1)
|
||||||
compass-rails (1.1.2)
|
compass-rails (1.1.2)
|
||||||
compass (>= 0.12.2)
|
compass (>= 0.12.2)
|
||||||
|
connection_pool (1.2.0)
|
||||||
cookiejar (0.3.0)
|
cookiejar (0.3.0)
|
||||||
|
couchbase (1.3.6)
|
||||||
|
connection_pool (~> 1.0, >= 1.0.0)
|
||||||
|
multi_json (~> 1.0)
|
||||||
|
yaji (~> 0.3, >= 0.3.2)
|
||||||
|
couchbase-docstore (0.3.0)
|
||||||
|
couchbase (>= 1.2)
|
||||||
|
couchbase-settings (>= 0.2.7)
|
||||||
|
couchbase-settings (0.3.4)
|
||||||
couchrest (1.2.0)
|
couchrest (1.2.0)
|
||||||
mime-types (~> 1.15)
|
mime-types (~> 1.15)
|
||||||
multi_json (~> 1.0)
|
multi_json (~> 1.0)
|
||||||
@@ -221,13 +239,14 @@ GEM
|
|||||||
mail (2.5.4)
|
mail (2.5.4)
|
||||||
mime-types (~> 1.16)
|
mime-types (~> 1.16)
|
||||||
treetop (~> 1.4.8)
|
treetop (~> 1.4.8)
|
||||||
|
map (6.5.3)
|
||||||
method_source (0.8.2)
|
method_source (0.8.2)
|
||||||
mime-types (1.25.1)
|
mime-types (1.25.1)
|
||||||
mini_magick (3.7.0)
|
mini_magick (3.7.0)
|
||||||
subexec (~> 0.2.1)
|
subexec (~> 0.2.1)
|
||||||
mini_portile (0.5.2)
|
mini_portile (0.5.2)
|
||||||
minitest (4.7.5)
|
minitest (4.7.5)
|
||||||
multi_json (1.8.2)
|
multi_json (1.9.0)
|
||||||
multipart-post (1.2.0)
|
multipart-post (1.2.0)
|
||||||
nokogiri (1.6.1)
|
nokogiri (1.6.1)
|
||||||
mini_portile (~> 0.5.0)
|
mini_portile (~> 0.5.0)
|
||||||
@@ -353,6 +372,7 @@ GEM
|
|||||||
websocket-driver (0.3.1)
|
websocket-driver (0.3.1)
|
||||||
xpath (2.0.0)
|
xpath (2.0.0)
|
||||||
nokogiri (~> 1.3)
|
nokogiri (~> 1.3)
|
||||||
|
yaji (0.3.5)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
ruby
|
ruby
|
||||||
@@ -367,6 +387,9 @@ DEPENDENCIES
|
|||||||
coffee-rails
|
coffee-rails
|
||||||
compass-rails
|
compass-rails
|
||||||
couch_potato!
|
couch_potato!
|
||||||
|
couchbase
|
||||||
|
couchbase-docstore
|
||||||
|
couchbase-structures!
|
||||||
database_cleaner
|
database_cleaner
|
||||||
devise
|
devise
|
||||||
devise_simply_stored!
|
devise_simply_stored!
|
||||||
@@ -382,6 +405,7 @@ DEPENDENCIES
|
|||||||
kaminari
|
kaminari
|
||||||
launchy
|
launchy
|
||||||
letter_opener
|
letter_opener
|
||||||
|
map
|
||||||
mini_magick
|
mini_magick
|
||||||
omniauth-facebook
|
omniauth-facebook
|
||||||
orm_adapter!
|
orm_adapter!
|
||||||
|
|||||||
@@ -12,15 +12,11 @@ private
|
|||||||
end
|
end
|
||||||
|
|
||||||
def broadcast_user(uid, event, data = {})
|
def broadcast_user(uid, event, data = {})
|
||||||
message = {channel: "/user/#{uid}", data: {event: event, data: data}}
|
Qwaiter.broadcast_user uid, event, data
|
||||||
uri = URI.parse(event_host)
|
|
||||||
Net::HTTP.post_form(uri, :message => message.to_json)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def broadcast_supplier(sid, event, data = {})
|
def broadcast_supplier(sid, event, data = {})
|
||||||
message = {channel: "/supplier/#{sid}", data: {event: event, data: data}}
|
Qwaiter.broadcast_supplier sid, event, data
|
||||||
uri = URI.parse(event_host)
|
|
||||||
Net::HTTP.post_form(uri, :message => message.to_json)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_locale
|
def set_locale
|
||||||
@@ -64,13 +60,6 @@ private
|
|||||||
end
|
end
|
||||||
alias json_notice js_notice
|
alias json_notice js_notice
|
||||||
|
|
||||||
# Return the hostname of the event server
|
|
||||||
def event_host
|
|
||||||
#TODO: do not do and environment check, its ugly!
|
|
||||||
"http://#{Rails.env.production? ? 'events.qwaiter.com' : 'localhost'}:9296/faye"
|
|
||||||
end
|
|
||||||
helper_method :event_host
|
|
||||||
|
|
||||||
def show_404
|
def show_404
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html { render 'dashboard/404', layout: true, status: 404}
|
format.html { render 'dashboard/404', layout: true, status: 404}
|
||||||
|
|||||||
@@ -270,6 +270,7 @@ class List
|
|||||||
return false unless user
|
return false unless user
|
||||||
order = Order.create list: self, supplier: supplier, user: user, section_id: section_id
|
order = Order.create list: self, supplier: supplier, user: user, section_id: section_id
|
||||||
return unless order.id
|
return unless order.id
|
||||||
|
orders_in_process_count = supplier.increment_orders_in_process_count!
|
||||||
loaded_products = self.class.database.load_document products.keys
|
loaded_products = self.class.database.load_document products.keys
|
||||||
products.each do |product_id, quantity|
|
products.each do |product_id, quantity|
|
||||||
quantity = quantity.to_i
|
quantity = quantity.to_i
|
||||||
@@ -280,9 +281,11 @@ class List
|
|||||||
save
|
save
|
||||||
for user_id in user_ids
|
for user_id in user_ids
|
||||||
broadcast_user user_id, 'new_order', order: order.with_products_as_json, total_amount: price
|
broadcast_user user_id, 'new_order', order: order.with_products_as_json, total_amount: price
|
||||||
|
broadcast_user user_id, 'orders_in_process_count', count: orders_in_process_count
|
||||||
end
|
end
|
||||||
broadcast_supplier supplier.id, 'list_update', active_model_serializer.new(self).as_json
|
broadcast_supplier supplier.id, 'list_update', active_model_serializer.new(self).as_json
|
||||||
broadcast_supplier supplier.id, 'new_order', OrderSerializer.new(order)
|
broadcast_supplier supplier.id, 'new_order', OrderSerializer.new(order)
|
||||||
|
broadcast_supplier supplier.id, 'orders_in_process_count', count: orders_in_process_count
|
||||||
order
|
order
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -77,20 +77,29 @@ class Order
|
|||||||
def is_being_processed!
|
def is_being_processed!
|
||||||
self.state = 'active'
|
self.state = 'active'
|
||||||
if save
|
if save
|
||||||
|
orders_in_process_count = supplier.decrement_orders_in_process_count!
|
||||||
|
orders_delivered_count = supplier.increment_orders_delivered_count!
|
||||||
for user_id in list.user_ids
|
for user_id in list.user_ids
|
||||||
broadcast_user user_id, 'order_being_processed', id: id, list_id: list_id
|
broadcast_user user_id, 'order_being_processed', id: id, list_id: list_id
|
||||||
|
broadcast_user user_id, 'orders_in_process_count', count: orders_in_process_count
|
||||||
|
broadcast_user user_id, 'orders_delivered_count', count: orders_delivered_count
|
||||||
end
|
end
|
||||||
broadcast_supplier supplier_id, 'order_being_processed', id: id, list_id: list_id
|
broadcast_supplier supplier_id, 'order_being_processed', id: id, list_id: list_id
|
||||||
|
broadcast_supplier supplier_id, 'orders_in_process_count', count: orders_in_process_count
|
||||||
|
broadcast_supplier supplier_id, 'orders_delivered_count', count: orders_delivered_count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def is_delivered!
|
def is_delivered!
|
||||||
self.state = 'delivered'
|
self.state = 'delivered'
|
||||||
if save
|
if save
|
||||||
|
orders_delivered_count = supplier.decrement_orders_delivered_count!
|
||||||
for user_id in list.user_ids
|
for user_id in list.user_ids
|
||||||
broadcast_user user_id, 'order_being_delivered', id: id, list_id: list_id
|
broadcast_user user_id, 'order_being_delivered', id: id, list_id: list_id
|
||||||
|
broadcast_user user_id, 'orders_delivered_count', count: orders_delivered_count
|
||||||
end
|
end
|
||||||
broadcast_supplier supplier_id, 'order_being_delivered', id: id, list_id: list_id
|
broadcast_supplier supplier_id, 'order_being_delivered', id: id, list_id: list_id
|
||||||
|
broadcast_supplier supplier_id, 'orders_delivered_count', count: orders_delivered_count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -137,6 +137,35 @@ class Supplier
|
|||||||
def week_starts_on_monday?
|
def week_starts_on_monday?
|
||||||
true
|
true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def increment_orders_in_process_count!
|
||||||
|
Qwaiter::Counter.incr "supplier:#{id}:orders_in_process"
|
||||||
|
end
|
||||||
|
|
||||||
|
def increment_orders_delivered_count!
|
||||||
|
Qwaiter::Counter.incr "supplier:#{id}:orders_delivered"
|
||||||
|
end
|
||||||
|
|
||||||
|
def decrement_orders_in_process_count!
|
||||||
|
Qwaiter::Counter.decr "supplier:#{id}:orders_in_process"
|
||||||
|
end
|
||||||
|
|
||||||
|
def decrement_orders_delivered_count!
|
||||||
|
Qwaiter::Counter.decr "supplier:#{id}:orders_delivered"
|
||||||
|
end
|
||||||
|
|
||||||
|
def orders_in_process_count
|
||||||
|
Qwaiter::Counter.get "supplier:#{id}:orders_in_process"
|
||||||
|
end
|
||||||
|
|
||||||
|
def orders_delivered_count
|
||||||
|
Qwaiter::Counter.get "supplier:#{id}:orders_delivered"
|
||||||
|
end
|
||||||
|
|
||||||
|
def active_order_count
|
||||||
|
orders_in_process_count + orders_delivered_count
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def add_section_on_create
|
def add_section_on_create
|
||||||
|
|||||||
@@ -20,14 +20,14 @@ html lang="en"
|
|||||||
javascript:
|
javascript:
|
||||||
var QMobile, Qwaiter, Quser;
|
var QMobile, Qwaiter, Quser;
|
||||||
var data_host = 'http://data.qwaiter.com';
|
var data_host = 'http://data.qwaiter.com';
|
||||||
var event_host = '#{event_host}';
|
var event_host = '#{Qwaiter.event_host}';
|
||||||
var $asset_path = '##assets_path##';
|
var $asset_path = '##assets_path##';
|
||||||
var Qstorage = localStorage;
|
var Qstorage = localStorage;
|
||||||
- else
|
- else
|
||||||
javascript:
|
javascript:
|
||||||
var QMobile, Qwaiter, Quser;
|
var QMobile, Qwaiter, Quser;
|
||||||
var data_host = 'http://data.qwaiter.com';
|
var data_host = 'http://data.qwaiter.com';
|
||||||
var event_host = '#{event_host}';
|
var event_host = '#{Qwaiter.event_host}';
|
||||||
var $asset_path = '/assets/';
|
var $asset_path = '/assets/';
|
||||||
var Qstorage = localStorage;
|
var Qstorage = localStorage;
|
||||||
#{user_dynamic_data_host}
|
#{user_dynamic_data_host}
|
||||||
|
|||||||
@@ -2,6 +2,6 @@
|
|||||||
var $locale = '<%= I18n.locale %>';
|
var $locale = '<%= I18n.locale %>';
|
||||||
var supplier_id = '<%= current_supplier.id %>';
|
var supplier_id = '<%= current_supplier.id %>';
|
||||||
var data_host = '';
|
var data_host = '';
|
||||||
var event_host = '<%= event_host %>';
|
var event_host = '<%= Qwaiter.event_host %>';
|
||||||
var datepicker_options = {dateFormat: 'yy-mm-dd', firstDay: <%= current_supplier.week_starts_on_monday? ? 1 : 0 %>};
|
var datepicker_options = {dateFormat: 'yy-mm-dd', firstDay: <%= current_supplier.week_starts_on_monday? ? 1 : 0 %>};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ require 'action_mailer/railtie'
|
|||||||
require 'rails/test_unit/railtie'
|
require 'rails/test_unit/railtie'
|
||||||
require 'sprockets/railtie'
|
require 'sprockets/railtie'
|
||||||
|
|
||||||
|
# custom override hack for the couchbase-setting gem, needs to be loaded before other gems, is settings only without dependencies
|
||||||
|
require File.expand_path('./../../lib/couchbase-setting', __FILE__)
|
||||||
|
|
||||||
if defined?(Bundler)
|
if defined?(Bundler)
|
||||||
# If you precompile assets before deploying to production, use this line
|
# If you precompile assets before deploying to production, use this line
|
||||||
Bundler.require(*Rails.groups(:assets => %w(development test)))
|
Bundler.require(*Rails.groups(:assets => %w(development test)))
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
defaults: &defaults
|
||||||
|
server: 127.0.0.1
|
||||||
|
|
||||||
|
development:
|
||||||
|
<<: *defaults
|
||||||
|
bucket: qwaiter_development
|
||||||
|
|
||||||
|
|
||||||
|
test:
|
||||||
|
<<: *defaults
|
||||||
|
bucket: qwaiter_test
|
||||||
|
|
||||||
|
production:
|
||||||
|
<<: *defaults
|
||||||
|
bucket: qwaiter
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#TODO: this is really ugly, can cause memory leaks and much more bad stuff. We need a new broadcaster....
|
||||||
require 'simply_stored/couch'
|
require 'simply_stored/couch'
|
||||||
module ModelBroadcast
|
module ModelBroadcast
|
||||||
def broadcast_supplier(*args)
|
def broadcast_supplier(*args)
|
||||||
@@ -8,4 +9,4 @@ module ModelBroadcast
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
SimplyStored::Couch.send(:include, ModelBroadcast)
|
SimplyStored::Couch.send(:include, ModelBroadcast)
|
||||||
SimplyStored::Couch.send(:extend, ModelBroadcast)
|
#SimplyStored::Couch.send(:extend, ModelBroadcast) # this should never happen!!!
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
Qwaiter.event_host = "http://#{Rails.env.production? ? 'events.qwaiter.com' : 'localhost'}:9296/faye"
|
||||||
|
Qwaiter.broadcaster = Qwaiter::Broadcaster::Faye.new
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# This is a replacement of the couchbase settings gem. The quality of this gem is not sufficient to
|
||||||
|
# work with. Since couchbase structures/docstore are using CouchbaseSetting we supply the right settings
|
||||||
|
# here
|
||||||
|
|
||||||
|
module CouchbaseSetting
|
||||||
|
mattr_accessor :config_type
|
||||||
|
mattr_accessor :configs
|
||||||
|
|
||||||
|
def self.server
|
||||||
|
config :server, default: '127.0.0.1'
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.bucket
|
||||||
|
config :bucket, default: 'qwaiter'
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.config(setting, default: nil)
|
||||||
|
configs[config_type][Rails.env.to_sym][setting] || default
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
CouchbaseSetting.configs = {
|
||||||
|
supplier_counters: {
|
||||||
|
development: {
|
||||||
|
bucket: 'qwaiter_development'
|
||||||
|
},
|
||||||
|
test:{
|
||||||
|
bucket: 'qwaiter_development'
|
||||||
|
},
|
||||||
|
production: {}
|
||||||
|
},
|
||||||
|
queue: {
|
||||||
|
development: {
|
||||||
|
bucket: 'qwaiter_development'
|
||||||
|
},
|
||||||
|
test:{
|
||||||
|
bucket: 'qwaiter_development'
|
||||||
|
},
|
||||||
|
production: {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# only one in use at the moment
|
||||||
|
CouchbaseSetting.config_type = :supplier_counters
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# this file is for backwards compatibility of the couchbase-structures gem since version 0.1.0 requires this file
|
||||||
|
# while couchbase-docstore is already over to the new require 'couchbase-docstore' syntax (kinda)
|
||||||
|
require 'couchbase-docstore'
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# this file is for backwards compatibility of the couchbase-structures gem since version 0.1.0 requires this file
|
||||||
|
# while couchbase-settings is custom for now
|
||||||
|
require 'couchbase-setting'
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# this file is for backwards compatibility of the couchbase-structures gem since version 0.1.0 requires this file
|
||||||
|
# while couchbase-settings is custom for now
|
||||||
|
require 'couchbase-setting'
|
||||||
@@ -1,6 +1,20 @@
|
|||||||
module Qwaiter
|
module Qwaiter
|
||||||
|
mattr_accessor :event_host
|
||||||
|
mattr_accessor :broadcaster
|
||||||
extend ActiveSupport::Autoload
|
extend ActiveSupport::Autoload
|
||||||
autoload :Distribution
|
autoload :Distribution
|
||||||
autoload :Serializer
|
autoload :Serializer
|
||||||
|
autoload :Counter
|
||||||
|
autoload :Broadcaster
|
||||||
|
|
||||||
|
def self.broadcast_user(uid, event, data)
|
||||||
|
message = {channel: "/user/#{uid}", data: {event: event, data: data}}
|
||||||
|
broadcaster.broadcast message
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.broadcast_supplier(sid, event, data)
|
||||||
|
message = {channel: "/supplier/#{sid}", data: {event: event, data: data}}
|
||||||
|
broadcaster.broadcast message
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
module Qwaiter
|
||||||
|
module Broadcaster
|
||||||
|
extend ActiveSupport::Autoload
|
||||||
|
autoload :Faye
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
module Qwaiter
|
||||||
|
module Broadcaster
|
||||||
|
class Faye
|
||||||
|
def broadcast(message)
|
||||||
|
@uri ||= URI.parse(Qwaiter.event_host)
|
||||||
|
Net::HTTP.post_form(@uri, :message => message.to_json)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
module Qwaiter
|
||||||
|
module Counter
|
||||||
|
mattr_accessor :connection
|
||||||
|
|
||||||
|
# mainly for testing purposes
|
||||||
|
def self.set(key, value)
|
||||||
|
connection.set(key, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.get(key)
|
||||||
|
connection.get(key).to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.incr(*args)
|
||||||
|
connection.incr(*args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.decr(*args)
|
||||||
|
connection.decr(*args)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# use the connection from couchbase-structures/documents
|
||||||
|
# will be overwritten in the specs since flushing the real
|
||||||
|
# thing is difficult
|
||||||
|
Qwaiter::Counter.connection = $cb
|
||||||
@@ -122,4 +122,36 @@ describe List do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#place_order' do
|
||||||
|
|
||||||
|
it 'returns an order object' do
|
||||||
|
list.place_order(user, product.id => 7).should be_a Order
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates an order' do
|
||||||
|
expect{ list.place_order(user, product.id => 7) }.to change{ Order.count }.by(1)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'broadcasting' do
|
||||||
|
it 'broadcasts to the user and the supplier the active order counter' do
|
||||||
|
list.place_order(user, product.id => 7)
|
||||||
|
|
||||||
|
expect{
|
||||||
|
list.place_order(user, product.id => 3)
|
||||||
|
}.to broadcast_to_user(user.id).message('orders_in_process_count').with(count: 2)
|
||||||
|
|
||||||
|
expect{
|
||||||
|
list.place_order(user, product.id => 5)
|
||||||
|
}.to broadcast_to_supplier(supplier.id).message('orders_in_process_count').with(count: 3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'sets the list price as kind of caching' do
|
||||||
|
list.place_order(user, product.id => 7)
|
||||||
|
list.reload
|
||||||
|
list.price.should == 3
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'product order creation'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -37,4 +37,64 @@ describe Order do
|
|||||||
it 'paginates'
|
it 'paginates'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#is_being_processed!' do
|
||||||
|
describe 'broadcasting' do
|
||||||
|
|
||||||
|
it 'broadcasts order info to the user' do
|
||||||
|
expect{ order.is_being_processed! }.to broadcast_to_user(user.id).message( 'order_being_processed' ).with(id: order.id, list_id: list.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'counters' do
|
||||||
|
before do
|
||||||
|
# hack some initial values
|
||||||
|
Qwaiter::Counter.set "supplier:#{supplier.id}:orders_in_process", 7
|
||||||
|
Qwaiter::Counter.set "supplier:#{supplier.id}:orders_delivered", 9
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'reduces the orders_in_process count and communicates it to user' do
|
||||||
|
expect{ order.is_being_processed! }.to broadcast_to_user(user.id).message( 'orders_in_process_count' ).with(count: 6)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'increases the orders_delivered count and communicates it to user' do
|
||||||
|
expect{ order.is_being_processed! }.to broadcast_to_user(user.id).message( 'orders_delivered_count' ).with(count: 10)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'reduces the orders_in_process count and communicates it to supplier' do
|
||||||
|
expect{ order.is_being_processed! }.to broadcast_to_supplier(supplier.id).message( 'orders_in_process_count' ).with(count: 6)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'increases the orders_in_process count and communicates it to supplier' do
|
||||||
|
expect{ order.is_being_processed! }.to broadcast_to_supplier(supplier.id).message( 'orders_delivered_count' ).with(count: 10)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'broadcasts order info to the supplier' do
|
||||||
|
expect{ order.is_being_processed! }.to broadcast_to_supplier(supplier.id).message( 'order_being_processed' ).with(id: order.id, list_id: list.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#is_delivered!' do
|
||||||
|
describe 'broadcasting' do
|
||||||
|
describe 'counters' do
|
||||||
|
before do
|
||||||
|
# hack some initial values
|
||||||
|
Qwaiter::Counter.set "supplier:#{supplier.id}:orders_in_process", 7
|
||||||
|
Qwaiter::Counter.set "supplier:#{supplier.id}:orders_delivered", 9
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'decreases the orders_delivered count and communicates it to user' do
|
||||||
|
expect{ order.is_delivered! }.to broadcast_to_user(user.id).message( 'orders_delivered_count' ).with(count: 8)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'decreases the orders_in_process count and communicates it to supplier' do
|
||||||
|
expect{ order.is_delivered! }.to broadcast_to_supplier(supplier.id).message( 'orders_delivered_count' ).with(count: 8)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,62 +1,67 @@
|
|||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
describe Supplier do
|
describe Supplier do
|
||||||
before :each do
|
let(:supplier){ build :supplier }
|
||||||
@supplier = build :supplier
|
|
||||||
end
|
|
||||||
# property open
|
# property open
|
||||||
describe :open do
|
describe :open do
|
||||||
it 'should be false by default' do
|
it 'should be false by default' do
|
||||||
@supplier.open.should == false
|
supplier.open.should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not be open? by default' do
|
it 'should not be open? by default' do
|
||||||
@supplier.open?.should == false
|
supplier.open?.should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should be closed? by default' do
|
it 'should be closed? by default' do
|
||||||
@supplier.closed?.should == true
|
supplier.closed?.should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
describe :mark_as_open! do
|
describe :mark_as_open! do
|
||||||
before :each do
|
before :each do
|
||||||
@supplier.mark_as_open!
|
supplier.mark_as_open!
|
||||||
end
|
end
|
||||||
it 'should be persisted in the database' do
|
it 'should be persisted in the database' do
|
||||||
@supplier.reload
|
supplier.reload
|
||||||
@supplier.open.should == true
|
supplier.open.should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should be open?' do
|
it 'should be open?' do
|
||||||
@supplier.open?.should == true
|
supplier.open?.should == true
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not be closed?' do
|
it 'should not be closed?' do
|
||||||
@supplier.closed?.should == false
|
supplier.closed?.should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
describe :mark_as_closed! do
|
describe :mark_as_closed! do
|
||||||
before :each do
|
before :each do
|
||||||
@supplier.mark_as_open!
|
supplier.mark_as_open!
|
||||||
@supplier.mark_as_closed!
|
supplier.mark_as_closed!
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should be persisted in the database' do
|
it 'should be persisted in the database' do
|
||||||
@supplier.reload
|
supplier.reload
|
||||||
@supplier.open.should == false
|
supplier.open.should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should be open?' do
|
it 'should be open?' do
|
||||||
@supplier.open?.should == false
|
supplier.open?.should == false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should not be closed?' do
|
it 'should not be closed?' do
|
||||||
@supplier.closed?.should == true
|
supplier.closed?.should == true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#decrement_orders_delivered_count!' do
|
||||||
|
it 'decreases orders_delivered' do
|
||||||
|
Qwaiter::Counter.set "supplier:#{supplier.id}:orders_delivered", 9
|
||||||
|
supplier.decrement_orders_delivered_count!.should == 8
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -43,6 +43,10 @@ module SpecSelectorHelpers
|
|||||||
%x(launchy http://localhost:3000/capybara.html)
|
%x(launchy http://localhost:3000/capybara.html)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# NOT THREADSAFE!!!!!! but good enough for testing since the real couchbase flush is slowwwwww....
|
||||||
|
Qwaiter::Counter.connection = InMemoryQCounter.new
|
||||||
|
|
||||||
RSpec.configure do |config|
|
RSpec.configure do |config|
|
||||||
# == Mock Framework
|
# == Mock Framework
|
||||||
#
|
#
|
||||||
@@ -56,6 +60,7 @@ RSpec.configure do |config|
|
|||||||
config.include FactoryAttributesFor
|
config.include FactoryAttributesFor
|
||||||
config.include Devise::TestHelpers, type: :controller
|
config.include Devise::TestHelpers, type: :controller
|
||||||
config.include EndWithMatcher
|
config.include EndWithMatcher
|
||||||
|
config.include Matchers
|
||||||
config.include Features::BasicHelpers, type: :feature
|
config.include Features::BasicHelpers, type: :feature
|
||||||
config.include SpecRouteHelpers, type: :feature
|
config.include SpecRouteHelpers, type: :feature
|
||||||
#config.use_transactional_fixtures = true
|
#config.use_transactional_fixtures = true
|
||||||
@@ -98,6 +103,7 @@ RSpec.configure do |config|
|
|||||||
|
|
||||||
config.before :each do
|
config.before :each do
|
||||||
CouchPotato.couchrest_database.recreate!
|
CouchPotato.couchrest_database.recreate!
|
||||||
|
Qwaiter::Counter.connection.flush
|
||||||
end
|
end
|
||||||
|
|
||||||
config.before :each, type: :feature do
|
config.before :each, type: :feature do
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# This is a non thread safe replacement for the
|
||||||
|
# couchbase counter mechanism since every test needs
|
||||||
|
# a clean start and Hash#clear is soooo much faster than
|
||||||
|
# a couchbase bucket flush
|
||||||
|
class InMemoryQCounter
|
||||||
|
STORE = {}
|
||||||
|
|
||||||
|
def get(key)
|
||||||
|
STORE[key]
|
||||||
|
end
|
||||||
|
|
||||||
|
def set(key, value)
|
||||||
|
STORE[key] = value
|
||||||
|
end
|
||||||
|
|
||||||
|
def incr(key, options = {})
|
||||||
|
STORE[key] ||= options[:initial].to_i
|
||||||
|
STORE[key] += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def decr(key, options = {})
|
||||||
|
STORE[key] ||= options[:initial].to_i
|
||||||
|
STORE[key] -= 1
|
||||||
|
end
|
||||||
|
|
||||||
|
def flush
|
||||||
|
STORE.clear
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
module Matchers
|
||||||
|
class BroadcastToSupplier
|
||||||
|
class TestBroadcaster
|
||||||
|
attr_reader :broadcasts
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@broadcasts = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def broadcast(object)
|
||||||
|
self.broadcasts << object
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(supplier_id)
|
||||||
|
@supplier_id = supplier_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches?(block)
|
||||||
|
old_broadcaster = Qwaiter.broadcaster
|
||||||
|
test_broadcaster = TestBroadcaster.new
|
||||||
|
Qwaiter.broadcaster = test_broadcaster
|
||||||
|
block.call
|
||||||
|
Qwaiter.broadcaster = old_broadcaster
|
||||||
|
|
||||||
|
relevant_broadcasts = test_broadcaster.broadcasts.select{|b| b[:channel] =~ /^\/supplier\/#{@supplier_id}/ && b[:data][:event] == @message}
|
||||||
|
@failure_debug_content = "was #{relevant_broadcasts.map{|b| b[:data][:data].inspect}.join(" and ")}"
|
||||||
|
relevant_broadcasts.any?{|b| b[:data][:data] == @target_object}
|
||||||
|
end
|
||||||
|
|
||||||
|
def message(msg)
|
||||||
|
@message = msg
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def with(target_object)
|
||||||
|
@target_object = target_object
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def failure_message
|
||||||
|
"supplier #{@supplier_id} did not receive broadcast #{@message} with #{@target_object.inspect} #{@failure_debug_content}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def broadcast_to_supplier(*args, &block)
|
||||||
|
BroadcastToSupplier.new(*args, &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
module Matchers
|
||||||
|
class BroadcastToUser
|
||||||
|
class TestBroadcaster
|
||||||
|
attr_reader :broadcasts
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
@broadcasts = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def broadcast(object)
|
||||||
|
self.broadcasts << object
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def initialize(user_id)
|
||||||
|
@user_id = user_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def matches?(block)
|
||||||
|
old_broadcaster = Qwaiter.broadcaster
|
||||||
|
test_broadcaster = TestBroadcaster.new
|
||||||
|
Qwaiter.broadcaster = test_broadcaster
|
||||||
|
block.call
|
||||||
|
Qwaiter.broadcaster = old_broadcaster
|
||||||
|
|
||||||
|
relevant_broadcasts = test_broadcaster.broadcasts.select{|b| b[:channel] =~ /^\/user\/#{@user_id}/ && b[:data][:event] == @message}
|
||||||
|
@failure_debug_content = "was #{relevant_broadcasts.map{|b| b[:data][:data].inspect}.join(" and ")}"
|
||||||
|
relevant_broadcasts.any?{|b| b[:data][:data] == @target_object}
|
||||||
|
end
|
||||||
|
|
||||||
|
def message(msg)
|
||||||
|
@message = msg
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def with(target_object)
|
||||||
|
@target_object = target_object
|
||||||
|
self
|
||||||
|
end
|
||||||
|
|
||||||
|
def failure_message
|
||||||
|
"user #{@user_id} did not receive broadcast #{@message} with #{@target_object.inspect} #{@failure_debug_content}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def broadcast_to_user(*args, &block)
|
||||||
|
BroadcastToUser.new(*args, &block)
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user