Ruby Websocket and Real-time App Tutorial

In this post I would like to present a small tutorial, I hope it will serve as a good introduction to web-socket api.

Websocket Server
In the part we focus on server part. In ruby we use eventmachine, em-websocket gem to install websocket server.
To install eventmachine run gem install eventmachine
To install em-websocket run gem install em-websocket
Make a file server.rb and implement codes below:

server.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
require 'eventmachine'
require 'em-websocket'

EventMachine.run {
  EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 8080) do |ws|
    ws.onopen {
      puts "WebSocket connection open"
    }

    ws.onmessage { |msg|
      puts msg
      ws.send(msg)
    }

    ws.onclose {
      puts "WebSocket connection closed"
    }
  end
}

What the code does is creates a websocket-server which listens at localhost:8080. Callbacks have been provided for open and close events, so when a client creates a connection or a connection gets closed the associated callbacks print an appropriate message to the terminal. And callbacks have been provided for message event when a client send the message.

To run websocket server run ruby sever.rb

Websocket Client
So far, so good. But the main purpose of a websocket server is to get the message from client and relay data to the client. How do we do that? Turns out that is pretty simple too.
Make a file index.html and implement codes below:

index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<html>
<head>
  <title>Websocket GeeKhmer</title>
  <script type="text/javascript">
    var ws = null;
    function init() {
      ws = new WebSocket("ws://localhost:8080");
      ws.onopen = function() {
        console.log("Connection is opened");
      }

      ws.onclose = function() {
        console.log("Connection is closed");
      }

      ws.onmessage = function(msg) {
        document.getElementById("display").innerHTML = msg.data;
      }
    }

    function send() {
      ws.send(document.getElementById("txt").value);
    }
  </script>
</head>
<body onload="init();">
  <h2>WebSocket GeeKhmer</h2>
  <input type="text" id="txt">
  <input type="button" onclick="send();" value="Send">
  <p id="display"></p>
</body>
</html>

Feel free to provide your suggestions and to point out errors.

Top Three Front-End MVC Framework

As more and more logic are executed in the browser, JavaScript front-end codebases grow larger and more difficult to maintain. As a way to solve this issue developers have been turning to MVC frameworks which maked productivity and maintainable code.

JavaScript MVC Frameworks are a big topic nowadays that we use JS to bind data, send it back between server and client and actually implement lots of logic, so we want to structure our code in the MVC or similar patterns. In this article I want to show the most front-end MVC framework:

AngularJS
A toolset based on extending the HTML vocabulary for your application. Let try AngularJS

Ember
Provides template written in the Handlebars templating language, views, controllers, models and a router. Let try EmberJS

Backbone
Provides models with key-value binding and custom events, collections, and connects it all to your existing API over a RESTful JSON interface. Let try Backbone

What Is Websocket?


WebSocket is a new standard for realtime communication for the Web & Mobile apps.

Websocket Benefit
- Websocket enables the server to push data to the connected clients.
- Reduce unnecessary network traffic and latency using full-duplex through a single connection (instead of two).
- Streaming through proxies and firewalls, supporting simultaneously upstream and downstream communication.
- Backward compatible with the pre-WebSocket world by switching from an HTTP connection to WebSockets.

Apps that should use Websocket
- Multi-User Apps.
- Real-Time Apps.
- Apps where live data is needed, like a stock market app…

Websocket Client
On web, websocket support in browsers such as Google Chrome, Firefox, Opera.
On mobile, websocket support in iOS & Android.
Websocket client on Web use javascript for requesting to Websocket Server. Let try w3schools, tutorialspoint

Websocket Server
On Server, websocket support in Ruby, Java, Objective-C, PHP, .NET, node.js, ActionScript and many other languages. Let try Ruby, Java, Objective-C(iOS), PHP, .NET, node.js

Processing

Assets_helper Gem

assets_helper is the gem that use to include css and javascript by controller name automatically, it mean that include only css and javascript file in the controller that you are running.

Installation
Add this line to your application’s Gemfile:
gem 'assets_helper'

And then execute:
$ bundle

Or install it yourself as:
$ gem install assets_helper

Usage
1. Add before_filter :include_css, :include_javascript in application_controller.rb:

application_controller.rb
1
2
3
4
5
class ApplicationController < ActionController::Base
  protect_from_forgery

  before_filter :include_css, :include_javascript
end

2. Add = yield :asset n your layout file (exp: application.html.haml):

application.html.haml
1
2
3
4
5
6
7
8
!!!
%html
  %head
    %title JongEat
    = stylesheet_link_tag    "application", :media => "all"
    = javascript_include_tag "application"
    = yield :asset
    = csrf_meta_tags

3. Example if you create a controller name homes:
$ rails generate controller homes

4. Go to app/assets/javascripts and create a folder name homes like your controller (homes) you create below. And input javascript file that you use for controller homes in this folder ( app/assets/javascripts/homes ), and no need to include in application.js file.

5. Go to app/assets/stylesheets and create a folder name homes like your controller(homes) you create below. And input css file that you use for controller homes in this folder(app/assets/stylesheets), and no need to include or import in application.css file.

So whenever you run homes controller, it include only css and javascript file that you use for homes controller, and can make your project run fast.

How to Set Facebook Page Tab Content Auto Resize Height?

The height of Facebook Page Tab is fixed at 800px, so to set Facebook Page Tab content auto resize height you must add code below at the bottom of body tag.

code for auto resize height
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div id="fb-root"></div>
<script type="text/javascript" src="http://connect.facebook.net/de_DE/all.js1">
</script>
<script type="text/javascript">
  window.fbAsyncInit = function() {
    FB.init({
      appId : 'APP_ID',
      cookie : true
    });
  }

  window.onload = function() {
    FB.Canvas.setAutoGrow(10);
  }
</script>

Enjoy it

How to Develop Facebook Page Tab?

One of the most interesting features of Apps on facebook.com is the ability for your apps (Facebook Page Tab) to be used within the context of a Facebook Fan Pages.

1. To create Facebook Page Tab go to the link https://developers.facebook.com/apps.
Then click button Create New App.

2. Create New App
Then enter App Name, App Namespace and choose Apps for Pages for App Category. And click button Continuce.

3. Setting Basic
Then select Website with Facebook Login and Page Tab to fill the information.

4. Fill the information
- With Website with Facebook Login, Enter your Site URL.
- With Page Tab, Enter your Page Tab Name, Page Tab URL, Secure Page Tab URL, Page Tab Edit URL and Page Tab Image. And click on button Save Changes.

5. Adding an Facebook Page Tab to a Page
- As a Facebook Page Tab App developer, you can prompt users to install your Page Tab App by including an “Install this Page Tab App” link.
- http://www.facebook.com/dialog/pagetab?app_id=APP_ID&next=URL
- Where APP_ID and URL can be found in your app setting (https://developers.facebook.com/apps).

Then please go to your Facebook Fan Page, and click on your Page Tab.

Enjoy it

What Is Closure, Proc and Lambda?

1. Closure
Closure is block of code/function/method that has two properties:
- It can be passed around like an object (to be called later).
- It remembers the values of all the variables that were in scope when the function was created, then it is able to access those variables when it is called.

Proc & Lambda are closure.

2. Proc (Procedure)
Proc is a closure and an object that can be bound to a variable and reused.

default proc
1
2
p = Proc.new { puts "Hello Rubyist" }
p.call # prints Hello Rubyist
proc with parameter
1
2
p = Proc.new { |a, b| puts "x: #{a}, y: #{b}" }
p.call(1, 2) # prints x: 1, y: 2
proc as closure
1
2
3
4
5
6
def proc_maker(arg)
  Proc.new { |a| a + arg }
end

p = proc_maker(10)
p.call(25) # return => 35
proc as closure
1
2
3
4
5
6
def to_do(p)
  p.call
end

p = Proc.new { puts "proc" }
to_do(p) # prints proc
proc as closure
1
2
3
4
5
6
7
8
9
10
11
12
def to_do(proc1, proc2)
  proc1.call
  proc2.call
end

a = Proc.new { puts "first proc" }
b = Proc.new { puts "second proc" }
to_do(a, b)

# prints
# first proc
# second proc

3. Lambda
Lambdas are a more strict form of Proc, something like:
- Lambda are more strict with regard to argument checking.
- Lambdas can return a value with the return keyword.

default lambda
1
2
l = lambda { puts "Hello Rubyist" }
l.call # prints "Hello Rubyist"
lambda with parameter
1
2
l = lambda { |a, b| puts "x: #{a}, y: #{b}" }
l.call(1, 2) # prints x: 1, y: 2
lambda as closure
1
2
3
4
5
6
def lambda_maker(arg)
  lambda { |a| a + arg }
end

l = lambda_maker(10)
l.call(25) # return 35
lambda as closure
1
2
3
4
5
6
def to_do(l)
  l.call
end

l = lambda { puts "lambda" }
to_do(l) # prints lambda
lambda as closure
1
2
3
4
5
6
7
8
9
10
11
12
def to_do(lambda1, lambda2)
  lambda1.call
  lambda2.call
end

a = lambda { puts "first proc" }
b = lambda { puts "second proc" }
to_do(a,b)

# prints
# first proc
# second proc

What Is Block?

A block is just a bit of code that can be executed.

example
1
2
3
4
5
6
[1, 2, 3].each { |num| puts num }

# print
# 1
# 2
# 3
example
1
2
3
4
5
6
7
8
[1, 2, 3].each do |num|
  puts num
end

# print
# 1
# 2
# 3

A block is a piece of code that is declared but not run in the place it’s written. The idea is to run when to call it.

default block using yield
1
2
3
4
5
6
7
8
9
10
11
12
def to_do
  yield
  yield
end

to_do do
  puts "hello"
end

# print
# hello
# hello
block with parameter using yield
1
2
3
4
5
6
7
8
9
10
11
12
def to_do
  yield "bunlong"
  yield "sky"
end

to_do do |name|
  puts "hi, #{name}"
end

# print
# hello, bunlong
# hello, sky
default block using call
1
2
3
4
5
def method_name(&block)
  block.call
end

method_name { puts "hello" } # prints hello
block with parameter using call
1
2
3
4
5
6
7
8
9
10
11
12
def eat(meal, &consume)
  if block_given?
    meal.each {|good| consume.call(good)}
  end
end

puts eat(['cheese', 'steak', 'wine']) {|food| puts 'Hmm, #{food}'}

# prints
# Hmm, cheese
# Hmm, steak
# Hmm, wine

AbstractClass

example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class AbstractKlass
  def method_name
    puts "#{hello} #{name}"
  end
end

class ConcreteKlass < AbstractKlass
  def hello; "Hello"; end
  def name; "Rubyist"; end

  # def hello
  #   "Hello"
  # end

  # def name
  #   "Rubyist"
  # end
end

ConcreteKlass.new.method_name # => "Hello Rubyist"  

Method_missing

method_missing use for creating dynamic methods.

example

example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Klass
  def method_missing(method_name, *args, &block)
    if method_name.to_s =~ /^find_by_(.+)$/
      run_find_by_method($1, *args, &block)
    else
      super
    end
  end

  def run_find_by_method(attrs, *args, &block)
    attrs = attrs.split('_and_')

    attrs_with_args = [attrs, args].transpose

    conditions = Hash[attrs_with_args]

    str = ''
    conditions.each { |key, value|
      str += "#{key} = '#{value}' and "
    }

    p "select * from tbl where #{str[0..-6]}"
  end
end

k = Klass.new
k.find_by_name("Bunlong")
k.find_by_name_and_email("Bunlong", "bunlong.van@gmail.com")