From 6f15c634910c660e6b8e40a3eb6ed37283f9168f Mon Sep 17 00:00:00 2001 From: Fernando Brito Date: Wed, 28 May 2014 09:30:58 -0300 Subject: [PATCH] Websocket-rails --- Gemfile | 2 ++ Gemfile.lock | 20 ++++++++++++++++++++ app/admin/v_libras_video.rb | 16 ++-------------- app/assets/javascripts/application.js | 3 ++- app/assets/javascripts/static/v_libras/rapid.js | 26 -------------------------- app/assets/javascripts/v_libras/requests/rapid.js | 20 ++++++++++++++++++++ app/assets/javascripts/v_libras/videos/index.js | 16 ++++++++++++++++ app/assets/stylesheets/bootstrap_overrides.css.scss | 5 +++++ app/controllers/v_libras/videos_controller.rb | 6 ++++-- app/helpers/application_helper.rb | 15 +++++++++------ app/models/v_libras/request.rb | 2 +- app/models/v_libras/video.rb | 2 +- app/views/layouts/application.html.erb | 1 + app/views/v_libras/requests/rapid.haml | 3 ++- app/views/v_libras/videos/index.haml | 8 ++++++-- config/environments/development.rb | 3 +++ config/events.rb | 14 ++++++++++++++ config/initializers/assets.rb | 3 ++- config/initializers/websocket_rails.rb | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ config/routes.rb | 2 +- lib/api_client/callback_processor.rb | 16 ++++++++++++++-- lib/api_client/client.rb | 10 +++++++--- 22 files changed, 195 insertions(+), 61 deletions(-) delete mode 100644 app/assets/javascripts/static/v_libras/rapid.js create mode 100644 app/assets/javascripts/v_libras/requests/rapid.js create mode 100644 app/assets/javascripts/v_libras/videos/index.js create mode 100644 config/events.rb create mode 100644 config/initializers/websocket_rails.rb diff --git a/Gemfile b/Gemfile index f5217d1..2ec0ef1 100644 --- a/Gemfile +++ b/Gemfile @@ -18,6 +18,8 @@ gem 'uglifier', '>= 1.3.0' gem 'coffee-rails', '~> 4.0.0' gem 'jquery-rails' gem 'therubyracer', :platform => :ruby +gem 'websocket-rails' + # gem 'turbolinks' gem 'devise' diff --git a/Gemfile.lock b/Gemfile.lock index 8711895..cd97abb 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -117,6 +117,8 @@ GEM warden (~> 1.2.3) diff-lcs (1.2.5) dotenv (0.7.0) + em-synchrony (1.0.3) + eventmachine (>= 1.0.0.beta.1) em-websocket (0.5.1) eventmachine (>= 0.12.9) http_parser.rb (~> 0.6.0) @@ -130,6 +132,9 @@ GEM railties (>= 3.0.0) faker (1.3.0) i18n (~> 0.5) + faye-websocket (0.7.3) + eventmachine (>= 0.12.0) + websocket-driver (>= 0.3.1) ffi (1.9.3) foreman (0.66.0) dotenv (~> 0.7.0) @@ -166,6 +171,7 @@ GEM actionpack (>= 3.2, < 5) activesupport (>= 3.2, < 5) hike (1.2.3) + hiredis (0.5.2) hpricot (0.8.6) html2haml (1.0.1) erubis (~> 2.7.0) @@ -276,6 +282,9 @@ GEM rb-fsevent (0.9.4) rb-inotify (0.9.4) ffi (>= 0.5.0) + redis (3.0.7) + redis-objects (0.9.1) + redis (>= 3.0.2) responders (1.0.0) railties (>= 3.2, < 5) rolify (3.4.0) @@ -363,6 +372,16 @@ GEM warden (1.2.3) rack (>= 1.0) websocket (1.0.7) + websocket-driver (0.3.3) + websocket-rails (0.7.0) + em-synchrony + faye-websocket + hiredis + rack + rails + redis + redis-objects + thin xpath (2.0.0) nokogiri (~> 1.3) @@ -419,3 +438,4 @@ DEPENDENCIES thin twitter-bootstrap-rails uglifier (>= 1.3.0) + websocket-rails diff --git a/app/admin/v_libras_video.rb b/app/admin/v_libras_video.rb index 6648e3a..0a80120 100644 --- a/app/admin/v_libras_video.rb +++ b/app/admin/v_libras_video.rb @@ -1,17 +1,5 @@ ActiveAdmin.register VLibras::Video do menu :priority => 15 - - # See permitted parameters documentation: - # https://github.com/gregbell/active_admin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters - # - # permit_params :list, :of, :attributes, :on, :model - # - # or - # - # permit_params do - # permitted = [:permitted, :attributes] - # permitted << :other if resource.something? - # permitted - # end - + + permit_params :url, :request_id end diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 06170c8..977b28f 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -13,4 +13,5 @@ //= require jquery //= require jquery_ujs //= require twitter/bootstrap -//= require_tree . +//= require websocket_rails/main + diff --git a/app/assets/javascripts/static/v_libras/rapid.js b/app/assets/javascripts/static/v_libras/rapid.js deleted file mode 100644 index fb8930f..0000000 --- a/app/assets/javascripts/static/v_libras/rapid.js +++ /dev/null @@ -1,26 +0,0 @@ -$(function() { - $("#service-video").click(function() { - console.log($(this).prop('defaultChecked')); - - $("#url").show('slow'); - $("#legend").hide('slow'); - }); - - $("#service-video-subtitle").click(function() { - console.log($(this).prop('defaultChecked')); - - $("#url").show('slow'); - $("#legend").show('slow'); - }); - - /* When user press "Back" on the browser */ - if ($("#service-video-subtitle")[0].checked) { - console.log('b'); - $("#service-video-subtitle").click(); - } - - if ($("#service-video")[0].checked) { - console.log('a'); - $("#service-video").click(); - } -}); \ No newline at end of file diff --git a/app/assets/javascripts/v_libras/requests/rapid.js b/app/assets/javascripts/v_libras/requests/rapid.js new file mode 100644 index 0000000..aa5bb31 --- /dev/null +++ b/app/assets/javascripts/v_libras/requests/rapid.js @@ -0,0 +1,20 @@ +$(function() { + $("#service-video").click(function() { + $("#url").show('slow'); + $("#legend").hide('slow'); + }); + + $("#service-video-subtitle").click(function() { + $("#url").show('slow'); + $("#legend").show('slow'); + }); + + /* When user press "Back" on the browser */ + if ($("#service-video-subtitle")[0].checked) { + $("#service-video-subtitle").click(); + } + + if ($("#service-video")[0].checked) { + $("#service-video").click(); + } +}); \ No newline at end of file diff --git a/app/assets/javascripts/v_libras/videos/index.js b/app/assets/javascripts/v_libras/videos/index.js new file mode 100644 index 0000000..db5933f --- /dev/null +++ b/app/assets/javascripts/v_libras/videos/index.js @@ -0,0 +1,16 @@ +$(function() { + $("a.badge").tooltip(); + + // connect to server like normal + // FIXME: how to get the right address + var dispatcher = new WebSocketRails('localhost:3000/websocket'); + + // subscribe to the channel + var channel = dispatcher.subscribe('requests_update'); + + // bind to a channel event + channel.bind('update', function(data) { + alert("channel updated"); + location.reload(); + }); +}); \ No newline at end of file diff --git a/app/assets/stylesheets/bootstrap_overrides.css.scss b/app/assets/stylesheets/bootstrap_overrides.css.scss index 8aecd73..2ac8507 100644 --- a/app/assets/stylesheets/bootstrap_overrides.css.scss +++ b/app/assets/stylesheets/bootstrap_overrides.css.scss @@ -43,4 +43,9 @@ } .breadcrumb .active a { color: #333333; +} + +.login { + padding: 3% 5%; + margin: 10px 35% 30px; } \ No newline at end of file diff --git a/app/controllers/v_libras/videos_controller.rb b/app/controllers/v_libras/videos_controller.rb index b446271..e889447 100644 --- a/app/controllers/v_libras/videos_controller.rb +++ b/app/controllers/v_libras/videos_controller.rb @@ -1,8 +1,10 @@ -class VLibras::VideosController < ApplicationController +class VLibras::VideosController < InheritedResources::Base + actions :destroy + before_filter :check_vlibras_api_status, :only => [ :index ] def index @videos = current_user.videos - @requests = current_user.requests.limit(10) + @requests = current_user.requests.limit(6) end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 2531728..1781fef 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -27,20 +27,23 @@ module ApplicationHelper end end - def request_status_label(status) - classes = [ 'label' ] + def request_status_label(request) + classes = [ 'badge' ] + + status = request.status case status when 'created' when 'processing' - classes << 'label-warning' + classes << 'badge-warning' when 'error' - classes << 'label-important' + classes << 'badge-important' when 'success' - classes << 'label-success' + classes << 'badge-success' end - content_tag(:div, t(status, scope: 'status'), :class => classes) + content_tag(:a, t(status, scope: 'status'), :class => classes, + :data => { 'toggle' => "tooltip" }, :title => request.response) end end diff --git a/app/models/v_libras/request.rb b/app/models/v_libras/request.rb index 76bccc2..69d39d0 100644 --- a/app/models/v_libras/request.rb +++ b/app/models/v_libras/request.rb @@ -19,7 +19,7 @@ class VLibras::Request < ActiveRecord::Base belongs_to :owner, :class => User - has_one :video, :class => VLibras::Video + has_one :video, :class => VLibras::Video, :dependent => :destroy validates :service_type, presence: true, diff --git a/app/models/v_libras/video.rb b/app/models/v_libras/video.rb index 888a88b..74bc6d4 100644 --- a/app/models/v_libras/video.rb +++ b/app/models/v_libras/video.rb @@ -10,5 +10,5 @@ # class VLibras::Video < ActiveRecord::Base - belongs_to :request, :class => VLibras::Request + belongs_to :request, :class => VLibras::Request, :dependent => :delete end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index f7cdf9d..6692471 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -4,6 +4,7 @@ GTAaaS <%= stylesheet_link_tag "application", :media => "all" %> <%= javascript_include_tag "application" %> + <%= yield :js %> <%= csrf_meta_tags %> diff --git a/app/views/v_libras/requests/rapid.haml b/app/views/v_libras/requests/rapid.haml index 2ba678f..7c23536 100644 --- a/app/views/v_libras/requests/rapid.haml +++ b/app/views/v_libras/requests/rapid.haml @@ -1,4 +1,5 @@ -= javascript_include_tag "static/v_libras/rapid" +- content_for :js do + = javascript_include_tag "v_libras/requests/rapid" .login %h2 diff --git a/app/views/v_libras/videos/index.haml b/app/views/v_libras/videos/index.haml index 09e956a..9dedb3e 100644 --- a/app/views/v_libras/videos/index.haml +++ b/app/views/v_libras/videos/index.haml @@ -1,3 +1,6 @@ +- content_for :js do + = javascript_include_tag "v_libras/videos/index" + .breadcrumb %h3= t('videos.list') @@ -7,7 +10,8 @@ = link_to image_tag("avatar.png"), video.url %p = link_to t('videos.show'), video_path(video), class: "btn btn-success" - = link_to t('videos.delete'), video_path(video), confirm: t('shared.confirm_delete'), method: :delete, class: "btn btn-danger" + = link_to t('videos.delete'), v_libras_video_path(video), method: :delete, + class: "btn btn-danger", data: { confirm: t('shared.confirm_delete') } .breadcrumb.requests %h4= t('requests.list') @@ -22,7 +26,7 @@ - @requests.each do |request| %tr - %td.span2= request_status_label(request.status) + %td.span2= request_status_label(request) %td.span5= request.video_filename %td.span5= time_ago_in_words(request.created_at) diff --git a/config/environments/development.rb b/config/environments/development.rb index 8273fec..fef692e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -56,4 +56,7 @@ Rails.application.configure do config.action_view.raise_on_missing_translations = true config.middleware.use Rack::LiveReload + + # websocket-rails + config.middleware.delete Rack::Lock end diff --git a/config/events.rb b/config/events.rb new file mode 100644 index 0000000..b40d976 --- /dev/null +++ b/config/events.rb @@ -0,0 +1,14 @@ +WebsocketRails::EventMap.describe do + # You can use this file to map incoming events to controller actions. + # One event can be mapped to any number of controller actions. The + # actions will be executed in the order they were subscribed. + # + # Uncomment and edit the next line to handle the client connected event: + # subscribe :client_connected, :to => Controller, :with_method => :method_name + # + # Here is an example of mapping namespaced events: + # namespace :product do + # subscribe :new, :to => ProductController, :with_method => :new_product + # end + # The above will handle an event triggered on the client like `product.new`. +end diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index e9b486f..b185f2e 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -1 +1,2 @@ -Rails.application.config.assets.precompile += %w( static/v_libras/rapid.js ) \ No newline at end of file +Rails.application.config.assets.precompile += %w( v_libras/requests/rapid.js ) +Rails.application.config.assets.precompile += %w( v_libras/videos/index.js ) \ No newline at end of file diff --git a/config/initializers/websocket_rails.rb b/config/initializers/websocket_rails.rb new file mode 100644 index 0000000..6029adf --- /dev/null +++ b/config/initializers/websocket_rails.rb @@ -0,0 +1,63 @@ +WebsocketRails.setup do |config| + + # Uncomment to override the default log level. The log level can be + # any of the standard Logger log levels. By default it will mirror the + # current Rails environment log level. + config.log_level = :debug + + # Uncomment to change the default log file path. + # config.log_path = "#{Rails.root}/log/websocket_rails.log" + + # Set to true if you wish to log the internal websocket_rails events + # such as the keepalive `websocket_rails.ping` event. + # config.log_internal_events = false + + # Change to true to enable standalone server mode + # Start the standalone server with rake websocket_rails:start_server + # * Requires Redis + config.standalone = false + + # Change to true to enable channel synchronization between + # multiple server instances. + # * Requires Redis. + config.synchronize = false + + # Prevent Thin from daemonizing (default is true) + # config.daemonize = false + + # Uncomment and edit to point to a different redis instance. + # Will not be used unless standalone or synchronization mode + # is enabled. + # config.redis_options = {:host => 'localhost', :port => '6379'} + + # By default, all subscribers in to a channel will be removed + # when that channel is made private. If you don't wish active + # subscribers to be removed from a previously public channel + # when making it private, set the following to true. + # config.keep_subscribers_when_private = false + + # Set to true if you wish to broadcast channel subscriber_join and + # subscriber_part events. All subscribers of a channel will be + # notified when other clients join and part the channel. If you are + # using the UserManager, the current_user object will be sent along + # with the event. + # config.broadcast_subscriber_events = true + + # Used as the key for the WebsocketRails.users Hash. This method + # will be called on the `current_user` object in your controller + # if one exists. If `current_user` does not exist or does not + # respond to the identifier, the key will default to `connection.id` + # config.user_identifier = :id + + # Uncomment and change this option to override the class associated + # with your `current_user` object. This class will be used when + # synchronization is enabled and you trigger events from background + # jobs using the WebsocketRails.users UserManager. + # config.user_class = User + + # Supporting HTTP streaming on Internet Explorer versions 8 & 9 + # requires CORS to be enabled for GET "/websocket" request. + # List here the origin domains allowed to perform the request. + # config.allowed_origins = ['http://localhost:3000'] + +end diff --git a/config/routes.rb b/config/routes.rb index fb82ea1..622e1e8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -17,7 +17,7 @@ Rails.application.routes.draw do post 'callback', on: :collection end - resources :videos, :only => [ :index ] + resources :videos, :only => [ :index, :destroy ] end diff --git a/lib/api_client/callback_processor.rb b/lib/api_client/callback_processor.rb index bad554c..5ba096c 100644 --- a/lib/api_client/callback_processor.rb +++ b/lib/api_client/callback_processor.rb @@ -1,7 +1,19 @@ class ApiClient::CallbackProcessor def self.process(params) request = VLibras::Request.find(params[:request_id]) - request.update(:status => 'success') - request.create_video(:url => params['response']) + + if params['error'] + Rails.logger.debug "[VLibras::Callback]: Error #{params}" + + request.update!(:status => 'error', :response => params['error']) + else + Rails.logger.debug "[VLibras::Callback] OK: #{params}" + + request.update!(:status => 'success') + request.create_video(:url => params['response']) + end + + Rails.logger.debug "[VLibras::Callback] Notifying websocket channel" + WebsocketRails[:requests_update].trigger(:update, {a: :b, c: :d}) end end \ No newline at end of file diff --git a/lib/api_client/client.rb b/lib/api_client/client.rb index 9d6c3df..c017761 100644 --- a/lib/api_client/client.rb +++ b/lib/api_client/client.rb @@ -7,7 +7,7 @@ module ApiClient::Client def self.submit(request, files) o = { query: request.params.clone } o[:query].merge!({ :servico => request.service_type }) - o[:query].merge!({ :callback => "http://150.165.205.192:3000/v_libras/requests/callback?request_id=#{request.id}" }) + o[:query].merge!({ :callback => "http://150.165.205.166:3000/v_libras/requests/callback?request_id=#{request.id}" }) o[:query].merge!({ :video => files[:video].file.to_file }) @@ -27,8 +27,12 @@ module ApiClient::Client else request.update!(:response => response.body, :status => 'error') end - rescue - + rescue => e + request.update!(:status => 'error', :response => e) + ensure + # FIXME: Running on another thread. Websocket not working :( + Delayed::Worker.logger.debug "[VLibras::Request] Sending message to websocket channel" + WebsocketRails[:requests_update].trigger(:update, {a: :b, c: :d}) end private -- libgit2 0.21.2