banter 1.4.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +1 -1
- data/Gemfile +1 -4
- data/README.md +0 -33
- data/Rakefile +0 -28
- data/banter.gemspec +2 -5
- data/lib/banter.rb +1 -1
- data/lib/banter/configuration.rb +2 -4
- data/lib/banter/notifier.rb +16 -0
- data/lib/banter/publisher.rb +1 -1
- data/lib/banter/railtie.rb +0 -4
- data/lib/banter/server/client_queue_listener.rb +4 -37
- data/lib/banter/server/rabbit_mq_subscriber.rb +6 -6
- data/lib/banter/server/subscriber_server.rb +0 -13
- data/lib/banter/version.rb +1 -1
- data/spec/banter/notifier_spec.rb +40 -0
- data/spec/banter/server/client_queue_listener_spec.rb +36 -84
- data/spec/banter/server/rabbitmq_subscriber_spec.rb +14 -10
- data/spec/banter/server/subscriber_server_spec.rb +0 -60
- data/spec/banter/subscriber_spec.rb +0 -81
- data/spec/spec_helper.rb +1 -8
- data/spec/support/test_notifier.rb +17 -0
- metadata +33 -100
- data/.ruby-version +0 -1
- data/lib/banter/web.rb +0 -34
- data/lib/banter/web/application.rb +0 -85
- data/lib/banter/web/helpers.rb +0 -13
- data/lib/banter/web/models/banter_message.rb +0 -124
- data/lib/banter/web/models/banter_worker.rb +0 -72
- data/lib/banter/web/serializers/banter_message_serializer.rb +0 -35
- data/lib/banter/web/serializers/banter_worker_serializer.rb +0 -40
- data/lib/banter/web/serializers/subscriber_serializer.rb +0 -26
- data/spec/banter/web/application_spec.rb +0 -181
- data/spec/banter/web/serializers/banter_message_serializer_spec.rb +0 -42
- data/spec/banter/web/serializers/banter_worker_serializer_spec.rb +0 -44
- data/spec/factories/banter_messages.rb +0 -28
- data/spec/factories/banter_workers.rb +0 -17
- data/spec/mongoid.yml +0 -7
- data/web/assets/javascripts/banter.js +0 -449
- data/web/assets/javascripts/dashboard_app/app.coffee +0 -4
- data/web/assets/javascripts/dashboard_app/controllers/message_controller.coffee +0 -28
- data/web/assets/javascripts/dashboard_app/controllers/messages_controller.coffee +0 -58
- data/web/assets/javascripts/dashboard_app/controllers/subscribers_controller.coffee +0 -25
- data/web/assets/javascripts/dashboard_app/controllers/worker_controller.coffee +0 -30
- data/web/assets/javascripts/dashboard_app/controllers/workers_list_controller.coffee +0 -28
- data/web/assets/javascripts/dashboard_app/routes.coffee +0 -82
- data/web/assets/javascripts/dashboard_app/services/common_methods_service.coffee +0 -6
- data/web/assets/javascripts/dashboard_app/services/message_methods_service.coffee +0 -18
- data/web/assets/javascripts/dashboard_app/services/messages_service.coffee +0 -17
- data/web/assets/javascripts/dashboard_app/services/subscribers_service.coffee +0 -8
- data/web/assets/javascripts/dashboard_app/services/worker_methods_service.coffee +0 -11
- data/web/assets/javascripts/dashboard_app/services/worker_service.coffee +0 -15
- data/web/assets/javascripts/ng-prettyjson.js +0 -15
- data/web/assets/stylesheets/banter.css +0 -78
- data/web/views/_message.haml +0 -74
- data/web/views/_messages.haml +0 -77
- data/web/views/_subscribers.haml +0 -22
- data/web/views/_worker.haml +0 -52
- data/web/views/_workers_list.haml +0 -35
- data/web/views/index.haml +0 -19
- data/web/views/layout.haml +0 -51
    
        data/web/views/_messages.haml
    DELETED
    
    | @@ -1,77 +0,0 @@ | |
| 1 | 
            -
            .clearfix
         | 
| 2 | 
            -
             | 
| 3 | 
            -
              %div.extra-bold.pull-left.btn.font-size-lg{data: {'ng-show' => "worker", 'ng-class' => "{'bg-danger' : !isWorkerAlive(worker), 'bg-success': isWorkerExecuting(worker) && isWorkerAlive(worker), 'bg-info': !isWorkerExecuting(worker) && isWorkerAlive(worker)}" }}
         | 
| 4 | 
            -
                %span{data: { 'ng-show' => 'isWorkerExecuting(worker)'}}
         | 
| 5 | 
            -
                  %span.glyphicon.glyphicon-refresh.spin
         | 
| 6 | 
            -
                  WORKING
         | 
| 7 | 
            -
                %span{data: { 'ng-show' => '!isWorkerExecuting(worker) && isWorkerAlive(worker)'}}
         | 
| 8 | 
            -
                  %span.glyphicon.glyphicon-play-circle
         | 
| 9 | 
            -
                  IDLE
         | 
| 10 | 
            -
                %span{data: { 'ng-show' => '!isWorkerAlive(worker)'}}
         | 
| 11 | 
            -
                  %span.glyphicon.glyphicon-off
         | 
| 12 | 
            -
                  DEAD
         | 
| 13 | 
            -
             | 
| 14 | 
            -
             | 
| 15 | 
            -
              .pull-right
         | 
| 16 | 
            -
                .btn-group{data: { 'ng-show' => "!isAutoUpdating()"}}
         | 
| 17 | 
            -
                  %a.btn.btn-default{data: { 'ng-click' => 'getFirstPage()', 'ng-disabled' => "!isAutoUpdating() && page == 1"}}
         | 
| 18 | 
            -
                    %span.glyphicon.glyphicon-fast-backward
         | 
| 19 | 
            -
                  %a.btn.btn-default{data: { 'ng-click' => 'getPreviousPage()', 'ng-disabled' => "!isAutoUpdating() && page == 1"}}
         | 
| 20 | 
            -
                    %span.glyphicon.glyphicon-backward
         | 
| 21 | 
            -
                  %a.btn.btn-default{data: { 'ng-click' => 'getNextPage()'}}
         | 
| 22 | 
            -
                    %span.glyphicon.glyphicon-forward
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                %a.btn.btn-primary{data: { 'ng-click' => 'pauseUpdating()', 'ng-show' => "isAutoUpdating()"}}
         | 
| 25 | 
            -
                  %span.glyphicon.glyphicon-pause
         | 
| 26 | 
            -
                  Pause Polling
         | 
| 27 | 
            -
                %a.btn.btn-primary{data: { 'ng-click' => 'resumeUpdating()', 'ng-show' => "!isAutoUpdating()"}}
         | 
| 28 | 
            -
                  %span.glyphicon.glyphicon-play
         | 
| 29 | 
            -
                  Resume Polling
         | 
| 30 | 
            -
            %h2{data: { 'ng-if' => '!worker && !subscriber'}}
         | 
| 31 | 
            -
              Messages
         | 
| 32 | 
            -
            %h2{data: { 'ng-if' => 'subscriber'}}
         | 
| 33 | 
            -
              Messages for {{subscriber}}
         | 
| 34 | 
            -
             | 
| 35 | 
            -
            .clearfix
         | 
| 36 | 
            -
              %div{ data: {'ng-if' => 'worker'}}
         | 
| 37 | 
            -
                %h2
         | 
| 38 | 
            -
                  Messages processed on {{worker.process_name}} (PID: {{worker.pid}} )
         | 
| 39 | 
            -
                {{ worker.job_count }}
         | 
| 40 | 
            -
                 
         | 
| 41 | 
            -
                (
         | 
| 42 | 
            -
                %span.text-success {{worker.success_count}} Succeeded
         | 
| 43 | 
            -
                \/
         | 
| 44 | 
            -
                %span.text-warning {{worker.failed_count}} Failed
         | 
| 45 | 
            -
                )
         | 
| 46 | 
            -
             | 
| 47 | 
            -
            .table.table-responsive.margin-top-md
         | 
| 48 | 
            -
              %table.table.table-striped.table-bordered.table-hover
         | 
| 49 | 
            -
                %thead
         | 
| 50 | 
            -
                  %tr
         | 
| 51 | 
            -
                    %th Worker
         | 
| 52 | 
            -
                    %th Subscriber
         | 
| 53 | 
            -
                    %th Status
         | 
| 54 | 
            -
                    %th Time Taken
         | 
| 55 | 
            -
                    %th Started
         | 
| 56 | 
            -
                    %th Finished
         | 
| 57 | 
            -
                    %th
         | 
| 58 | 
            -
                %tbody
         | 
| 59 | 
            -
                  %tr{data: { 'ng-repeat' => 'message in messages', 'ng-class' => "{'danger': isMessageFailed(message)}"}}
         | 
| 60 | 
            -
                    %td
         | 
| 61 | 
            -
                      %a{data: { 'ng-href' => dashboard_path("workers/{{message.worker.id}}")}}
         | 
| 62 | 
            -
                        {{ message.worker.process_name}}\#{{message.worker.pid}}
         | 
| 63 | 
            -
                    %td
         | 
| 64 | 
            -
                      %a{data: {'ng-href' => dashboard_path("subscribers/{{message.subscriber_class}}/messages")}}
         | 
| 65 | 
            -
                        {{ message.subscriber_class }}
         | 
| 66 | 
            -
                    %td {{ message.status }}
         | 
| 67 | 
            -
                    %td
         | 
| 68 | 
            -
                      %div{data: {'ng-if' => 'message.done_at' }}
         | 
| 69 | 
            -
                        {{ timeElapsed(message) }}ms
         | 
| 70 | 
            -
                    %td {{ asTime(message.started_at) | amDateFormat:'MM/DD/YYYY, h:mm:ss a' }}
         | 
| 71 | 
            -
                    %td
         | 
| 72 | 
            -
                      %div{data: {'ng-if' => 'message.done_at' }}
         | 
| 73 | 
            -
                        {{ asTime(message.done_at) | amDateFormat:'MM/DD/YYYY, h:mm:ss a' }}
         | 
| 74 | 
            -
                    %th
         | 
| 75 | 
            -
                      %a{data: { 'ng-href' => dashboard_path("messages/{{message.id}}") }}
         | 
| 76 | 
            -
                        View
         | 
| 77 | 
            -
                        %span.glyphicon.glyphicon-chevron-right
         | 
    
        data/web/views/_subscribers.haml
    DELETED
    
    | @@ -1,22 +0,0 @@ | |
| 1 | 
            -
            %h2 Subscribers
         | 
| 2 | 
            -
            .table.table-responsive
         | 
| 3 | 
            -
              %table.table.table-striped.table-bordered.table-hover
         | 
| 4 | 
            -
                %thead
         | 
| 5 | 
            -
                  %tr
         | 
| 6 | 
            -
                    %th Subscriber
         | 
| 7 | 
            -
                    %th Messages Processed
         | 
| 8 | 
            -
                    %th Processing
         | 
| 9 | 
            -
                    %th Succeeded
         | 
| 10 | 
            -
                    %th Errored
         | 
| 11 | 
            -
                    %th Validation Failed
         | 
| 12 | 
            -
                %tbody
         | 
| 13 | 
            -
                  %tr{data: {'ng-repeat' => 'subscriber in subscribers'}}
         | 
| 14 | 
            -
                    %td
         | 
| 15 | 
            -
                      %a{data: { 'ng-href' => dashboard_path("subscribers/{{subscriber.class_name}}/messages")}}
         | 
| 16 | 
            -
                        {{ subscriber.class_name }}
         | 
| 17 | 
            -
                    %td {{ subscriber.total }}
         | 
| 18 | 
            -
                    %td {{ subscriber.started_count }}
         | 
| 19 | 
            -
                    %td {{ subscriber.success_count }}
         | 
| 20 | 
            -
                    %td {{ subscriber.errored_count }}
         | 
| 21 | 
            -
                    %td {{ subscriber.validation_failed_count }}
         | 
| 22 | 
            -
             | 
    
        data/web/views/_worker.haml
    DELETED
    
    | @@ -1,52 +0,0 @@ | |
| 1 | 
            -
            .clearfix
         | 
| 2 | 
            -
              %div.extra-bold.pull-right.padding-large.font-size-lg.rounded-corners-md{data: { 'ng-class' => "{'bg-danger' : !isWorkerAlive(worker), 'bg-success': isWorkerExecuting(worker) && isWorkerAlive(worker), 'bg-info': !isWorkerExecuting(worker) && isWorkerAlive(worker)}" }}
         | 
| 3 | 
            -
                %span{data: { 'ng-show' => 'isWorkerExecuting(worker)'}}
         | 
| 4 | 
            -
                  %span.glyphicon.glyphicon-refresh.spin
         | 
| 5 | 
            -
                  WORKING
         | 
| 6 | 
            -
                %span{data: { 'ng-show' => '!isWorkerExecuting(worker)'}}
         | 
| 7 | 
            -
                  %span.glyphicon.glyphicon-play-circle
         | 
| 8 | 
            -
                  IDLE
         | 
| 9 | 
            -
                %span{data: { 'ng-show' => '!isWorkerAlive(worker)'}}
         | 
| 10 | 
            -
                  %span.glyphicon.glyphicon-off
         | 
| 11 | 
            -
                  DEAD
         | 
| 12 | 
            -
              %h2
         | 
| 13 | 
            -
                Worker
         | 
| 14 | 
            -
             | 
| 15 | 
            -
            %ul.list-group
         | 
| 16 | 
            -
              %li.list-group-item.row
         | 
| 17 | 
            -
                .col-sm-3.bold Host Name
         | 
| 18 | 
            -
                .col-sm-9 {{ worker.hostname }}
         | 
| 19 | 
            -
              %li.list-group-item.row
         | 
| 20 | 
            -
                .col-sm-3.bold Process Name
         | 
| 21 | 
            -
                .col-sm-9 {{ worker.process_name}} (PID: {{worker.pid}}
         | 
| 22 | 
            -
              %li.list-group-item.row
         | 
| 23 | 
            -
                .col-sm-3.bold Subscriber Classes
         | 
| 24 | 
            -
                .col-sm-9
         | 
| 25 | 
            -
                  %div{data: { 'ng-repeat' => "worker_class in worker.worker_classes" }}
         | 
| 26 | 
            -
                    %a{data: {'ng-href' => dashboard_path("subscribers/{{worker_class}}/messages")}} {{worker_class}}
         | 
| 27 | 
            -
              %li.list-group-item.row
         | 
| 28 | 
            -
                .col-sm-3.bold Started Time
         | 
| 29 | 
            -
                .col-sm-9 {{ asTime(worker.started_at)  | amCalendar }}
         | 
| 30 | 
            -
              %li.list-group-item.row{data: { 'ng-if' => 'worker.stopped_at'}}
         | 
| 31 | 
            -
                .col-sm-3.bold Stopped Time
         | 
| 32 | 
            -
                .col-sm-9 {{ asTime(worker.stopped_at)  | amCalendar }}
         | 
| 33 | 
            -
              %li.list-group-item.row
         | 
| 34 | 
            -
                .col-sm-3.bold
         | 
| 35 | 
            -
                  %a{data: { 'ng-href' => dashboard_path("workers/{{worker.id}}/messages")}} Messages Processed
         | 
| 36 | 
            -
                .col-sm-9
         | 
| 37 | 
            -
                  %a{data: { 'ng-href' => dashboard_path("workers/{{worker.id}}/messages")}} {{ worker.job_count }}
         | 
| 38 | 
            -
                   
         | 
| 39 | 
            -
                  (
         | 
| 40 | 
            -
                  %span.text-success {{worker.success_count}} Succeeded
         | 
| 41 | 
            -
                  \/
         | 
| 42 | 
            -
                  %span.text-warning {{worker.failed_count}} Failed
         | 
| 43 | 
            -
                  )
         | 
| 44 | 
            -
              %li.list-group-item.row{data: { 'ng-if' => "isWorkerExecuting(worker)"}}
         | 
| 45 | 
            -
                .col-sm-3.bold
         | 
| 46 | 
            -
                  %a{href: "#{root_path}messages/{{worker.current_message['_id']}}"} Current Job
         | 
| 47 | 
            -
                .col-sm-9
         | 
| 48 | 
            -
                  {{ worker.current_message.subscriber_class }}
         | 
| 49 | 
            -
              %li.list-group-item.row{data: { 'ng-if' => "isWorkerExecuting(worker)"}}
         | 
| 50 | 
            -
                .col-sm-3.bold Current Payload
         | 
| 51 | 
            -
                .col-sm-9
         | 
| 52 | 
            -
                  %pre{data: { 'pretty-json' => 'worker.current_message.payload'}}
         | 
| @@ -1,35 +0,0 @@ | |
| 1 | 
            -
            %h2
         | 
| 2 | 
            -
              Workers
         | 
| 3 | 
            -
             | 
| 4 | 
            -
            .table.table-responsive{data: { 'ng-if' => "workers.length > 0"} }
         | 
| 5 | 
            -
              %table.table.table-striped.table-bordered.table-hover
         | 
| 6 | 
            -
                %thead
         | 
| 7 | 
            -
                  %tr
         | 
| 8 | 
            -
                    %th Hostname
         | 
| 9 | 
            -
                    %th Process Name
         | 
| 10 | 
            -
                    %th PID
         | 
| 11 | 
            -
                    %th Started
         | 
| 12 | 
            -
                    %th Subscribers
         | 
| 13 | 
            -
                    %th Current Job
         | 
| 14 | 
            -
                %tbody
         | 
| 15 | 
            -
                  %tr{data: {'ng-repeat' => 'worker in workers'}}
         | 
| 16 | 
            -
                    %td
         | 
| 17 | 
            -
                      %a{data: { 'ng-href' => dashboard_path("workers/{{worker.id}}")}} {{ worker.hostname }}
         | 
| 18 | 
            -
                    %td {{ worker.process_name }}
         | 
| 19 | 
            -
                    %td {{ worker.pid }}
         | 
| 20 | 
            -
                    %td
         | 
| 21 | 
            -
                      {{ asTime(worker.started_at) | amCalendar }}
         | 
| 22 | 
            -
                    %td
         | 
| 23 | 
            -
                      %div{data: {'ng-if' => 'worker.worker_classes.length > 2'}}
         | 
| 24 | 
            -
                        {{worker.worker_classes.length}} Subscribers
         | 
| 25 | 
            -
                      %div{data: {'ng-if' => 'worker.worker_classes.length <= 2'}}
         | 
| 26 | 
            -
                        %div{data: { 'ng-repeat' => 'worker_class in worker.worker_classes'}}
         | 
| 27 | 
            -
                          %a{data: { 'ng-href' => dashboard_path("subscribers/{{worker_class}}/messages")}}{{ worker_class }}
         | 
| 28 | 
            -
             | 
| 29 | 
            -
                    %td
         | 
| 30 | 
            -
                      %div{data: { 'ng-show' => 'worker.current_message'}}
         | 
| 31 | 
            -
                        %a{data: { 'ng-href' => dashboard_path("messages/{{worker.current_message.id}}")}}
         | 
| 32 | 
            -
                          {{ worker.current_message.subscriber_class }}
         | 
| 33 | 
            -
                        %span.glyphicon.glyphicon-refresh.spin
         | 
| 34 | 
            -
                      %div{data: { 'ng-show' => '!worker.current_message'}}
         | 
| 35 | 
            -
                        Idle
         | 
    
        data/web/views/index.haml
    DELETED
    
    | @@ -1,19 +0,0 @@ | |
| 1 | 
            -
            %base{href: "#{root_path}dashboard/"}
         | 
| 2 | 
            -
            %div{data: { 'ng-app' => "dashboardApp"}}
         | 
| 3 | 
            -
              %div{data: { 'ng-view' => ''}}
         | 
| 4 | 
            -
             | 
| 5 | 
            -
              %script{type: 'text/ng-template', id: 'banter/workers-list.html'}
         | 
| 6 | 
            -
                = haml :_workers_list
         | 
| 7 | 
            -
             | 
| 8 | 
            -
              %script{type: 'text/ng-template', id: 'banter/worker.html'}
         | 
| 9 | 
            -
                = haml :_worker
         | 
| 10 | 
            -
             | 
| 11 | 
            -
              %script{type: 'text/ng-template', id: 'banter/message.html'}
         | 
| 12 | 
            -
                = haml :_message
         | 
| 13 | 
            -
             | 
| 14 | 
            -
              %script{type: 'text/ng-template', id: 'banter/messages.html'}
         | 
| 15 | 
            -
                = haml :_messages
         | 
| 16 | 
            -
             | 
| 17 | 
            -
              %script{type: 'text/ng-template', id: 'banter/subscribers.html'}
         | 
| 18 | 
            -
                = haml :_subscribers
         | 
| 19 | 
            -
             | 
    
        data/web/views/layout.haml
    DELETED
    
    | @@ -1,51 +0,0 @@ | |
| 1 | 
            -
            !!! 5
         | 
| 2 | 
            -
            %html(lang="en")
         | 
| 3 | 
            -
              %head
         | 
| 4 | 
            -
                %meta(charset="utf-8")
         | 
| 5 | 
            -
                %meta(http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1")
         | 
| 6 | 
            -
                %meta(name="viewport" content="width=device-width, initial-scale=1.0")
         | 
| 7 | 
            -
                %title Banter
         | 
| 8 | 
            -
                / Le HTML5 shim, for IE6-8 support of HTML elements
         | 
| 9 | 
            -
                /[if lt IE 9]
         | 
| 10 | 
            -
                  %script{src: "//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.6.1/html5shiv.js" }
         | 
| 11 | 
            -
                %link{:href=>"//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css", :rel=>"stylesheet"}
         | 
| 12 | 
            -
                %link{href: 'http://fonts.googleapis.com/css?family=Open+Sans:700,800,400', rel: 'stylesheet', type:'text/css'}
         | 
| 13 | 
            -
                %link{href: "#{root_path}stylesheets/banter.css", rel: 'stylesheet', type:'text/css'}
         | 
| 14 | 
            -
             | 
| 15 | 
            -
             | 
| 16 | 
            -
              %body
         | 
| 17 | 
            -
                %nav.navbar.navbar-default.navbar-fixed-top
         | 
| 18 | 
            -
                  .container
         | 
| 19 | 
            -
                    .navbar-header
         | 
| 20 | 
            -
                      %button.navbar-toggle{type: 'button', data: { toggle: 'collapse', target: '#banter-navbar-collapse'}}
         | 
| 21 | 
            -
                        %span.icon-bar
         | 
| 22 | 
            -
                        %span.icon-bar
         | 
| 23 | 
            -
                        %span.icon-bar
         | 
| 24 | 
            -
                      %a.navbar-brand{href: root_path} Banter
         | 
| 25 | 
            -
                    .collapse.navbar-collapse#banter-navbar-collapse
         | 
| 26 | 
            -
                      %ul.nav.navbar-nav
         | 
| 27 | 
            -
                        %li
         | 
| 28 | 
            -
                          %a{href: dashboard_path} Workers
         | 
| 29 | 
            -
                        %li
         | 
| 30 | 
            -
                          %a{href: dashboard_path("subscribers")} Subscribers
         | 
| 31 | 
            -
                        %li
         | 
| 32 | 
            -
                          %a{href: dashboard_path("messages")} Messages
         | 
| 33 | 
            -
             | 
| 34 | 
            -
                .container{style: 'margin-top: 55px; padding-top: 10px'}
         | 
| 35 | 
            -
                  = yield
         | 
| 36 | 
            -
                  %footer
         | 
| 37 | 
            -
                    %p
         | 
| 38 | 
            -
                      Banter © #{Date.today.year} (Developed & Maintained by
         | 
| 39 | 
            -
                      %a{href: 'https://www.honest.com'} The Honest Company
         | 
| 40 | 
            -
                      )
         | 
| 41 | 
            -
                :javascript
         | 
| 42 | 
            -
                    window.Banter || (window.Banter = {});
         | 
| 43 | 
            -
                    window.Banter.rootPath = "#{root_path}";
         | 
| 44 | 
            -
             | 
| 45 | 
            -
                %script{:src=>"//code.jquery.com/jquery-2.1.1.min.js"}
         | 
| 46 | 
            -
                %script{:src=>"//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"}
         | 
| 47 | 
            -
                %script{src: '//ajax.googleapis.com/ajax/libs/angularjs/1.2.19/angular.js' }
         | 
| 48 | 
            -
                %script{src: '//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.18/angular-route.min.js' }
         | 
| 49 | 
            -
                %script{src: '//cdnjs.cloudflare.com/ajax/libs/moment.js/2.7.0/moment.min.js' }
         | 
| 50 | 
            -
                %script{src: '//cdnjs.cloudflare.com/ajax/libs/angular-moment/0.7.1/angular-moment.min.js' }
         | 
| 51 | 
            -
                %script{src: "#{root_path}javascripts/banter.js" }
         |