Search code examples
ruby-on-railsmodel-view-controllerruby-on-rails-3.1

Rails 3.1 Different Views for One Model


I have an application where I have a Shipment model. I have created a view that allows me to create shipments and view shipments in a table based layout. Everything lies in the index.html.erb because all actions are done through ajax.

When a shipment is created, the status is "OPEN" by default. Later on when a bill of lading is printed, the status will change to "PRINTED".

My goal is to create another view that lists only the open shipments allowing an operator to print the bill of lading using a separate form. My question is how does rails handle the rendering of multiple forms and views for one model? Should I use a separate controller/view to handle the action/views associated with printing, or should I use two models for ex. Shipment and OpenShipment? I'm having a hard time finding documentation that explains this issue.

Listed below is my schema for this Model as well as a directory structure for the current view. Hope this helps explain the issue.

Shipment Model
  t.string    :item_code
  t.string    :status
  t.string    :bill_of_lading
  t.integer   :qty_shipped
  t.datetime  :ship_date
  t.datetime  :delivery_date

View Directory Structure

views
   shipments
      index.html.erb
      _shipment.html.erb
      _shipment_table.html.erb
      _form.html.erb
      _edit_form.html.erb
      create.js.coffee
      edit.js.coffee
      update.js.coffee
      destroy.js.coffee     

Solution

  • As I see, you will be showing the same thing twice. You could solve this in two ways: either you add a parameter, and keep the same controller action, or you add a new controller action (which possibly makes a cleaner url --depends on your preference).

    First, you define a scope on Shipment:

    class Shipment
    
      scope :open, lambda { where(:status => 'open')
    
    end
    

    This will allow to write something like:

    Shipment.open
    

    and this will give you all the open shipments.

    So you could define a new controller action as follows

    def open_shipments
      @shipments = Shipment.open
      render :index
    end
    

    This will retrieve the open shipments, and then render the same view as for index.

    To make it even cleaner, you could make the state a parameter in your url. In your config/routes.rb write

    get 'shipments/status/:status', :as => 'shipments#index'
    

    And then you will have to edit your index action as follows:

    def index
      if params[:status]
        @shipments = Shipment.where(:status => params[:status])
      else
        @shipments = Shipment.all
      end
    end
    

    And you can then just visit the url shipments/status/open which will give the open shipments, and likewise shipments/status/printed will give all the printed shipments.

    But the url shipments?status=open will give you the same result (without any changes to the routes necessary). Depends on your flavour.

    Hope this helps.