Adding json responses to all of your controller actions

published 2008-01-14

Gerald has decided to use JSON responses for the mobile phone app we'll be building at the intermediate Rails workshop. I'm a lazy guy by nature, so there was no way I was going to paste in

format.json { render :json => @bookmark }

in to very controller method.

Now, the easiest way to do this would be to add JSON response to the scaffolding. The templates are in RAILS_ROOT/vendor/rails/lib/rails_generator/generators/components/scaffold/. Open up the controller.rb template and add in the JSON response shown above to the index, show, update and destroy methods and you're done.

Unfortunately, I had already mostly developed the API when I realized that I had to add in the JSON responses (It's not Gerald's fault, he told me long ago). So, I decided to write a quick rake task to do the job for me. To use it, create a file called add_json.rake in RAILS_ROOT/lib/tasks and copy the following code in to it:

namespace :rails do

desc "Adds a 'format.json ...' line for each 'format.xml ...' line in
every controller"
task :add_json => :get_controller_list do
@controllers.each do |controller|
new_lines = File.open(controller, 'r').readlines.collect do |line|
if line =~ /^\s+format\.xml/
[line, line.gsub(/xml/, 'json')]
else
line
end
end.flatten

file = File.open(controller, 'w') do |file|
file.puts new_lines
end
end
end

task :get_controller_list => :environment do
@controllers = Dir.glob(File.join(RAILS_ROOT, 'app', 'controllers',
'*_controller.rb'))
end
end

Call the task from RAILS_ROOT like this: rake rails:add_json

The task opens up every controller, and every time it finds a line that starts with format.xml, it makes a copy of that line just below with every instance of 'xml' replaced with 'json'. It's ~~pretty~~ very brain-dead: it doesn't check if the json response is already there, so don't run it twice on the same project.