<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Christoph Bünte &nbsp;&raquo; Software Entwicklung Berlin</title>
	<atom:link href="http://www.christophbuente.de/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.christophbuente.de</link>
	<description>Software Entwicklung</description>
	<lastBuildDate>Tue, 07 Dec 2010 11:30:07 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.5</generator>
		<item>
		<title>Rails Hosting bei Rocket Rentals &#8211; auch mit Staging Umgebung</title>
		<link>http://www.christophbuente.de/2010-07-20-rails-hosting-bei-rocket-rentals-auch-mit-staging-umgebung/</link>
		<comments>http://www.christophbuente.de/2010-07-20-rails-hosting-bei-rocket-rentals-auch-mit-staging-umgebung/#comments</comments>
		<pubDate>Tue, 20 Jul 2010 09:19:09 +0000</pubDate>
		<dc:creator>Christoph Bünte</dc:creator>
				<category><![CDATA[howto]]></category>
		<category><![CDATA[Apache]]></category>
		<category><![CDATA[Capistrano]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[hosting]]></category>
		<category><![CDATA[passenger]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[staging]]></category>
		<category><![CDATA[Virtualhost]]></category>

		<guid isPermaLink="false">http://www.christophbuente.de/?p=449</guid>
		<description><![CDATA[Mein aktuelles Projekt an dem ich arbeite ist wheelmap.org. Wheelmap.org stellt eine Anwendung für Rollstuhlfahrer bereit, die es ihnen ermöglicht herauszufinden, welche Orte rollstuhlgerecht sind, und welche nicht. So werden Orte aufgezeigt, welche Fahrst&#252;hle, abgesenkte Bordsteinkanten oder auch sogenannte Rollstuhllifte anbieten. Wheelmap wird auf den Server von Rocket Rentals gehostet. Die Jungs von Rocket Rentals [...]]]></description>
			<content:encoded><![CDATA[<p>Mein aktuelles Projekt an dem ich arbeite ist <a title="Rollstuhlgerechte Orte finden" href="http://wheelmap.org">wheelmap.org</a>. Wheelmap.org stellt eine Anwendung für Rollstuhlfahrer bereit, die es ihnen ermöglicht herauszufinden, welche Orte rollstuhlgerecht sind, und welche nicht. So werden Orte aufgezeigt, welche Fahrst&uuml;hle, abgesenkte Bordsteinkanten oder auch <a href="http://www.lifta.de/treppenlift/rollstuhllift.html">sogenannte Rollstuhllifte</a> anbieten. Wheelmap wird auf den Server von <a title="To the web and back" href="http://www.rocket-rentals.de/de/">Rocket Rentals</a> gehostet. Die Jungs von Rocket Rentals bieten neben Rails Hosting auch <a title="CoWorking bei Rocket Rentals" href="http://www.rocket-rentals.de/coworking">Co-Working Space</a> und professionelle Anwendungsentwicklung.<br />
Da ich hauptsächlich in meinem Büro entwickle, besteht die Notwendigkeit in regelmässigen Abständen meinen Fortschritt zu präsentieren. Und das möglichst auf einem Server im Netz und nicht auf meiner Entwicklungsmaschine. Dafür eignet sich die Live Anwendung allerdings schlecht. Kleinere Fehler oder unvollständige Features möchte man nicht auf den echten Benutzer loslassen. Deswegen habe ich eine Staging Umgebung eingerichtet, die jeweils den aktuellen Entwicklungsstand zeigt. Die Live Umgebung läuft weiterhin nur mit einer stabilen Version. Und so gehts:<span id="more-449"></span>Als erstes muss in DNS Konfiguration eine Subdomain eingerichtet werden. Das ist von Rocket Rentals unabhängig und sollte durch den DNS Provider oder auf dessen Weboberfläche vorgenommen werden. In meinem Fall ist die Domain: <a href="http://staging.wheelmap.org">staging.wheelmap.org</a></p>
<p><img class="alignleft size-medium wp-image-460" style="margin: 5px;" title="screenshot_admin_rocket_rentals" src="http://www.christophbuente.de/wp-content/uploads/screenshot_admin_rocket_rentals-300x147.jpg" alt="screenshot_admin_rocket_rentals" width="300" height="147" /> Damit der Rocket Rentals Server richtig auf den Request reagieren kann, muss im Admin Frontend ebenfalls eine Subdmain angelegt werden. Dazu logged man sich unter beim <a title="Rocket Rentals Login" href="https://login.rocket-rentals.de:8080/">Hosting</a> ein. Im oberen Menü wählt man &#8220;Sites&#8221;. Aus dem linken Menü wählt man dann &#8220;Subdomain&#8221; aus. Das Host Feld beinhaltet den Namen der Subdomain. Der Redirect Type ist &#8220;No flag&#8221;. Der Redirect Path ist &#8220;/&lt;subdomain&gt;_&lt;domain&gt;_&lt;tld&gt;&#8221;. Beispiel: &#8220;/staging_wheelmap_org&#8221;. Nach dem Speichern dauert es höchstens 15 Minuten, bis die Änderungen aktiv sind. In der Zwischenzeit können wir aber schon eine neue Datenbank anlegen. Das ist besonders wichtig, da wir nicht die Produktivdatenbank versehentlich verändern wollen, wenn die Auftraggeber die neue Version ausprobieren und dabei Daten manipulieren. Auch das kann auf der Admin Seite des Rocket Rentals Frontend geschehen. Usernamen und Passwort für die Datenbank nicht vergessen!</p>
<p>Dann muss auf dem Rechner, der das deployment durchführt eine Capistrano Erweiterung installiert werden:</p>
<pre lang="bash&quot;">sudo gem install capistrano-ext</pre>
<p>Danach muss die deploy.rb Datei etwas angepasst werden. Füge folgende Zeilen an den Anfang der Datei:</p>
<pre lang="ruby"># config/deploy.rb

set :stages,        ['staging', 'production']
set :default_stage, 'staging'
require 'capistrano/ext/multistage'</pre>
<p>Jetzt werden für jede Umgebung im Rails Projekt unter config/deploy/ eine eigene Datei mit dem Umgebungsnamen angelegt:</p>
<pre lang="bash">mkdir -p config/deploy
touch config/deploy/staging.rb
touch config/deploy/production.rb</pre>
<p>Aus der bisherigen deploy.rb Datei müssen folgende Zeilen in die config/deploy/production.rb kopiert werden:</p>
<pre lang="ruby"># config/deploy/production.rb

set :application, 'domain_tld' # Beispiel: wheelmap_org
set :db_names, :production =&gt; 'prod_db_name'
set :db_user, 'prod_db_username'
set :db_password, 'prod_db_password'
set :rails_env,   'production'</pre>
<p>Anschließend müssen diese Zeilen in der config/deploy.rb auskommentiert oder gelöscht werden.</p>
<p>In der config/deploy/staging.rb Datei müssen jetzt die Angaben für die Staging Umgebung gemacht werden:</p>
<pre lang="ruby"># config/deploy/staging.rb

set :application, 'subdomain_domain_tld' #Beispiel: staging_wheelmap_org
set :db_names, :production =&gt; 'staging_db_name'
set :db_user, 'staging_db_username'
set :db_password, 'staging_db_password'
set :rails_env,   'staging'</pre>
<p>Nun sind alle Vorbereitungen getroffen und wir können die Staging Umgebung einrichten:</p>
<pre>cap staging deploy:setup</pre>
<p>Danach kann die Anwendung deployed werden:</p>
<pre>cap staging deploy:cold</pre>
<p>Will man die Live Version deployen führt man folgenden Befehl aus:</p>
<pre>cap production deploy</pre>
<p>Bei Problemen oder Fragen einfach einen Kommentar hinterlassen.</p>
<div id="crp_related"><h3>Ähnliche Beiträge:</h3><ul><li><a href="http://www.christophbuente.de/2007-11-25-ruby-on-rails-auf-mac-os-x-5-minuten-kurzanleitung/" rel="bookmark" class="crp_title">Ruby on Rails auf Mac OS X &#8211; 5 Minuten Kurzanleitung</a></li><li><a href="http://www.christophbuente.de/2007-11-17-canoo-webtest-web-anwendungen-automatisch-testen/" rel="bookmark" class="crp_title">canoo webtest &#8211; Web-Anwendungen automatisch testen</a></li><li><a href="http://www.christophbuente.de/2007-11-24-advancing-rails-ein-workshop-mit-david-a-black/" rel="bookmark" class="crp_title">Advancing Rails &#8211; Ein Workshop mit David A. Black</a></li><li><a href="http://www.christophbuente.de/2007-12-21-voiceglue-konfiguration-server-fur-sprachanwendungen-einrichten/" rel="bookmark" class="crp_title">VoiceGlue Konfiguration &#8211; Server für Sprachanwendungen einrichten</a></li><li><a href="http://www.christophbuente.de/2008-07-01-mysql-myisam-index-oder-nicht/" rel="bookmark" class="crp_title">MySQL MyISAM &#8211; Index oder nicht?</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.christophbuente.de/2010-07-20-rails-hosting-bei-rocket-rentals-auch-mit-staging-umgebung/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Opensocial Gadgets &#8211; Apps für StudiVZ selbst entwickeln</title>
		<link>http://www.christophbuente.de/2009-10-29-opensocial-gadgets-apps-fur-studivz-selbst-entwickeln/</link>
		<comments>http://www.christophbuente.de/2009-10-29-opensocial-gadgets-apps-fur-studivz-selbst-entwickeln/#comments</comments>
		<pubDate>Thu, 29 Oct 2009 19:39:51 +0000</pubDate>
		<dc:creator>Christoph Bünte</dc:creator>
				<category><![CDATA[Web Entwicklung]]></category>
		<category><![CDATA[backend]]></category>
		<category><![CDATA[beispiel]]></category>
		<category><![CDATA[example]]></category>
		<category><![CDATA[gadgets]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[meinvz]]></category>
		<category><![CDATA[opensocial]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[schuelervz]]></category>
		<category><![CDATA[studivz]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[widgets]]></category>

		<guid isPermaLink="false">http://www.christophbuente.de/?p=399</guid>
		<description><![CDATA[Wie StudiVZ bereits angekündigt hat, werden die ersten opensocial Anwendungen für ihre Plattform bald live gehen. Entwickler können sich schon jetzt registrieren und ihre so genannten Gadgets in einer Sandbox ausprobieren. Ich habe das Vergnügen für meinen aktuellen Kunden DaWanda ein Gadget für StudiVZ zu entwickeln. Ein Gadget besteht aus einer XML Datei, die definiert, [...]]]></description>
			<content:encoded><![CDATA[<p>Wie <a href="http://developer.studivz.net/2009/09/24/opensocial-is-now-available-in-our-vz-sandbox/">StudiVZ</a> bereits angekündigt hat, werden die ersten <a href="http://code.google.com/intl/de-DE/apis/opensocial/">opensocial</a> Anwendungen für ihre Plattform bald live gehen. Entwickler können sich schon jetzt registrieren und ihre so genannten Gadgets in einer Sandbox ausprobieren.</p>
<p>Ich habe das Vergnügen für meinen aktuellen Kunden <a href="http://www.dawanda.com">DaWanda</a> ein Gadget für StudiVZ zu entwickeln. Ein Gadget besteht aus einer XML Datei, die definiert, um welche Anwendung es sich handelt, wer der Author ist usw. Dazu gehören wahlweise mehrere CSS und Javascript Dateien. Nachdem man alles in eine Zip Datei, die den gleichen namen wie die XML Datei trägt, gepackt hat, kann man die Anwendung in die Sandbox hochladen und ausprobieren. Eine Beispiel Datei könnte so aussehen:</p>
<pre escaped="true" lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;Module&gt;
  &lt;ModulePrefs
    title="Example StudiVZ Gadget"
    title_url="http://www.christophbuente.de"
    author="Christoph Bünte"
    author_email="info@christophbuente.de"
    description="Example description"
    screenshot="http://www.christophbuente.de/images/screenshot.jpg"
    thumbnail="http://www.christophbuente.de/images/thumbnail.jpg"&gt;
    &lt;Require feature="opensocial-0.8" /&gt;
    &lt;Require feature="views" /&gt;
  &lt;/ModulePrefs&gt;
  &lt;Content type="html" &gt;
    &lt;![CDATA[
      &lt;script&gt;
        function init() {
          // Put initialization code here
        }
        gadgets.util.registerOnLoadHandler(init);
      &lt;/script&gt;
    &lt;div id='container'&gt;&lt;/div&gt;
    ]]&gt;
  &lt;/Content&gt;
&lt;/Module&gt;</pre>
<p><span id="more-399"></span><br />
Jede Interaktion des Benutzers mit der Anwendung wird mit Hilfe weiterer Javascript Funktionen behandelt. Dazu stehen eine Reihe eingebauter Funktionen aus dem Opensocial Container bereit. Darüber hinaus haben die Entwickler von StudiVZ eine <a href="http://developer.studivz.net/wiki/index.php/Gadgets_API">API Beschreibung</a> der zusätzlichen Funktionen bereit gestellt. Was aber, wenn man nun nicht mit Javascript entwickeln möchte bzw. kann? Es besteht die Möglichkeit Flash Content einzubinden. Man kann aber auch ein beliebiges Backend einbinden. Dieses Backend muss nur 2 Bedingungen erfüllen:</p>
<ul>
<li>Es muss auf <acronym title="Hypertext Transfer Protocol">HTTP</acronym> Requests reagieren können und beliebiges <acronym title="Hypertext Markup Language">HTML</acronym>,<acronym title="Cascading Style Sheet">CSS</acronym> und JavaScript zurück liefern</li>
<li>Es muss im Namen des Applikationsbenutzers einen OAuth signierten Request an die StudiVZ <acronym title="Representational State Transfer">REST</acronym> <acronym title="Application Programming Interface">API</acronym> schicken können.</li>
</ul>
<p><a href="http://www.christophbuente.de/wp-content/uploads/Bild-7.png"><img class="size-full wp-image-419 alignleft" title="Request Opensocial Backend" src="http://www.christophbuente.de/wp-content/uploads/Bild-7.png" alt="Schema: Request Opensocial Backend" width="348" height="376" /></a><br />
Wie im Schema zu sehen, sendet der User einen Request, um die Applikation zu benutzen. Der Container liest darauf hin den Inhalt der XML Datei aus. Dort ist neben einem DIV Container lediglich ein externes Javascript referenziert. In dem Javascript sind einfache Methoden zum Navigieren und Interagieren definiert. Das rendern des HTML übernimmt ein Ruby Backend. Das braucht zum Render unter Umständen noch zusätzliche Informationen wie zum Beispiel Name und Foto des Benuter usw. Diese Informationen holt es sich mit einem OAuth signierten Request von der abgebildeten REST API. Das vom Ruby Backend erzeugte HTML rendert der Opensocial Container in einem IFrame im Browser des Benutzers. Für eine bessere Übersicht definieren wir im XML einzelne Views, die jeweils einen eigenen Endpunkt im Backend haben. Eine einfache gadget.xml mit 2 definierten Views für Profil und Vollansicht mit Backend Anbindung:</p>
<pre escaped="true" lang="xml">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;Module&gt;
  &lt;ModulePrefs
    title="Spitzenmässiges StudiVZ Gadget mit Backendanbindung"
    title_url="http://www.christophbuente.de"
    author="Christoph Bünte"
    author_email="info@christophbuente.de"&gt;
    &lt;Require feature="opensocial-0.8" /&gt;
    &lt;Require feature="views" /&gt;
  &lt;/ModulePrefs&gt;
  &lt;Content type="html" view="profile" &gt;
    &lt;![CDATA[
      &lt;script type="text/javascript" src="http://www.yourbackend.com/profile.js" &gt;&lt;/script&gt;
      &lt;div id='profile'&gt;&lt;/div&gt;
    ]]&gt;
  &lt;/Content&gt;
  &lt;Content type="html" view="canvas" &gt;
    &lt;![CDATA[
      &lt;script type="text/javascript" src="http://www.yourbackend.com/canvas.js" &gt;&lt;/script&gt;
      &lt;div id='canvas'&gt;&lt;/div&gt;
    ]]&gt;
  &lt;/Content&gt;
&lt;/Module&gt;</pre>
<p>Das referenzierte Javascript ist ebenfalls sehr schlank. Darin wird lediglich eine Backend URL aufgerufen und deren Response Body in das profile bzw. canvas div geschrieben.</p>
<pre>function init{
  var url = 'http://www.yourbackend.com/profile/'
  var params = {};
  params[gadgets.io.RequestParameters.AUTHORIZATION]=gadgets.io.AuthorizationType.SIGNED;
  gadgets.io.makeRequest(url, requestCallback, params);

}

function requestCallback(obj) {
	document.getElementById('profile').innerHTML = obj.data;
}</pre>
<p>Damit die REST API benutzt werden kann, muss man sich an ihr Authentifizieren. Da das Backend aber dumm ist, hat es keine Userdaten, um sich dort anzumelden. Glücklicherweise ist der Request aus dem Javascript mit dem verschlüsselten Authentifierungsdaten des angemeldeten Anwendungsbenutzers signiert. Mit deren Hilfe können wir einen neuen, signierten Request erzeugen, den die API akzeptieren wird. Doch zuerst muss die Glültigkeit der Signatur überprüft werden:</p>
<p><code>sudo gem install oauth --source http://gemcutter.org</code></p>
<pre lang="ruby">
require 'oauth'
require 'oauth/consumer'
require 'oauth/request_proxy/action_controller_request'
require 'oauth/signature/rsa/sha1'
require 'oauth/signature/hmac/sha1'

class ApplicationController < ActionController::Base

  before_filter <img src='http://www.christophbuente.de/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> auth_required

  def oauth_required
    cert_file = File.join(RAILS_ROOT, 'public', 'public.cer')
    cert_str = File.read(cert_file)
    consumer = OAuth::Consumer.new(ConsumerToken, cert_str)

    begin
      pass = OAuth::Signature.build(request, :consumer => consumer).verify
      logger.info "Signature verification returned: #{pass}"
    rescue OAuth::Signature::UnknownSignatureMethod => e
      logger.error "ERROR "+ e.message
    end

    render :text => "OAuth access denied", :status => :unauthorized  unless pass
  end
</pre>
<p>Die URL für das öffentliche Zertifikat wird mit jedem Request mit geschickt. Einmal runterladen sollte reichen. Ich denke, man muss es nicht bei jedem Request erneut vom StudiVZ Server laden. Den Consumer Token findet ihr in der OAuth Section eurer Gadget Sandbox (http://www.meinvz.net/GadgetDeveloper/GadgetOAuth/xxx). xxx ist deine Gadget ID.</p>
<p>Sollte der before_filter nicht abbrechen war die Signatur korrekt und der Request kann bearbeitet werden. Aus einem mir nicht bekannten Grund ist der Request des Containers an das Backend mit der RSA-SHA1 Methode signiert. Dafür wird das Zertifikat benötigt. Für den Request an die API muss die HMAC-SHA1 Methode verwendet werden. Dafür wird ein neuer Consumer benötigt:</p>
<pre lang="ruby">def get_owner
  consumer = OAuth::Consumer.new(ConsumerToken, ConsumerSecret,
      :signature_method => 'HMAC-SHA1',
      :site => "http://sandbox.gadgets.apivz.net",
      :scheme => :query_string,
      :http_method => :get)
  requestor_param = {:xoauth_requestor_id => params[:opensocial_owner_id]}.to_param
  access_token = OAuth::AccessToken.new(consumer)
  response = access_token.get("/social/rest/people/#{params[:opensocial_owner_id]}/@self?#{requestor_param}")
  owner_attributes = JSON.parse(response.body)['entry']
end</pre>
<p>Feedback, Fragen und Kritik sind immer gerne willkommen.</p>
<div id="crp_related"><h3>Ähnliche Beiträge:</h3><ul><li><a href="http://www.christophbuente.de/2007-11-10-paypal-subscriptions-abonnements-in-java-integrieren/" rel="bookmark" class="crp_title">Paypal subscriptions &#8211; Abonnements in Java integrieren</a></li><li><a href="http://www.christophbuente.de/2010-07-20-rails-hosting-bei-rocket-rentals-auch-mit-staging-umgebung/" rel="bookmark" class="crp_title">Rails Hosting bei Rocket Rentals &#8211; auch mit Staging Umgebung</a></li><li><a href="http://www.christophbuente.de/2007-10-23-bots-aussperren-mit-captcha/" rel="bookmark" class="crp_title">captcha tutorial &#8211; Bots aussperren</a></li><li><a href="http://www.christophbuente.de/2007-12-06-voiceglue-installation-interactive-voice-response-leicht-gemacht/" rel="bookmark" class="crp_title">VoiceGlue Installation &#8211; Interactive Voice Response leicht gemacht</a></li><li><a href="http://www.christophbuente.de/2007-11-17-canoo-webtest-web-anwendungen-automatisch-testen/" rel="bookmark" class="crp_title">canoo webtest &#8211; Web-Anwendungen automatisch testen</a></li></ul></div>]]></content:encoded>
			<wfw:commentRss>http://www.christophbuente.de/2009-10-29-opensocial-gadgets-apps-fur-studivz-selbst-entwickeln/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using memcached (Feed is rejected)
Page Caching using memcached
Database Caching 5/18 queries in 0.025 seconds using memcached
Object Caching 683/709 objects using memcached

Served from: www.christophbuente.de @ 2012-02-07 08:00:08 -->
