Internetbureau Holder

Using the question mark for string equations.

Roy van der Meij di 22 jun 10

In rails we have the method Rails.env.production? which simply checks if Rails.env equals “production”

I kinda liked that and I was curious how they did that.
It appears that DHH himself made a class StringInquirer which had a nifty method_missing method.

Let’s check it out! (you can find this file in gems/active_support#{version}/lib/active_support/string_inquirer.rb)

  module ActiveSupport
    class StringInquirer < String
      def method_missing(method_name, *arguments)
        if method_name.to_s[-1,1] == "?"
          self == method_name.to_s[0..-2]
        else
          super
        end
      end
    end
  end

With this knowledge we can do something like this.

  fancyness = ActiveSupport::StringInquirer.new("fancy")
  fancyness.fancy?
   => true
  fancyness.lame?
   => false

So what do we do when we want to make this core functionality for any stringg?
Simple! Monkey patch the class String!

  class String
    def method_missing(method_name, *arguments)
      if method_name.to_s[-1,1] == "?"
        self == method_name.to_s[0..-2]
      else
        super
      end
    end
  end

  "fancy".fancy?
   => true
  a = "awesome"
  a.awesome?
   => true
  a.stupid?
   => false

I personally like it more to have core extensions in separate modules instead of hacking the String class directly. So here is the cleaned up version.

module CoreExtensions
  module StringExtensions
    def method_missing(method_name, *arguments)
      if method_name.to_s[-1,1] == "?"
        self == method_name.to_s[0..-2]
      else
        super
      end
    end
  end
end

String.send :include, CoreExtensions::StringExtensions

"fancy".fancy?
 => true

So… is it fancy?

Gepost in hor |  0 reacties

Netzke

Jeroen Bulters ma 21 jun 10

While I didn’t have the time to check it out myself yet; a friend of mine recommended me to have a look at Netzke. Netzke is a gem designed for usage with Rails which will allow you to easily include ExtJS components into your app (i.e. views).

I’m personally not the biggest fan of these semi-native bindings, but basic usage looks quite simple (and promising). This one goes into the list for usage on a next weekend-side-project.

Gepost in hor |  0 reacties

Immutable Attributes in Ruby On Rails

Chiel Wester ma 21 jun 10

Sometimes you want to have some attributes on models that can be changed only on creation or only on certain conditions.

Of course there is attr_protected (to prevent mass assignment) and attr_readonly, but with these methods it’s difficult to create the conditions we actually want to apply.

For these situations you can install the immutable_attributes gem. Simple set the following in your model:

class Relation < ActiveRecord::Base
  attr_immutable :name
end

The attribute will be readonly for all (in this case) relations.

When you want to apply the immutable function only on certain conditions, you can do the following:

class Relation < ActiveRecord::Base
  validates_immutable :name, :if => Proc.new{|relation| relation.is_active?}
end

This function works like a validation, so you will get an validation error when you try to change the specified attribute.

Gepost in hor |  0 reacties

Smash Into Vim

Dax Huiberts ma 14 jun 10

Not so long ago PeepCode released a screencast titled ‘Smash Into Vim’. In this screencast created by Andrew Stewart (voiceover by Dan Benjamin) you will be introduced to the power of the Vim text editor. Vim was specifically build to help programmers edit text more efficiently. Because of it’s origins in the terminal it can be daunting at first, but with a little practice you will find it well worth the effort.

The things that are covered are:
- Install Vim for your platform
- Use Vim for simple editing via SSH
- Configure Vim with sensible defaults (basic and advanced configurations are included in the code download)
- Use operators and commands to manipulate text
- Work with files, windows and buffers
- Install plugins

While you might be very happy with TextMate or another editor of your choice. I believe it’s a good idea to at least try it out. It may very well become your most powerful tool in your Ruby toolbox. As usual, this screencast costs a mere $9!

PS: Part II is in post-production and will go further into advanced editing and plugins.

Gepost in hor |  1 reactie

Fixing i18n backend cache key when using memcached and Ruby 1.8.6

Paul Engel vr 11 jun 10

Implementing internationalization for Rails sites is a common thing. Most of you are likely using the i18n library developed by Sven Fuchs.

Backends and chaining them together

The default backend (I18n::Backend:: Simple) reads its translations from YAML files stored in the /config/locales directory and uses an in-memory hash to ensure efficiency. In most cases, this backend is sufficient enough when the application doesn’t require translation management by end-users. But if so, storing translations within YAML files isn’t preferred. You want to use a database for doing this.

Fortunately, i18n also provides a backend for database storage (I18n::Backend::ActiveRecord). Chaining both backends enables you to define translations within the YAML files and to override them with translations stored in the database.

I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)

The usage of memcached ensures efficiency.

require "memcache"

yaml   = YAML.load(File.read(File.join(RAILS_ROOT, "config", "memcached.yml")))
config = yaml["defaults"].merge yaml[RAILS_ENV || "development"]

mem_cache               = MemCache.new config
mem_cache.servers = config["servers"]

I18n.cache_store = ActiveSupport::Cache.lookup_store :mem_cache_store, mem_cache

The problem

Using this setup in Ruby 1.8.6 can raise an error caused by an invalid memcached cache key. This key is generated by the protected method I18n::Backend::Cache.cache_key which doesn’t provide a clean key in Ruby 1.8.6 as it uses the Hash.hash method to create the key. The pitfall is that isn’t reliable in Ruby < 1.8.7:

{}.hash != {}.hash.

The fix

A solution is to upgrade Ruby, but doing this can bring a lot of side effects to Ruby dependent libraries on your system. We are clearly searching for some 1.8.7 goodies to use in 1.8.6. Fortunately, Marc-André Lafortune has created the gem Backports which provides us just that.

But as backports is not endorsed by ruby-core and you’re noted to use this with caution!

To fix the I18n cache key problem, just extract the hash method backport and use it in your project:

class Hash
  
  def hash
    h = 0
    each do |key, value|
      h ^= key.hash ^ value.hash
    end
    h
  end unless {}.hash == {}.hash
  
end

Enjoy!

Gepost in hor |  0 reacties

Rails 3 screen casts

Johan Vermeulen wo 09 jun 10

Gregg Pollack just released a couple of screencasts about all what’s new in Rails 3.

These are the topics that will be covered:

Getting Started & Action Dispatch

Bundler &
Action Mailer

Active Relation & Active Model

Cross-site scripting & Unobtrusive JS

The New Action Controller

Have fun watching!

Gepost in hor |  1 reactie

$ 3.0.0.beta4

Stephan Kaag di 08 jun 10

The Rails core team is very pleased to announce Rails 3 beta 4, which they will be hammering on and tuning during RailsConf. At the end of RailsConf, they will be putting out the release candidate.

You can install the latest beta with gem install rails --pre

Gepost in hor |  0 reacties

Unroller

Jeroen Bulters ma 07 jun 10

When working with a new piece of code, being a new plugin, gem or just some code someone else wrote, and you want to familiarise yourself with the inner workings you can do a few things.

Play around with it in irb (or script/console) and try out different options, while keeping the code as a reference. Or you pull out the debugging-swiss-army-knife named Unroller (available as a gem with the same name).

Unroller is a custom tracing module designed with this kind of situations in mind and is very easy to use.

Image the following – useless – piece of Ruby code which calls the same function 4 times, followed by some other function.

require 'rubygems'
require 'unroller'

class Recurse
    def self.some_recursive_function(times, callback, depth=0)
        if depth == times
            self.send(callback)
            return
        else
            puts "Depth is #{depth}"
            some_recursive_function(times, callback, depth+1)    
        end
    end

    def self.end_of_recursion_callback
        puts "End of recursion"
    end
end

Recurse.some_recursive_function(3, :end_of_recursion_callback)

Of course, this example is quite trivial, but imagine for a second we do not understand how it works.

By wrapping the method call in a Unroller block we can easily generate an easily understandable stacktrace.

So, we replace the Recurse#some_recursive_function call with the following:

Unroller::trace do
    Recurse.some_recursive_function(3, :end_of_recursion_callback)
end

And run the file again.

This time, we are presented with a nice stack trace showing each step of the execution:

 |    Recurse.some_recursive_function(3, :end_of_recursion_callback)    | unroll.rb:23                                                                    
 |  \ calling Recurse::some_recursive_function                        

Recurse::some_recursive_function (unroll.rb:6) (line):
 |  |    (times = 3; callback = :end_of_recursion_callback; depth = 0)...
             def self.some_recursive_function(times, callback, depth=0)
      ->         if depth == times
                     self.send(callback)
                     return
                 else
                     puts "Depth is #{depth}"
                     some_recursive_function(times, callback, depth+1)    
                 end
             end
         
--- SNIP FOR BREVITY ---

                  Recurse.some_recursive_function(3, :end_of_recursion_callback)
                  
                  Unroller::trace do
                      Recurse.some_recursive_function(3, :end_of_recursion_callback)
                  end

 |  |  |  |  / returning from Recurse::some_recursive_function        
 |  |  |  / returning from Recurse::some_recursive_function           
 |  |  / returning from Recurse::some_recursive_function              
 |  / returning from Recurse::some_recursive_function    

Unroller shows us all the code being executed, the current line and the depth of the function in the stacktrace.

This kind of output can come quite in handy when debugging complicated situations like ActiveRecord filter chains.

More information on Unroller is found at http://unroller.rubyforge.org/.

Gepost in hor |  0 reacties

$ 3.0.0.beta2

Stephan Kaag di 06 apr 10

It took longer than they thought, but then again, what doesn’t? The second beta release of Rails 3.0 is released and hopefully the last stop before a release candidate.

You can install beta 2 and try it out with new and existing applications. (gem install rails —prerelease after you make sure you’re on Ruby Gems 1.3.6 with gem update —system).

Gepost in hor |  0 reacties

Itsy bitsy monad

Jeroen Bulters wo 31 mrt 10

Functional programming has been sort of a hype lately. Therefore I thought it would be nice to try and apply some concepts from functional programming languages to Ruby (and, ergo: Rails).

One of my personal best friends in Ruby is Mr. NilClass (not really), he always makes me add stuff to my if statements to check if he’s there. So, I’m constantly doing stuff like:

if (customer && customer.address && customer.address.zipcode)

Sure, not to big of a deal, but I just don’t like it.

Several functional programming languages know a concept known as Monad’s. I’m not going to give an introduction to Monad’s (read a good one at moonbase), but I can give a useable monad implementation in Ruby to illustrate the concept.

Monad’s basically wrap an object in a container, allow you to perform actions on it and – when you’re done playing – unwrap the resultant value from the monad.

So, after constructing the monad, and connecting some of the functionality to the Ruby Object class. I should be able to do:

any_object.if_possible?.other.value #=> 'the value I put in here'
nil.if_possible?.other.value #=> nil
any_object.if_possible?.nil.value #=> nil

All without yielding any exceptions.

Let’s start with adding the if_possible? method to wrap our object in a monad.

class Object
  def if_possible?
    Monad::Maybe.new(self)
  end
end

Note: This monad is actually called the Maybe monad in a.o. Haskell

Now, we create the monad itself (nicely in the Monad module). Please note that the mentioned unwrapping is achieved through the attr_accessor and that you should choose a more semantic name for it.

module Monad
  class Maybe
    # Unwrapping through the accessor
    attr_accessor :value
  
    def initialize val
      @value = val
    end
    
    def monadBind proc
      if @value != nil
        # We get the result, and rewrap
        # that in a the Maybe monad again.
        proc.call.if_possible?
      else
        self
      end
    end

    def method_missing(method_name, *args)
      monadBind(Proc.new {@value.send(method_name, *args)})
    end
  end
end

Now let’s try this out with the following file:

class Test1
    attr_accessor :other
    def initialize(other)
        @other = other
    end
end
class Test2
    attr_accessor :value
    def initialize(value)
        @value = value
    end
end

Load it into irb (or put the following in the same file) and try this:

value = Test2.new(true)
working = Test1.new(value)
puts working.other.value
puts working.if_possible?.other.value.value
puts nil.if_possible?.other.value

When run, it produces the following output, without throwing exceptions:

[bulters@~/monadic_art]$ ruby monad.rb 
true
true
nil

So, what did we do? Basically, we constructed a nicer way to check for nil’s, and propagating the handling of it back to our program.

The line

if (customer && customer.address && customer.address.zipcode)

can now be written as:

if(customer.if_possible?.address.zipcode.value)

which is – in my opinion – not only shorter, but also a bit easier on the eyes.

Gepost in hor |  1 reactie

Welcome to Holland On Rails

This weblog is the official Ruby techblog from the guys at Holder, a Ruby development company. Holder is also the company behind the RubyAndRails Europe Conference in Amsterdam.

Recente Jobs


Bekijk alle jobs »»

Gereedschapskist

Onmisbare tools voor
iedere developer!
Ruby On Rails
Framework voor de web 2.0 developer. Eindelijk vooruitgang!
TextMate
Editor for true pro's
Typ, tab, top :-)
Nee, niet voor Win.
Made On A Mac
En nou is het over met die saaie grijze Windows bak van je!

Auteurs op deze site

Chris Obdam

'Less is more' evangelist, past dit ook dagelijks toe op zijn tandenborstel.

Chiel Wester

Snelheidswonder op Ruby wielen. Leuk om mee te pair-programmen ;-) Recommend Me

Stephan Kaag

Het eerste Rails coreteam- member uit Nederland? Rails evangelist van het eerste uur.

Paul Engel

Én Rails programmeren én interfaces designen? Je zou hem superman kunnen noemen..

Dax Huiberts

Official Zip-Programmer, skinny code is helemaal zijn ding. Haalt meer code weg dan dat er bij komt.

Freek Monteban

Het nieuwste telg uit het Holland on Rails nest! Hij doet niets anders meer!

Johan Vermeulen

De stylesheet-koning uit de kop van Noord-Holland!