Today, I would like to show you an improved way to manage Single Table Inheritance with ActiveScaffold. It s a real time safer.
STI Models should hopefully have a big overlap of attributes, which is the base assumption for my implementation of STI in ActiveScaffold.
Basically, we will show an index view of parent sti controller, in which member actions such as edit, show,delete are linking to corresponding specific sti controller. Create link opens a popup menu showing the different sti models.
That s the concept let s try it out. I will use an example from the book: “Agile Web Development with Rails” written by Dave Thomas and David Heinemeier Hansson.
That example consist of the following models:
- Person (sti_parent)
- Customer
- Employee (Parent of Manager)
- Manager
It s quite tedious to set up an application with these models, therefore we will shorten that process.
Setup Example Application
- Download: one_step_active_scaffold
- Download: sti_blog.rb and rename it to model_setup.rb
- Execute following command: ruby one_step_activescaffold.rb sti jquery
Great, we ve prepared our example application, now we have to configure our controllers
Controller Inheritance
ActiveScaffold configuration can be inherited, which is quite useful for sti, because many columns are shared.
class CustomersController < PeopleController
class EmployeesController < PeopleController
class ManagersController < EmployeesController
Definition of column set for each Controller
We have to define for each controller, which columns we would like to use. Please note that we do not have to define anything specific for manager controller because it should use same settings as employee controller.
class PeopleController < ApplicationController
active_scaffold :person do |conf|
conf.columns = [:type, :name, :email]
end
end
class CustomersController < PeopleController
active_scaffold :customer do |conf|
conf.columns = [:type, :name, :email, :balance]
conf.update.columns = [:name, :email, :balance]
conf.create.columns = [:name, :email, :balance]
end
end
class EmployeesController < PeopleController
active_scaffold :employee do |conf|
conf.columns = [:type, :name, :email, :boss, :department]
conf.update.columns = [:name, :email, :boss, :department]
conf.create.columns = [:name, :email, :boss, :department]
end
end
Parent Controller STI Child Models
One last step, we have to tell the parent controller, which sti_models he should be able to manage.
class PeopleController < ApplicationController
active_scaffold :person do |conf|
....
conf.sti_children = [:employee, :customer, :manager]
....
end
Our Application is ready, start the server and go to: localhost:3000/people.
Hopefully, you will benefit as much as I did.
May 12, 2011 @ 02:05:11
This worked like a charm. But then I discovered that my columns which are many_to_many associations are now broken in the nested list edit. These same associations work fine in the update view, but not inline edit. Looking at the log file I see that a bogus SQL select is being created, where the order by clause is nonsensical.
For your example, imagine that the Person (base class) has_and_belongs_to_many Organizations. Any problem with that?
I’m using Rails 3.0.6 and Ruby 1.8.6
If you’re interested I can send more details.
Thanks again for your many contributions.
May 12, 2011 @ 07:02:03
Can you please open an issue in my github issue tracker with some more details and it would be great if you could create your own github repository with a simple test application showing your issue (using sqlite). That would be great.
May 12, 2011 @ 20:07:26
I went through the exercise of setting up a demonstration of the bug in git only to find it worked fine! After this, I removed my AS from vendor/plugins and reinstalled it as a gem via bundler, and it’s fixed. False alarm!
May 13, 2011 @ 06:17:45
Great and glad that everything is working according to your expectations.
Sep 06, 2011 @ 12:33:33
I have a setup working, but I am not able to use I18n localization on the production environment (it always use the default locale). Where do I have to put the I18n labels in order to make it work?
Thanks in advance.
Sep 06, 2011 @ 17:24:18
That s a general rails 3 issue. Take a look eg at http://www.ruby-forum.com/topic/215421