http://www.rvdh.de/Reads for Rubyists2011-12-02T00:00:00+00:00Ralph von der HeydenWhy I roll my own authenticationhttp://www.rvdh.de//2012/01/12/why-i-roll-my-own-authentication/2012-01-12T00:00:00+00:00<p>This is what got me started writing this post:</p>
<p><img src="/images/authentication_1.png" alt="Chat with phil76 1">
<img src="/images/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 "graspability". 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>
Classes are separations of concerns or why too much magic hurtshttp://www.rvdh.de//2011/12/02/classes-are-separations-of-concerns-or-why-too-much-magic-hurts/2011-12-02T00:00:00+00:00<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, ->(customer) do
where(:customer_id => customer.to_i)
end
end
end
end
# app/models/user.rb
class User < 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
don't 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, ->(customer) do
where(:customer_id => customer.to_i)
end
Customer.class_eval <<-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'll 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're 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, don't 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="/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 = -> { 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>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>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>
Splitting your Rails classes into modules: How does it work?http://www.rvdh.de//2011/12/01/splitting-your-rails-classes-into-modules-how-does-it-work/2011-12-01T00:00:00+00:00<p>We all like the "Fat models, skinny controllers"-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 < 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's 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's 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 didn't 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>
Enabling debugger support in ruby-1.9.3-p0 with RVMhttp://www.rvdh.de//2011/11/01/enabling-debugger-support-in-ruby-1.9.3-p0-with-rvm/2011-11-01T00:00:00+00:00<p><strong><span class="caps">UPDATE</span>:</strong></p>
<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 \
> vendor/cache/linecache19-0.5.13.gem
curl http://files.rubyforge.vm.bytemark.co.uk/ruby-debug19/ruby-debug-base19-0.11.26.gem \
> 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>Slides of our Rails usergroup Hamburg talk about Redishttp://www.rvdh.de//2010/08/11/rails-usergroup-hamburg-redis-talk/2010-08-11T00:00:00+00:00<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>Slides of my Rails usergroup Hamburg talk about Herokuhttp://www.rvdh.de//2010/04/20/rails-usergroup-hamburg-heroku-talk/2010-04-20T00:00:00+00:00<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>
<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"><br />
<param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=heroku-100420064848-phpapp01&stripped_title=rails-usergroup-hamburg-heroku" /><br />
<param name="allowFullScreen" value="true"/><br />
<param name="allowScriptAccess" value="always"/><br />
</object></p>Developing for the iPhone vs. developing for the webhttp://www.rvdh.de//2010/04/11/developing-for-the-iphone-vs-developing-for-the-web/2010-04-11T00:00:00+00:00<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>
<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="/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>
</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>Pro tip: Using mysql with Rails 3.0.0.beta2 and Ruby 1.9.2http://www.rvdh.de//2010/04/03/pro-tip-using-mysql-with-rails-3-0-0-beta2-and-ruby-1-9-2/2010-04-03T00:00:00+00:00<p>I know <a href="http://en.wikipedia.org/wiki/NoSQL">NoSQL</a> is upon us, but some of you might <strong>still</strong> be stuck with MySQL for the time being. Saying that, the <a href="http://rubygems.org/gems/mysql">mysql gem</a> is not the best way to talk to your database using Ruby 1.9, at least if you are expecting <span class="caps">UTF</span>-8 characters to “just work”. The default mysql gem will simply <span class="caps">ASCII</span>-encode all the strings returned from the database, no matter what you set in database.yml. But fortunately, the solution is near! Just use the <a href="http://rubygems.org/gems/ruby-mysql">ruby-mysql gem</a> instead. It is made by the same guy, Tomita Masahiro, but targets the 1.9 branch of Ruby.</p>
<p>For some reason I don’t understand, the current Rails 3 beta still uses the old mysql gem when you are generating a new application. So after running <code>rails application awesome_shop -d mysql</code>, you will have a <code>gem 'mysql'</code> entry in your <code>Gemfile</code>. Just change this entry to <code>gem 'ruby-mysql'</code>, <code>bundle install</code> again and your are good to go!</p>
<p>See an example:</p>
<h4>Using the old mysql gem:</h4>
<p><strong>In rails console:</strong><br />
<code>rails console</code><br />
<code>Loading development environment (Rails 3.0.0.beta2)</code><br />
<code>ruby-1.9.2-head > p = Product.first</code><br />
<code>=> #<Product id: 1, title: "fd\xC3\xB6\xC3\xA4\xC3\xB6\xC3\xA4fdsf", description: "fasf \xC3\xB6a\xC3\xA4sf af\xC3\xB6\xC3\xA4fa ", created_at: "2010-04-03 08:34:52", updated_at: "2010-04-03 08:34:52"></code></p>
<p><strong>In the browser:</strong><br />
<code>ActionView::TemplateError (incompatible character encodings: ASCII-8BIT and UTF-8)</code></p>
<h4>Using the new, shiny ruby-mysql gem:</h4>
<p><strong>In rails console:</strong><br />
<code>rails console</code><br />
<code>Loading development environment (Rails 3.0.0.beta2)</code><br />
<code>ruby-1.9.2-head > p = Product.first</code><br />
<code>=> #<Product id: 1, title: "fdöäöäfdsf", description: "fasf öaäsf aföäfa ", created_at: "2010-04-03 08:34:52", updated_at: "2010-04-03 08:34:52"></code></p>
<p><strong>In the browser:</strong><br />
No errors or whatsoever. <span class="caps">UTF</span>-8 awareness all the way down.</p>
<p>q.e.d :)</p>The phone platform of the futurehttp://www.rvdh.de//2010/02/14/the-phone-platform-of-the-future/2010-02-14T00:00:00+00:00<p>You <a href="http://twitter.com/ralph/status/8319603144">may</a> <a href="http://twitter.com/ralph/status/8340889761">have</a> <a href="http://twitter.com/ralph/status/8690268177">heard</a> that my 1st gen iPhone broke only recently. This is why I got an iPhone 3GS today, but not without an ache in my stomach. That is not only because of the big heap of money I needed to hand over to get an unlocked phone. It’s more because I have a strong doubt whether the iPhone will continue to attract developers and thus be the phone platform of the future, given the App Store rules won’t change significantly in the near future.</p>
<p>While many iPhone developers are of the opinion that developing for the iPhone is a joy compared to all other mobile devices, the waiting time between submission and approval is horrible. That is especially true in an agile world, where you have a dozen bugs fixed and two features added in the 2-week timespan that Apple needs to review the “new” version of your application.</p>
<p>So what’s the advantage of reviewing stuff? A quick review of an application won’t guarantee it’s not malicious. There has been malicious software in the App Store before. Only a review of the source code could prevent malicious software, but of course Apple does not have access to all the source code of all the applications in the App Store. And if it had, it would not have the time to review it properly.</p>
<p>Next, Apple promises that the reviewing process makes sure that applications are more reliable. I think the opposite is true. By delaying application updates by roughly two weeks, more stable versions of the same software could better be shipped via snail mail.</p>
<p>So what should Apple do?</p>
<p>Well, that’s easy. Just take a look at how the operating system works that I am currently using to write this post, and that as served me so well in the past years. I can install any kind of software in my local MacBook Pro running Mac <span class="caps">OSX</span>. Have I ever had problems with malicious or unstable software? Not any more than on the iPhone. So Apple should open its doors for any kinds of applications, without the cumbersome and unreliable reviewing process.</p>
<p>I’m not trying to say that rejecting or pulling an app is essentially a bad thing. If users complain about a software being malicious, pull it. If lots of users complain about an app crashing all the time, give the developers a deadline, then pull it. What I’m trying to say is, the strict rules of the App Store, and the delay caused by Apple for each new version of a software will eventually kill the innovation that drives the iPhone platform. The innovation that is currently still inherent among iPhone developers. So it is time to give up those unnecessary rules before the innovation has died.</p>The 100-year languagehttp://www.rvdh.de//2010/02/13/the-100-year-language/2010-02-13T00:00:00+00:00<blockquote>
<p>We know that Java must be pretty good, because it is the cool, new programming language. Or is it? If you look at the world of programming languages from a distance, it looks like Java is the latest thing. (From far enough away, all you can see is the large, flashing billboard paid for by Sun.) But if you look at this world up close, you find that there are degrees of coolness. Within the hacker subculture, there is another language called Perl that is considered a lot cooler than Java. Slashdot, for example, is generated by Perl. I don’t think you would find those guys using Java Server Pages. But there is another, newer language, called Python, whose users tend to look down on Perl, and another called Ruby that some see as the heir apparent of Python.</p>
</blockquote>
<p>– Paul Graham, Hackers and Painters, p. 183</p>
<p>He’s right.</p>