From 95e268adea696bc6d13b662bfde414dbf7796a68 Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Fri, 7 Mar 2014 13:37:01 +0100 Subject: [PATCH] Implement spring and reset counters functionality --- Gemfile | 2 + Gemfile.lock | 5 +++ app/models/order.rb | 3 +- app/models/supplier.rb | 29 +++++++++++++ {script => bin}/build_mobile_app.rb | 0 {script => bin}/rails | 4 ++ bin/rake | 7 ++++ bin/spring | 18 ++++++++ config/cucumber.yml | 8 ---- lib/tasks/counters.rake | 5 +++ lib/tasks/cucumber.rake | 65 ----------------------------- script/cucumber | 10 ----- spec/factories/order_factory.rb | 6 +++ spec/models/supplier_spec.rb | 26 ++++++++++++ 14 files changed, 104 insertions(+), 84 deletions(-) rename {script => bin}/build_mobile_app.rb (100%) rename {script => bin}/rails (79%) create mode 100755 bin/rake create mode 100755 bin/spring delete mode 100644 config/cucumber.yml create mode 100644 lib/tasks/counters.rake delete mode 100644 lib/tasks/cucumber.rake delete mode 100755 script/cucumber diff --git a/Gemfile b/Gemfile index f40a9d22..ade2ab35 100644 --- a/Gemfile +++ b/Gemfile @@ -72,6 +72,8 @@ group :development do gem 'thin' gem 'faye' gem 'pry-rails' + gem 'spring' + gem 'spring-commands-rspec' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index 34dd55c6..0d7a0f4b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -336,6 +336,9 @@ GEM railties (>= 3.0, < 4.1) slim (~> 2.0) slop (3.4.7) + spring (1.1.2) + spring-commands-rspec (1.0.1) + spring (>= 0.9.1) sprockets (2.10.1) hike (~> 1.2) multi_json (~> 1.0) @@ -420,6 +423,8 @@ DEPENDENCIES simplecov simply_stored! slim-rails + spring + spring-commands-rspec thin turnip uglifier (>= 1.0.3) diff --git a/app/models/order.rb b/app/models/order.rb index 7cc6e6c8..92f23242 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -26,7 +26,8 @@ class Order } }], reduce_function: '_sum' - view :by_supplier_id_and_id, key: [:supplier_id, :_id] # Do not comment me out + view :by_supplier_id_and_id, key: [:supplier_id, :_id] # Do not comment me out this is for security, TODO: make the security server side for speed and space optimization + view :by_supplier_id_and_state, key: [:supplier_id, :state], reduce_function: '_sum' def self.for_supplier(supplier, options = {}) total_entries = database.view(by_supplier_id_and_id({startkey: ["#{supplier.id}\u9999"], endkey: [supplier.id], include_docs: false, reduce: true, descending: true})) diff --git a/app/models/supplier.rb b/app/models/supplier.rb index 57683f7d..b8143382 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -115,6 +115,35 @@ class Supplier confirmable end + def self.reset_counters! + spec = Order.by_supplier_id_and_state(reduce: true, group_level: 2) + reset_order_counters_with_spec spec + end + + def reset_counters! + spec = Order.by_supplier_id_and_state(startkey: [id], endkey: [id, {}], reduce: true, group_level: 2) + self.class.reset_order_counters_with_spec spec + end + + def self.reset_order_counters_with_spec(spec) + # taken from the couch_potato source since we want a model/custom mix here (hmmmm, something that should be fixed in the couchbase version) + results = CouchPotato::View::ViewQuery.new( + database.couchrest_database, + spec.design_document, + {spec.view_name => { map: spec.map_function, reduce: spec.reduce_function} }, + ({spec.list_name => spec.list_function} unless spec.list_name.nil?), + spec.language + ).query_view!(spec.view_parameters) + Array.wrap(results['rows']).each do |result| + supplier_id, state = result['key'] + case state + when 'placed' then Qwaiter::Counter.set "supplier:#{supplier_id}:orders_in_process", result['value'] + when 'active' then Qwaiter::Counter.set "supplier:#{supplier_id}:orders_delivered", result['value'] + end + end + end + + # Send confirmation instructions by email def send_confirmation_instructions(*args) self.confirmation_token = nil if reconfirmation_required? diff --git a/script/build_mobile_app.rb b/bin/build_mobile_app.rb similarity index 100% rename from script/build_mobile_app.rb rename to bin/build_mobile_app.rb diff --git a/script/rails b/bin/rails similarity index 79% rename from script/rails rename to bin/rails index f8da2cff..1c894d52 100755 --- a/script/rails +++ b/bin/rails @@ -1,4 +1,8 @@ #!/usr/bin/env ruby +begin + load File.expand_path("../spring", __FILE__) +rescue LoadError +end # This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application. APP_PATH = File.expand_path('../../config/application', __FILE__) diff --git a/bin/rake b/bin/rake new file mode 100755 index 00000000..0fb4e07e --- /dev/null +++ b/bin/rake @@ -0,0 +1,7 @@ +#!/usr/bin/env ruby +begin + load File.expand_path("../spring", __FILE__) +rescue LoadError +end +require 'bundler/setup' +load Gem.bin_path('rake', 'rake') diff --git a/bin/spring b/bin/spring new file mode 100755 index 00000000..253ec37c --- /dev/null +++ b/bin/spring @@ -0,0 +1,18 @@ +#!/usr/bin/env ruby + +# This file loads spring without using Bundler, in order to be fast +# It gets overwritten when you run the `spring binstub` command + +unless defined?(Spring) + require "rubygems" + require "bundler" + + if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ spring \((.*?)\)$.*?^$/m) + ENV["GEM_PATH"] = ([Bundler.bundle_path.to_s] + Gem.path).join(File::PATH_SEPARATOR) + ENV["GEM_HOME"] = "" + Gem.paths = ENV + + gem "spring", match[1] + require "spring/binstub" + end +end diff --git a/config/cucumber.yml b/config/cucumber.yml deleted file mode 100644 index 19b288df..00000000 --- a/config/cucumber.yml +++ /dev/null @@ -1,8 +0,0 @@ -<% -rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : "" -rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}" -std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags ~@wip" -%> -default: <%= std_opts %> features -wip: --tags @wip:3 --wip features -rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip diff --git a/lib/tasks/counters.rake b/lib/tasks/counters.rake new file mode 100644 index 00000000..5f02eba5 --- /dev/null +++ b/lib/tasks/counters.rake @@ -0,0 +1,5 @@ +namespace :counters do + task reset: :environment do + Supplier.reset_counters! + end +end diff --git a/lib/tasks/cucumber.rake b/lib/tasks/cucumber.rake deleted file mode 100644 index 83f79471..00000000 --- a/lib/tasks/cucumber.rake +++ /dev/null @@ -1,65 +0,0 @@ -# IMPORTANT: This file is generated by cucumber-rails - edit at your own peril. -# It is recommended to regenerate this file in the future when you upgrade to a -# newer version of cucumber-rails. Consider adding your own code to a new file -# instead of editing this one. Cucumber will automatically load all features/**/*.rb -# files. - - -unless ARGV.any? {|a| a =~ /^gems/} # Don't load anything when running the gems:* tasks - -vendored_cucumber_bin = Dir["#{Rails.root}/vendor/{gems,plugins}/cucumber*/bin/cucumber"].first -$LOAD_PATH.unshift(File.dirname(vendored_cucumber_bin) + '/../lib') unless vendored_cucumber_bin.nil? - -begin - require 'cucumber/rake/task' - - namespace :cucumber do - Cucumber::Rake::Task.new({:ok => 'db:test:prepare'}, 'Run features that should pass') do |t| - t.binary = vendored_cucumber_bin # If nil, the gem's binary is used. - t.fork = true # You may get faster startup if you set this to false - t.profile = 'default' - end - - Cucumber::Rake::Task.new({:wip => 'db:test:prepare'}, 'Run features that are being worked on') do |t| - t.binary = vendored_cucumber_bin - t.fork = true # You may get faster startup if you set this to false - t.profile = 'wip' - end - - Cucumber::Rake::Task.new({:rerun => 'db:test:prepare'}, 'Record failing features and run only them if any exist') do |t| - t.binary = vendored_cucumber_bin - t.fork = true # You may get faster startup if you set this to false - t.profile = 'rerun' - end - - desc 'Run all features' - task :all => [:ok, :wip] - - task :statsetup do - require 'rails/code_statistics' - ::STATS_DIRECTORIES << %w(Cucumber\ features features) if File.exist?('features') - ::CodeStatistics::TEST_TYPES << "Cucumber features" if File.exist?('features') - end - end - desc 'Alias for cucumber:ok' - task :cucumber => 'cucumber:ok' - - task :default => :cucumber - - task :features => :cucumber do - STDERR.puts "*** The 'features' task is deprecated. See rake -T cucumber ***" - end - - # In case we don't have ActiveRecord, append a no-op task that we can depend upon. - task 'db:test:prepare' do - end - - task :stats => 'cucumber:statsetup' -rescue LoadError - desc 'cucumber rake task not available (cucumber not installed)' - task :cucumber do - abort 'Cucumber rake task is not available. Be sure to install cucumber as a gem or plugin' - end -end - -end diff --git a/script/cucumber b/script/cucumber deleted file mode 100755 index 7fa5c920..00000000 --- a/script/cucumber +++ /dev/null @@ -1,10 +0,0 @@ -#!/usr/bin/env ruby - -vendored_cucumber_bin = Dir["#{File.dirname(__FILE__)}/../vendor/{gems,plugins}/cucumber*/bin/cucumber"].first -if vendored_cucumber_bin - load File.expand_path(vendored_cucumber_bin) -else - require 'rubygems' unless ENV['NO_RUBYGEMS'] - require 'cucumber' - load Cucumber::BINARY -end diff --git a/spec/factories/order_factory.rb b/spec/factories/order_factory.rb index e36aaad9..10a7c80d 100644 --- a/spec/factories/order_factory.rb +++ b/spec/factories/order_factory.rb @@ -3,5 +3,11 @@ FactoryGirl.define do association :list association :user association :supplier #TODO warning! this may create a different supplier than the one created by the associated table + trait :placed do + state 'placed' + end + trait :active do + state 'active' + end end end diff --git a/spec/models/supplier_spec.rb b/spec/models/supplier_spec.rb index e02c8ff4..3fa95242 100644 --- a/spec/models/supplier_spec.rb +++ b/spec/models/supplier_spec.rb @@ -2,6 +2,32 @@ require 'spec_helper' describe Supplier do let(:supplier){ build :supplier } + + describe '.reset_counters!' do + it 'sets the counters to the right values' do + supplier1 = create :supplier + supplier2 = create :supplier + create_list :order, 2, :placed, supplier: supplier1 + create_list :order, 7, :active, supplier: supplier1 + create_list :order, 3, :placed, supplier: supplier2 + Supplier.reset_counters! + supplier1.orders_in_process_count.should == 2 + supplier1.orders_delivered_count.should == 7 + supplier2.orders_in_process_count.should == 3 + end + end + + describe '#reset_counters!' do + it 'sets the counters to the right values' do + supplier = create :supplier + create_list :order, 5, :placed, supplier: supplier + create_list :order, 9, :active, supplier: supplier + supplier.reset_counters! + supplier.orders_in_process_count.should == 5 + supplier.orders_delivered_count.should == 9 + end + end + # property open describe :open do it 'should be false by default' do