Every repository with this icon (
Every repository with this icon (
tree 6656fd81c01f461840af90d56c7f6aa44659dc70
parent 102e83d999e88f2c68239a8b280b520fe4dec569
| name | age | message | |
|---|---|---|---|
| |
.gitignore | Sun Jan 25 16:05:34 -0800 2009 | |
| |
MIT-LICENSE | Tue Sep 02 02:25:31 -0700 2008 | |
| |
README.textile | Sun Jan 25 16:35:54 -0800 2009 | |
| |
Rakefile | Sun Jan 25 16:05:34 -0800 2009 | |
| |
TODO | Sun Jan 25 16:25:00 -0800 2009 | |
| |
example/ | Sun Jan 25 14:53:02 -0800 2009 | |
| |
init.rb | Wed Jan 21 07:40:46 -0800 2009 | |
| |
install.rb | Tue Sep 02 02:05:18 -0700 2008 | |
| |
lib/ | Sun Jan 25 16:05:34 -0800 2009 | |
| |
spec/ | Sun Jan 25 13:10:50 -0800 2009 | |
| |
tasks/ | Tue Sep 02 02:05:18 -0700 2008 | |
| |
uninstall.rb | Tue Sep 02 02:05:18 -0700 2008 |
Conductor Plugin
Conductor is a Rails plugin which helps you manage creating and updating a record and its associations via a single form submission. More generally, it is an implementation of the Unit of Work design pattern.
What it does:
- Allows complex nested parameters to represent associations
- Creates, finds or deletes the associated objects as necessary
- Performs database changes only when told to and within a transaction
- Aggregates error messages occurring on the objects it manages
This plugin is written by Jon Leighton. You can contact me at j at jonathanleighton dot com.
Overview
Please see the example app for a fully working version of the code below.
Manually parsing form data
Conductor can be used as an object-oriented way to parse form data – it gives a place to put code which doesn’t really belong in either the controller or the model.
class BookConductor < Conductor::Base
def publisher=(publisher_name)
record.publisher = Publisher.find_by_name(publisher_name)
end
end
Automatically managing associations
In its simplest form, we can do the following:
class Book < ActiveRecord::Base
has_many :tags
end
class BookConductor < Conductor::Base
has_many :tags
end
@book = Book.find(4)
@book.tag_ids # => [4, 6, 3]
@book_conductor = BookConductor.new(@book)
@book_conductor.tag_ids = [5, 2, 6]
# Neither the database nor the @book object have changed because we haven't saved the conductor:
@book.tag_ids # => [4, 6, 3]
@book_conductor.save # => false - the @book still hasn't changed because something failed, so all changes were rolled back
# ... fix the problem ...
@book_conductor.save # => true
@book.tag_ids # => [5, 2, 6]
We can do more complex things as well, including creating/updating join records on the fly:
class Book < ActiveRecord::Base
has_many :authorships
has_many :authors, :through => :authorships
end
class BookConductor < Conductor::Base
has_many :authorships, :require => :author_id
end
@book_conductor.authorships = {
# Record doesn't exist (no id field) and won't be created (no author_id field)
0 => { :role => "" },
# Record is currently associated, but will be removed (no author_id field)
1 => { :id => 5, :role => "Lead Writer" },
# Record doesn't exist (no id field), but will be created and associated with the book
2 => { :author_id => 34, :role => "Editor" }
}
Known Problems
Patches welcome!
- Currently only works with PostgreSQL
- The documentation sucks. I am rubbish at writing documentation, so it would be really great if some people could write tutorials/blog posts/etc…
Relationship with the Presenter pattern
This started out as an implementation of a conductor as described by New Bamboo in their blog post “Presenters and Conductors on Rails”.
A conductor initially seems similar to a presenter, particularly as the example Jay Fields gives manages multiple objects in order to keep the controller concise. However, the distinction in my mind is this:
- A presenter handles view-related state and behaviour in a cleaner and more object-oriented way than helpers
- A conductor assists the controller in parsing form parameters into one or more objects, and saving them







