For one of my latest projects, I had to implement a "generic" controller allowing management of various types of ActiveRecord objects.
An administrator should for example be able to validate comments & links suggestions before they appear on the website.
This validation should be done through a common interface (a common controller /activations) to avoid code duplication.
Thanks to Ruby dynamic nature it was of course very easy to implement.
But the following tips helped me to achieve my goals :
The following code allows you to work with a class when his name is only known at runtime :
klass_name = "Article"
klass = Kernel.const_get(klass_name)
klass.find(:all, :order => 'created_at DESC')
It's sometimes also very useful to create/get instance variables dynamically :
var_name = "article"
instance_variable_set("@#{var_name}", klass.find(params[:id]))
instance_variable_get("@#{var_name}")
Talking about instance variables... Do you know how it is possible to access instance variables you defined in your controllers into your views?
In most frameworks, you have to specify explicitly which data you want to make available for your views.
For example, using Java and Spring, you have to create a Map object with all your data and then use this map as a parameter for the render method.
With Ruby on Rails it's done automatically and it's a good news! But how does it work?
It's very simple.
The following method is defined in the ActionView::Base class (actionpack/lib/action_view/base.rb) :
def copy_ivars_from_controller
if @controller
variables = @controller.instance_variable_names
variables -= @controller.protected_instance_variables if @controller.respond_to?(:protected_instance_variables)
variables.each { |name| instance_variable_set(name, @controller.instance_variable_get(name)) }
end
end
... and this method will be called from the render method of your view.
What it does is simply get all the instance variables of the current controller (subtracting protected vars) and then recreate each of them in the current view using instance_variable_set.
Add a comment
0 comment for this article