Uploads with respond_to

Posted by Luke
on Tuesday, May 08

File this one under “Stupid Rails Tricks.”

You’re probably familiar with using respond_to in your controller to generate different content representations based on the HTTP Accept: header or the URL extension:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def list
  respond_to do |wants|
    wants.html {
      @people = Person.find(:all)
    }
    wants.csv {
      people = Person.find(:all)
      csv = FasterCSV.generate do |csv|
        csv << ["user name", "first name", "last name", "email"]
        people.each do |person|
          csv << [person.user_name, person.first_name, person.last_name, person.email]
        end
      end

      send_data(csv, :filename => 'people.csv', 
                :type => 'text/csv', :disposition => 'attachment')
    }
  end
end

With RESTful routing, the first form gets the named route people_path, and the second form gets formatted_people_path(:csv).

But did you know you can use respond_to on uploads, too?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
def create
  respond_to do |wants|
    
    wants.html {
      @person = Person.new(params[:player])
      @person.group = @group        
      if @person.save
        redirect_to people_path(@group)
      else
        flash[:error] = "Person wasn't saved."
        render :template => 'person/new'
      end
    }
    
    wants.csv {
      row_count = import_csv(params[:csv_file]
      flash[:message] = "Imported #{row_count} players."
      redirect_to people_path
    }
  end
end

If you POST a multipart form to formatted_people_path(:csv) you’ll get the CSV creation method.

This can be used to keep your URLs clean and you controllers a little smaller. I’m not sure if it’s very useful, but it is kind of neat.

Comments

Leave a response