Named scopes, still needed ?

Wijnand Wiersma vr 25 jun 10

I am wondering what the use cases are for named scope in the Rails3 release.
Just creating a class method which returns an ActiveRelation object gives more clear code and allows for more customisations.

The most obvious use case are old rails 2.3 lambda scopes.
See this example:

named_scope :for, lambda {|author| {:conditions => ["customer_id IS NULL OR customer_id = ?", author.customer_id]} }

You can call this like

Post.for(author) # eg anything that responds to customer

This looks like a method call, so I was happy to be able to do this in Rails3:

def self.for(testmaker)
 where(:customer_id => testmaker.customer_id)
end

Now it’s not just like calling a method, it actually is a method!

For me this feels far more natural and thanks to Arel magic it just works in the same way too.
You can still chain it as if it was an instance method:

Post.limit(10).for(author)

So if we had to use the hackish lambda scopes regularly (the real need is questionable off course) and now we are better served with a class method: wouldn’t it be far more natural to skip named scopes and just create intelligent class methods?

Rails2:

named_scope :published, :conditions => {:published => true}

Rails3:
scope :published, where(:published => true)

The Rails3 way I like it:
def self.published
 where(:published => true)
end

So unless anybody can give me a compelling reason to use named scopes (lines of code arguments will be rejected) I will proceed on this path.
I think Rails apps should become more Ruby like instead, too much magic hurts my brains.

And remember, everytime you write a lambda scope, god kills an unicorn.

Gepost in hor |  2 reacties

Phusion Passenger 2.2.15 just released

Paul Engel do 24 jun 10

Although earlier this month the guys of Phusion teased us with performance improvement stats of Passenger 3, they have just blogged about their Phusion Passenger 2.2.15 release.

It contains the following:

- Apache: Fixed incorrect temp dir cleanup by passenger-status
- Apache: Fixed some upload handling problems
- Nginx: Fixed compilation issues with Nginx >= 0.7.66
- Nginx: Changed its default Nginx version from 0.7.65 to 0.7.67
- Bundler: Fixed some problems

For further details, please check out their blog post in which upgrade instructions to 2.2.15 are also provided.

Gepost in hor |  0 reacties

Smooth menu's for real browsers

Johan Vermeulen wo 23 jun 10

With the features which are introduced in de CSS3 standard, it is possible to create rounded border corners. This can be a real time saver when slicing a website.

In this example I created a simple menu with rounded corners and a background image for the on hover and active events.

Result in browsers which support HTML5/CSS3:

Result in older browsers:

Download the sprite

The HTML:

<ul>
  <li class="first"><a href="weblog.html">Weblog</a></li>
  <li><a href="weenies.html">Weenies</a></li>
  <li><a href="jobs.html">Jobs</a></li>
  <li class="last"><a href="zandbak.html">Zandbak</a></li>
</ul>

The CSS

Tweaks:

If you like you can add webkit and mozilla specific CSS to create the same results in Firefox 3 or webkit 1 enabled browsers:

-moz-border-radius: 10px;
-webkit-border-radius: 10px;

Gepost in hor |  0 reacties

Custom Subdomains in Rails 3

Stephan Kaag wo 23 jun 10

Rails 3 supports subdomains out of the box, which is great. But did you know that the constraints in the Router can actually match patterns too? This means instead of hardcoding each subdomain into your routes you can allow your customers to decide their own subdomains.

I created a ‘lib/sub_domain.rb’ with the following code:

class AdminSubdomain
  def self.matches?(request)
    subdomain = request.subdomain
    ['admin', 'backend', 'adminpanel'].include? subdomain
  end
end

In my routes.rb file I can now wrap all routes I want under a custom subdomain

# config/routes.rb
TestApp::Application.routes.draw do |map|
  constraints(AdminSubdomain) do
    get "admin/index"
  end

  root :to => "home#index"
end

The admin panel is now reachable at all three subdomains.

Gepost in hor |  0 reacties

nifty rails 3.0 methods

Daniel Willemse di 22 jun 10

So with the Rails 3.0 beta release as of late, I decided to try and play around with a new rails app. I’m pretty new to Ruby and Rails, so trying a new version of Rails (where they also changed routing, one of the things I personally have most problems with) was pretty challenging for me.

For those that haven’t yet checked out the new and cool stuff that’s available with rails 3, here’s some new code versus the 2.x version.
I had a fresh app in rails 2.3.5, which I tried to rebuild in rails 3.0.
In the old app for instance, there was code like:

Invoice.find(:all, :conditions => ["number > ?", 5])
or
Invoice.find(:all, :order => "number DESC")

While in the new and improved rails,
you can write it much easier like this:

Invoice.where("number > ?", 5) and
Invoice.order("number DESC")

The cool part about this, is that you can chain these new methods like this:

Invoice.order("number DESC").where("number > ?" 5)

This technique also works for named scopes. With rails 3.0, you can easily make a named scope as follows:

scope :above_1, where("number > 1")
scope :below_5, where("number < 5")
scope :above_1_and_below_5, above_1.below_5

(notice how it’s no longer called named_scope!!)
These scopes don’t make any sense, but you get the picture.

There are more of these new methods and as I play more with rails 3.0 I’ll try and update

So besides making it easier for you to chain together find options, why would you use these above the find methods
in rails 2.x?
Well I found my answer in a railscast where it is explained that the find option has been revised.
http://railscasts.com/episodes/202-active-record-queries-in-rails-3
In the video, it is shown that for instance, Model.scope (Article.recent in the video) returns an active record relation instead of performing the query. And that the query is performed when you try and get the actual data.

I have not yet been able to reproduce the same queries as in the railscast so I’ve not figured out how it works.
When I do however, I’ll try and share my findings and post an update.

Daniel Willemse

(the code I use, which should show me an active record relation in the console)

class Invoice < ActiveRecord::Base
  scope :above_1, where("number > 1")
  scope :below_5, where("number < 5")
  scope :above_1_and_below_5, above_1.below_5
end

>> i = Invoice.above_2_and_below_5.all

returns:

=>#<Invoice id: 4, …. ….. ….. , updated_at: "2010-06-22 19:50:29">]

Where I expect it to return something along the lines of
#<ActiveRecord::NamedScope::Scope

Gepost in hor |  1 reactie

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

Welkom op Holland On Rails

Het startpunt voor Ruby On Rails in Nederland. Vind de laatste technieken, meningen en nieuwtjes.

Recente Jobs

Gezocht: Ruby On Rails ontwikkelaar (junior of senior)

Eet, drink en droom jij over Ruby On Rails? Wil jij het liefste dag en nacht bezig zijn met jehobby; super coole webapplicaties ontwikkelen in Ruby On Rails?

Dan willen wij jou graag een podium bieden om je Ruby skills te vertonen aan onze nationale en internationale klanten!

@ Internetbureau Holder, Obdam

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
Src-120-attending

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!