socketable-rails 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ Copyright 2013 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,62 @@
1
+ = SocketableRails
2
+
3
+ Tests coming soon.
4
+
5
+ Socketable-rails uses @DanKnox Websocket-Rails gem: http://github.com/DanKnox/websocket-rails.
6
+
7
+ == Installation
8
+
9
+ Add to Gemfile
10
+ gem 'socketable-rails'
11
+
12
+ Then
13
+ $ cd rails/app/path
14
+ $ bundle install
15
+ $ rake socketable:install
16
+ $ thin start
17
+
18
+
19
+ == Usage
20
+
21
+ Building a realtime chat:
22
+
23
+ === message.rb
24
+ Normal model
25
+ class Message < ActiveRecord::Base
26
+ attr_accessible :content
27
+ end
28
+
29
+
30
+ === home/index.html.erb
31
+ You need to add a :websocket => true parameter to your form
32
+ <%= form_for @message, :websocket => true do |f| %>
33
+ <%= f.text_area :content %>
34
+ <button class="btn">Submit</button>
35
+ <% end %>
36
+ <div id="msgs">
37
+ </div>
38
+
39
+ === messages_controller.rb
40
+ Create a function named *websocket* in your controller to handle the request
41
+ class MessagesController < ApplicationController
42
+ def websocket(params, socket)
43
+ message = Message.create(params[:message])
44
+ socket.broadcast(message, :create_message)
45
+ end
46
+ end
47
+
48
+ === javascript
49
+ Bind the event you triggered in the controller
50
+ Socketable.dispatcher().bind('create_message', function(data) {
51
+ $('#msgs').append($('<div></div>').html(data.content));
52
+ });
53
+
54
+
55
+
56
+ == Contributing
57
+
58
+ 1. Fork it
59
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
60
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
61
+ 4. Push to the branch (`git push origin my-new-feature`)
62
+ 5. Create new Pull Request
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = 'SocketableRails'
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
22
+
23
+
24
+
25
+
26
+ Bundler::GemHelper.install_tasks
27
+
@@ -0,0 +1,44 @@
1
+ class SocketableController < WebsocketRails::BaseController
2
+ attr_accessor :params
3
+
4
+ # Handle all requests
5
+ def request
6
+ begin
7
+ @params = formated_params
8
+ controller.new.websocket(params, self)
9
+ rescue Exception => e
10
+ error_message e
11
+ end
12
+ end
13
+
14
+ def emit(data, to_event)
15
+ send_message(to_event, data)
16
+ end
17
+
18
+ def broadcast(data, to_event)
19
+ broadcast_message(to_event, data)
20
+ end
21
+
22
+
23
+ private
24
+
25
+ def formated_params
26
+ params = {}
27
+ Rack::Utils.parse_nested_query(data).each do |key, value|
28
+ key = key.to_sym
29
+ params[key] = value
30
+ end
31
+ params[:path] = Rails.application.routes.recognize_path(params[:path])
32
+ params
33
+ end
34
+
35
+ def error_message(e)
36
+ puts "-- Error in websocket function"
37
+ puts e.message
38
+ end
39
+
40
+ def controller
41
+ "#{@params[:path][:controller]}_controller".camelize.constantize
42
+ end
43
+
44
+ end
@@ -0,0 +1,32 @@
1
+ WebsocketRails.setup do |config|
2
+ # Uncomment to override the default log level. The log level can be
3
+ # any of the standard Logger log levels. By default it will mirror the
4
+ # current Rails environment log level.
5
+ # config.log_level = :debug
6
+
7
+ # Uncomment to change the default log file path.
8
+ # config.log_path = "#{Rails.root}/log/websocket_rails.log"
9
+
10
+ # Set to true if you wish to log the internal websocket_rails events
11
+ # such as the keepalive `websocket_rails.ping` event.
12
+ # config.log_internal_events = false
13
+
14
+ # Change to true to enable standalone server mode
15
+ # Start the standalone server with rake websocket_rails:start_server
16
+ # * Requires Redis
17
+ config.standalone = false
18
+
19
+ # Change to true to enable channel synchronization between
20
+ # multiple server instances.
21
+ # * Requires Redis.
22
+ config.synchronize = false
23
+
24
+ # Uncomment and edit to point to a different redis instance.
25
+ # Will not be used unless standalone or synchronization mode
26
+ # is enabled.
27
+ # config.redis_options = {:host => 'localhost', :port => '6379'}
28
+ end
29
+
30
+ WebsocketRails::EventMap.describe do
31
+ subscribe :request, "socketable#request"
32
+ end
@@ -0,0 +1,39 @@
1
+ module ActionView::Helpers::FormHelper
2
+ alias :orig_form_for :form_for
3
+
4
+ def form_for(record, options = {}, &proc)
5
+ if options.include?(:websocket)
6
+ options[:html] ||= {}
7
+ options[:html][:websocket] = options.delete(:websocket) if options.has_key?(:websocket)
8
+ end
9
+ orig_form_for(record, options, &proc)
10
+ end
11
+ end
12
+
13
+ module ActionView::Helpers::FormTagHelper
14
+ def html_options_for_form(url_for_options, options)
15
+ options.stringify_keys.tap do |html_options|
16
+ html_options["enctype"] = "multipart/form-data" if html_options.delete("multipart")
17
+ # The following URL is unescaped, this is just a hash of options, and it is the
18
+ # responsibility of the caller to escape all the values.
19
+ html_options["action"] = url_for(url_for_options)
20
+ html_options["accept-charset"] = "UTF-8"
21
+
22
+ html_options["data-remote"] = true if html_options.delete("remote")
23
+
24
+ # Add option for data-websocket
25
+ html_options["data-websocket"] = true if html_options.delete("websocket")
26
+
27
+ if html_options["data-remote"] &&
28
+ !embed_authenticity_token_in_remote_forms &&
29
+ html_options["authenticity_token"].blank?
30
+ # The authenticity token is taken from the meta tag in this case
31
+ html_options["authenticity_token"] = false
32
+ elsif html_options["authenticity_token"] == true
33
+ # Include the default authenticity_token, which is only generated when its set to nil,
34
+ # but we needed the true value to override the default of no authenticity_token on data-remote.
35
+ html_options["authenticity_token"] = nil
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,3 @@
1
+ //= require websocket_rails/main
2
+ //= require ./socketable_ujs
3
+ //= require ./socketable_init
@@ -0,0 +1,7 @@
1
+ $(function() {
2
+ if (Socketable.exists()) {
3
+ Socketable.onDefaultAction(function() {
4
+ Socketable.dispatcher().trigger('request', Socketable.data());
5
+ });
6
+ }
7
+ });
@@ -0,0 +1,33 @@
1
+ (function(window, $) {
2
+ window.Socketable = function() {
3
+ var selector, dispatcher, path, host_with_port;
4
+
5
+ path = window.location.pathname;
6
+ host_with_port = window.location.host;
7
+ selector = 'form[data-websocket]';
8
+
9
+ return {
10
+ DEFAULT_EVENT_NAME: 'request',
11
+ dispatcher: function() {
12
+ if(typeof dispatcher !== 'object') {
13
+ dispatcher = new WebSocketRails(host_with_port + "/websocket");
14
+ }
15
+ return dispatcher;
16
+ },
17
+ exists: function() {
18
+ return $(selector).length > 0;
19
+ },
20
+ data: function() {
21
+ // if seletor is form
22
+ return $(selector).serialize() + "&path=" + $(selector).attr('action');
23
+ },
24
+ onDefaultAction: function(fn) {
25
+ // if selector is form
26
+ $(selector).submit(function(e) {
27
+ e.preventDefault();
28
+ fn();
29
+ });
30
+ }
31
+ };
32
+ }();
33
+ })(window, jQuery);
@@ -0,0 +1,5 @@
1
+ require "socketable-rails/engine"
2
+ require "websocket-rails"
3
+
4
+ module SocketableRails
5
+ end
@@ -0,0 +1,4 @@
1
+ module SocketableRails
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module SocketableRails
2
+ VERSION = "0.1.2"
3
+ end
@@ -0,0 +1,67 @@
1
+ require 'rails'
2
+ namespace :socketable do
3
+ task :install => [:add_js_to_manifest, :remove_rack_lock_on_development]
4
+
5
+ desc "Add config.middleware.delete(Rack::Lock)"
6
+ task :remove_rack_lock_on_development do
7
+ config = "config/environments/development.rb"
8
+
9
+ def remove_middleware_code
10
+ out = ?\n
11
+ out << " # Line generated by socketable:install task"
12
+ out << ?\n
13
+ out << " config.middleware.delete(Rack::Lock)"
14
+ out << ?\n
15
+ out << 'end'
16
+ end
17
+
18
+ def config.middleware_removed?
19
+ not (contents =~ /config\.middleware\.delete\(Rack::Lock\)/m).nil?
20
+ end
21
+
22
+ def config.contents
23
+ open(self).read
24
+ end
25
+
26
+ def config.add_configuration_code
27
+ data = contents
28
+ data = data.split('end')
29
+ data.delete_at(data.length-1)
30
+
31
+ data.last.concat ?\n
32
+ data.last.concat " # Line generated by socketable:install task"
33
+ data.last.concat ?\n
34
+ data.last.concat " config.middleware.delete(Rack::Lock)"
35
+ data.last.concat ?\n
36
+ data << nil
37
+
38
+ data = data.join('end')
39
+
40
+ open self, 'w' do |f|
41
+ f << data
42
+ # f << data.gsub!(/(.*)\nend/, "\1#{remove_middleware_code}")
43
+ end
44
+ end
45
+
46
+ unless config.middleware_removed?
47
+ config.add_configuration_code
48
+ end
49
+ end
50
+
51
+ desc "Add socketable javascript to manifest"
52
+ task :add_js_to_manifest do
53
+ manifest = "app/assets/javascripts/application.js"
54
+
55
+ def manifest.socketable_added?
56
+ not (open(self).read =~ /\/\/= require socketable_rails\/main/m).nil?
57
+ end
58
+
59
+ def manifest.add_socketable_js_to_manifest
60
+ open(self, 'a+'){ |f| f << "\n//= require socketable_rails/main\n" }
61
+ end
62
+
63
+ unless manifest.socketable_added?
64
+ manifest.add_socketable_js_to_manifest
65
+ end
66
+ end
67
+ end
metadata ADDED
@@ -0,0 +1,106 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: socketable-rails
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Rafael Garcia
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rails
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.12
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.12
30
+ - !ruby/object:Gem::Dependency
31
+ name: websocket-rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: coffee-rails
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ description: Very small and simple gem that makes using websockets really easy.
63
+ email:
64
+ - rafbgarcia@gmail.com
65
+ executables: []
66
+ extensions: []
67
+ extra_rdoc_files: []
68
+ files:
69
+ - app/controllers/socketable_controller.rb
70
+ - config/initializers/form_builder.rb
71
+ - config/initializers/events.rb
72
+ - lib/socketable-rails.rb
73
+ - lib/tasks/install.rake
74
+ - lib/socketable-rails/version.rb
75
+ - lib/socketable-rails/engine.rb
76
+ - lib/assets/javascripts/socketable_rails/socketable_init.js
77
+ - lib/assets/javascripts/socketable_rails/main.js
78
+ - lib/assets/javascripts/socketable_rails/socketable_ujs.js
79
+ - MIT-LICENSE
80
+ - Rakefile
81
+ - README.rdoc
82
+ homepage: https://github.com/rafbgarcia/socketable-rails
83
+ licenses: []
84
+ post_install_message:
85
+ rdoc_options: []
86
+ require_paths:
87
+ - lib
88
+ required_ruby_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ required_rubygems_version: !ruby/object:Gem::Requirement
95
+ none: false
96
+ requirements:
97
+ - - ! '>='
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 1.8.25
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Rails websocket made easy
106
+ test_files: []