Question

I'm serving a versioned web service from Rails.

I would very much like to be able to call render like normal:

render 'index'

And have it correctly serve the requested version from the following:

index.v1.json.jbuilder
index.v2.json.jbuilder
index.v3.json.jbuilder

Assuming that I already know the requested version within the context of the controller action execution, how do I get render() to leverage it?

Was it helpful?

Solution

I have used the versioncake gem

You should definitely check this out. File name will be very close to what you have:

index.v1.json.jbuilder

would be

index.json.v1.jbuilder

OTHER TIPS

Sounds like a builder design pattern might work here. Have a view builder object that returns the desired behavior.

module ViewBuiler

  def build(name, api_version)
    View.new(name, api_version).build
  end

  class View < Struct(:name, :api_version)
    def build 
      [name, api_version, 'json', 'jbuilder'].join('.')
    end
  end
end

and in your controller you could just do something like:

ApplicationController
  include ViewBuilder

end

MyController < ApplicationController

  def index
    ...
    # you can pass either strings or symbols to build and it will 
    # return 'index.v1.json.jbuilder'
    render build(:index, params[:api_version])
  end
end

And disclaimer, this is just an idea and not something I've implemented. I like the approach for 2 reason. The Controller actions remain skinny and don't have logic in it. A builder like this seems pretty easy to test. And it keeps the thing that might change (views etc) isolated into something that can change frequently as long as it retains it's interface that the Controllers will work with.

This seems like a candidate for Variants. This is new to 4.1 though.

class MyController < ActionController::Base
  before_action :set_variant

  def my_action
    .....
    respond_to do |format|
      format.json do |json|
        json.v1 do
          # render whatever you need here
        end 
      end
    end 
  end

  protected

  def set_variant
    request.variant = :v1 if request.params[:version] == "v1"
    ....
  end


end
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top