socketable-rails 0.1.2

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.
@@ -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: []