Search this site:

Some Rails plugins: acts_as_magic_model

This is the third plugin I have been working on for Rails - It’s the one that still needs most work to be fully usable (for what I originally envisioned it), but is almost there - I have not touched it (nor the other two I recently presented here, acts_as_catalog and Real FK because real-life has demanded my time on various other fronts. Anyway, this is IMHO the most interesting of the three plugins I’ve written so far. So, following what I did with the other plugins: You can go to acts_as_magic_model’s main page, or jump straight to its SVN repo. And the basic description follows: Rails plugin to allow for extensible models, where inter-model relations are inferred from the database’s structure, and not necessarily from explicit declarations in the models. This means, when one of your models acts_as_magic_model, this plugin will try to infer all the basic relations (has_many, belongs_to and has_and_belongs_to_many) its base table has with other tables in the database, adapting the model correspondingly.

Using the plugin

In order to use this plugin, you only have to declare it in your model. As an example, say you have the proverbial project-management system, where you have projects (each of which can be of several different types) and people, and a HABTM relation between people and projects. So, you have the following tables (expressed as migrations here): create_table :people, :force => true do |t| t.column :name, :string end

create_table :project_types, :force => true do |t|
  t.column :name, :string

create_table :projects, :force => true do |t|
  t.column :name, :string
  t.column :project_type_id, :integer

create_table :people_projects, :force => true, :id => false do |t|
  t.column :person_id, :integer
  t.column :project_id, :integer

</code> Using acts_as_magic_model, you can skip declaring the relations in your models, like this: (of course, each of the classes still has to be declared in its own file) class Person < ActiveRecord::Base acts_as_magic_model end

class Project < ActiveRecord::Base

class ProjectType < ActiveRecord::Base
end </code> And the gaps will be filled in for you - that is, you can go on and ask for <tt>Project.find(:first).people</tt>, <tt>ProjectType.find(:first).projects.size</tt>, <tt>Person.find(:first) {|pr| pr.project_type}</tt>, and whatever you fancy. In future versions of the plugin, I expect even to get rid to explicitly declare the class declarations. Of course, you should be warned: Initializing a model using this plugin <em>is quite database-intensive</em>. It <em>will</em> clutter your logs, and it might be unbearable if you use it in development mode. Still, its convenience is very often worth it. Its main uses should be when prototyping and when designing a system that <em>needs</em> to be flexible to the data models themselves - If you don't expect your system's data structures to be highly malleable, you should probably use <tt>acts_as_magic_model</tt> only as a prototyping aid.


admin 2008-05-02 15:05:44

They look quite nice, at least from the description

I do not like over-magicizing too many things ;-) But yes, he went on quite a similar direction to mine. Thanks!

toupeira 2008-04-14 13:47:50


Are you aware of Dr. Nic’s Magic Models plugin, which also infers validation rules, and actually even lets you skip defining any models at all? Now that’s magic ;)