Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a JSON service as a Rails model

How can I use a JSON service as a model for a Rails 3.2 application?

I would like to link model methods to JSON requests, e.g.

  • MyModel.create to generate a JSON request to create a new record
  • MyModel.find to generate a JSON request to retrieve a record and decode the JSON response into a model object

What is the preferred way to build this type of functionality? One option that I am looking at is to create a custom DataMapper adapter.

Thanks.

Update:
Note that I can't use ActiveResource because this requires the JSON service to respond in a certain way, which it doesn't in this instance.

like image 766
gjb Avatar asked Aug 02 '12 23:08

gjb


3 Answers

Short answer: it depends on your JSON service.

Is the service RESTful, for starters? If so, you're in luck. ActiveResource is dead, so I wouldn't advise using it, but the code itself would provide a good starting point for creating a set of wrapper methods like create and find to access your API and manipulate records the way ActiveRecord creates and queries records in the DB. That's relatively easy if your API is RESTful because rails is built around RESTful-ness, so the mapping between the two becomes much cleaner.

This article sums it up well:

Rails makes it extremely easy to build Web services that follow the REST principles and work equally well with Web browsers and the programmable Web. In fact, a lot of that simplicity comes directly from following these principles. We didn’t have to tell our client how to create, read, update or delete the resource, those all followed from using the proper HTTP methods. All we had to do is point our client at the right place.

If your service is not RESTful, which judging from the comments on other questions I think is perhaps the case, then you'll have your work cut out for you. ActiveModel will not do this work for you: create is defined in ActiveRecord::Persistence, and find is defined in ActiveRecord::FinderMethods. They're not in ActiveModel. ActiveResource is able to reproduce them fairly easily because it makes assumptions about the type of service it is interfacing with (i.e. that it is RESTful, plus a few other things).

What ActiveModel offers is all the other stuff that makes rails so useful for dealing with models: its validation system, serialization methods, dirty tracking of attribute changes, callbacks (before_save, after_save, etc.), translation/localization, and so on. These are all very useful functions to have, but they still leave you with the problem of wrapping your API calls.

So here's what I would recommend, based on my albeit limited experience (see my final note about that):

  1. First, take a close look at your API and figure out how close it is to being RESTful. If it is not RESTful, you'll have to think about how to work around this so you can treat it like a RESTful service. A good reference on how to do this is O'Reilly's RESTful Web Services (specifically Chapter 2, "Writing Web Service Clients".)
  2. Create an API wrapper around it that implements create, find and whatever other ActiveRecord-like functionality you want to have. You'll probably want to use a gem like Faraday or HTTParty for actually making requests to the API rather than working directly with Net::HTTP. (I've never used DataMapper so can't comment on that.)
  3. Include whatever elements of ActiveModel you want to use to make your wrapper class more like a rails model: validations, serialization etc. In Rails 4, you can actually include everything using the new barebones ActiveModel::Model.

That will get you much of the way to using your JSON service as a Rails model.

For the record, my experience in actually implementing this kind of thing is limited to building an API wrapper (in the works) for accessing an XML API. The wrapper has a class which includes ActiveModel validators for validating queries to the API. I've found the ActiveModel validators really useful for guaranteeing that the API is accessed correctly, but the wrapper is only for getting records from the API, not for actually creating or updating them, so the interface is quite a lot easier than what I expect you'll be building.

like image 112
Chris Salzberg Avatar answered Oct 19 '22 02:10

Chris Salzberg


I think what you're looking for is ActiveResource, you can use it instead of ActiveRecord to work with a RESTful JSON API see this link and this (apidock)

like image 22
Amir Avatar answered Oct 19 '22 03:10

Amir


The best way to do this is to implement an ActiveModel. This railscast covers the basics.

like image 1
Tanzeeb Khalili Avatar answered Oct 19 '22 03:10

Tanzeeb Khalili