giovedì 27 novembre 2014

Create la tua Dashboard con freeboard e PubNub

ciao,
in questo post spiego brevemente come creare una semplice ma efficace dashboard basata su un paio di servizi molto interessanti:



Ci sono due concetti fondamentali:

  • DataSource: cioe' come e da dove la dashbaord riceve i dati da visualizzare
  • Widget: oggetto grafico che visualizza in modo specifico i dati provenienti dal DataSource 







Questi sono i tipi di DataSource supportati ad oggi:




Mentre i Widget supportati sono i seguenti:





E' possibile sviluppare il proprio widget in modo da visualizzare al meglio i propri dati. Questo pero' non fa parte di questo post.


Temperatura Ambienti

Vediamo adesso un esempio pratico. Immaginiamo che in ogni stanza della nostra casa abbiamo un termometro connesso che sia in grado di inviare le letture della temperatura via Internet.

In questo caso immaginiamo che il termometro invii periodicamente il valore di temperatura rilevato come messaggio PubNub su un canale dedicato (e.g. temp1, temp2, temp3)

Per emulare il nostro termometro usiamo PubNub Console. Qui impostate la vostra pub e sub key e inserite il nome del canale.





In questo modo possiamo inviare un semplice messaggio contenente la temperatura della stanza.

Adesso dobbiamo creare la nostra Dashboard:

Dopo aver effettuato il login su freeboard crea una nuova dashboard inserendo il nome.

A questo punto dobbiamo creare un DataSource che "ascolti" il nostro sensore di temperatura (PubNub console nel nostro esempio):

  • Aggiungi un DataSource di tipo PubNub
  • Name: Cucina (o quello che preferisci)
  • Subscriber Key: e' la SUB KEY di PubNub. Deve coincidere con quella inserita in PubNub Console
  • Channel: il canale su cui mettersi in ascolto per le letture di temperatura. Deve coincidere con quello inserito in PubNub Console




Adesso che abbiamo creato un DataSource valido aggiungiamo il widget in questo modo:

  • ADD PANE: un nuovo pannello vuoto viene creato
  • Fai click sull'icona +:
  • TYPE: Sparkline 
  • TITLE: Temperatura Cucina
  • VALUE: datasources["Cucina"]["temperatura"]




A questo punto un nuovo widget vuoto di tipo Sparkline viene aggiunto alla tua dashboard




Adesso non ci resta che inviare le letture di temperatura tramite PubNub Console (prova ad inviare 5 letture diverse di temperatura). In realta' queste saranno inviate dal nostro termometro intelligente in modo automatico

Ogni volta che invierete una nuova lettura di temperatura il vostro widget nella vostra dashboard si aggiornera' automaticamente.





Spero sia utile.

Altre idee su come usare freeboard? dai aspetto i vostri commenti






martedì 25 novembre 2014

Controllo Remoto per Caldaia - Raspberry e Client SW

Dopo aver visto come assemblare la parte HW/elettrica per il nostro  Controllo Remoto per Caldaia - HW in questo post descrivo come ho realizzato il software per il Raspberry

Architettura SW





Raspberry pi SW

Come avrete letto negli altri post sono un estimatore del pattern Publish-Subscribe e la rete PubNub lo implementa egregiamente.

Piu' nello specifico il Raspberry Pi si comporta da Subscriber in quanto ascolta il canale di comunicazione e attende la recezione di messaggi indirizzatti al Raspberri.

Al contrario i vari client (nel mio caso semplicissima web app per mobile e calendario di configurazione per PC) si comportano da Publisher in quanto inviato messaggi di comando indirizzati al Raspberry.

Tutti i messaggi sono protetti da encryption AES e sono veicolati su un canale SSL (PubNub fornisce tutti questi servizi). In aggiunta ho implemntato un semplice meccanismo di autorizzazione in modo da essere sicuro che soltanto i client autorizzati (i miei) possano pilotare la mia caldaia.

Per chi ricorda questo episodio di Big Bang Theory https://www.youtube.com/watch?v=BW9FbjjkKo4 alla fine della puntata dei ragazzi asiatici accendono e spengono le luci di Howard. Ecco noi cerchiamo di evitare questa cosa... :)


Vantaggi

Come e' ovvio altri tipi di arcitetture o meccanismi di comunicazione sono possibili.
Io ho scelto di usare PubNub in quanto:

  • PubNub fornisce un SDK praticamente per qualunque piattaforma esistente
  • Il software su Raspberry e' semplificato al massimo
  • Non devo far girare un webserver e quindi aprire una porta del mio firewall
  • Posso implementare semplicemente un mecchanismo di analytics/monitoring

Codice

Ho messo a disposizione di tutti su GitHub il codice che deve girare sul Raspberry.
Chiunque lo puo' scaricare e migliorare. 


Client SW

Per il lato client ho sviluppato 2 semplicissime applicazioni che girano su OpenShift (come avrete letto nei post precedenti sono un'utente di OpenShift molto soddisfatto - il datacenter e' Cisco UCS).


La prima e' una semplice applicazione web che mi permette di controllare lo stato della caldaia e di accenderla e spegnerla su mio comando.




Come potete vedere la veste grafica e' veramente poco attraente. Se qualcuno di voi ha capacita' grafiche si faccia avanti. Aiutera' certamente a migliorare questo progetto


La seconda e' un'applicazione legegrmente piu' complessa che va usata su PC e permette la programmazione settimanale della caldaia. Esattamente come il termostato a muro ma molto piu' flessibile.



Come vedete in figura io uso nella mia programmazione anche le informazioni relative alle valvole termostatiche applicate sul termosifone ma e' solo una visualizzazione grafica.
Cio' che accende e spegne la caldaia sono solo gli eventi "caldaia" rappresentati in verde nel mio esempio.

Ovviamente le due applicazioni sono utilizzabili parallelamente. Quindi se ho programmato l'accensione della caldaia ad un certo orario e per esempio rietro a casa con 2 ore di ritardo posso decidere di spegnere la caldaia manualmente tramite la prima app.


Il codice di entrambe le applicazioni (e' una sola applicazione Rails) e' disponibile qui SMHAC


Spero questo vi sia utile e spero che qualcuno contribuisca al miglioramento della veste grafica.

domenica 23 novembre 2014

Controllo Remoto per Caldaia - HW

In questo post descrivo come ho sviluppato un semplice controllo remoto per il mio sistema di riscaldamente casalingo.

Il mio obiettivo e' di creare un semplice sistema che risponde a queste due domande:


  1. come accendo/spengo il riscaldamento quando sono fuori casa? 
  2. come programmo in modo flessibile il mio sistema di riscaldamento? 

Attualmente il riscaldamento autonomo e' controllato dal classico termostato a muro



Cio' non mi fornisce la flessibilita' richiesta per i punti #1 e #2

Un giorno che mi e' capitato un raspberry pi model B per le mani e quindi mi sono detto: perche' non rimpiazzare il termostato a muro con un raspberry?

Da qui ho iniziato questo home project.

Il primo passo e' stato ottenere l'approval dal mio boss (moglie ???) :), la quale ha immediatamente aggiunto un terzo requisito:

3. il controllo tramite termostato a muro deve sempre essere funzionante e non essere rimpiazzato dal raspberry

 Bene adesso che tutti i requisiti sono chiari posso iniziare la realizzazione.

Circuito Iniziale

Il circuito di accensione della caldaia e' il seguente:




Circuito Finale

Per rispettare il requisito #3 ho modificato questo semplice circuito nel modo seguente:




In questo modo abbiamo realizzato un OR logico tra il Raspberry Pi ed il termostato a muro permettendomi di soddisfare tutti e 3 i requisiti:


  1.  tramite il raspebbry posso far scattare il relay e quindi accendere/spegnere la caldaia da remoto
  2. tramite software posso programmare il raspberry per accendere e spegnere la caldaia in modo flessibile
  3. in caso in qui il Rasperry non funzioni (mancanza di rete, guasto, etc...) la caldaia viene attivata normalmente dal termostato a muro

Assemblaggio

Per realizzare il controllo remoto della caldaia ho utilizzato i seguenti componenti:


Passo 1: Preparazione del contenitore
Ho posizionato il raspberry in un angolo della scatola di derivazione, dove verra' poi fissato tramite una vite







Siccome la mia scatola di derivazione non e' grande abbastanza per contenere totalemnte il raspberry ho dovuto, in maniera un po' spartana, segnare con una matita dove dovranno essere create le fessure per il cavetto di alimentazione  e per la schedina SD.





Come notate le fessure sono state effettuate con un trapano ed una piccola punta da legno. Se avete uno strumento migliore otterrete delle fessure piu' regolari. Non sono proprio orgoglioso di come ho realizzato le fessure :)

Passo 2: Fissaggio Scatola a muro

Ho forato la scatola con una piccola punta in modo da poter inserire un dado e bullone per fissare il raspberry alla scatola.



Successivamente ho incollato la scatola al muro del mio vano caldaia tramite una colla "mille chiodi". In questo modo ho evitate di forare il muro e di inserire almeno due tasselli.

Ovviamente questa e' stata la mia preferenza. Il lettore e' libero di fissare la scatola al muro nel migliore dei modi.

Passo 3: Cablaggio Raspberry

Il cablaggio e' veramente semplice. Ci servono solamente:

  • VCC +5V
  • GND
  • 1x GPIO (#15) ma se ne puo' usare uno a piacere. Io ho scelto il 15 per ragioni di layout dei fili




In particolare ho cablato i fili sul raspberry in questo modo:



  • filo verde   -> +5V  = Pin 2
  • filo bianco -> GND = Pin 6
  • filo giallo  ->  GPIO 15 = Pin 10


Questi Pin sono validi per Raspberry B revision 2. Se usi un raspberry diversi assicurati di usare il GPIO layout corretto per evitare malfunzionamenti.




Passo 4: Cablaggio modulo rele'

Come visto nello schema del circuito finale devo aggiungere un rele' che sia pilotato da un GPIO (#15) del raspberry.

Tempo fa' ho acquistato un module relay a 5V da un sito online http://www.dx.com/p/arduino-5v-relay-module-blue-black-121354#.VHJFwIvF98E


Siccome avevo disponibile questo modulino l'ho usato per questo progetto. Ovviamente il lettore puo' decidere di usare un altro modulo oppure di usare un rele' senza modulo. Suggerisco in ogni caso l'aggiunta del diodo di protezione altrimenti si rischia di bruciare il raspberry o almeno la linea del GPIO usato.

Ho effettuato il cablaggio del modulo rele' in questo modo:




filo bianco ->  pin - del modulo
filo verde   ->  pin + del modulo
filo giallo   ->  pin S del modulo

Per ragioni di assemblaggio all'interno della scatola a muro ho usato 3 coppie di fili in modo da avere un cablaggio piu' lungo. Infatti con i fili a mia disposizione ho trovato difficile far restare in posizioni i fili sul connettore dei GPIO di raspberry. Al contrario con un cablaggio piu' lungo ho eviatto il problema.

Quindi nel mio caso ho poi collegato i fili dal raspberry a quelli del modulo rele' tramite un piccolo mammut




Questo cablaggio non e' obbligatorio. Lascio al lettore la decisione finale.

Passo 5: Assemblaggio del circuito nella scatola a muro

A questo punto abbiamo finito con i semplici cablaggi del raspberry e del modulo rele'. Adesso non mi resta che montare il tutto all'interno della scatola a muro.

Ho fissato il raspberry alla scatola tramite la vite precedentemente inserita. Assicuratevi che la colla mille chiodi abbia fatto presa bene (a me si e' staccata due volte :) )

Dopo ho collegato il Netgear WNCE2001  ad unaporta USB per l'alimentazione dello stesso ed un corto cavo ethernet alla porta del raspebrry.
In questo modo ho una connettivita' alla mia rete wifi stabile e funzionante.





Il dongle Wifi a mia disposizione si e' rivelato instabile e non affidabile.

Come sempre il lettore e' libero di utilizzare la soluzione preferita per avere connettivita' ad Internet.

Ora devo alloggiare il modulo rele' correttamente cablato come visto sopra.
Per far cio' ho adottato un piccolo stratagemma dato che non avevo altro spazio utile nella scatola a muro.
Ho inserito una piccola lastra di plexiglass sopra il raspberry e l'ho fissata tramite l'unica vite presente.




In questo modo ho creato un secondo "piano" su cui alloggiare  il modulo rele' che a sua volta e' fissato tramite l'unica vite presente.


Passo 6: Collegamento alla caldaia e chiusura scatola a muro

A questo punto siamo nella fase finale.


  • Inserimento scheda SD con Raspian e software di controllo
  • Inserimento spinotto di alimentazione
  • Collegamento al circuito di accensione della caldaia come definito nel circuito finale




Dopo di cio' ho chiuso la scatola a muro che le viti fornite


Se gradito si possono chiudere le fessure con silicone o altro sigillante. Io non l'ho fatto siccome sono lazy e siccome il vano caldaia e' completamente asciutto.

Ovviamente in un futuro (mai :) ) mettero' del nastro isolante per coprire i fili che per'altro sono gia isolati :). Insomma la parte da elettricista non mi interessa. :) La parte divertente e' il software di controllo.....

Ottimizzazioni

Possibili ottimizzazioni che ho gia' in mente:

  • sostituzione modulo Netgear per connettivita' Wifi con dongle USB funzionante
  • sostituzione raspberry con modello A+ di minor dimensioni e consumo
  • sostituzione scatola a muro con una di minor dimensioni
  • sostituzione raspberry con modulo arduino e ricevitore RF con conseguente riduzione costi

Software

In questo post Controllo remoto per caldaia e raspberry ho descritto il software per il Raspberry e per il client.

Conclusioni

Questo mini progettino casalingo mi ha divertito parecchio. Con poca spesa adesso ho un sistema di controllo del mio riscaldamento casalingo infinitamente piu' flessibile del classico termostato a muro.

Ovviamente avrei potuto cercare delle soluzioni sul mercato, ma in puro spirito "maker", "tinkering" e' piu' divertente farsi le cose dasolo.

Chiunque abbia delle migliorie si faccia sotto. Saro' ben felice di apportarle al mio progetto.


Nota

Nel mio caso ho notato che il raspberry dopo un certo periodo (circa 30+ minuti) di inattivita' perdeva la connettivita' wifi. Molto probabilmente e' dovuto ad uno stand-by del modulo Netgear.


Per evitare cio' ho aggiunto una semplicissima linea al cron

*/30 * * * * /home/pi/cron_ping.sh


more cron_ping.sh

#!/bin/bash



logger "*********************************************"

upt=`uptime | awk -F " " '{print $3}'`

for i in {1..3}; do

    ping -c 1 www.google.com

    logger `date` ping GOOGLE $i -- uptime: $upt

    sleep 1

done

logger "*********************************************"
Lo script e' banalissimo e pinga google per 3 volte ogni 30 minuti

Cosi' il problema e' stato risolto in maniera banale ed ora il raspberry e' sempre raggiungibile via Internet (ops non proprio da tutti ) :)

PS: tempo libero permettendo seguiranno un paio di post per il software di controllo sia lato server che lato client.....



venerdì 14 novembre 2014

Quickly add delayed job to your rails app

In some of my rails app I need to have delayed/background jobs as a consequence of a controller's action call

Below quick instructions on how to add delayed jobs to any rails app:


1- add the following to Gemfile

gem 'delayed_job'
gem 'delayed_job_active_record'
gem 'daemons'


2- execute bundle install

3- create the delayed jobs tables
rails generate delayed_job:active_record

4- migrate the DB
rake db:migrate

5- in your rails root create a directory called jobs

6- add the following lines in config/application.rb
config.autoload_paths += %W(#{config.root}/jobs) #autoload delayed_jobs job
Delayed::Worker.destroy_failed_jobs = false
Delayed::Worker.sleep_delay = 60
Delayed::Worker.read_ahead = 5 #default value

7- in the jobs directory creare delayed_task.rb
DelayedTask = Struct.new(:x, :y) do

def task_worker
    begin
        res = self.x + self.y
        Rails.logger.info "Task calculating x + y = " + res.to_s
   end
end

def perform
    task_worker
end
end

8- add somewhere in your controller

Delayed::Job.enqueue(DelayedTask.new(2,3), {:priority => 0, :run_at =>  Time.now + 10.seconds})
9- start the jobs worker
rake jobs:work
or
bin/delayed_job start
10- start your raisl app and when your controller method will be called a new delayed job (DelayedTask) will be schedule and execute at the proper time

martedì 26 agosto 2014

How to hot deploy a RedHat Openshift application

Some time when you make a change to your application (in my case is a rails application) you would like to deploy the code change to your running app without restarting the cartridge on Openshift.

By default every time you perform a git push to your Openshift application, the framework execute the entire stop, build, deploy and restart activities.
This might take quite some time and your online application will not be available for few minutes.

However if you want, you can instruct Openshift to Hot Deploy your application, which means git push your code changes without restarting the application.

This will definitely reduce the downtime of your application (in most of the cases only the web server will be restarted and not the entire application cartridge like Ruby or PHP).

Enabling Hot Deploy is easy.
Add an empty hot_deploy file in the .openshift/markers directory.
Deploy this change and Openshift will understand that it should not restart the entire application when you git push your code changes


# touch .openshift/markers/hot_deploy
# git add .
# git commit -m "implementing hot deploy"
# git push


If everything is correct, next time you will push code changes to your Openshift apps, you should see something similar

remote: Not stopping cartridge ruby because hot deploy is enabled

Now your code change will be online in a quite short amount of time and especially with a very limited app downtime.

venerdì 25 luglio 2014

How easily implement PubSub in your application with PubNub

I have recently got interested in PubSub message exchange pattern.
PubSub is a great way to decouple sender and receiver and to scale to large mass of subscribers.
For networking guys, this is somehow similar to multicast. I send my IP multicat packet and I don't know who is receiving it.
In PubSub is the same, Sender app send a message which is not addressed directly to any specific receiver. On the other side Receiver listen to the communication channel without looking for a specific client.

Here I am showing very basic usage of a great service called pubnub.
The service has a free tier for developer and for testing purposed. Should you find this service the right one for your application then you can purchase service directly on pubnub web site.

Anyway, let's see how to publish (send) a message and how to subscribe (receive) a message using pubnub.
I am showing code sample in Ruby, but please note that pubnub provide API/SDK to an impressive number of platform/languages

First of all register to pubnub. You can register with you Google account or create a free account.

After successful registration you will access to a page similar to this one




Here you need to take note of two important information:

  • Subscribe Key: necessary if you want to subscribe to channels and receive messages
  • Publish Key: necessary to send message to a channel

Let's now see the code of a very simple sender and receiver


# sudo gem install pubnub
# pubnub_receive.rb

#!/usr/bin/ruby

require 'pubnub'


pubnub = Pubnub.new(
 :publish_key   => 'your publish key',
    :subscribe_key => 'your subscribekey',
    :error_callback   => lambda { |msg| puts "Error connecting to PubNub: #{msg.inspect}" },
    :connect_callback => lambda { |msg| puts "Connected to PUBNUB: #{msg.inspect}" }
 )

message_cb = lambda { |msg|
 time = Time.now
 puts "-------Received Message-------"
 puts "Channel:: #{msg.channel}"
 puts "Message:: #{msg.message}"
 puts "Message received at #{time}"
 puts "------------------------------"
}

pubnub.subscribe(
    :channel  => 'mancusoa74demo',
    :callback => message_cb
 ) 

while(1) do
 puts "."
  sleep(5)
end

Pubnub.new creates a new pubnub object and connects us to the PubNub service.
You need to specify your publish and subscribe key otherwise you will not be able to send or receive messages.

Now that we have a valid pubnub object, we can subscribe to a channel.
This is done by calling the subscribe method on pubnub object.
We need to pass (at minimum) a channel name. Here I am also specifying a callback which is executed every time we receive a message from the channel.

In the call back I simply print out the channel name, the received message and the time on which the message has been received.

As we want to listen to the channel forever I have add a simple forever loop. This is obviously not appropriate for a real implementation, but you certainly get the point of this simple example.

That's it: this is all what you need to receive message from anywhere in the world, from any device on any platform. Beauty of PubSub pattern :)


# pubnub_send.rb

#!/usr/bin/ruby

require 'pubnub'
 
pubnub = Pubnub.new(
 :publish_key   => 'your publish key',
    :subscribe_key => 'your subscribekey',
    :error_callback   => lambda { |msg| puts "Error connecting to PubNub: #{msg.inspect}" },
    :connect_callback => lambda { |msg| puts "Connected to PUBNUB: #{msg.inspect}" }
 )

pubnub.publish(
 :channel  => 'mancusoa74demo',
    :message => !ARGV[0].nil?? Time.now.to_s + " ## " + ARGV[0] : "empty message",
 ) { |data| puts "Messaage status is #{data.response_message}" }


 sleep(1)


Similarly to sender, also to receive we need to connect to PubNub network and instantiate a Pubnub object.
Unlike the receiver, to send it is not needed to subscribe to a channel.

So in order to publish/send a message we call the publish method on the pubnub object.
You need to pass the channel name and the message you want to send.

Bam!!! as simple as that. You have now sent a message to all your subscribers around the world on different devices and platform. Again beauty of PubSub pattern :)

This model/service can be used for a tons of different purposes. Example: connect with your mobile subscribers, implement a scalable chat/messaging system, implement a scalable logging system, implement a scalable analytics system, ...

In conclusion I hope it is clear from this post that communicate with your subscribers is very simple and PubNub is offering the infrastructure to support your needs.

If you have ideas or experience how to use it in your domain let me know. I am always interested to discover new things.

Cheers

Note: In this post I discuss about pubnub service. I would like to make it very clear that I have absolutely  NO affiliation with pubsub. This is just the description of my finding while looking for cool technologies out there.

giovedì 24 luglio 2014

Build a simple RESTful Web Service JSON API with Ruby and Sinatra

In one my activities I have the needs to quickly prototype a RESTful web service API.
Obviously I want to do it with my current preferred language Ruby.

It is clear I can easily do it with Rails but probably it will be an overkill for what I need to do.
Reading different articles about major differences between Rails and Sinatra micro-framework I have decided to build the simple REST web service I need using Sinatra.

I am here sharing what I have done. This is something I put together quite quickly, so it is not complete.
Anyone of you which wants to help can contribute.

Let's install the necessary ruby gems.

# cd ~
#
# mkdir rails_api
#
# mkdir rails_api/json
#
# sudo gem install sinatra
#
# sudo gem install rabl
#
# sudo gem install oj
#
# sudo gem install data_mapper
#
# sudo gem install dm-sqlite-adapter
#
# sudo gem install thin

I am using Rabl gem as this provides great flexibility in creating JSON replies to API request

Now in the rails_api/json directory create 3 files with the below content

#post.rabl
object @post
attributes :id, :title, :body

#posts.rabl
collection @posts
attributes :id, :title, :body

#error.rabl
object @error
attributes :message

Those files render the JSON replay to our RESTful API call. Now in the rails_api directory create the following file
#rest_api.rb

require 'rubygems'
require 'sinatra'
require 'rabl'
require 'data_mapper'
require 'json' 

######## setup sqlite DB ########
DataMapper.setup(:default, 'sqlite:rest_api.db')

######## Post Model ########
class Post
  include DataMapper::Resource

  property :id,         Serial    # An auto-increment integer key
  property :title,      String    # A varchar type string, for short strings
  property :body,       Text      # A text block, for longer string data.
end

DataMapper.finalize
Post.auto_upgrade!


######## Very simple Error class ########
class Error 
 attr_accessor :message
 def initialize(mex)
  @message = mex
 end
end

######## register Rabl. This is required for Sinatra ########
Rabl.register!

######## retrun 404 in case of invalid URL request ########
not_found do
 status 404 #page not found
end

######## simple helper to return HTTP 400 ########
def status_400(mex)
 @error = Error.new(mex)
 status 400
 rabl :'error', :format => "json", :views => 'json' 
end

######## simple helper to return HTTP 404 ########
def status_404(mex)
 @error = Error.new(mex)
 status 404
 rabl :'error', :format => "json", :views => 'json' 
end

######## simple helper to return HTTP 200 ########
def status_200
 status 200
end

######## simple helper to return HTTP 201 ########
def status_201(link)
 status 201
 #headers "location:/post/43"
 headers "Location"   => link
end

######## REST CRUD APIs for Post resource ########

######## index of Post ########
#GET post
get '/post' do 
 @posts = Post.all
 if @posts.empty?
  status_404("The reuqested resource does not exists")
 else
  status_200
    rabl :'posts', :format => "json", :views => 'json'
   end
end

######## show one Post ########
# GET /post/:id
get '/post/:id' do
 @post = Post.get(params[:id])
 if @post.nil?
  status_404("The reuqested resource does not exists")
 else
  status_200
    rabl :'post', :format => "json", :views => 'json'
   end
end

######## create a Post ########
#POST /post
post '/post' do
 begin
  post_data =  JSON.parse request.body.read 

  if post_data.nil? or !post_data.has_key?('title') or !post_data.has_key?('body')
   raise "exception"
  else
   post = Post.create(:title => post_data['title'], :body => post_data['body'])
   post.save
   status_201("/post/#{post.id}")
  end
 rescue => ex
  status_400("Invalid client request")
 end
end

######## Update a Post ########
#PUT /post/:id
put '/post/:id' do
 begin
  put_data =  JSON.parse request.body.read 

  if put_data.nil? or !put_data.has_key?('title') or !put_data.has_key?('body')
   raise "exception"
  else
   post = Post.get(params[:id])
   if post.nil?
    status_404("The reuqested resource does not exists")
   else
    post.title = put_data['title']
    post.body = put_data['body']
    post.save
    status_200
   end
  end
 rescue => ex
  status_400("Invalid client request")
 end

end

######## Remove a Post ########
#DELETE /post/:id
delete '/post/:id' do
 post = Post.get(params[:id])
 if post.nil?
  status_404("The reuqested resource does not exists")
 else
  post.destroy
  status_200
 end
end
Ok now just run it with
# ruby rest_api.rb -o 0.0.0.0
You should get something like this
== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from Thin
Thin web server (v1.6.2 codename Doc Brown)
Maximum connections set to 1024
Listening on 0.0.0.0:4567, CTRL+C to stop

Let's now test our RESTful Web Service. You can use your preferred tool like POSTMAN in Chrome.
I will use the always available curl to test the typical CRUD functions

CREATE

# curl -H "Content-type: application/json" -X POST  -d '{"title": "post1", "body": "this is post 1"}'  http://127.0.0.1:4567/post
READ
# curl  http://127.0.0.1:4567/post

# curl  http://127.0.0.1:4567/post/1
UPDATE
# curl -H "Content-type: application/json" -X PUT  -d '{"title": "post 5", "body": "this is post #5"}'  http://127.0.0.1:4567/post/1
DELETE
# curl -X DELETE http://127.0.0.1:4567/post/1

I am sure it is quite easy to argue that the HTTP return code I have used are not correct. Looks like this is quite an open topic.

In my example here I have mapped HTTP Status Code to REST call according to what described in this article (Using HTTP Status Codes correctly in your REST Web API)

As always let me know about any improvement, suggestion or correction.

Hope this helps someone out there.


martedì 15 luglio 2014

rails console and dbconsole on OpenShift

in my rails development environment I can start the console or the DB console by issuing the well know commands:


rails c(onsole)
rails dbconsole

In order to achieve the same result in production environment on OpenShift issue the following:

cd $OPENSHIFT_REPO_DIR

RAILS_ENV=production bundle excec rails c(onsole)

RAILS_ENV=production bundle excec rails dbconsole

lunedì 14 luglio 2014

How to force HTTPS on Openshift for Rails applications

RedHat OpenShift provides the possibility to enable HTTPS for your Rails application.

By default your Rails application will be available on

http://appname-domain.rhcloud.com

and

https://appname-domain.rhcloud.com

In my applications I want every request to be handled by HTTPS. In order to achieve that add to your public directory a .htaccess file with the below content


RewriteEngine on


RewriteCond %{HTTP:X-Forwarded-Proto} !https

RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [R,L]


For additional information for non-Apache based applications check OpenShift article out

mercoledì 2 luglio 2014

How to delete a scheduled rails delayed_job

In one of my "experiment" I am using collectiveidea/delayed_job gem to execute background and delayed tasks/jobs.

Now the question is: how to delete a job  which has already been scheduled/queued?

As simple as that:



#schedule a delayed method call
dj = reminder.delay(run_at: 5.minutes.from_now).send #this is your delayed method object

#delete a scheduled delayed job
djid = dj.id #this is the assigned delayed_job id

Delayed::Job.delete(djid)