Acts As Tree With Dotted IDs
I have finally released that plugin I have been hapilly using for almost a couple of years now.
Say hello to acts_as_tree_with_dotted_ids!
I have finally released that plugin I have been hapilly using for almost a couple of years now.
Say hello to acts_as_tree_with_dotted_ids!
Things have been very quiet down here and hectic everywhere else. As a proof that this is no lame excuse, my first Rails patch was just committed into the trunk.
For the record, it addresses an issue in ActiveResource which could not locate resources defined in nested modules.
I've been using ARes a lot in my current project in which I've built a rich client-side API packaged into a Rails plugin. To be honest, I'm into a love-hate relationship with ARes and things were not as smooth as initially advertised.
I've experienced some severe hiccups with nested resources, inflected collection names, attributes vs prefix hashes and some nasty XML (un)marshalling oddities. If I find some time, I will document here the problems I encountered during this wild ride...
Even though it has given me some serious headaches, I still think this REST approach is better than dealing with a huge black box supposedly implementing some funky flavor of SOAP.
ARes is not totally mature in its current state but the size of its code base still allows a mere mortal to dive into it and see what's happening.
If the popularity of REST services keep on rising, ARes will need some real refactoring and internal plumbing work to bring it to the same level as ActiveRecord in the ORM field.
The bottom line is: ARes is a neat library you may want to play with but you must be warned that things are not as simple as they seem and it may require some significant tweaking on both sides of the wire...
As your domain model grows in complexity, you may want to factor out some common traits and behaviour into a MixIn. For the Java crowd out there, mixins are just a much simpler way to do AOP.
While adding instance methods via a MixIn is straightforward, adding constraints to your model requires to execute code in the scope of the class in which you include the module. It took me a while to get this one right so I thought I'd share:
module Discountable def self.included(base) base.class_eval do validates_inclusion_of :discount_type, :in => %w{ None Percentage Absolute } validates_numericality_of :discount_value end end def compute_discount(price) # ... end # ... end
Now in your actual ActiveRecord class:
class OrderItem < ActiveRecord::Base # Associations belongs_to :order belongs_to :product # Validations validates_presence_of :quantity, :unit_price validates_numericality_of :quantity, :unit_price # Add discountable properties and constraints include Discountable end
The same method can be used to declare associations or activate any kind of "acts as" behaviors.
I love this game.
Perl is dying, I surely won't cry and I'm not the only one. Back in 1996, when I was looking for a day to day programming language that was better than bash or AWK and more productive than C++, I considered learning Perl and I must say I never got any further that the first few pages of the tutorial. The syntax was simply too hairy and the support for OOP was a sick joke. I quickly switched to Python which was, in many respects, several orders of magnitude cleaner than Perl... and a lot more fun to write!
A few weeks ago, InfoQ launched. The content is slightly better than TSS but I'm not sure it was such a good idea to put Ruby as a main topic, on par with the evil twins of Enterprise software: Java EE and .NET.
Ruby is more a programming language than a complete software platform. Ruby's breakthrough into the major league could be seen as a big push toward the Enterprise but It will most likely fuel up flamewars between Ruby enthusiasts and people who might have forgotten what the simple joy of programming was all about.
Of course, you're all so damn right, Rails could have been written in Java. Just like it could have been written in assembly language. It's not about what Rails does, it's how it does it and how it gets your things done.
Ruby on Rails features newcomers overlook most of the time:
webrick.restart if last_change_set.include?(RAILS_ROOT+"lib/*")
File.delete("/tmp/ruby_sess.*")
if Rails.crazy_http_500_without_logging_info?
There are many ways to share helper modules with Ruby on Rails but I couldn't quite figure out how to get an helper part of a module (located for instance in /app/helpers/some_module/other_helper) mixed-in my templates. After some head scratching, I finally came up with this:
class SomeModule::SomeController < SomeModule::BaseController
helper "some_module/other_helper".to_sym
end
Although this line of code gives me cold sweat, it seems to work fine and looking at the current implementation of the Controller::Base.helper method it looks it's all I can do but... Am I missing something here?
The best thing that happened to this world since sliced bread has now a version number compatible with your local project manager!
Heartful congratulations to David and his hitsquad. Nice minimal redesign as well.
I've been annoyed by the lack of i18n in Rails since its very inception. Building web applications for the Belgian market makes proper i18n support a requirement for any framework.
I skimmed through a bunch of plug-ins but some makes way too much assumption about the way content is organized in the application.
Fortunately things recently got easier thanks to a clever and dead simple localization module written by Thomas Fuchs of the Scriptaculous fame. It's the less intrusive solution I found so far but one thing was missing: the localization of texts stored in the model. So I rolled up my sleeves and started hacking an extension to ActiveRecord.Base.
The idea is to provide a locale-aware accessor for the fields that needs a translation. Localized text would be stored in the same table as the model (no metadata nightmare) following a simple naming convention. Let's say we have a products table with a name attribute to be localized: products.name would hold the text for the :default language, products.name_fr would then hold the french translation, products.name_nl for the dutch, and so on...
Let's start by providing a Railsish interface to this new facility:
class Product < ActiveRecord::Base # Will create a locale-aware _name accessor localize :name end
Now you can output the localized name for any product, based on Localization.lang:
# some_view.rhtml <%= @product._name %>
And here's the black magic:
class ActiveRecord::Base def self.localize(*attribute_names) attribute_names.each { |attribute_name| class_eval %{ def _#{attribute_name} unless Localization.lang == :default localized_method = "#{attribute_name}_\#{Localization.lang.to_s}" return send(localized_method.to_sym) if respond_to?(localized_method) end #{attribute_name} end } } end end
And voila! ;)
This worked fine for me. The column redundancy in the database may look ugly and kind of anti-DRY but Rails migrations make it a piece of cake to deal with new languages.
I should now have a look at the shiny new plug-in API...