Alex Pooley's Blog

Hello there, my name is Alex Pooley and I'm a freelance web developer residing in Perth, Western Australia. My passion is in the development of web sites that solve everyday problems. Here's a gallery of some of my notable work. If you need a web site designer or developer, contact me with further details. Lastly, you can read more about me.

Sub List Rails Plugin

October 12th, 2007
My fixes to this plugin have been superseded by a plugin I wrote from scratch. I highly recommend you check it out.

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 &#038;&#038; @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 &#038;&#038; @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

5 Responses to “Sub List Rails Plugin”

  1. Tristan Says:

    Is there any way to shoehorn this into working with a has_many :through relationship?

  2. Tristan Says:

    By the way, great post :)

  3. Alex Says:

    Tristan: I’m not sure on the implications :through would have on the function of the plugin. I’ll forward your comments to Luke (the plugin owner) and see if he can offer advice.

  4. Joli Says:

    RoR newbie here. Can’t get this plugin to work. Would you be willing to share the other sample code (layout, partial, table structure etc.) so I can study an actual working sample? Thanks in advance.

  5. Alex Says:

    Joli: Luke and I are working on a new release starting from scratch. If you’re having trouble with the current plugin you are probably better off waiting for the improved version that we’re working on.

Leave a Reply