开发者

Data structure versioning in rails

First a disclaimer: don't know if I'm trying the impossible here.

Our rails (2.3.12) application is growing up very fast. The little bugger already has >20 models and >100 migrations. One of the tasks of this application is to provide an API. We are currently introducing an API versioning scheme along the lines of: Best practices for API versioning?.

However, in addition to having different ve开发者_Go百科rsions of controllers, we would like to also have different versions of models/db tables. In version V1.0 of the API for example, we provide a method to get a JSON list of all cars, let's say something like this:

http://we.com/v1.0/cars/

For that, we have a car model (and according migrations) that looks like this:

class car
   attr_accessible :maker, :country
end

Now for version 2 of the API, we want our API call to look like this:

http://we.com/v2.0/cars

and the model to look like this:

class car
    attr_accessible :make, :country_code, :country_name
end

I hope you get the picture. What I don't understand (or don't have the right idea yet) is:

Do I have to create two models for this to work using namespaces? E.g.

app/models/v1.0/car.rb
app/models/v2.0/car.rb

...or can I somehow have one model that respects the DATA STRUCTURE version? (Note: I'm not looking to versioning my model instances, vestal_versions etc. is no solution here)

Is it possible to use the two models concurrently? I mean is there a clever way to use both versions of the model on the same data? Patterns like 'decorator' or 'adaptor' come to mind, I've just not found any example. But given we had a converter method (in our example) that would convert

[:country] to [:country_code, :country_name]

and vice versa, wouldn't that work?

Is that possible? Do you know a gem that deals with this?


If you have a method of converting [:country] to [:country_code, :country_name] like you say, I don't see a problem. You'd simply have to ensure that the controllers for each of your APIs are returning the right thing.

I don't know how exactly you're generating your JSON, but you could probably just write methods like @car.to_json_1_0 and @car.to_json_2_0 or pass in the version as an argument to the JSON conversion method.


I don't think that there is a baked solution for such kind of problems. I think the best way for you to maintain api versions is do this:

Create a solid acceptance test suite for all API versions. (It should treat your API as black box - there should not be any implementation details like field names etc.) And this will solve your problem - you'll be able to change old versions api implementation details without changing behavior. So in your example when you'll decide to change field name - your test suite immediately will show you that your API is broken and you have to adjust its implementation (but not the external behavior!). I think that this would be much easier than maintaining different model versions which I think is almost impossible and redundant.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜