Sub List Rails Plugin
The Sub List Rails plugin will make your coding experience 10 time easier. It’s a simple way to CRUD children objects within a parent form. For example, let’s say you’re building a system to track a basketball league. You have two tables among others called Teams, and Players. Each Team has_many :players. Using standard Rails scaffolding you will have CRUD screens to modify each team, but you won’t have a convenient way to add players to a team. Using the Sub List plugin you provide a _player partial, add a few calls to the parent’s controller, add a few calls to your views, bada boom bada bing, your done - “instant” AJAX’ed parent/child forms.
I found a few bugs with the current version. I contacted Luke but have not heard back so here’s an archived copy with quite a few fixes. One of the fixes requires sessions enabled.
Sub List Rails Plugin With My Modifications
You can find more info, and the original release at http://rorsublist.rubyforge.org/
There’s also a handy tutorial available: http://cottee.org/articles/2006/06/30/ror-sublist-plugin (I’m getting a 500 error right now, but I’ve seen the page online before).
Expand the code below to see an example controller using the SubList plugin. You will find that the modifications required to the base scaffold code is very minimal. This controller is fully functional, so you can refer to this code if you hit a wall (there’s a few subtleties to trip on). Note that the last method in the code below is a hack and you may need to add it to your controller should you have problems deleting your children objects.
BTW, I’m running with Ruby On Rails 2 Pre-Release.
class InvoicesController < ApplicationController
include UIEnhancements::SubList
helper :SubList
sub_list 'Purchase', 'invoice' do |new_purchase|
end
# GET /invoices
# GET /invoices.xml
def index
@invoices = Invoice.find(:all)
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @invoices }
end
end
# GET /invoices/1
# GET /invoices/1.xml
def show
@invoice = Invoice.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => @invoice }
end
end
# GET /invoices/new
# GET /invoices/new.xml
def new
@invoice = Invoice.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => @invoice }
end
end
# GET /invoices/1/edit
def edit
@invoice = Invoice.find(params[:id])
initialize_purchases
prepare_purchases
end
# POST /invoices
# POST /invoices.xml
def create
@invoice = Invoice.new(params[:invoice])
respond_to do |format|
if initialize_purchases && @invoice.save
flash[:notice] = "Invoice was successfully created."
format.html { redirect_to(@invoice) }
format.xml { render :xml => @invoice, :status => :created, :location => @invoice }
else
format.html { prepare_purchases; render :action => "new" }
format.xml { render :xml => @invoice.errors, :status => :unprocessable_entity }
end
end
end
# PUT /invoices/1
# PUT /invoices/1.xml
def update
@invoice = Invoice.find(params[:id])
respond_to do |format|
if initialize_purchases && @invoice.update_attributes(params[:invoice])
flash[:notice] = "Invoice was successfully updated."
format.html { redirect_to(@invoice) }
format.xml { head :ok }
else
format.html { prepare_purchases; render :action => "edit" }
format.xml { render :xml => @invoice.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /invoices/1
# DELETE /invoices/1.xml
def destroy
@invoice = Invoice.find(params[:id])
@invoice.destroy
respond_to do |format|
format.html { redirect_to(invoices_url) }
format.xml { head :ok }
end
end
# FIXME This is meant to be auto inserted by sublist
def remove_purchase
obj = find_purchase(params[:id])
if ! obj.nil?
obj.destroy
end
render :text => "
end
end