Browse the Ruby on Rails Community.

You are here: Browse Railsplugins Acts As Saturn

Acts As Saturn

= Why do we need one?

This plugin came from the requirement to have a nice way to consume hierarchies of xml. As it currently stands, the RESTful interface for rails will consume single objects in either HTML or XML format. but if you add in a child item, you will get an error.

For example, if you have departments that contain employees thus:

Class Department < ActiveRecord::Base
  has_many :employees
  ...
Class Employee < ActiveRecord::Base
  belongs_to :department
  ...

Rails will happily consume an employee via the EmployeeController, or an empty department via the DepartmentController.

If you wish to pass in employees belonging to a department, you must first create the employees and determine their rails ids – then pass those ids in with the department.

But what I really wanted to do was pass in a structure like this to DepartmentController:

<department>
  <name>A branch</name>
  <employees>
    <employee>
      <name>Bob Jones</name>
      <salary>100000</salary>
    </employee>
    <employee>
      <name>Jan Brown</name>
      <salary>110000</salary>
    </employee>
  </employees>
</department>

Then the system should create employees at the same time as departments, and put them into the department.

Thus was born this project – out of a requirement for an object to be able to consume its own children.

= Usage

Install into the vendor/plugins directory. Then pass in the children that it should consume thus:

Class Department < ActiveRecord::Base
  has_many :employees
  acts_as_saturn :employees
  #...
end
Class Employee < ActiveRecord::Base
  belongs_to :department
  acts_as_saturn :department
  #...
end

Currently acts_as_saturn can consume any of has_one, has_many, belongs_to and has_and_belongs_to_many.

I don’t currently cater for :through relationships – they may or may not work as expected, I simply haven’t tested them yet.

Also note – currently it only works for children named after their model – I don’t cater for alternative class-names etc. If your model overloads the class name or uses non-default function names etc – it just won’t work right now.

For has_X relationships it will just create them (even if they already exist). For the others it will simply find them (exploding if they don’t exist) and add them into the relationship. This can be overloaded by passing in the “find_or_create” variable thus:

Class Employee < ActiveRecord::Base
  belongs_to :department
  acts_as_saturn :department, :find_or_create => true
  #...
end

If the department doesn’t exist – it will be created. If something special has to be done to create the object with reference to the parent object – then you can overload the “create_<thing>” method. Eg, if the owner of an object must be put into the non-child object being created. Eg:

Class Department &lt; ActiveRecord::Base
  has_many :employees
  belongs_to :manager
  acts_as_saturn :employees, :manager, :find_or_create => true
  def create_manager(*args)
    args = args.merge(:department_id => self.id)
    manager = Manager.create(args)
  end
  #...
end

= Planned functionality enhancements

  • An ability to call it more than once – thus allowing differing values of find_or_create for different objects. It currently doesn’t do this as any later call to acts_as_saturn overwrites the after_save hook… which overwrites an earlier version.
  • An ability to allow has_X ones to find existing items (if they exist).
  • Use reflections to cater for non-default model names etc.

= Author etc

This plugin was written by Taryn East. http://www.taryneast.com/ I haven’t yet released it under svn – but it’s in the works. Send any questions to: taryn@taryneast.com

Categories: Technology