From 8ea2e79dc201e52cc905f394b412aae5d2d779dc Mon Sep 17 00:00:00 2001 From: Benjamin ter Kuile Date: Mon, 30 Sep 2013 17:49:22 +0200 Subject: [PATCH] Qwaiter supplier on Ember 1.0 --- .rspec | 3 +- Gemfile | 10 +-- Gemfile.lock | 69 ++++----------- .../controllers/index_controller.js.coffee | 1 + .../supplier/app/models/list.js.coffee | 5 ++ .../supplier/app/models/order.js.coffee | 6 +- .../modifications/model_extensions.js.coffee | 20 ++++- .../javascripts/supplier/app/router.js.coffee | 3 +- .../supplier/app/routes/index_route.js.coffee | 15 +++- .../javascripts/supplier/app/store.js.coffee | 2 +- .../supplier/app/templates/active_list.emblem | 8 +- .../app/templates/active_order.emblem | 6 +- .../supplier/app/templates/section.emblem | 2 +- .../app/views/active_list_view.js.coffee | 2 + .../app/views/active_order_view.js.coffee | 3 +- .../javascripts/supplier/qsupplier.js.coffee | 25 +++--- app/assets/javascripts/user/quser.js.coffee | 4 +- app/controllers/application_controller.rb | 2 +- app/controllers/supplier_controller.rb | 4 +- app/controllers/suppliers/lists_controller.rb | 2 +- .../suppliers/orders_controller.rb | 11 ++- app/models/list.rb | 19 +++-- app/models/order.rb | 7 +- app/models/product_order.rb | 2 +- app/models/supplier.rb | 8 +- app/models/user.rb | 2 + app/serializers/order_serializer.rb | 12 ++- app/templates/supplier/_active_list.mustache | 2 +- app/templates/supplier/_active_order.mustache | 2 +- app/templates/supplier/_list_order.mustache | 2 +- .../user/_active_list_order.mustache | 2 +- app/views/supplier/home.html.slim | 4 +- .../suppliers/supplier_main_board.feature | 47 +++++++++++ spec/acceptance_steps/global_steps.rb | 13 +++ spec/acceptance_steps/list_steps.rb | 20 +++++ spec/acceptance_steps/order_steps.rb | 13 +++ .../suppliers/authentication_steps.rb | 6 ++ .../suppliers/existance_steps.rb | 5 ++ .../suppliers/main_board_steps.rb | 83 +++++++++++++++++++ .../suppliers/navigation_steps.rb | 7 ++ spec/factories/product_order_factory.rb | 6 ++ .../suppliers/product_categories_spec.rb | 20 ----- spec/models/list_spec.rb | 31 ++++--- spec/spec_helper.rb | 18 ++-- 44 files changed, 378 insertions(+), 156 deletions(-) create mode 100644 spec/acceptance/suppliers/supplier_main_board.feature create mode 100644 spec/acceptance_steps/global_steps.rb create mode 100644 spec/acceptance_steps/list_steps.rb create mode 100644 spec/acceptance_steps/order_steps.rb create mode 100644 spec/acceptance_steps/suppliers/authentication_steps.rb create mode 100644 spec/acceptance_steps/suppliers/existance_steps.rb create mode 100644 spec/acceptance_steps/suppliers/main_board_steps.rb create mode 100644 spec/acceptance_steps/suppliers/navigation_steps.rb create mode 100644 spec/factories/product_order_factory.rb delete mode 100644 spec/features/suppliers/product_categories_spec.rb diff --git a/.rspec b/.rspec index 4e1e0d2f..7115a783 100644 --- a/.rspec +++ b/.rspec @@ -1 +1,2 @@ ---color +--color --format Fuubar +-r turnip/rspec diff --git a/Gemfile b/Gemfile index 21edcfad..04b07c32 100644 --- a/Gemfile +++ b/Gemfile @@ -57,7 +57,6 @@ gem 'mini_magick' group :development do #gem 'pry-remote' gem 'rspec-rails' - gem 'guard-rspec' gem 'quiet_assets' gem 'letter_opener' gem 'thin' @@ -68,13 +67,12 @@ end group :test do #gem 'steak' gem 'rspec-rails' - gem 'cucumber-rails' - gem 'poltergeist' - gem 'selenium-webdriver' gem 'database_cleaner' + gem 'capybara-webkit' + gem 'turnip' + gem 'launchy' + gem 'fuubar' gem 'rb-fsevent', :require => false #if RUBY_PLATFORM =~ /darwin/i - gem 'ruby_gntp' - gem 'guard-rspec' gem 'factory_girl_rails' gem 'pry-rails' end diff --git a/Gemfile.lock b/Gemfile.lock index d932e9ce..fed6a9c3 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -103,12 +103,12 @@ GEM rack (>= 1.0.0) rack-test (>= 0.5.4) xpath (~> 2.0) - childprocess (0.3.9) - ffi (~> 1.0, >= 1.0.11) + capybara-webkit (1.0.0) + capybara (~> 2.0, >= 2.0.2) + json chunky_png (1.2.8) climate_control (0.0.3) activesupport (>= 3.0) - cliver (0.2.1) cocaine (0.5.1) climate_control (>= 0.0.3, < 1.0) coderay (1.0.9) @@ -130,17 +130,6 @@ GEM mime-types (~> 1.15) multi_json (~> 1.0) rest-client (~> 1.6.1) - cucumber (1.3.8) - builder (>= 2.1.2) - diff-lcs (>= 1.1.3) - gherkin (~> 2.12.1) - multi_json (>= 1.7.5, < 2.0) - multi_test (>= 0.0.2) - cucumber-rails (1.4.0) - capybara (>= 1.1.2) - cucumber (>= 1.2.0) - nokogiri (>= 1.5.0) - rails (>= 3.0.0) daemons (1.1.9) database_cleaner (1.1.1) devise (3.1.0) @@ -194,20 +183,13 @@ GEM faye-websocket (0.7.0) eventmachine (>= 0.12.0) websocket-driver (>= 0.3.0) - ffi (1.9.0) - formatador (0.2.4) fssm (0.2.10) + fuubar (1.1.1) + rspec (~> 2.0) + rspec-instafail (~> 0.2.0) + ruby-progressbar (~> 1.0) gherkin (2.12.1) multi_json (~> 1.3) - guard (1.8.2) - formatador (>= 0.2.4) - listen (>= 1.0.0) - lumberjack (>= 1.0.2) - pry (>= 0.9.10) - thor (>= 0.14.6) - guard-rspec (3.0.3) - guard (>= 1.8) - rspec (~> 2.13) haml (4.0.3) tilt haml-rails (0.4) @@ -236,11 +218,6 @@ GEM addressable (~> 2.3) letter_opener (1.1.2) launchy (~> 2.2) - listen (1.3.1) - rb-fsevent (>= 0.9.3) - rb-inotify (>= 0.9) - rb-kqueue (>= 0.2) - lumberjack (1.0.4) mail (2.5.4) mime-types (~> 1.16) treetop (~> 1.4.8) @@ -250,7 +227,6 @@ GEM subexec (~> 0.2.1) mini_portile (0.5.1) multi_json (1.8.0) - multi_test (0.0.2) nokogiri (1.6.0) mini_portile (~> 0.5.0) paperclip (3.5.1) @@ -258,11 +234,6 @@ GEM activesupport (>= 3.0.0) cocaine (~> 0.5.0) mime-types - poltergeist (1.4.1) - capybara (~> 2.1.0) - cliver (~> 0.2.1) - multi_json (~> 1.0) - websocket-driver (>= 0.2.0) polyglot (0.3.3) pry (0.9.12.2) coderay (~> 1.0.5) @@ -298,10 +269,6 @@ GEM thor (>= 0.14.6, < 2.0) rake (10.1.0) rb-fsevent (0.9.3) - rb-inotify (0.9.2) - ffi (>= 0.5.0) - rb-kqueue (0.2.0) - ffi (>= 0.5.0) rdoc (3.12.2) json (~> 1.4) rest-client (1.6.7) @@ -314,6 +281,7 @@ GEM rspec-core (2.14.5) rspec-expectations (2.14.2) diff-lcs (>= 1.1.3, < 2.0) + rspec-instafail (0.2.4) rspec-mocks (2.14.3) rspec-rails (2.14.0) actionpack (>= 3.0) @@ -322,18 +290,12 @@ GEM rspec-core (~> 2.14.0) rspec-expectations (~> 2.14.0) rspec-mocks (~> 2.14.0) - ruby_gntp (0.3.4) - rubyzip (0.9.9) + ruby-progressbar (1.1.1) sass (3.2.10) sass-rails (3.2.6) railties (~> 3.2.0) sass (>= 3.1.10) tilt (~> 1.3) - selenium-webdriver (2.35.1) - childprocess (>= 0.2.5) - multi_json (~> 1.0) - rubyzip (< 1.0.0) - websocket (~> 1.0.4) simple_form (2.1.0) actionpack (~> 3.0) activemodel (~> 3.0) @@ -366,13 +328,15 @@ GEM treetop (1.4.15) polyglot polyglot (>= 0.3.1) + turnip (1.1.0) + gherkin (>= 2.5) + rspec (~> 2.0) tzinfo (0.3.37) uglifier (2.2.1) execjs (>= 0.3.0) multi_json (~> 1.0, >= 1.0.2) warden (1.2.3) rack (>= 1.0) - websocket (1.0.7) websocket-driver (0.3.0) xpath (2.0.0) nokogiri (~> 1.3) @@ -385,11 +349,11 @@ DEPENDENCIES active_decorator bootstrap-sass bourbon + capybara-webkit cmtool! coffee-rails (~> 3.2.1) compass-rails couch_potato! - cucumber-rails database_cleaner devise (= 3.1.0) devise_simply_stored! @@ -398,15 +362,15 @@ DEPENDENCIES emblem-rails factory_girl_rails faye - guard-rspec + fuubar jquery-rails jquery-ui-rails js-routes kaminari + launchy letter_opener mini_magick orm_adapter! - poltergeist pry-rails quiet_assets rack-cors @@ -414,11 +378,10 @@ DEPENDENCIES rb-fsevent rqrcode rspec-rails - ruby_gntp sass-rails (~> 3.2.3) - selenium-webdriver simple_form simply_stored! slim-rails thin + turnip uglifier (>= 1.0.3) diff --git a/app/assets/javascripts/supplier/app/controllers/index_controller.js.coffee b/app/assets/javascripts/supplier/app/controllers/index_controller.js.coffee index c6ae6ded..af559ef3 100644 --- a/app/assets/javascripts/supplier/app/controllers/index_controller.js.coffee +++ b/app/assets/javascripts/supplier/app/controllers/index_controller.js.coffee @@ -17,6 +17,7 @@ Qsupplier.App.IndexController = Ember.ObjectController.extend list = Qsupplier.App.List.find(id) list.set('needs_help', false) $.post '/supplier/mark_list_as_helped', {list_id: id} + closeList: (id)-> list = Qsupplier.App.List.find(id) list.set('state', 'closed') diff --git a/app/assets/javascripts/supplier/app/models/list.js.coffee b/app/assets/javascripts/supplier/app/models/list.js.coffee index 6a59c0d3..ee02b33c 100644 --- a/app/assets/javascripts/supplier/app/models/list.js.coffee +++ b/app/assets/javascripts/supplier/app/models/list.js.coffee @@ -11,3 +11,8 @@ Qsupplier.App.List = DS.Model.extend orders: DS.hasMany('Qsupplier.App.Order') section: DS.belongsTo('Qsupplier.App.Section') section_id: attr('string') + close: -> + @get('orders').forEach (order)-> + order.close() + @set('table', null) + @list.set('state', 'closed') diff --git a/app/assets/javascripts/supplier/app/models/order.js.coffee b/app/assets/javascripts/supplier/app/models/order.js.coffee index 4918c392..b8f84f30 100644 --- a/app/assets/javascripts/supplier/app/models/order.js.coffee +++ b/app/assets/javascripts/supplier/app/models/order.js.coffee @@ -2,7 +2,7 @@ attr = DS.attr Qsupplier.App.Order = DS.Model.extend state: attr('string') list: DS.belongsTo('Qsupplier.App.List') - total_amount: attr('number') + price: attr('number') product_orders: attr('object') section: DS.belongsTo('Qsupplier.App.Section') section_id: attr('string') @@ -13,5 +13,9 @@ Qsupplier.App.Order = DS.Model.extend needs_supplier_attention: (-> @get('state') == 'placed' || @get('state') == 'active').property('state') display: (-> + return '' unless @get('product_orders') @get('product_orders').map((po)-> "#{po.product_name} (#{po.quantity})").join(',') ).property('product_orders') + + close: -> + @set('state', 'closed') diff --git a/app/assets/javascripts/supplier/app/modifications/model_extensions.js.coffee b/app/assets/javascripts/supplier/app/modifications/model_extensions.js.coffee index d4b39678..c9f02432 100644 --- a/app/assets/javascripts/supplier/app/modifications/model_extensions.js.coffee +++ b/app/assets/javascripts/supplier/app/modifications/model_extensions.js.coffee @@ -3,9 +3,25 @@ DS.Model.reopen updated_at: DS.attr('string') DS.Model.reopenClass findCached: (id)-> + return null unless id @all().findProperty('id', id) - updateOrCreate: (attributes)-> + updateOrAdd: (attributes)-> if cached = @findCached(attributes.id) cached.setProperties attributes else - @createRecord(attributes) + @find(attributes.id) + pushByAttriburtes: (attributes)-> + #store = @all().get('store') + + #Ugly hack at the cost of an extra request since I do not yet know the proper + #code for adding a record by its attributes and having its associations set + #@find(attributes.id) + + Ember.get(@, 'relationships').forEach (model, relation)-> + relation = relation[0] + if relation.kind == 'belongsTo' and attributes["#{relation.name}_id"] + attributes[relation.name] = model.find(attributes["#{relation.name}_id"]) + delete attributes["#{relation.name}_id"] + + #store.push @, attributes + @createRecord attributes diff --git a/app/assets/javascripts/supplier/app/router.js.coffee b/app/assets/javascripts/supplier/app/router.js.coffee index 7263149a..5e22a576 100644 --- a/app/assets/javascripts/supplier/app/router.js.coffee +++ b/app/assets/javascripts/supplier/app/router.js.coffee @@ -1,4 +1,5 @@ # For more information see: http://emberjs.com/guides/routing/ +# and for queryParams: https://github.com/alexspeller/website/blob/a96d9afe4506454b155cc64299e86e558ce3c9f1/source/guides/routing/query-params.md Qsupplier.App.Router.reopen location: 'history' rootURL: '/supplier' @@ -6,4 +7,4 @@ Qsupplier.App.Router.reopen Qsupplier.App.Router.map -> @resource 'sections', -> @resource 'section', path: ':section_id' - + @resource 'lists', queryParams: ['state'] diff --git a/app/assets/javascripts/supplier/app/routes/index_route.js.coffee b/app/assets/javascripts/supplier/app/routes/index_route.js.coffee index 2c9edc42..85f76f6d 100644 --- a/app/assets/javascripts/supplier/app/routes/index_route.js.coffee +++ b/app/assets/javascripts/supplier/app/routes/index_route.js.coffee @@ -1,11 +1,20 @@ Qsupplier.App.IndexRoute = Ember.Route.extend - model: -> + model: (params, queryParams)-> + # Preload only active lists and orders + @store.find 'list', state: 'active' + @store.find 'order', state: 'active' Ember.Object.create - lists: Qsupplier.App.List.find({state: 'active'}) - orders: Qsupplier.App.Order.find() + # Find with condition does not work since the resulting array promise is not updated for newly created records + #lists: Qsupplier.App.List.find({state: 'active'}) + #orders: Qsupplier.App.Order.find({state: 'active'}) + #lists: @store.filter 'list', (l)-> l.get('state') == 'active' # DOES NOT WORK!!!! (yet) + # use filter to create a scope on all the records + lists: Qsupplier.App.List.filter -> true + orders: Qsupplier.App.Order.filter -> true setupController: (controller, model)-> controller.set('model', model) $('#section_selector').on 'change', (-> controller.set('sectionId', $(this).val())) + #controller.set 'lists', @store.all('list') #controller.set 'lists', Qsupplier.App.List.all() #.filterProperty('state', 'active') #controller.set 'orders', Qsupplier.App.Order.all() #controller.set 'lists', model.get('lists') diff --git a/app/assets/javascripts/supplier/app/store.js.coffee b/app/assets/javascripts/supplier/app/store.js.coffee index a295d7bc..7731d046 100644 --- a/app/assets/javascripts/supplier/app/store.js.coffee +++ b/app/assets/javascripts/supplier/app/store.js.coffee @@ -1,7 +1,7 @@ # http://emberjs.com/guides/models/defining-a-store/ Qsupplier.App.Store = DS.Store.extend - revision: 11 + revision: 13 adapter: DS.RESTAdapter.create namespace: 'supplier' diff --git a/app/assets/javascripts/supplier/app/templates/active_list.emblem b/app/assets/javascripts/supplier/app/templates/active_list.emblem index bc6c09b3..af9184e3 100644 --- a/app/assets/javascripts/supplier/app/templates/active_list.emblem +++ b/app/assets/javascripts/supplier/app/templates/active_list.emblem @@ -4,11 +4,11 @@ td.list-status if view.content.needs_payment span.list-needs-payment-indicator € td.numeric.table_number {{view.content.table_number}} -td.section_title {{view.content.section_title}} -td.currency.total_list_amount {{currency total_amount}} +td.section_title {{view.content.section.title}} +td.currency.total_list_amount {{currency view.content.price}} td.actions if view.content.needs_help - button.btn.btn-info{ action markListAsHelped view.content.id} {{t 'list.is_helped_button'}} - button.btn.btn-warning{ action closeList view.content.id} {{t 'list.close_list' }} + button.btn.btn-info.mark_list_as_helped{ action markListAsHelped view.content.id} {{t 'list.is_helped_button'}} + button.btn.btn-warning.close_list{ action closeList view.content.id} {{t 'list.close_list' }} a.btn href="/supplier/lists/{{unbound view.content.id}}" span.icon-list   diff --git a/app/assets/javascripts/supplier/app/templates/active_order.emblem b/app/assets/javascripts/supplier/app/templates/active_order.emblem index 2f8afabf..015638ac 100644 --- a/app/assets/javascripts/supplier/app/templates/active_order.emblem +++ b/app/assets/javascripts/supplier/app/templates/active_order.emblem @@ -1,7 +1,7 @@ td {{view.content.display}} -td.numeric.table_number {{view.content.table_number}} -td.section_title {{view.content.section_title}} -td.currency {{currency view.content.total_amount}} +td.numeric.table_number {{view.content.list.table.number}} +td.section_title {{view.content.section.title}} +td.currency {{currency view.content.price }} td.actions if view.content.placed button.btn.btn-success{ action markOrderActive view.content.id} {{t 'order.being_processed'}} diff --git a/app/assets/javascripts/supplier/app/templates/section.emblem b/app/assets/javascripts/supplier/app/templates/section.emblem index b35e01dd..b4968039 100644 --- a/app/assets/javascripts/supplier/app/templates/section.emblem +++ b/app/assets/javascripts/supplier/app/templates/section.emblem @@ -17,7 +17,7 @@ view Ember.TextField valueBinding="width" classNames="dimension" span x view Ember.TextField valueBinding="height" classNames="dimension" - a.btn.btn-mini{ action finishEditable} + a.btn.btn-mini{ action finishEditable } span.icon-ok else a.btn.btn-mini{ action makeEditable } diff --git a/app/assets/javascripts/supplier/app/views/active_list_view.js.coffee b/app/assets/javascripts/supplier/app/views/active_list_view.js.coffee index 6e5e900e..38c69d69 100644 --- a/app/assets/javascripts/supplier/app/views/active_list_view.js.coffee +++ b/app/assets/javascripts/supplier/app/views/active_list_view.js.coffee @@ -1,3 +1,5 @@ Qsupplier.App.ActiveListView = Ember.View.extend tagName: 'tr' templateName: 'active_list' + classNameBindings: ['classIdentifier'] + classIdentifier: (-> "list-row-#{@get('content.id')}").property() diff --git a/app/assets/javascripts/supplier/app/views/active_order_view.js.coffee b/app/assets/javascripts/supplier/app/views/active_order_view.js.coffee index ad25dc30..aed7accd 100644 --- a/app/assets/javascripts/supplier/app/views/active_order_view.js.coffee +++ b/app/assets/javascripts/supplier/app/views/active_order_view.js.coffee @@ -1,4 +1,5 @@ Qsupplier.App.ActiveOrderView = Ember.View.extend tagName: 'tr' templateName: 'active_order' - classNameBindings: ['content.active:active', 'content.delivered:delivered'] + classNameBindings: ['content.active:active', 'content.delivered:delivered', 'classIdentifier'] + classIdentifier: (-> "order-row-#{@get('content.id')}").property() diff --git a/app/assets/javascripts/supplier/qsupplier.js.coffee b/app/assets/javascripts/supplier/qsupplier.js.coffee index c3f154ba..304bfa37 100644 --- a/app/assets/javascripts/supplier/qsupplier.js.coffee +++ b/app/assets/javascripts/supplier/qsupplier.js.coffee @@ -4,7 +4,7 @@ root.Qsupplier= faye = new Faye.Client(event_host) faye.subscribe "/supplier/"+supplier_id, (e)=> if(e.event == 'new_order') - Qsupplier.App.Order.create(e.data.order) + Qsupplier.App.Order.pushByAttriburtes(e.data.order) if Qsupplier.App # old stuff body = $('#active-orders-table tbody') order = new Order(e.data.order) @@ -12,14 +12,14 @@ root.Qsupplier= body.append @mustache('#active-order-template', order) $('.section-table-list-'+order.list_id()).addClass('active_order') else if(e.event == 'list_needs_help') - if list = Qsupplier.App.List.findCached(e.data.id) + if Qsupplier.App and list = Qsupplier.App.List.findCached(e.data.id) list.set('needs_help', true) # old stuff $('#list-needs-help-indicator-'+e.data.id).removeClass('hide') $('#list-is-helped-button-'+e.data.id).removeClass('hide') $('.section-table-list-'+e.data.id).addClass('needs_help') else if(e.event == 'list_needs_payment') - if list = Qsupplier.App.List.findCached(e.data.id) + if Qsupplier.App and list = Qsupplier.App.List.findCached(e.data.id) list.set('needs_payment', true) # old stuff $('#list-needs-payment-indicator-'+e.data.id).removeClass('hide') @@ -28,10 +28,10 @@ root.Qsupplier= if list = Qsupplier.App.List.findCached(e.data.id) list.set('needs_payment', false) else if e.event == 'list_update' - Qsupplier.App.List.updateOrCreate(e.data.list) + Qsupplier.App.List.updateOrAdd(e.data.list) if Qsupplier.App # old stuff list = new List(e.data.list) - row = $('#list-row-'+list.id()) + row = $('#active-lists-table .list-row-'+list.id()) content = @mustache('#active-list-template', list) if row.length then row.replaceWith(content) else $('#active-lists-table tbody').append(content) table = $('#section-table-'+list.table_id()) @@ -42,15 +42,14 @@ root.Qsupplier= table.addClass('needs_payment') if list.needs_payment() table.addClass('active_order') if list.has_active_orders() else if e.event == 'list_closed' - if list = Qsupplier.App.List.findCached(e.data.id) - list.set('table', null) - list.set('state', 'closed') - $('#list-row-'+e.data.id).remove() + if Qsupplier.App and list = Qsupplier.App.List.findCached(e.data.id) + list.close() + $('.list-row-'+e.data.id).remove() $('.of-list-'+e.data.id).remove() table_list_class = 'section-table-list-'+e.data.id $('.'+table_list_class).removeClass('occupied needs_help needs_payment active_order').removeClass(table_list_class) else if e.event == 'list_helped' - if list = Qsupplier.App.List.findCached(e.data.id) + if Qsupplier.App and list = Qsupplier.App.List.findCached(e.data.id) list.set('needs_help', false) list_id = e.data.id $('#list-needs-help-indicator-'+list_id).addClass('hide') @@ -58,13 +57,13 @@ root.Qsupplier= $('.section-table-list-'+list_id).removeClass('needs_help') else if e.event == 'order_being_processed' $('#order-in-process-button-'+e.data.id).hide() - $('#order-row-'+e.data.id).removeClass('placed').addClass('active') + $('.order-row-'+e.data.id).removeClass('placed').addClass('active') else if e.event == 'order_being_delivered' - $('#order-row-'+e.data.id).remove() + $('.order-row-'+e.data.id).remove() $('.section-table-list-'+e.data.list_id).removeClass('active_order') else if e.event == 'list_changed_table' list = new List(e.data.list) - list_row = $('#list-row-'+list.id()) + list_row = $('.list-row-'+list.id()) list_row.find('.table_number').text(list.table_number()).addClass('changed') list_row.find('.section_title').text(e.data.section_title) order_rows = $('.of-list-'+list.id()) diff --git a/app/assets/javascripts/user/quser.js.coffee b/app/assets/javascripts/user/quser.js.coffee index 6d16ce09..736f1470 100644 --- a/app/assets/javascripts/user/quser.js.coffee +++ b/app/assets/javascripts/user/quser.js.coffee @@ -23,9 +23,9 @@ class Quser window.active_list.needs_help = false @list_needs_help_default_action() else if(e.event == 'order_being_processed') - $('#order-row-'+e.data.id).addClass('active') + $('.order-row-'+e.data.id).addClass('active') else if(e.event == 'order_being_delivered') - $('#order-row-'+e.data.id).addClass('delivered') + $('.order-row-'+e.data.id).addClass('delivered') else if(e.event == 'list_changed_table') list = new List(e.data.list) $('.table-number').text(list.table_number()) diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 0355ac8f..4d7a5fc3 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -24,7 +24,7 @@ private end def set_locale - I18n.locale = (params[:locale].presence || :nl).to_sym + I18n.locale = (params[:locale].presence || Rails.configuration.i18n.default_locale).to_sym end def layout_by_resource diff --git a/app/controllers/supplier_controller.rb b/app/controllers/supplier_controller.rb index b3e0269a..f5400d8a 100644 --- a/app/controllers/supplier_controller.rb +++ b/app/controllers/supplier_controller.rb @@ -43,8 +43,8 @@ class SupplierController < ApplicationController ho = {products: []} order_total = 0.0 for product_order in order.product_orders - order_total += (product_order.amount * product_order.price).round(2) - ho[:products] << {name: product_order.product.name, id: product_order.product_id, number: product_order.amount, price: product_order.price} + order_total += (product_order.quantity * product_order.price).round(2) + ho[:products] << {name: product_order.product.name, id: product_order.product_id, number: product_order.quantity, price: product_order.price} end ho[:total_amount] = order_total.round(2) ho[:state] = order.state diff --git a/app/controllers/suppliers/lists_controller.rb b/app/controllers/suppliers/lists_controller.rb index 86eeb131..ece21593 100644 --- a/app/controllers/suppliers/lists_controller.rb +++ b/app/controllers/suppliers/lists_controller.rb @@ -33,7 +33,7 @@ module Suppliers respond_to do |format| format.html {} format.json do - render json: {list: @list.with_orders_as_json} + render json: @list end end end diff --git a/app/controllers/suppliers/orders_controller.rb b/app/controllers/suppliers/orders_controller.rb index 18c86b11..5066246e 100644 --- a/app/controllers/suppliers/orders_controller.rb +++ b/app/controllers/suppliers/orders_controller.rb @@ -6,12 +6,19 @@ module Suppliers if params[:state] == 'active' @orders = Order.active_for_supplier(current_supplier.id) else - @orders = Order.for_supplier(current_supplier, page: params[:page], per_page: params['per_page'] || 10) + @orders = Order.for_supplier(current_supplier, page: params[:page], per_page: params['per_page'] || 25) end respond_to do |format| format.html # index.html.erb - format.json { render json: {orders: @orders.map(&:with_products_as_json)} } + format.json { render json: @orders } + end + end + + def show + @order = current_supplier.find_order(params[:id]) + respond_to do |format| + format.json { render json: @order } end end end diff --git a/app/models/list.rb b/app/models/list.rb index 2f6bd201..24675db5 100644 --- a/app/models/list.rb +++ b/app/models/list.rb @@ -243,12 +243,13 @@ class List end end + # Store the final list price in a property def set_price list_total = 0.0 for order in orders order_total = 0.0 for product_order in order.product_orders - order_total += (product_order.amount * product_order.price).round(2) + order_total += (product_order.quantity * product_order.price).round(2) end list_total += order_total.round(2) end @@ -269,23 +270,23 @@ class List order = Order.create list: self, supplier: supplier, user: user, section_id: section_id return unless order.id loaded_products = self.class.database.load_document products.keys - products.each do |product_id, number| - number = number.to_i + products.each do |product_id, quantity| + quantity = quantity.to_i product = loaded_products.find{|p| p.id == product_id} # to get the price - ProductOrder.create order: order, product_id: product_id, amount: number, price: product.price if number > 0 + ProductOrder.create order: order, product_id: product_id, quantity: quantity, price: product.price if quantity > 0 end set_price save for user_id in user_ids broadcast_user user_id, 'new_order', order: order.with_products_as_json, total_amount: price end - broadcast_supplier supplier.id, 'list_update', list: with_info_as_json + broadcast_supplier supplier.id, 'list_update', active_model_serializer.new(self).as_json broadcast_supplier supplier.id, 'new_order', order: order.with_products_as_json order end def as_json(*args) - super.merge(table_number: table_number, has_active_orders: has_active_orders? ) + super.merge(id: id, table_number: table_number, has_active_orders: has_active_orders? ) end def with_orders_as_json @@ -301,8 +302,8 @@ class List ho[:state] = order.state order_total = 0.0 for product_order in order.product_orders - order_total += (product_order.amount * product_order.price).round(2) - ho[:products] << {name: product_order.product_name, id: product_order.product_id, number: product_order.amount, price: product_order.price} + order_total += (product_order.quantity * product_order.price).round(2) + ho[:products] << {name: product_order.product_name, id: product_order.product_id, number: product_order.quantity, price: product_order.price} end ho[:total_amount] = order_total.round(2) ho[:state] = order.state @@ -343,7 +344,7 @@ class List def with_info_as_json return @with_info_as_json if @with_info_as_json.present? hl = as_json - hl[:total_amount] = orders.inject(0.0){|sum, o| sum + o.product_orders.inject(0.0){|s, po| s + (po.amount * po.price).round(2)}}.round(2) + hl[:total_amount] = orders.inject(0.0){|sum, o| sum + o.product_orders.inject(0.0){|s, po| s + (po.quantity * po.price).round(2)}}.round(2) hl[:section_title] = table.section.try(:title) @with_info_as_json = hl end diff --git a/app/models/order.rb b/app/models/order.rb index a5a10d9d..ccf54fd2 100644 --- a/app/models/order.rb +++ b/app/models/order.rb @@ -1,5 +1,6 @@ class Order include SimplyStored::Couch + include ActiveModel::SerializerSupport property :state, default: 'placed' # placed, active, delivered, cancelled, closed @@ -115,9 +116,9 @@ class Order ho[:product_orders] = [] order_total = 0.0 for product_order in product_orders - order_total += (product_order.amount * product_order.price).round(2) - ho[:products] << {name: product_order.product.name, id: product_order.product_id, number: product_order.amount, price: product_order.price} - ho[:product_orders] << {product_name: product_order.product.name, id: product_order.id, quantity: product_order.amount, price: product_order.price} + order_total += (product_order.quantity * product_order.price).round(2) + ho[:products] << {name: product_order.product.name, id: product_order.product_id, number: product_order.quantity, price: product_order.price} + ho[:product_orders] << {product_name: product_order.product.name, id: product_order.id, quantity: product_order.quantity, price: product_order.price} end ho[:total_amount] = order_total.round(2) @with_products_as_json = ho diff --git a/app/models/product_order.rb b/app/models/product_order.rb index ad4ac49f..aa2ac828 100644 --- a/app/models/product_order.rb +++ b/app/models/product_order.rb @@ -1,7 +1,7 @@ class ProductOrder include SimplyStored::Couch - property :amount, type: Fixnum + property :quantity, type: Fixnum property :price, type: Float belongs_to :product diff --git a/app/models/supplier.rb b/app/models/supplier.rb index 642ee210..a069e679 100644 --- a/app/models/supplier.rb +++ b/app/models/supplier.rb @@ -11,7 +11,7 @@ class Supplier #LOCATION property :lat, type: Float, default: 52.08062426379751 property :lng, type: Float, default: 4.312562942504883 - + #WIFI property :offer_wifi property :wifi_ssid @@ -112,6 +112,12 @@ class Supplier self.devise_mailer.confirmation_instructions(self).deliver end + def find_order(id) + order = Order.find(id) + raise SimplyStored::RecordNotFound unless order.supplier_id == self.id + order + end + def send_creation_notifications SupplierMailer.creation(self).deliver end diff --git a/app/models/user.rb b/app/models/user.rb index 393c83e4..5e7b37dc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,6 +7,8 @@ class User devise :database_authenticatable, :recoverable, :rememberable, :trackable, :token_authenticatable # , :registerable + property :authentication_token + has_and_belongs_to_many :lists, storing_keys: false has_many :orders diff --git a/app/serializers/order_serializer.rb b/app/serializers/order_serializer.rb index 866aadd9..6846d9ac 100644 --- a/app/serializers/order_serializer.rb +++ b/app/serializers/order_serializer.rb @@ -1,4 +1,14 @@ class OrderSerializer < Qwaiter::Serializer embed :ids - attributes :state, :list_id, :section_id + attributes :state, :list_id, :section_id, :product_orders, :price + + def product_orders + @product_orders ||= object.product_orders.include_relation(:product) .map do |product_order| + {product_name: product_order.product.name, id: product_order.id, quantity: product_order.quantity, price: product_order.price} + end + end + + def price + product_orders.inject(0){|sum, po| sum + po[:quantity] * po[:price]}.round(2) + end end diff --git a/app/templates/supplier/_active_list.mustache b/app/templates/supplier/_active_list.mustache index d29c5560..974d3570 100644 --- a/app/templates/supplier/_active_list.mustache +++ b/app/templates/supplier/_active_list.mustache @@ -1,4 +1,4 @@ - + ? diff --git a/app/templates/supplier/_active_order.mustache b/app/templates/supplier/_active_order.mustache index 5a69092b..56c07d08 100644 --- a/app/templates/supplier/_active_order.mustache +++ b/app/templates/supplier/_active_order.mustache @@ -1,4 +1,4 @@ - + {{display}} {{table_number}} {{section_title}} diff --git a/app/templates/supplier/_list_order.mustache b/app/templates/supplier/_list_order.mustache index 42e72ea4..d6c76b03 100644 --- a/app/templates/supplier/_list_order.mustache +++ b/app/templates/supplier/_list_order.mustache @@ -1,4 +1,4 @@ - + {{display}} {{#currency}}{{total_amount}}{{/currency}} diff --git a/app/templates/user/_active_list_order.mustache b/app/templates/user/_active_list_order.mustache index 42e72ea4..d6c76b03 100644 --- a/app/templates/user/_active_list_order.mustache +++ b/app/templates/user/_active_list_order.mustache @@ -1,4 +1,4 @@ - + {{display}} {{#currency}}{{total_amount}}{{/currency}} diff --git a/app/views/supplier/home.html.slim b/app/views/supplier/home.html.slim index 2bc675d8..985103b0 100644 --- a/app/views/supplier/home.html.slim +++ b/app/views/supplier/home.html.slim @@ -1,8 +1,8 @@ .pull-right = select_tag('current_section_selector', options_for_select([[current_supplier.name, '']] + current_supplier.sections.map{|s| ["- #{s.title}", s.id]}, params[:section_id]), id: :section_selector) a.icon-arrow-right.go-to-tables-view.hide href=tables_view_suppliers_section_path('0000') -= render template: 'supplier/active_lists' -= render template: 'supplier/active_orders' +/= render template: 'supplier/active_lists' +/= render template: 'supplier/active_orders' - content_for :footer do javascript: $(function(){ diff --git a/spec/acceptance/suppliers/supplier_main_board.feature b/spec/acceptance/suppliers/supplier_main_board.feature new file mode 100644 index 00000000..36fafaa8 --- /dev/null +++ b/spec/acceptance/suppliers/supplier_main_board.feature @@ -0,0 +1,47 @@ +Feature: Supplier main board + + @javascript + Scenario: the active list should be present and contained in row having its id + Given there is an active list and order + And I am signed in as supplier + + When I visit the supplier root path + Then the supplier dashboard should display the active list + And the supplier dashboard should display the active order + + When I click on translation 'supplier.order.being_processed' + # waiting here only needed in old style implementation + And I wait 1 second + Then the supplier order row should be marked as active + + When I click on translation 'supplier.order.being_served' + And I wait 1 second + Then the order in the supplier dashboard should not be displayed anymore + And the order should be marked as delivered + + And the list on the supplier dashboard should not be marked as in need of help + When the list is marked as in need of help + # waiting here only needed in old style implementation + And I wait 1 second + Then the list on the supplier dashboard should be marked as in need of help + + When I click on the mark list as helped button in the supplier dashboard + Then the list on the supplier dashboard should not be marked as in need of help + + When the list is marked as in need of payment + Then the list on the supplier dashboard should be marked as in need of payment + + When another order is placed + Then the supplier dashboard list should display the updated price + And the new order should be present in the supplier dashboard + + When a new order on a table in another section is created + And I wait 1 second + Then the new list should appear in the supplier dashboard + And the new order on a table in another section should be present in the supplier dashboard + + When I click on the close list button in the supplier dashboard + And I wait 1 second + Then the list in the supplier dashboard should not be displayed anymore + And the list should be marked as closed + diff --git a/spec/acceptance_steps/global_steps.rb b/spec/acceptance_steps/global_steps.rb new file mode 100644 index 00000000..49ada761 --- /dev/null +++ b/spec/acceptance_steps/global_steps.rb @@ -0,0 +1,13 @@ +step "there is a fresh database with a user and supplier" do + CouchPotato.couchrest_database.recreate! + create_confirmed_supplier 'supplier@qwaiter.com' + create_user 'user@qwaiter.com' +end + +step "I click on translation :translation" do |translation_key| + text = I18n.t(translation_key) + click_on text +end +step "I wait :number second/seconds" do |number| + sleep number.to_f +end diff --git a/spec/acceptance_steps/list_steps.rb b/spec/acceptance_steps/list_steps.rb new file mode 100644 index 00000000..3c22bc1f --- /dev/null +++ b/spec/acceptance_steps/list_steps.rb @@ -0,0 +1,20 @@ +step "the list is marked as in need of help" do + @list.needs_help.should_not be_true + @list.needs_help! +end + +step "the list is marked as in need of payment" do + @list.needs_payment! +end + +step "the list should be marked as closed" do + @list.reload + @list.state.should == 'closed' +end + +step 'a new order on a table in another section is created' do + @new_section = create :section, title: 'Terrace', supplier: @supplier + @new_table = create :table, number: 59, section: @new_section, supplier: @supplier + @new_list = create :list, section: @new_section, table: @new_table, supplier: @supplier, user_ids: [@user.id] + @new_order = @new_list.place_order @user, {@product.id => 3} +end diff --git a/spec/acceptance_steps/order_steps.rb b/spec/acceptance_steps/order_steps.rb new file mode 100644 index 00000000..359ce9a0 --- /dev/null +++ b/spec/acceptance_steps/order_steps.rb @@ -0,0 +1,13 @@ +step "the order should be closed" do + @order.reload + @order.state.should == 'closed' +end + +step "the order should be marked as delivered" do + @order.reload + @order.state.should == 'delivered' +end + +step "another order is placed" do + @new_order = @list.place_order @user, {@product.id => 5} +end diff --git a/spec/acceptance_steps/suppliers/authentication_steps.rb b/spec/acceptance_steps/suppliers/authentication_steps.rb new file mode 100644 index 00000000..56756fb7 --- /dev/null +++ b/spec/acceptance_steps/suppliers/authentication_steps.rb @@ -0,0 +1,6 @@ +step "I am signed in as supplier" do + step 'visit the supplier sign in path' + find('#supplier_email').set @supplier.email + find('#supplier_password').set @supplier_password + click_on 'Inloggen' +end diff --git a/spec/acceptance_steps/suppliers/existance_steps.rb b/spec/acceptance_steps/suppliers/existance_steps.rb new file mode 100644 index 00000000..a97f8341 --- /dev/null +++ b/spec/acceptance_steps/suppliers/existance_steps.rb @@ -0,0 +1,5 @@ +step 'there is a confirmed and open supplier' do + @supplier_password = 'secret1' + @supplier = create :supplier, email: 'supplier@qwaiter.com', password: @supplier_password, confirmation_token: 'abc', confirmed_at: Time.now.utc, open: true + @section = create :section, title: 'Room', supplier: @supplier +end diff --git a/spec/acceptance_steps/suppliers/main_board_steps.rb b/spec/acceptance_steps/suppliers/main_board_steps.rb new file mode 100644 index 00000000..e35dea8f --- /dev/null +++ b/spec/acceptance_steps/suppliers/main_board_steps.rb @@ -0,0 +1,83 @@ +step "there is an active list and order" do + @user ||= create :user + step 'there is a confirmed and open supplier' + @table = create :table, supplier: @supplier, section: @section + @section.should be_present + @list = create :list, state: 'active', supplier: @supplier, table: @table, section: @section, user_ids: [@user.id] + @product = create :product, price: 2.22, supplier: @supplier + @order = create :order, user: @user, list: @list, supplier: @supplier, section: @section + @product_order = create :product_order, order: @order, product: @product, quantity: 3, price: 2.11 +end + +step "the supplier dashboard should display the active list" do + el = find(".list-row-#{@list.id}") + el['class'].should_not =~ /active/ +end + +step "the list in the supplier dashboard should not be displayed anymore" do + page.should_not have_selector(".list-row-#{@list.id}") +end + +step "the supplier dashboard should display the active order" do + el = find(".order-row-#{@order.id}") + el['class'].should_not =~ /active/ +end +step "the supplier order row should be marked as active" do + el = find(".order-row-#{@order.id}") + el['class'].should =~ /active/ +end + +step "the order in the supplier dashboard should not be displayed anymore" do + page.should_not have_selector(".order-row-#{@order.id}") +end + +step "the list on the supplier dashboard should not be marked as in need of help" do + page.should_not have_selector(".list-row-#{@list.id} .list-needs-help-indicator") +end + +step "the list on the supplier dashboard should be marked as in need of help" do + page.should have_selector(".list-row-#{@list.id} .list-needs-help-indicator") +end + +step "the list on the supplier dashboard should not be marked as in need of payment" do + page.should_not have_selector(".list-row-#{@list.id} .list-needs-payment-indicator") +end + +step "the list on the supplier dashboard should be marked as in need of payment" do + page.should have_selector(".list-row-#{@list.id} .list-needs-payment-indicator") +end + +step "the supplier dashboard list should display the updated price" do + el = find(".list-row-#{@list.id} .total_list_amount") + # original order is 3 * 2.11 = 6.33 + # new order price = 5 * 2.22 = 11.10 + # therefore the updated price should be 17.43 + el.text.should =~ /17.43/ +end + +step "the new order should be present in the supplier dashboard" do + el = find(".order-row-#{@new_order.id}") + el.find('.table_number').text.should == @table.number.to_s + el.find('.section_title').text.should == @section.title +end + +step "the new order on a table in another section should be present in the supplier dashboard" do + el = find(".order-row-#{@new_order.id}") + el.find('.table_number').text.should == @new_table.number.to_s + el.find('.section_title').text.should == @new_section.title +end + +step "the new list should appear in the supplier dashboard" do + el = find(".list-row-#{@new_list.id}") + el.find('.total_list_amount').text.should =~ /6.66/ + el.find('.section_title').text.should == 'Terrace' + el.find('.table_number').text.should == @new_table.number.to_s +end + +step "I click on the close list button in the supplier dashboard" do + find(".list-row-#{@list.id} .close_list").click +end + +step "I click on the mark list as helped button in the supplier dashboard" do + find(".list-row-#{@list.id} .mark_list_as_helped").click +end diff --git a/spec/acceptance_steps/suppliers/navigation_steps.rb b/spec/acceptance_steps/suppliers/navigation_steps.rb new file mode 100644 index 00000000..f69350d7 --- /dev/null +++ b/spec/acceptance_steps/suppliers/navigation_steps.rb @@ -0,0 +1,7 @@ +step 'visit the supplier sign in path' do + visit '/suppliers/sign_in' +end + +step "I visit the supplier root path" do + visit '/supplier' unless page.current_path == '/supplier' +end diff --git a/spec/factories/product_order_factory.rb b/spec/factories/product_order_factory.rb new file mode 100644 index 00000000..1b2b06bb --- /dev/null +++ b/spec/factories/product_order_factory.rb @@ -0,0 +1,6 @@ +FactoryGirl.define do + factory :product_order do + association :order + association :product + end +end diff --git a/spec/features/suppliers/product_categories_spec.rb b/spec/features/suppliers/product_categories_spec.rb deleted file mode 100644 index 40f4e815..00000000 --- a/spec/features/suppliers/product_categories_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -require 'spec_helper' -feature 'Supplier product categories spec', %q{ - In order to manage product categories - As a confirmed supplier - I want to have control over product categories and associated products -} do - background do - create_confirmed_supplier 'supplier@qwaiter.com' - end - context "GET #index" do - background do - @product_category = create :product_category, supplier: @supplier - end - scenario "I can see a drag handle having class .handle for sorting the product categories" do - login_supplier_as 'supplier@qwaiter.com' - visit '/supplier/product_categories' - page.should have_selector '.handle' - end - end -end diff --git a/spec/models/list_spec.rb b/spec/models/list_spec.rb index 6062f953..8dac2652 100644 --- a/spec/models/list_spec.rb +++ b/spec/models/list_spec.rb @@ -3,10 +3,15 @@ require 'spec_helper' describe List do let(:supplier) { create :supplier } + let(:supplier_password){'secret1'} + let(:supplier) { create :supplier, email: 'supplier@qwaiter.com', password: supplier_password, confirmation_token: 'abc', confirmed_at: Time.now.utc, open: true } let(:user) { create :user } let(:section) { create :section, supplier: supplier} let(:table) { create :table, supplier: supplier} - let(:list){ create :list, supplier: supplier, table: table, user_ids: [user.id] } + let(:list){ create :list, supplier: supplier, table: table, section: section, user_ids: [user.id] } + let(:product){ create :product, price: 2.22, supplier: supplier } + let(:order) { create :order, user: user, list: list, supplier: supplier, section: section } + let(:product_order ){ create :product_order, order: order, product: product, quantity: 3, price: 2.11 } subject { list } describe :as_json do it 'should include _id in as_json serialization' do @@ -17,16 +22,22 @@ describe List do end end - describe :mark_as_payed do - it "should set payed_at to a time" do - list.payed_at.should be_nil - list.mark_as_payed - list.payed_at.should be_kind_of Time + describe :mark_as_paid do + it "should set paid_at to a time" do + list.paid_at.should be_nil + list.is_paid! + list.paid_at.should be_kind_of Time end - it "should set is_payed to true" do - list.is_payed.should be_false - list.mark_as_payed - list.is_payed.should be_true + it "should set is_paid to true" do + list.is_paid.should be_false + list.is_paid! + list.is_paid.should be_true + end + end + + describe '#set_price' do + it 'takes the product_order price in stead of the product price' do + product_order and list.set_price.should == 6.33 end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 5c630366..09b286e8 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -2,16 +2,19 @@ ENV["RAILS_ENV"] ||= 'test' require File.expand_path("../../config/environment", __FILE__) require 'rspec/rails' -require 'rspec/autorun' +require 'rspec/matchers' +require 'capybara/rspec' +require 'turnip/capybara' # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} #Dir[Rails.root.join("spec/factories/**/*.rb")].each {|f| require f } +Dir.glob("spec/acceptance_steps/**/*steps.rb") { |f| load f, true } -I18n.locale = :en +I18n.locale = Rails.configuration.i18n.default_locale Devise.stretches = 1 -Capybara.javascript_driver = :selenium +Capybara.javascript_driver = :webkit #Capybara.default_driver = :selenium module FactoryAttributesFor @@ -45,7 +48,7 @@ RSpec.configure do |config| config.tty = true # Use the specified formatter - config.formatter = :documentation # :progress, :html, :textmate + #config.formatter = :documentation # :progress, :html, :textmate # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures #config.fixture_path = "#{::Rails.root}/spec/fixtures" @@ -58,10 +61,11 @@ RSpec.configure do |config| config.before :each do CouchPotato.couchrest_database.recreate! end - config.before :each, type: :request do - #Capybara.current_driver = :selenium - #sign_in_user_through_request + + config.before :each, type: :feature do + Supplier.any_instance.stub send_confirmation_instructions: true end + # If true, the base class of anonymous controllers will be inferred # automatically. This will be the default behavior in future versions of # rspec-rails.