<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Ralph von der Heyden]]></title><description><![CDATA[Software Developer]]></description><link>https://www.rvdh.de/</link><image><url>https://www.rvdh.de/favicon.png</url><title>Ralph von der Heyden</title><link>https://www.rvdh.de/</link></image><generator>Ghost 2.25</generator><lastBuildDate>Sat, 25 Jan 2020 19:33:15 GMT</lastBuildDate><atom:link href="https://www.rvdh.de/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Review of the 2015 Apple Macbook]]></title><description><![CDATA[<h3 id="tldr">TL;DR</h3>
<p>Many people turned up their noses on the new 2015 Macbook specs. My first reaction was &quot;skip&quot;, after reading the specs and trying the keyboard. Now, I'm loving it.</p>
<h3 id="lookingforanewmachine">Looking for a new machine</h3>
<p>The timing for the 2015 Macbook model was as right as it</p>]]></description><link>https://www.rvdh.de/2015/08/04/review-of-the-2015-apple-macbook/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd1b</guid><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Tue, 04 Aug 2015 12:11:21 GMT</pubDate><content:encoded><![CDATA[<h3 id="tldr">TL;DR</h3>
<p>Many people turned up their noses on the new 2015 Macbook specs. My first reaction was &quot;skip&quot;, after reading the specs and trying the keyboard. Now, I'm loving it.</p>
<h3 id="lookingforanewmachine">Looking for a new machine</h3>
<p>The timing for the 2015 Macbook model was as right as it gets. My Macbook Air was almost written off, and I was looking for a new machine. Using a MacBook Pro at work, I was about to buy a beefy machine of that kind for myself. Enter the introduction of the new Macbook. Size and screen seemed tempting. But as a developer, can you deal with that rather slow CPU, a new kind of keyboard and a touchpad sans mechanical click?</p>
<h3 id="tryingitout">Trying it out</h3>
<p>In order to find out, I tried one in the Apple Store Hamburg Jungfernstieg. What a gorgeous little thing it was! Such a slim body. So lightweight. A brilliant 12&quot; screen. Next, I tried the keyboard, and my sentiment flipped to the opposite. I could not really write on the keyboard. I missed keys, I pressed the wrong keys, I wasn't even able to touch type three consecutive words correctly. In my mind, I marked the 2015 Macbook as unsuitable for me.</p>
<h3 id="grievingaboutit">Grieving about it</h3>
<p>Yet, I could not get the compact form factor and the screen out of my mind. So I read reviews to find out if the new keyboard was something you could get used to. And indeed, reviewers had the same feeling as I did. The keys of the new keyboard have a lot less travelling distance while being pressed, so it takes some getting used to. But it's all fine after some weeks, they said.</p>
<h3 id="gettingone">Getting one</h3>
<p>So, I put all my prejudice aside, and ordered one. Could this little beauty work for me?</p>
<h4 id="thekeyboard">The keyboard</h4>
<p>Most important, the keyboard is great. It took a week or so to get used to it, but now I like it even better than the old Apple keyboard. In fact, keys on the old keyboard feel all wobbly and inaccurate once you get used to the new thing. After trying the keyboard for the first time, I thought &quot;No way they can put this in their Pro line machines!&quot;. Now I'm thinking &quot;I hope they'll put this in ALL of their machines!&quot;. That said, there is still room for improvement. I think Apple could increase key travel distance just a little bit on their thicker Macbook models. But the precision and larger surface area of the keys just feel great.</p>
<h4 id="thetrackpad">The trackpad</h4>
<p>I did not even realize that there is no mechanical click. Force touch seems nice, but I'm rarely using it. No big deal compared to the previous trackpad.</p>
<h4 id="thecpu">The CPU</h4>
<p>Performance is ok with the new Macbook. I have the 1,3 GHz version, and it's faster than my 2012 Macbook Air. That being said, I rarely had performance problems with my Macbook Air. I'm using the machine for software development, photo editing (Lightroom) and general tasks like web browsing, document editing etc. No issues so far.</p>
<h4 id="thescreen">The screen</h4>
<p>What a gorgeous little screen! Finally retina resolution in a compact portable MacBook! Mirroring is visible, but negligible. You can even use it outside in good weather, as long as you keep in the shadows.</p>
<h4 id="thebattery">The battery</h4>
<p>I only use the Macbook for a couple of hours each day, and I need to charge like every 3 days. Sounds legit. Charging works way faster than in my previous Macbook Air, but maybe that is because the battery was worn out.</p>
<h4 id="thelackofmagsafe">The lack of Magsafe</h4>
<p>I can live with it. On my desk, there's no danger of pulling the little thing off. Anywhere else I use it, I don't plug it in. Really, I thought this was a bummer, but until now, no big deal.</p>
<h4 id="thelackofports">The lack of ports</h4>
<p>I bought both the USB-C-to-USB-A adapter, AND the USB-C-to-USB-A/HDMI/USB-C adapter, throwing another 120 EUR or so at Apple. I don't even have use for HDMI, but I need to be able to plug in a hard drive and charge the machine at the same time, simple as that.</p>
<p>You have to know, I'm a hardcore laptop only user. I don't have any external screens, keyboards, mice or anything. Just the laptop, and I have everything I need to work. I once even <a href="http://de.slideshare.net/ralphvdh/small-screen-development">gave a talk</a> about it, although it is a bit outdated.</p>
<p>The lack of ports or card readers may seem disturbing at first, but I think it's a good thing. On the road, you rarely plug in anything but your headphones. And at home: Imaging plugging in just one port, just the one little thing, and being done with the stuff that most people have on their desks:</p>
<ul>
<li>power</li>
<li>keyboard</li>
<li>mouse</li>
<li>external screen</li>
</ul>
<p>It does not get more practical than this. If you are using an external screen, it can probably serve as an USB hub, too. This means no bigger mess on you desk than usual.</p>
<h3 id="conclusion">Conclusion</h3>
<p>I don't regret buying the 2015 Macbook model. It really is a great little machine. You may want to wait for the next upgrade, which will probably provide a more capable CPU and bigger RAM. If you don't need a beefy CPU, you'll be just fine.</p>
]]></content:encoded></item><item><title><![CDATA[Time based triggers in Ember.JS]]></title><description><![CDATA[<p>Sometimes you want to poll an API for new data periodically. Sometimes you depend on properties that change over time, but are out of Ember's control. Fear not, Ember's <code>run.later</code> has you covered.</p>
<p>If you want to re-evaluate a computed property on a schedule, you need to depend that</p>]]></description><link>https://www.rvdh.de/2014/11/14/time-based-triggers-in-ember-js/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd19</guid><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Fri, 14 Nov 2014 09:14:14 GMT</pubDate><content:encoded><![CDATA[<p>Sometimes you want to poll an API for new data periodically. Sometimes you depend on properties that change over time, but are out of Ember's control. Fear not, Ember's <code>run.later</code> has you covered.</p>
<p>If you want to re-evaluate a computed property on a schedule, you need to depend that property on a property that changes over time. Turns out that creating such a property is fairly simple. This function triggers a change every second:</p>
<pre><code>currentTimeMetronome: function() {
  var interval = 1000;
  Ember.run.later(this, function() {
    this.notifyPropertyChange('currentTimePulse');
    this.currentTimeMetronome();
  }, interval);
}.on('init'),
</code></pre>
<p>Computed properties can depend on the <code>currentTimePulse</code> to get re-evaluated every second:</p>
<pre><code>currentTime: function() {
  var date = new Date();
  return date.toString();
}.property('currentTimePulse'),
</code></pre>
<p>The trick is to use <code>Ember.run.later</code> here. It receives 3 arguments, the last being the time (in ms) to postpone running the function in the 2nd argument. The first argument is the context the function should be run in.</p>
<p>You can apply the same pattern to functions, for example to poll APIs for new data:</p>
<pre><code>App.IndexRoute = Ember.Route.extend({
  model: function() {
    var interval = 1000 * 60;
    Ember.run.later(this, function() {
      this.model().then(function(json) {
        this.controller.set('model', json);
      }.bind(this));
    }, interval);

    return Ember.$.getJSON('https://api.github.com/repos/emberjs/ember.js/commits');
  },
});
</code></pre>
<p>Check out this JSbin if you want to see a running demo:<br>
Demo: <a href="http://emberjs.jsbin.com/xoriq/6">http://emberjs.jsbin.com/xoriq/6</a><br>
Code: <a href="http://emberjs.jsbin.com/xoriq/6/edit?js,output">http://emberjs.jsbin.com/xoriq/6/edit?js,output</a></p>
<p><strong>UPDATE</strong>: Reader <a href="https://twitter.com/dhruvparmar">Dhruv Parmar</a> pointed me to an <a href="http://livsey.org/blog/2013/02/20/tick-tock/">article</a> by <a href="https://twitter.com/rlivsey">Richard Livsey</a> that shows how to &quot;install&quot; a clock inside your Ember app that is then injected into controllers, routes and the like. If you need a clock in multiple places, this is definitely the way to go. The downside of Richard's solution is using <code>setTimeout()</code>, which can be less efficient than <a href="http://emberjs.com/api/classes/Ember.run.html#method_later"><code>Ember.run.later</code></a>.</p>
]]></content:encoded></item><item><title><![CDATA[Simple file encryption on the command line]]></title><description><![CDATA[<p>If you quickly want to encrypt a file using the command line, you don't want to go all fancy with PGP and public keys and stuff. Your preinstalled openssl and a password is all you need.</p>
<p>Few people are aware of the fact that openssl can encrypt files, and fewer</p>]]></description><link>https://www.rvdh.de/2014/11/12/simple-file-encryption-on-the-command-line/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd18</guid><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Wed, 12 Nov 2014 10:01:23 GMT</pubDate><content:encoded><![CDATA[<p>If you quickly want to encrypt a file using the command line, you don't want to go all fancy with PGP and public keys and stuff. Your preinstalled openssl and a password is all you need.</p>
<p>Few people are aware of the fact that openssl can encrypt files, and fewer can memoize the right command line arguments. This is why I added these two zsh functions to my <code>~/.zshrc</code>:</p>
<pre><code>encrypt () { openssl des3 -in $1 -out $1.encrypted }
decrypt () { FILENAME=$(echo $1|sed -e 's/\.encrypted$//g'); openssl des3 -d -in $1 -out $FILENAME }
</code></pre>
<p>Now encryption is just a matter of running <code>encrypt secret.txt</code>. Decryption assumes the file has an <code>.encrypted</code> suffix, so you run it like <code>decrypt secret.txt.encrypted</code>. Finally, encryption as easy as pie! :)</p>
]]></content:encoded></item><item><title><![CDATA[Wrapping localStorage and other POJOs with Ember.Object]]></title><description><![CDATA[<p>While working in Ember.Object land, you benefit from all the binding and computed property magic EmberJS has to offer. But what to do when you have to step outside its doors?</p>
<p>It's actually fairly easy to wrap any JavaScript object using <code>Ember.Object</code>. You just have to make sure</p>]]></description><link>https://www.rvdh.de/2014/05/08/wrapping-localstorage-and-other-pojos-with-ember-object/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd16</guid><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Thu, 08 May 2014 19:12:58 GMT</pubDate><content:encoded><![CDATA[<p>While working in Ember.Object land, you benefit from all the binding and computed property magic EmberJS has to offer. But what to do when you have to step outside its doors?</p>
<p>It's actually fairly easy to wrap any JavaScript object using <code>Ember.Object</code>. You just have to make sure that all manipulations to the wrapped object are going through the wrapper, e.g. using <code>object.set(attribute, value)</code> instead of <code>object[attribute] = value</code>.</p>
<p>So, how about wrapping localStorage, so you can bind to its properties from other objects? Here's an example:</p>
<p><a class="jsbin-embed" href="http://jsbin.com/ketaqiwe/embed?output&height=450px">Ember Starter Kit</a><script src="http://static.jsbin.com/js/embed.js"></script></p>
<p>You can find the Source Code in the JavaScript tab. In essence, the wrapper uses the <code>unknownProperty</code> and <code>setUnknownProperty</code> methods to sync the <code>Ember.Object</code>'s attributes with the ones of the native object. That's pretty much all there is to it.</p>
<p>If you have trouble finding the templates, they are in the HTML tab.</p>
<p><a href="https://gist.github.com/ralph/b734f0bba0154c66a891">Here's a Gist</a> if you prefer to view it that way.</p>
]]></content:encoded></item><item><title><![CDATA[reptyr: Resume running processes in screen or tmux]]></title><description><![CDATA[<p>reptyr is a wonderful little utility for Linux systems which enables you to reattach long running processes in screen or tmux. Great if you started something and have to close ssh.</p>
<p>In order to install, you need to clone the <a href="https://github.com/nelhage/reptyr">repository</a>, run make and copy the <code>reptyr</code> binary to some</p>]]></description><link>https://www.rvdh.de/2014/03/26/reptyr-resume-running-processes-in-screen-or-tmux/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd15</guid><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Wed, 26 Mar 2014 12:34:24 GMT</pubDate><content:encoded><![CDATA[<p>reptyr is a wonderful little utility for Linux systems which enables you to reattach long running processes in screen or tmux. Great if you started something and have to close ssh.</p>
<p>In order to install, you need to clone the <a href="https://github.com/nelhage/reptyr">repository</a>, run make and copy the <code>reptyr</code> binary to some directory in your <code>$PATH</code>. Typical usage works like this:</p>
<ul>
<li>Start a long running process, e.g. <code>top</code></li>
<li>Background the process with CTRL-Z</li>
<li>Resume the process in the background: <code>bg</code></li>
<li>Display your running background jobs with <code>jobs -l</code>, this should look like this:
<ul>
<li><code>[1]+ 4711 Stopped (signal) top</code></li>
<li>(The <code>-l</code> in <code>jobs -l</code> makes sure you'll get the PID)</li>
</ul>
</li>
<li>Disown the jobs from the current parent with <code>disown top</code>. After that, <code>jobs</code> will not show the job any more, but <code>ps -a</code> will.</li>
<li>Start your terminal multiplexer of choice, e.g. <code>tmux</code></li>
<li>Reattach to the backgrounded process: <code>reptyr 4711</code></li>
<li>Detach your terminal multiplexer (e.g. CTRL-A D) and close ssh</li>
<li>Reconnect ssh, attach to your multiplexer (e.g. <code>tmux attach</code>), rejoice!</li>
</ul>
<p>I think reptyr is the perfect companion for tmux and should be installed on every Linux box, just like tmux.</p>
]]></content:encoded></item><item><title><![CDATA[Rails middleware to enable History API for your Single Page Apps]]></title><description><![CDATA[<p>Everybody loves single page apps, but paths containing a pound sign (&quot;#&quot;) are a little odd. This is why I like using the <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history">History API</a> in my <a href="http://emberjs.com/">EmberJS</a> powered apps.</p>
<p>Turning on History API in Ember is just the matter of <a href="http://emberjs.com/guides/routing/specifying-the-location-api/">switching an attribute</a>. But on the backend side,</p>]]></description><link>https://www.rvdh.de/2014/03/24/rails-middleware-to-enable-history-api-for-your-single-page-apps/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd14</guid><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Mon, 24 Mar 2014 14:24:37 GMT</pubDate><content:encoded><![CDATA[<p>Everybody loves single page apps, but paths containing a pound sign (&quot;#&quot;) are a little odd. This is why I like using the <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history">History API</a> in my <a href="http://emberjs.com/">EmberJS</a> powered apps.</p>
<p>Turning on History API in Ember is just the matter of <a href="http://emberjs.com/guides/routing/specifying-the-location-api/">switching an attribute</a>. But on the backend side, your server does not know that incoming paths are meant to be interpreted by your Ember app, not by the server. In larger deploys with a load balancer, you can setup rules to redirect API traffic (e.g. paths containing <code>/api/…</code>) to the backend server, and other traffic to the asset server. But if you're using a smaller setup, like a <a href="https://www.heroku.com/">Heroku</a> deployed app, it's easier to fix right in the Rails app with the <a href="https://github.com/jtrupiano/rack-rewrite">Rack::Rewrite</a> gem, as long as you namespace your API. Here's how to do it:</p>
<p>First, add these two gems to your Gemfile and run <code>bundle</code> after that:</p>
<pre><code>gem 'rails_12factor', group: :production # static file serving on Heroku
gem 'rack-rewrite' # for the actual rewriting
</code></pre>
<p>Then, add the following section to your <code>config/application.rb</code>:</p>
<pre><code>config.middleware.insert_before(Rack::Runtime, Rack::Rewrite) do
  index_file = Rails.root.join('public', 'index.html').to_s
  send_file(/.*/, index_file, if: -&gt;(rack_env) {
    rack_env['PATH_INFO'] !~ /^\/api.*$/
  })
end
</code></pre>
<p>This will direct all <code>/api/…</code> to the backend, all other paths are served by your Ember app in the <code>index.html</code> file. Static files will still be served, though, no matter the path.</p>
<p>This means that your JS app must be contained in the public folder of your Rails app. If you are using a build tool like <a href="http://iamstef.net/ember-app-kit/">Ember App Kit</a>, this is easy to achieve:</p>
<pre><code>grunt dist &amp;&amp; rsync -av --delete dist/ ../backend/public
</code></pre>
<p>Run this from your JS app's folder, with <code>../backend/public</code> being the path to your Rails app's public folder.</p>
<p>I hope you found this useful. :)</p>
]]></content:encoded></item><item><title><![CDATA[Notizen zum Vortrag "EmberJS mit Rails" bei der Ruby Usergroup Hamburg, 12.03.2014]]></title><description><![CDATA[<p><em>Kleine Ergänzung:</em> Falls jemand von euch mit mir arbeiten möchte, ich bin ab ungefähr Mitte des Jahres wieder für neue Projekte zu haben. Konkrete Fragen zu dem Thema beantworte ich aber auch gerne per Mail. Andere Leute mit Erfahrungen in dem Bereich in Hamburg sind <a href="http://manuel.funkensturm.de/">Manuel Wiedenmann</a> und <a href="http://hawkins.io/">Adam Hawkins</a></p>]]></description><link>https://www.rvdh.de/2014/03/13/notizen-zum-vortrag-emberjs-mit-rails-bei-der-ruby-usergroup-hamburg-12-03-2014/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd13</guid><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Thu, 13 Mar 2014 19:52:02 GMT</pubDate><content:encoded><![CDATA[<p><em>Kleine Ergänzung:</em> Falls jemand von euch mit mir arbeiten möchte, ich bin ab ungefähr Mitte des Jahres wieder für neue Projekte zu haben. Konkrete Fragen zu dem Thema beantworte ich aber auch gerne per Mail. Andere Leute mit Erfahrungen in dem Bereich in Hamburg sind <a href="http://manuel.funkensturm.de/">Manuel Wiedenmann</a> und <a href="http://hawkins.io/">Adam Hawkins</a>.</p>
<h1 id="emberjsmitrails">EmberJS mit Rails</h1>
<h2 id="emberjs">EmberJS</h2>
<ul>
<li>Opinionated JS Framework</li>
<li>Wird verwendet von:
<ul>
<li>Yahoo</li>
<li>Netflix</li>
<li>Travis CI</li>
<li>Zendesk</li>
<li>Bustle</li>
<li>NBC News</li>
<li>Runtastic</li>
<li>Code School</li>
<li>Discourse</li>
<li>Ghost</li>
<li>Living Social</li>
<li>Vine.co</li>
<li>Harvest</li>
<li>Nest (gekauft von Google)</li>
<li>...</li>
<li>Beispiel: <img src="https://www.rvdh.de/content/images/2014/Mar/nbcnews-1.png" alt="nbcnews mit ember inspector"></li>
</ul>
</li>
<li>Viele unabhängige Unternehmen, die mit Ember Apps schon heute Geld verdienen</li>
<li>Qualität für den Produktionseinsatz bewiesen</li>
<li>Weiterentwicklung sichergestellt, Ökosystem vorhanden</li>
</ul>
<h3 id="emberjs">EmberJS</h3>
<ul>
<li>Framework für Single Page Apps</li>
<li>Aus einem Guss</li>
<li>Convention over Configuration</li>
<li>Man findet sich schnell zurecht</li>
<li>Aus einem Guss</li>
<li>In Ember sind zig Probleme, die einem als Entwickler begegnen, schon gelöst, z.B. Routing (State), Datei-Organisation, asynchroner Datenaustausch mit Assoziationen etc.</li>
<li>Relativ groß <img src="https://www.rvdh.de/content/images/2014/Mar/js_size-1.png" alt></li>
<li>Framework lock-in<br>
<img src="https://www.rvdh.de/content/images/2014/Mar/half_assed_framework-1.png" alt></li>
<li>Verwendet eigene Getter/Setter
<ul>
<li>Unschöner als POJOs (object.get('attribute') vs. object.attribute)</li>
<li>Man bekommt dafür tolle Features und alles ist rock solid</li>
<li>Schneller und oft stabiler als Angular (das watcher/notifier verwendet)</li>
<li>Man kann alles mit Ember.Object wrappen, z.B. LocalStorage</li>
</ul>
</li>
</ul>
<h2 id="emberjsvsangular">EmberJS vs. Angular</h2>
<ul>
<li>EmberJS:
<ul>
<li>&quot;A framework&quot;</li>
</ul>
</li>
<li>Angular:
<ul>
<li>&quot;A framework to build frameworks&quot;</li>
<li>&quot;Angular isn't a framework; it's an HTML compiler&quot;</li>
</ul>
</li>
</ul>
<h3 id="angular">Angular</h3>
<ul>
<li>Klein (der Code selbst, Abhängigkeiten)</li>
<li>Weniger Konventionen</li>
<li>Macht weniger als Ember</li>
<li>Viele Wege <img src="https://www.rvdh.de/content/images/2014/Mar/angular_routing.png" alt></li>
<li>Google hat bis jetzt keine User-facing-App mit Angular entwickelt</li>
<li>Angular 2.0 wird ein kompletter Rewrite, Kompatibilität mit aktuellen Anwendungen unbekannt</li>
<li>Supportet Google nach Erscheinen von v2.0 noch 1.0, obwohl sie es selbst nicht nutzen?</li>
</ul>
<h2 id="wiegehtember">Wie geht Ember?</h2>
<h3 id="router">Router</h3>
<ul>
<li>State</li>
<li>URL kopieren, Tab zu, URL pasten, alles wie vorher</li>
<li>Sorgt dafür, dass Models verfügbar sind</li>
<li>Unterstützt History-API (&quot;/foo&quot; anstatt &quot;/#/foo&quot;)</li>
</ul>
<h3 id="template">Template</h3>
<ul>
<li>Handlebars</li>
<li>Wie Rails Views</li>
<li>Schnurrbart-Platzhalter</li>
</ul>
<h3 id="component">Component</h3>
<ul>
<li>Eigene HTML-Tags (naja, Web Components)</li>
<li>Logik geschrieben in JS</li>
<li>Viele vorgefertigte, z.B. für Formularelemente, Links…</li>
<li>Können geerbt (angepasst) werden</li>
</ul>
<h3 id="model">Model</h3>
<ul>
<li>Repräsentieren Daten</li>
<li>POJOs, Ember.Objects, Ember Data…</li>
</ul>
<h3 id="controller">Controller</h3>
<ul>
<li>View-Controller (wie iOS, nicht wie Rails)</li>
<li>Repräsentieren Daten, die nur für den View gebraucht werden
<ul>
<li>z.B. PostController#hasComments</li>
</ul>
</li>
<li>Repräsentieren nicht-persistente Daten, z.B. Panel expand/collapsed-Status</li>
</ul>
<h3 id="view">View</h3>
<ul>
<li>Setzen DOM-Events in semantische Events um</li>
<li>Z.B. Element in Viewport -&gt; Formulardaten nachladen</li>
<li>So selten wie weiße Raben</li>
</ul>
<h2 id="emberjsmitrails">EmberJS mit Rails</h2>
<ul>
<li>Datenaustausch mit JSON-Backend</li>
<li>Backend-Seite: rails-api + <code>active_model_serializers</code></li>
<li>Frontend-Seite:
<ul>
<li><code>$.getJSON</code></li>
<li>Ember Data</li>
</ul>
</li>
<li>Token Based Authentication (z.B JWT)</li>
</ul>
<h3 id="emberdata">Ember Data</h3>
<ul>
<li>Definiert Models <img src="https://www.rvdh.de/content/images/2014/Mar/ember_data_model.png" alt></li>
<li>Austausch mit JSON-API
<ul>
<li><img src="https://www.rvdh.de/content/images/2014/Mar/finding_unloaded_record_step1_diagram.png" alt></li>
<li><img src="https://www.rvdh.de/content/images/2014/Mar/finding_loaded_record_diagram.png" alt></li>
</ul>
</li>
<li>Finding</li>
<li>Persisting</li>
<li>Metadata (z.B. Pagination)</li>
<li>Für Dev/Test:
<ul>
<li>FixtureAdapter</li>
<li>Toll, aber hat Macken</li>
</ul>
</li>
<li>Real Thing: ActiveModelAdapter</li>
<li>Anmerkung von <a href="http://manuel.funkensturm.de/">Manuel Wiedenmann</a>: Wenn man erst mal ohne Backend entwickeln will (zu empfehlen), der Fixture-Adapter aber Bugs hat, dann ist der <a href="https://github.com/rpflorence/ember-localstorage-adapter">Local Storage Adapter</a> sehr zu empfehlen.</li>
</ul>
<h2 id="buildprozess">Build-Prozess</h2>
<ul>
<li>Concat, Minify, develepment/production versions, cache busting…</li>
<li>Backend und Frontend in einer App oder getrennt?</li>
<li>Getrennt hat Vorteile:
<ul>
<li>UI-Entwickler brauchen keine Ruby/Rails-Installation</li>
<li>Entwicklung mit FixtureAdapter, <a href="https://github.com/rpflorence/ember-localstorage-adapter">Local Storage Adapter</a>, API-Stub oder API-Staging-Server</li>
</ul>
</li>
<li>Mit Sprockets
<ul>
<li>Rails Asset Pipeline</li>
<li>Rake Pipeline</li>
</ul>
</li>
<li>Mit Grunt
<ul>
<li>Ember App Kit</li>
<li>Brunch etc.</li>
</ul>
</li>
<li>Mit Broccoli
<ul>
<li><a href="https://github.com/stefanpenner/ember-cli">ember-cli</a></li>
<li>Neuer offizieller Weg</li>
<li>Ergänzung für Grunt, kein Ersatz</li>
</ul>
</li>
</ul>
<h2 id="deployment">Deployment</h2>
<ul>
<li>Separate Apps empfehlenswert</li>
<li>API-Namespace (z.B. &quot;/api/v1&quot;)
<ul>
<li><img src="https://www.rvdh.de/content/images/2014/Mar/rails_routes.png" alt></li>
<li><img src="https://www.rvdh.de/content/images/2014/Mar/ember_data_routes.png" alt></li>
</ul>
</li>
<li>Load Balancer:
<ul>
<li>Alles mit &quot;/api&quot; auf die Backend-Server</li>
<li>Alles andere auf den Static Assets Host</li>
<li>Bei History-API: Alles ohne API im Pfad, das keine statische Datei ist, auf die index.html auf dem Static Assets Host</li>
</ul>
</li>
<li>Einfaches Deployment mit Heroku
<ul>
<li>gem 'rails_12factor', group: :production</li>
<li>dist bauen</li>
<li>ins public-Verzeichnis vom Backen syncen</li>
<li>rsync -av --delete dist/ ../backend/public</li>
<li>backend deployen</li>
<li>Nachteil: Backend-Prozess wird neu gestartet</li>
</ul>
</li>
</ul>
<h2 id="entwicklungsprozess">Entwicklungsprozess</h2>
<ul>
<li>Frontend-getrieben</li>
<li>Fangt nicht mit der API an!
<ul>
<li>Die API passt nicht zum Frontend</li>
<li>Das Frontend passt nicht zum Product Owner und damit auch nicht zum Backend</li>
</ul>
</li>
<li>Erst mal nur Frontend machen</li>
<li>Daten mit POJOs oder Ember.Objects repräsentieren</li>
<li>Dann FixtureAdapter</li>
<li>SO LANGE WIE MÖGLICH OHNE API/BACKEND !!!</li>
<li>Nochmal: NICHT MIT DER API ANFANGEN!</li>
<li>Dann API-Anbindung</li>
</ul>
<h2 id="seocrawling">SEO/Crawling</h2>
<ul>
<li>Yahoo kann Ember (ein bisschen)</li>
<li>Dünne HTML-Schicht zwischen JSON und Crawler (z.B. Discourse)</li>
<li>Mit PhantomJS HTML generieren</li>
<li>Externe Services</li>
<li>NBCNews, Bustle etc. zeigen, dass es geht</li>
</ul>
<h1 id="fazit">Fazit</h1>
<ul>
<li>Ember ist toll und ausgereift</li>
<li>Ember Data ist ok bis gut, aber besser als alles andere</li>
<li>Rails nur als API vereinfacht den Backend-Part enorm
<ul>
<li>Anzahl Gems/Plugins… (Prozessgröße)</li>
<li>Code-Komplexität</li>
</ul>
</li>
<li>Frontend-first erzeugt schnelleres Feedback</li>
<li>Komplexer Frontend-Code sauberer als bei vielen Rails-Apps</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Introduction to strace]]></title><description><![CDATA[<p>Thinking that you have pretty profound UNIX knowledge? Think again if you don't know how to <code>strace</code>.</p>
<p>This <a href="http://chadfowler.com/blog/2014/01/26/the-magic-of-strace/">introduction to strace</a> by <a href="http://chadfowler.com/">Chad Fowler</a> finally persuaded me to check out this little UNIX tool. I made several attempts in the past, but each time I attached it to a running</p>]]></description><link>https://www.rvdh.de/2014/02/01/introduction-to-strace/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd10</guid><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Sat, 01 Feb 2014 13:54:07 GMT</pubDate><content:encoded><![CDATA[<p>Thinking that you have pretty profound UNIX knowledge? Think again if you don't know how to <code>strace</code>.</p>
<p>This <a href="http://chadfowler.com/blog/2014/01/26/the-magic-of-strace/">introduction to strace</a> by <a href="http://chadfowler.com/">Chad Fowler</a> finally persuaded me to check out this little UNIX tool. I made several attempts in the past, but each time I attached it to a running process, I just saw, well, gibberish. And as no one else on my teams in the last years was fluent with strace, I kind of gave it up each time. But by reading that post, I learned that this gibberish is not that hard to read after all. In fact, it's pretty much straight forward and contains so much useful information that is hard to obtain otherwise. I can only guess how many times this knowledge would have helped me in the past.</p>
<p>Related: <a href="http://jorge.fbarr.net/2013/09/19/introduction-to-lsof/">Introduction to lsof</a>, a great companion to strace.</p>
]]></content:encoded></item><item><title><![CDATA[Why I roll my own authentication]]></title><description><![CDATA[<p>This is what got me started writing this post:</p>
<p><img src="https://www.rvdh.de/content/images/2014/Jan/authentication_1.png" alt="Chat with phil76 1"><br>
<img src="https://www.rvdh.de/content/images/2014/Jan/authentication_2.png" alt="Chat with phil76 2"></p>
<p>In the Rails world, we are holding up the DRY principle high. One outcome of this is that people do put stuff that has to be done for many applications into gems, to be reused. Authentication is such a case, as</p>]]></description><link>https://www.rvdh.de/2012/01/12/why-i-roll-my-own-authentication/</link><guid isPermaLink="false">5be0af79faa38d02e21fbcfa</guid><category><![CDATA[rails]]></category><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Thu, 12 Jan 2012 11:00:00 GMT</pubDate><content:encoded><![CDATA[<p>This is what got me started writing this post:</p>
<p><img src="https://www.rvdh.de/content/images/2014/Jan/authentication_1.png" alt="Chat with phil76 1"><br>
<img src="https://www.rvdh.de/content/images/2014/Jan/authentication_2.png" alt="Chat with phil76 2"></p>
<p>In the Rails world, we are holding up the DRY principle high. One outcome of this is that people do put stuff that has to be done for many applications into gems, to be reused. Authentication is such a case, as you need authenticaton for nearly every web application you write. And <a href="https://github.com/plataformatec/devise">devise</a> seems to be the <a href="https://www.ruby-toolbox.com/categories/rails_authentication">most mature and poplular solution</a> in this regard. Yet I decided to roll my own authentication for my latest project. Why?</p>
<p>Well, first of all, I am trying to get rid of all external dependencies, wherever possible. In my last project, we used 161 (!!!) gems. It was not a crazily complex project, just a regular, larger web application.  But each and every gem has to be added to the load path, slowing down each and every require statement throughout the application. The led to server startup times of 15 seconds and above, depending on the machine.  To make things worse, this time was needed for every launch of the Rails console, for every single isolated test you would run. That is just too much wrench in the works for me, so I absolutely wanted to avoid this in my new project. So, no dependency if I do not absolutely need it.</p>
<p>The next point, however, is simple &quot;graspability&quot;. We all know source code is read far more often than written, so it should be easy for fellow developers to grasp what is going on. And although I like the devise source code, it is harder to grasp than code in your own application. First of all, people have to run <code>bundle open devise</code> to take look at the source. This is not really hard, but it is another obstacle. Next, the devise code is far more abstract than your own code.  You can name your user model <code>User</code>, but you could also name it <code>ChemistryTeacher</code>. The same is true for your Controllers. Devise can handle that, which is great! But this flexibility comes at a price, and that is the brainpower needed to understand how the code works. This problem becomes worse, as soon as you want to change some of the behaviour. Instead of just writing or adjusting the tests and implementing your code, you must go to great lengths to to find out how to hook into the existing gem code from your application. And the result? Not very satisfying. Some of the behaviour is defined in the gem, some in your application. Scattered in two places. Making graspability even harder.</p>
<p>My last point of criticism is bloat. Devise is very powerful, and certainly offers stuff I do not need. I just want session management and password reset. Yet the code for all the other stuff devise has to offer is loaded into memory when I require the gem. While this is negligible for a single gem, memory consumption becomes insanely high for each Rails process when you are using 161 gems.</p>
<p>Luckily, Rails 3.1 was out when I started on the new project, and this version introduced the <a href="http://api.rubyonrails.org/classes/ActiveModel/SecurePassword/ClassMethods.html#method-i-has_secure_password"><code>has_secure_password</code></a> method in <code>ActiveModel</code>. When I saw this in <a href="http://railscasts.com/episodes/270-authentication-in-rails-3-1">Ryan Bates Railscast</a>, it immediately clicked. For me, that is the least common denominator, the one thing that is the same for each and every application. I do not need a gem to define my controllers, because I will want to change their behaviour anyway, at some point of time. But what <code>has_secure_password</code> does, that is the one thing I will need anywhere.</p>
<p>So I just ditched every authentication gem out there and just went to write my own authenticaton. The process was smooth and easy, and in about a day of purely test driven development, I had a nice and easy to grasp authentication process inside my own application, with password recovery and everything else I need. And as soon as I or anyone else on the team wants to change the logic, she or he can just open their <code>test</code> and <code>app</code> folders and go for it. So in my opinion, it is absolutely worth trying.</p>
<p>So, what is your experience with authentication in Rails apps? Ever tried to roll your own? Would you do so in your next project?</p>
]]></content:encoded></item><item><title><![CDATA[Classes are separations of concerns or why too much magic hurts]]></title><description><![CDATA[<p>I am currently working on a project that requires me to scope nearly all database queries by <code>customer_id</code>, because, you probably get the idea, each and every customer has its own set of data. Furthermore, the <code>Customer</code> class does not inherit from <code>ActiveRecord::Base</code>, nor is it an <code>ActiveModel</code></p>]]></description><link>https://www.rvdh.de/2011/12/02/classes-are-separations-of-concerns-or-why-too-much-magic-hurts/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd0f</guid><category><![CDATA[rails]]></category><category><![CDATA[ruby]]></category><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Fri, 02 Dec 2011 11:19:00 GMT</pubDate><content:encoded><![CDATA[<p>I am currently working on a project that requires me to scope nearly all database queries by <code>customer_id</code>, because, you probably get the idea, each and every customer has its own set of data. Furthermore, the <code>Customer</code> class does not inherit from <code>ActiveRecord::Base</code>, nor is it an <code>ActiveModel</code> class.</p>
<p>So in order to create the scopes for all the classes, I created the following module, which is included in all the classes needing the scope:</p>
<pre><code># app/models/shared/customer.rb
module Shared
  module Customer
    extend ActiveSupport::Concern

    included do
      scope :for_customer, -&gt;(customer) do
        where(:customer_id =&gt; customer.to_i)
      end
    end
  end
end

# app/models/user.rb
class User &lt; ActiveRecord::Base
  include Shared::Customer
end
</code></pre>
<p>This scope helps already, but in the end I want to do the following in my controllers:</p>
<pre><code>@users = customer.users.all
@user = customer.users.find(params[:id])
@user = customer.users.new(params[:user])
</code></pre>
<p>So for each model including the shared customer module, I need to create a scope like that:</p>
<pre><code># app/models/customer.rb
class Customer
  def users
    User.for_customer(id)
  end
end
</code></pre>
<p>That seemed like to much work for me. I mean, we are using Ruby, and I do not want to do boring routing stuff. So I created the following magic which frees me of the task to create this association method by hand for nearly each and every model:</p>
<pre><code># app/models/shared/customer.rb
module Shared
  module Customer
    extend ActiveSupport::Concern

    included do |base|
      scope :for_customer, -&gt;(customer) do
        where(:customer_id =&gt; customer.to_i)
      end

      Customer.class_eval &lt;&lt;-EOS
        def #{base.tableize}
          #{base}.for_customer(id)
        end
      EOS
    end
  end
end
</code></pre>
<p>No more routine work, wheeeee! One might think. But of course, this code is causing problems. First of all, the load order matters now. If we log into <code>rails console</code> and try calling the users method on a customer object, we will be out of luck. This is because the <code>Customer</code> class by itself does not know that there might be another class putting code into the <code>Customer</code> class at some later point of time. And requiring all the classes by hand would make a mockery of the whole automation idea, plus it does not look very clean. This is not a problem in the production and test environment, because all the models get loaded there. But it will definitely fall on your feet while you are developing stuff, trust me.</p>
<p>The other problem is readability: How the heck is someone reading the <code>Customer</code> class supposed to know where the association comes from? And if she/he finds out after 2 hours, do not be surprised if she/he shouts death threats in your direction. So in the end I abandoned the whole idea, and settled for something else. I just created a new <a href="https://www.rvdh.de/2011/12/01/splitting-your-rails-classes-into-modules-how-does-it-work/">concern</a> for the customer class, taking care of the associations.</p>
<pre><code># app/models/customer/associations.rb
class Customer
  module Associations
    extend ActiveSupport::Concern

    module ClassMethods
      def associate_with(*item_names)
        item_names.each do |item_name|
          method = -&gt; { item_name.to_s.classify.constantize.for_customer(id) }
          define_method(item_name, method)
        end
      end
      private :associate_with
    end

    included do
      associate_with :users, :pizzas, :schnitzels
    end
  end
end

# app/models/customer.rb
class Customer
  include Associations
end
</code></pre>
<p>As you can see in the snippet, I still have to add each class that needs to be associated with <code>Customer</code> to the <code>associate_with</code> macro. But I can live with that. It's the best solution I could find, finally. Adding a word to the macro ain't too hard, and you can easily find the source of the association.</p>
<p>Plus, this code looks very clean to me. Classes should not know too much of each other, they may share data internally, but they ought to have a well defined interface externally. So a class walking over to another class, modifying its interface, that's just not very clean.</p>
<h4 id="conclusion">Conclusion:</h4>
<p>Use metaprogramming to free yourself from routine programming tasks and to create clean and concise code. But don't be too clever, and always think about the readability of your code. Because, remember, kids: Code is read much more often than it is written.</p>
<h4 id="conclusion2">Conclusion 2:</h4>
<p>Discussing stuff with other developers (<a href="http://twitter.com/codebeaker">Lee</a> in this case) will make you a better programmer, in the end. Heck, it's the reason why I'm bloggind this!</p>
]]></content:encoded></item><item><title><![CDATA[Splitting your Rails classes into modules: How does it work?]]></title><description><![CDATA[<p>We all like the &quot;Fat models, skinny controllers&quot;-rule, but what to do if your models are becoming too fat? Split them up into smaller chunks, exactly.  Of course this technique works for other classes, too.</p>
<p>The first thing to do, is to check whether the module you're</p>]]></description><link>https://www.rvdh.de/2011/12/01/splitting-your-rails-classes-into-modules-how-does-it-work/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd0e</guid><category><![CDATA[rails]]></category><category><![CDATA[ruby]]></category><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Thu, 01 Dec 2011 11:16:00 GMT</pubDate><content:encoded><![CDATA[<p>We all like the &quot;Fat models, skinny controllers&quot;-rule, but what to do if your models are becoming too fat? Split them up into smaller chunks, exactly.  Of course this technique works for other classes, too.</p>
<p>The first thing to do, is to check whether the module you're looking at should be split up into several classes. Those classes don't necessarily have to inherit from <code>ActiveRecord::Base</code>, they might as well be regular Ruby classes. For example, if you are doing a lot of radius calculations in your <code>Search</code> model, you might as well add a new <code>Radius</code> class that does all the hard calculation work for you and can be tested in isolation.</p>
<p>But if you think that all the methods and macros belong into one class, you can still use modules to modularize different concerns into their own files. Doing this is easy, since we have <code>ActiveSupport::Concern</code> in Rails 3.</p>
<p>Example:</p>
<pre><code># app/models/user/authentication.rb
class User
  module Authentication
    extend ActiveSupport::Concern

    included do
      has_secure_password
    end

    def create_password_reset_token
      token = SecureRandom.base64.tr('+/=lIO0', 'zomglol')
      self.update_attribute(:password_reset_token, token)
    end
  end
end

# app/models/user.rb
class User &lt; ActiveRecord::Base
  include Authentication
  include Validations
  # ...
end
</code></pre>
<p>As you can see, we have put all authentication related methods into their own module, so this module encapsulates the authentication concern.</p>
<p>A little explaination: Extending the module with <code>ActiveSupport::Concern</code> enables the magic that makes writing modules so much easier. The first aspect of this is the <code>included</code> block, that will be run in the context of the class including the module. So it is perfect for validations or <code>acts_as_something</code> style macros. You can even pass in the base class (class including the module) if you use the <code>inlcuded do |base|</code> syntax instead, if you need to.</p>
<p>The <code>create_password_reset_token</code> method gets included into the base class, as ususal. But if you want to include class methods as well as instance methods, you can create a separate module for the ClassMethods inside the <code>Authentication</code> module. You would have to call it <code>ClassMethods</code>, so that <code>ActiveSupport::Concern</code> can find it and do the right thing. The <code>ClassMethods</code> module will be extended into the base class, which means that these methods will act as if you wrote them with <code>def self.method_name</code>.</p>
<p>So what are the hard parts? Of course it is naming things, and deciding where to put stuff. First, I created a folder called <code>user_extensions</code> to hold my concerns for the <code>User</code> class. I did not particularly like this, because I wanted to apply the same conventions that are valid in gems, which is the folder should have the same name as the class. Then I moved on to naming the folder the same as the class file and adding the <code>_extension</code> suffix to each of the module files, until realizing that this is useless. Even if there is a name clash, like an <code>Authentication</code> class somewhere else, our module will be picked up first, because it lives in the namespace of the <code>User</code> class. The downside of this is that you have to address the <em>other</em> <code>Authentication</code> class (if it exists and you need to use it in the User class) with <code>::Authentication</code>, but I can live with that, as it is a rare case. So no more name clutter, just the stuff that is important.</p>
<p>Your test names and folder structure should mimic the ones of the tested classes and concerns. So I have separate unit tests for each of the concerns. Test class names mimic the ones of the classes, so the <code>User::AuthenticationTest</code> tests the behaviour of the <code>User::Authentication</code> module. And of course the test is placed in <code>test/unit/user/authentication_test.rb</code>.</p>
<p>By the way, at the moment I am the only developer on my current project, so I enjoy the occasional developer chat. The above evolved after talking to <a href="https://twitter.com/enebo">Thorsten</a>, <a href="https://twitter.com//codebeaker">Lee</a> and <a href="https://twitter.com//roidrage">Mathias</a>. Thanks for your opinions, guys!</p>
]]></content:encoded></item><item><title><![CDATA[Enabling debugger support in ruby-1.9.3-p0 with RVM]]></title><description><![CDATA[<p>Forget what you read here before, and just do the following:</p>
<pre><code>curl -O http://files.rubyforge.vm.bytemark.co.uk/ruby-debug19/linecache19-0.5.13.gem
curl -O http://files.rubyforge.vm.bytemark.co.uk/ruby-debug19/ruby-debug-base19-0.11.26.gem
gem install {linecache19-0.5.13.gem,ruby-debug-base19-0.11.26.gem} \
  --</code></pre>]]></description><link>https://www.rvdh.de/2011/11/01/enabling-debugger-support-in-ruby-1-9-3-p0-with-rvm-2/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd0d</guid><category><![CDATA[ruby]]></category><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Tue, 01 Nov 2011 11:13:00 GMT</pubDate><content:encoded><![CDATA[<p>Forget what you read here before, and just do the following:</p>
<pre><code>curl -O http://files.rubyforge.vm.bytemark.co.uk/ruby-debug19/linecache19-0.5.13.gem
curl -O http://files.rubyforge.vm.bytemark.co.uk/ruby-debug19/ruby-debug-base19-0.11.26.gem
gem install {linecache19-0.5.13.gem,ruby-debug-base19-0.11.26.gem} \
  -- --with-ruby-include=$rvm_path/src/`rvm current | sed 's/@.*//'`
</code></pre>
<p>Or, if you do vendor your gems with bundler, use the following:</p>
<pre><code>curl http://files.rubyforge.vm.bytemark.co.uk/ruby-debug19/linecache19-0.5.13.gem \
  &gt; vendor/cache/linecache19-0.5.13.gem
curl http://files.rubyforge.vm.bytemark.co.uk/ruby-debug19/ruby-debug-base19-0.11.26.gem \
  &gt; vendor/cache/ruby-debug-base19-0.11.26.gem
bundle config build.ruby-debug-base19 \
  --with-ruby-include=$rvm_path/src/`rvm current | sed 's/@.*//'`
</code></pre>
<p>You can also find this <a href="https://gist.github.com/1333360">as a gist</a>.</p>
]]></content:encoded></item><item><title><![CDATA[Slides of our Rails usergroup Hamburg talk about Redis]]></title><description><![CDATA[<p>I know it’s been a month now, but here are the Slides of our (that’s <a href="https://www.xing.com/profile/Mark_Schmidt15/">Mark Schmidt</a> and me) <a href="http://redis-rughh.heroku.com/">Talk about Redis at the Rails Usergroup Hamburg</a>. In the worldcup prediction game section, I added the numbers for MySQL with and index, and those numbers are not anywhere</p>]]></description><link>https://www.rvdh.de/2010/08/11/rails-usergroup-hamburg-redis-talk/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd0c</guid><category><![CDATA[talks]]></category><category><![CDATA[performance]]></category><category><![CDATA[ruby]]></category><category><![CDATA[mysql]]></category><category><![CDATA[redis]]></category><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Wed, 11 Aug 2010 10:12:00 GMT</pubDate><content:encoded><![CDATA[<p>I know it’s been a month now, but here are the Slides of our (that’s <a href="https://www.xing.com/profile/Mark_Schmidt15/">Mark Schmidt</a> and me) <a href="http://redis-rughh.heroku.com/">Talk about Redis at the Rails Usergroup Hamburg</a>. In the worldcup prediction game section, I added the numbers for MySQL with and index, and those numbers are not anywhere as dramatic as the presented ones (see slide 104). But still, Redis wins :)</p>
<p>You will see that the presentation is actually a website. It was done using <a href="http://github.com/schacon/showoff">ShowOff</a> and works best in fullscreen capable browsers like Google Chrome. The <a href="http://github.com/ralph/redis_talk_rails_ug_hh">source code of the presentation</a> can also be inspected on Github.</p>
]]></content:encoded></item><item><title><![CDATA[Slides of my Rails usergroup Hamburg talk about Heroku]]></title><description><![CDATA[<p>Better late than never, here are <a href="http://www.slideshare.net/ralphvdh/rails-usergroup-hamburg-heroku">the slides</a> of my talk at the last Rails usergroup Hamburg about <a href="http://www.slideshare.net/ralphvdh/rails-usergroup-hamburg-heroku">heroku</a>.</p>
<object type="application/x-shockwave-flash" data="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=heroku-100420064848-phpapp01&stripped_title=rails-usergroup-hamburg-heroku" style="margin:0px" width="425" height="355">
<param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=heroku-100420064848-phpapp01&stripped_title=rails-usergroup-hamburg-heroku">\
 <param name="allowFullScreen" value="true">\
 <param name="allowScriptAccess" value="always">
</object>]]></description><link>https://www.rvdh.de/2010/04/20/rails-usergroup-hamburg-heroku-talk/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd0b</guid><category><![CDATA[talks]]></category><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Tue, 20 Apr 2010 10:10:00 GMT</pubDate><content:encoded><![CDATA[<p>Better late than never, here are <a href="http://www.slideshare.net/ralphvdh/rails-usergroup-hamburg-heroku">the slides</a> of my talk at the last Rails usergroup Hamburg about <a href="http://www.slideshare.net/ralphvdh/rails-usergroup-hamburg-heroku">heroku</a>.</p>
<object type="application/x-shockwave-flash" data="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=heroku-100420064848-phpapp01&stripped_title=rails-usergroup-hamburg-heroku" style="margin:0px" width="425" height="355">
<param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=heroku-100420064848-phpapp01&stripped_title=rails-usergroup-hamburg-heroku">\
 <param name="allowFullScreen" value="true">\
 <param name="allowScriptAccess" value="always">
</object>
]]></content:encoded></item><item><title><![CDATA[Developing for the iPhone vs. developing for the web]]></title><description><![CDATA[<p>As you may know, I sincerely enjoy developing stuff for the web. But I also enjoy using native applications on my iPhone, so learning iPhone development has been on my todo list for a long time. Today, I stroke the item off the list, without having learnt anything about it.</p>]]></description><link>https://www.rvdh.de/2010/04/11/developing-for-the-iphone-vs-developing-for-the-web/</link><guid isPermaLink="false">5be0af79faa38d02e21fbd0a</guid><category><![CDATA[rails]]></category><category><![CDATA[iphone]]></category><category><![CDATA[web]]></category><dc:creator><![CDATA[Ralph von der Heyden]]></dc:creator><pubDate>Sun, 11 Apr 2010 10:08:00 GMT</pubDate><content:encoded><![CDATA[<p>As you may know, I sincerely enjoy developing stuff for the web. But I also enjoy using native applications on my iPhone, so learning iPhone development has been on my todo list for a long time. Today, I stroke the item off the list, without having learnt anything about it. It’s just not interesting to me any more.</p>
<p>In order to explain my reasons, I have assembled a list that compares the possibilities of native iPhone development using Objective-C with web development.</p>
<table>
	<tbody><tr>
		<td> </td>
		<th>iPhone</th>
		<th>web</th>
	</tr>
	<tr>
		<td>Apps can be used by other mobile operating systems?</td>
		<td>no</td>
		<td>yes</td>
	</tr>
	<tr>
		<td>Familiar web technologies like <span class="caps">HTML</span> and JavaScript can be reused?</td>
		<td>no</td>
		<td>yes</td>
	</tr>
	<tr>
		<td>Apps can be updated whenever you want/need to?</td>
		<td>no</td>
		<td>yes</td>
	</tr>
	<tr>
		<td>You can use new technologies like <a href="http://en.wikipedia.org/wiki/NoSQL">NoSQL</a> and <a href="http://nodejs.org/">node.js</a>?</td>
		<td>no</td>
		<td>yes</td>
	</tr>
	<tr>
		<td>Apps have to go through some stupid <a href="https://www.rvdh.de/2010/02/14/the-phone-platform-of-the-future/">review process</a>?</td>
		<td>yes</td>
		<td>no</td>
	</tr>
	<tr>
		<td>Available features and languages are defined by some kind of <a href="http://www.taoeffect.com/blog/2010/04/steve-jobs-response-on-section-3-3-1/">control freak</a>?</td>
		<td>yes</td>
		<td>no</td>
	</tr>
	<tr>
		<td><a href="http://angelo.dinardi.name/2008/09/20/mailwrangler-and-the-apple-app-store/">Apps that compete with Apple software</a> will be banned?</td>
		<td>yes</td>
		<td>no</td>
	</tr>
	<tr>
		<td>You have to submit a <a href="http://boredzo.org/killed-iphone-apps/">final app</a> (costing time and money) to find out whether your app will be accepted?</td>
		<td>yes</td>
		<td>no</td>
	</tr>
</tbody></table>
<p>Just counting the yes and nos, there is no clear winner. Of course, this list is 100% objective and complete. If you have anything to add, against all expectations and common sense, please leave a comment.</p>
<p><strong>Update:</strong> <a href="http://37signals.com/svn/posts/2273-five-rational-arguments-against-apples-331-policy">This blog post by 37signals</a> sums up my feelings about Apple pretty well.</p>
]]></content:encoded></item></channel></rss>